hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/nfsd/nfs4proc.c
....@@ -36,6 +36,9 @@
3636 #include <linux/file.h>
3737 #include <linux/falloc.h>
3838 #include <linux/slab.h>
39
+#include <linux/kthread.h>
40
+#include <linux/sunrpc/addr.h>
41
+#include <linux/nfs_ssc.h>
3942
4043 #include "idmap.h"
4144 #include "cache.h"
....@@ -231,7 +234,7 @@
231234 if (!*resfh)
232235 return nfserr_jukebox;
233236 fh_init(*resfh, NFS4_FHSIZE);
234
- open->op_truncate = 0;
237
+ open->op_truncate = false;
235238
236239 if (open->op_create) {
237240 /* FIXME: check session persistence and pnfs flags.
....@@ -364,7 +367,7 @@
364367 if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
365368 return nfserr_inval;
366369
367
- open->op_created = 0;
370
+ open->op_created = false;
368371 /*
369372 * RFC5661 18.51.3
370373 * Before RECLAIM_COMPLETE done, server should deny new lock
....@@ -426,6 +429,7 @@
426429 goto out;
427430 open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
428431 reclaim = true;
432
+ fallthrough;
429433 case NFS4_OPEN_CLAIM_FH:
430434 case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
431435 status = do_open_fhandle(rqstp, cstate, open);
....@@ -501,12 +505,20 @@
501505 union nfsd4_op_u *u)
502506 {
503507 struct nfsd4_putfh *putfh = &u->putfh;
508
+ __be32 ret;
504509
505510 fh_put(&cstate->current_fh);
506511 cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
507512 memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
508513 putfh->pf_fhlen);
509
- return fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS);
514
+ ret = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS);
515
+#ifdef CONFIG_NFSD_V4_2_INTER_SSC
516
+ if (ret == nfserr_stale && putfh->no_verify) {
517
+ SET_FH_FLAG(&cstate->current_fh, NFSD4_FH_FOREIGN);
518
+ ret = 0;
519
+ }
520
+#endif
521
+ return ret;
510522 }
511523
512524 static __be32
....@@ -528,9 +540,9 @@
528540 return nfserr_restorefh;
529541
530542 fh_dup2(&cstate->current_fh, &cstate->save_fh);
531
- if (HAS_STATE_ID(cstate, SAVED_STATE_ID_FLAG)) {
543
+ if (HAS_CSTATE_FLAG(cstate, SAVED_STATE_ID_FLAG)) {
532544 memcpy(&cstate->current_stateid, &cstate->save_stateid, sizeof(stateid_t));
533
- SET_STATE_ID(cstate, CURRENT_STATE_ID_FLAG);
545
+ SET_CSTATE_FLAG(cstate, CURRENT_STATE_ID_FLAG);
534546 }
535547 return nfs_ok;
536548 }
....@@ -540,9 +552,9 @@
540552 union nfsd4_op_u *u)
541553 {
542554 fh_dup2(&cstate->save_fh, &cstate->current_fh);
543
- if (HAS_STATE_ID(cstate, CURRENT_STATE_ID_FLAG)) {
555
+ if (HAS_CSTATE_FLAG(cstate, CURRENT_STATE_ID_FLAG)) {
544556 memcpy(&cstate->save_stateid, &cstate->current_stateid, sizeof(stateid_t));
545
- SET_STATE_ID(cstate, SAVED_STATE_ID_FLAG);
557
+ SET_CSTATE_FLAG(cstate, SAVED_STATE_ID_FLAG);
546558 }
547559 return nfs_ok;
548560 }
....@@ -555,8 +567,14 @@
555567 union nfsd4_op_u *u)
556568 {
557569 struct nfsd4_access *access = &u->access;
570
+ u32 access_full;
558571
559
- if (access->ac_req_access & ~NFS3_ACCESS_FULL)
572
+ access_full = NFS3_ACCESS_FULL;
573
+ if (cstate->minorversion >= 2)
574
+ access_full |= NFS4_ACCESS_XALIST | NFS4_ACCESS_XAREAD |
575
+ NFS4_ACCESS_XAWRITE;
576
+
577
+ if (access->ac_req_access & ~access_full)
560578 return nfserr_inval;
561579
562580 access->ac_resp_access = access->ac_req_access;
....@@ -566,17 +584,11 @@
566584
567585 static void gen_boot_verifier(nfs4_verifier *verifier, struct net *net)
568586 {
569
- __be32 verf[2];
570
- struct nfsd_net *nn = net_generic(net, nfsd_net_id);
587
+ __be32 *verf = (__be32 *)verifier->data;
571588
572
- /*
573
- * This is opaque to client, so no need to byte-swap. Use
574
- * __force to keep sparse happy. y2038 time_t overflow is
575
- * irrelevant in this usage.
576
- */
577
- verf[0] = (__force __be32)nn->nfssvc_boot.tv_sec;
578
- verf[1] = (__force __be32)nn->nfssvc_boot.tv_nsec;
579
- memcpy(verifier->data, verf, sizeof(verifier->data));
589
+ BUILD_BUG_ON(2*sizeof(*verf) != sizeof(verifier->data));
590
+
591
+ nfsd_copy_boot_verifier(verf, net_generic(net, nfsd_net_id));
580592 }
581593
582594 static __be32
....@@ -585,9 +597,9 @@
585597 {
586598 struct nfsd4_commit *commit = &u->commit;
587599
588
- gen_boot_verifier(&commit->co_verf, SVC_NET(rqstp));
589600 return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
590
- commit->co_count);
601
+ commit->co_count,
602
+ (__be32 *)commit->co_verf.data);
591603 }
592604
593605 static __be32
....@@ -759,7 +771,7 @@
759771 struct nfsd4_read *read = &u->read;
760772 __be32 status;
761773
762
- read->rd_filp = NULL;
774
+ read->rd_nf = NULL;
763775 if (read->rd_offset >= OFFSET_MAX)
764776 return nfserr_inval;
765777
....@@ -780,7 +792,7 @@
780792 /* check stateid */
781793 status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
782794 &read->rd_stateid, RD_STATE,
783
- &read->rd_filp, &read->rd_tmp_file);
795
+ &read->rd_nf, NULL);
784796 if (status) {
785797 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
786798 goto out;
....@@ -796,8 +808,8 @@
796808 static void
797809 nfsd4_read_release(union nfsd4_op_u *u)
798810 {
799
- if (u->read.rd_filp)
800
- fput(u->read.rd_filp);
811
+ if (u->read.rd_nf)
812
+ nfsd_file_put(u->read.rd_nf);
801813 trace_nfsd_read_done(u->read.rd_rqstp, u->read.rd_fhp,
802814 u->read.rd_offset, u->read.rd_length);
803815 }
....@@ -862,16 +874,15 @@
862874 struct nfsd4_rename *rename = &u->rename;
863875 __be32 status;
864876
865
- if (opens_in_grace(SVC_NET(rqstp)) &&
866
- !(cstate->save_fh.fh_export->ex_flags & NFSEXP_NOSUBTREECHECK))
877
+ if (opens_in_grace(SVC_NET(rqstp)))
867878 return nfserr_grace;
868879 status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
869880 rename->rn_snamelen, &cstate->current_fh,
870881 rename->rn_tname, rename->rn_tnamelen);
871882 if (status)
872883 return status;
873
- set_change_info(&rename->rn_sinfo, &cstate->current_fh);
874
- set_change_info(&rename->rn_tinfo, &cstate->save_fh);
884
+ set_change_info(&rename->rn_sinfo, &cstate->save_fh);
885
+ set_change_info(&rename->rn_tinfo, &cstate->current_fh);
875886 return nfs_ok;
876887 }
877888
....@@ -980,7 +991,7 @@
980991 if (status)
981992 goto out;
982993 status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
983
- 0, (time_t)0);
994
+ 0, (time64_t)0);
984995 out:
985996 fh_drop_write(&cstate->current_fh);
986997 return status;
....@@ -992,7 +1003,7 @@
9921003 {
9931004 struct nfsd4_write *write = &u->write;
9941005 stateid_t *stateid = &write->wr_stateid;
995
- struct file *filp = NULL;
1006
+ struct nfsd_file *nf = NULL;
9961007 __be32 status = nfs_ok;
9971008 unsigned long cnt;
9981009 int nvecs;
....@@ -1005,23 +1016,23 @@
10051016 trace_nfsd_write_start(rqstp, &cstate->current_fh,
10061017 write->wr_offset, cnt);
10071018 status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
1008
- stateid, WR_STATE, &filp, NULL);
1019
+ stateid, WR_STATE, &nf, NULL);
10091020 if (status) {
10101021 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
10111022 return status;
10121023 }
10131024
10141025 write->wr_how_written = write->wr_stable_how;
1015
- gen_boot_verifier(&write->wr_verifier, SVC_NET(rqstp));
10161026
10171027 nvecs = svc_fill_write_vector(rqstp, write->wr_pagelist,
10181028 &write->wr_head, write->wr_buflen);
10191029 WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec));
10201030
1021
- status = nfsd_vfs_write(rqstp, &cstate->current_fh, filp,
1031
+ status = nfsd_vfs_write(rqstp, &cstate->current_fh, nf,
10221032 write->wr_offset, rqstp->rq_vec, nvecs, &cnt,
1023
- write->wr_how_written);
1024
- fput(filp);
1033
+ write->wr_how_written,
1034
+ (__be32 *)write->wr_verifier.data);
1035
+ nfsd_file_put(nf);
10251036
10261037 write->wr_bytes_written = cnt;
10271038 trace_nfsd_write_done(rqstp, &cstate->current_fh,
....@@ -1031,8 +1042,8 @@
10311042
10321043 static __be32
10331044 nfsd4_verify_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1034
- stateid_t *src_stateid, struct file **src,
1035
- stateid_t *dst_stateid, struct file **dst)
1045
+ stateid_t *src_stateid, struct nfsd_file **src,
1046
+ stateid_t *dst_stateid, struct nfsd_file **dst)
10361047 {
10371048 __be32 status;
10381049
....@@ -1054,8 +1065,8 @@
10541065 }
10551066
10561067 /* fix up for NFS-specific error code */
1057
- if (!S_ISREG(file_inode(*src)->i_mode) ||
1058
- !S_ISREG(file_inode(*dst)->i_mode)) {
1068
+ if (!S_ISREG(file_inode((*src)->nf_file)->i_mode) ||
1069
+ !S_ISREG(file_inode((*dst)->nf_file)->i_mode)) {
10591070 status = nfserr_wrong_type;
10601071 goto out_put_dst;
10611072 }
....@@ -1063,9 +1074,11 @@
10631074 out:
10641075 return status;
10651076 out_put_dst:
1066
- fput(*dst);
1077
+ nfsd_file_put(*dst);
1078
+ *dst = NULL;
10671079 out_put_src:
1068
- fput(*src);
1080
+ nfsd_file_put(*src);
1081
+ *src = NULL;
10691082 goto out;
10701083 }
10711084
....@@ -1074,7 +1087,7 @@
10741087 union nfsd4_op_u *u)
10751088 {
10761089 struct nfsd4_clone *clone = &u->clone;
1077
- struct file *src, *dst;
1090
+ struct nfsd_file *src, *dst;
10781091 __be32 status;
10791092
10801093 status = nfsd4_verify_copy(rqstp, cstate, &clone->cl_src_stateid, &src,
....@@ -1083,12 +1096,399 @@
10831096 goto out;
10841097
10851098 status = nfsd4_clone_file_range(src, clone->cl_src_pos,
1086
- dst, clone->cl_dst_pos, clone->cl_count);
1099
+ dst, clone->cl_dst_pos, clone->cl_count,
1100
+ EX_ISSYNC(cstate->current_fh.fh_export));
10871101
1088
- fput(dst);
1089
- fput(src);
1102
+ nfsd_file_put(dst);
1103
+ nfsd_file_put(src);
10901104 out:
10911105 return status;
1106
+}
1107
+
1108
+void nfs4_put_copy(struct nfsd4_copy *copy)
1109
+{
1110
+ if (!refcount_dec_and_test(&copy->refcount))
1111
+ return;
1112
+ kfree(copy);
1113
+}
1114
+
1115
+static bool
1116
+check_and_set_stop_copy(struct nfsd4_copy *copy)
1117
+{
1118
+ bool value;
1119
+
1120
+ spin_lock(&copy->cp_clp->async_lock);
1121
+ value = copy->stopped;
1122
+ if (!copy->stopped)
1123
+ copy->stopped = true;
1124
+ spin_unlock(&copy->cp_clp->async_lock);
1125
+ return value;
1126
+}
1127
+
1128
+static void nfsd4_stop_copy(struct nfsd4_copy *copy)
1129
+{
1130
+ /* only 1 thread should stop the copy */
1131
+ if (!check_and_set_stop_copy(copy))
1132
+ kthread_stop(copy->copy_task);
1133
+ nfs4_put_copy(copy);
1134
+}
1135
+
1136
+static struct nfsd4_copy *nfsd4_get_copy(struct nfs4_client *clp)
1137
+{
1138
+ struct nfsd4_copy *copy = NULL;
1139
+
1140
+ spin_lock(&clp->async_lock);
1141
+ if (!list_empty(&clp->async_copies)) {
1142
+ copy = list_first_entry(&clp->async_copies, struct nfsd4_copy,
1143
+ copies);
1144
+ refcount_inc(&copy->refcount);
1145
+ }
1146
+ spin_unlock(&clp->async_lock);
1147
+ return copy;
1148
+}
1149
+
1150
+void nfsd4_shutdown_copy(struct nfs4_client *clp)
1151
+{
1152
+ struct nfsd4_copy *copy;
1153
+
1154
+ while ((copy = nfsd4_get_copy(clp)) != NULL)
1155
+ nfsd4_stop_copy(copy);
1156
+}
1157
+#ifdef CONFIG_NFSD_V4_2_INTER_SSC
1158
+
1159
+extern struct file *nfs42_ssc_open(struct vfsmount *ss_mnt,
1160
+ struct nfs_fh *src_fh,
1161
+ nfs4_stateid *stateid);
1162
+extern void nfs42_ssc_close(struct file *filep);
1163
+
1164
+extern void nfs_sb_deactive(struct super_block *sb);
1165
+
1166
+#define NFSD42_INTERSSC_MOUNTOPS "vers=4.2,addr=%s,sec=sys"
1167
+
1168
+/*
1169
+ * Support one copy source server for now.
1170
+ */
1171
+static __be32
1172
+nfsd4_interssc_connect(struct nl4_server *nss, struct svc_rqst *rqstp,
1173
+ struct vfsmount **mount)
1174
+{
1175
+ struct file_system_type *type;
1176
+ struct vfsmount *ss_mnt;
1177
+ struct nfs42_netaddr *naddr;
1178
+ struct sockaddr_storage tmp_addr;
1179
+ size_t tmp_addrlen, match_netid_len = 3;
1180
+ char *startsep = "", *endsep = "", *match_netid = "tcp";
1181
+ char *ipaddr, *dev_name, *raw_data;
1182
+ int len, raw_len;
1183
+ __be32 status = nfserr_inval;
1184
+
1185
+ naddr = &nss->u.nl4_addr;
1186
+ tmp_addrlen = rpc_uaddr2sockaddr(SVC_NET(rqstp), naddr->addr,
1187
+ naddr->addr_len,
1188
+ (struct sockaddr *)&tmp_addr,
1189
+ sizeof(tmp_addr));
1190
+ if (tmp_addrlen == 0)
1191
+ goto out_err;
1192
+
1193
+ if (tmp_addr.ss_family == AF_INET6) {
1194
+ startsep = "[";
1195
+ endsep = "]";
1196
+ match_netid = "tcp6";
1197
+ match_netid_len = 4;
1198
+ }
1199
+
1200
+ if (naddr->netid_len != match_netid_len ||
1201
+ strncmp(naddr->netid, match_netid, naddr->netid_len))
1202
+ goto out_err;
1203
+
1204
+ /* Construct the raw data for the vfs_kern_mount call */
1205
+ len = RPC_MAX_ADDRBUFLEN + 1;
1206
+ ipaddr = kzalloc(len, GFP_KERNEL);
1207
+ if (!ipaddr)
1208
+ goto out_err;
1209
+
1210
+ rpc_ntop((struct sockaddr *)&tmp_addr, ipaddr, len);
1211
+
1212
+ /* 2 for ipv6 endsep and startsep. 3 for ":/" and trailing '/0'*/
1213
+
1214
+ raw_len = strlen(NFSD42_INTERSSC_MOUNTOPS) + strlen(ipaddr);
1215
+ raw_data = kzalloc(raw_len, GFP_KERNEL);
1216
+ if (!raw_data)
1217
+ goto out_free_ipaddr;
1218
+
1219
+ snprintf(raw_data, raw_len, NFSD42_INTERSSC_MOUNTOPS, ipaddr);
1220
+
1221
+ status = nfserr_nodev;
1222
+ type = get_fs_type("nfs");
1223
+ if (!type)
1224
+ goto out_free_rawdata;
1225
+
1226
+ /* Set the server:<export> for the vfs_kern_mount call */
1227
+ dev_name = kzalloc(len + 5, GFP_KERNEL);
1228
+ if (!dev_name)
1229
+ goto out_free_rawdata;
1230
+ snprintf(dev_name, len + 5, "%s%s%s:/", startsep, ipaddr, endsep);
1231
+
1232
+ /* Use an 'internal' mount: SB_KERNMOUNT -> MNT_INTERNAL */
1233
+ ss_mnt = vfs_kern_mount(type, SB_KERNMOUNT, dev_name, raw_data);
1234
+ module_put(type->owner);
1235
+ if (IS_ERR(ss_mnt))
1236
+ goto out_free_devname;
1237
+
1238
+ status = 0;
1239
+ *mount = ss_mnt;
1240
+
1241
+out_free_devname:
1242
+ kfree(dev_name);
1243
+out_free_rawdata:
1244
+ kfree(raw_data);
1245
+out_free_ipaddr:
1246
+ kfree(ipaddr);
1247
+out_err:
1248
+ return status;
1249
+}
1250
+
1251
+/*
1252
+ * Verify COPY destination stateid.
1253
+ *
1254
+ * Connect to the source server with NFSv4.1.
1255
+ * Create the source struct file for nfsd_copy_range.
1256
+ * Called with COPY cstate:
1257
+ * SAVED_FH: source filehandle
1258
+ * CURRENT_FH: destination filehandle
1259
+ */
1260
+static __be32
1261
+nfsd4_setup_inter_ssc(struct svc_rqst *rqstp,
1262
+ struct nfsd4_compound_state *cstate,
1263
+ struct nfsd4_copy *copy, struct vfsmount **mount)
1264
+{
1265
+ struct svc_fh *s_fh = NULL;
1266
+ stateid_t *s_stid = &copy->cp_src_stateid;
1267
+ __be32 status = nfserr_inval;
1268
+
1269
+ /* Verify the destination stateid and set dst struct file*/
1270
+ status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
1271
+ &copy->cp_dst_stateid,
1272
+ WR_STATE, &copy->nf_dst, NULL);
1273
+ if (status)
1274
+ goto out;
1275
+
1276
+ status = nfsd4_interssc_connect(&copy->cp_src, rqstp, mount);
1277
+ if (status)
1278
+ goto out;
1279
+
1280
+ s_fh = &cstate->save_fh;
1281
+
1282
+ copy->c_fh.size = s_fh->fh_handle.fh_size;
1283
+ memcpy(copy->c_fh.data, &s_fh->fh_handle.fh_base, copy->c_fh.size);
1284
+ copy->stateid.seqid = cpu_to_be32(s_stid->si_generation);
1285
+ memcpy(copy->stateid.other, (void *)&s_stid->si_opaque,
1286
+ sizeof(stateid_opaque_t));
1287
+
1288
+ status = 0;
1289
+out:
1290
+ return status;
1291
+}
1292
+
1293
+static void
1294
+nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct nfsd_file *src,
1295
+ struct nfsd_file *dst)
1296
+{
1297
+ nfs42_ssc_close(src->nf_file);
1298
+ fput(src->nf_file);
1299
+ nfsd_file_put(dst);
1300
+ mntput(ss_mnt);
1301
+}
1302
+
1303
+#else /* CONFIG_NFSD_V4_2_INTER_SSC */
1304
+
1305
+static __be32
1306
+nfsd4_setup_inter_ssc(struct svc_rqst *rqstp,
1307
+ struct nfsd4_compound_state *cstate,
1308
+ struct nfsd4_copy *copy,
1309
+ struct vfsmount **mount)
1310
+{
1311
+ *mount = NULL;
1312
+ return nfserr_inval;
1313
+}
1314
+
1315
+static void
1316
+nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct nfsd_file *src,
1317
+ struct nfsd_file *dst)
1318
+{
1319
+}
1320
+
1321
+static struct file *nfs42_ssc_open(struct vfsmount *ss_mnt,
1322
+ struct nfs_fh *src_fh,
1323
+ nfs4_stateid *stateid)
1324
+{
1325
+ return NULL;
1326
+}
1327
+#endif /* CONFIG_NFSD_V4_2_INTER_SSC */
1328
+
1329
+static __be32
1330
+nfsd4_setup_intra_ssc(struct svc_rqst *rqstp,
1331
+ struct nfsd4_compound_state *cstate,
1332
+ struct nfsd4_copy *copy)
1333
+{
1334
+ return nfsd4_verify_copy(rqstp, cstate, &copy->cp_src_stateid,
1335
+ &copy->nf_src, &copy->cp_dst_stateid,
1336
+ &copy->nf_dst);
1337
+}
1338
+
1339
+static void
1340
+nfsd4_cleanup_intra_ssc(struct nfsd_file *src, struct nfsd_file *dst)
1341
+{
1342
+ nfsd_file_put(src);
1343
+ nfsd_file_put(dst);
1344
+}
1345
+
1346
+static void nfsd4_cb_offload_release(struct nfsd4_callback *cb)
1347
+{
1348
+ struct nfsd4_copy *copy = container_of(cb, struct nfsd4_copy, cp_cb);
1349
+
1350
+ nfs4_put_copy(copy);
1351
+}
1352
+
1353
+static int nfsd4_cb_offload_done(struct nfsd4_callback *cb,
1354
+ struct rpc_task *task)
1355
+{
1356
+ return 1;
1357
+}
1358
+
1359
+static const struct nfsd4_callback_ops nfsd4_cb_offload_ops = {
1360
+ .release = nfsd4_cb_offload_release,
1361
+ .done = nfsd4_cb_offload_done
1362
+};
1363
+
1364
+static void nfsd4_init_copy_res(struct nfsd4_copy *copy, bool sync)
1365
+{
1366
+ copy->cp_res.wr_stable_how = NFS_UNSTABLE;
1367
+ copy->cp_synchronous = sync;
1368
+ gen_boot_verifier(&copy->cp_res.wr_verifier, copy->cp_clp->net);
1369
+}
1370
+
1371
+static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy)
1372
+{
1373
+ struct file *dst = copy->nf_dst->nf_file;
1374
+ struct file *src = copy->nf_src->nf_file;
1375
+ ssize_t bytes_copied = 0;
1376
+ size_t bytes_total = copy->cp_count;
1377
+ u64 src_pos = copy->cp_src_pos;
1378
+ u64 dst_pos = copy->cp_dst_pos;
1379
+
1380
+ do {
1381
+ if (kthread_should_stop())
1382
+ break;
1383
+ bytes_copied = nfsd_copy_file_range(src, src_pos, dst, dst_pos,
1384
+ bytes_total);
1385
+ if (bytes_copied <= 0)
1386
+ break;
1387
+ bytes_total -= bytes_copied;
1388
+ copy->cp_res.wr_bytes_written += bytes_copied;
1389
+ src_pos += bytes_copied;
1390
+ dst_pos += bytes_copied;
1391
+ } while (bytes_total > 0 && !copy->cp_synchronous);
1392
+ return bytes_copied;
1393
+}
1394
+
1395
+static __be32 nfsd4_do_copy(struct nfsd4_copy *copy, bool sync)
1396
+{
1397
+ __be32 status;
1398
+ ssize_t bytes;
1399
+
1400
+ bytes = _nfsd_copy_file_range(copy);
1401
+ /* for async copy, we ignore the error, client can always retry
1402
+ * to get the error
1403
+ */
1404
+ if (bytes < 0 && !copy->cp_res.wr_bytes_written)
1405
+ status = nfserrno(bytes);
1406
+ else {
1407
+ nfsd4_init_copy_res(copy, sync);
1408
+ status = nfs_ok;
1409
+ }
1410
+
1411
+ if (!copy->cp_intra) /* Inter server SSC */
1412
+ nfsd4_cleanup_inter_ssc(copy->ss_mnt, copy->nf_src,
1413
+ copy->nf_dst);
1414
+ else
1415
+ nfsd4_cleanup_intra_ssc(copy->nf_src, copy->nf_dst);
1416
+
1417
+ return status;
1418
+}
1419
+
1420
+static void dup_copy_fields(struct nfsd4_copy *src, struct nfsd4_copy *dst)
1421
+{
1422
+ dst->cp_src_pos = src->cp_src_pos;
1423
+ dst->cp_dst_pos = src->cp_dst_pos;
1424
+ dst->cp_count = src->cp_count;
1425
+ dst->cp_synchronous = src->cp_synchronous;
1426
+ memcpy(&dst->cp_res, &src->cp_res, sizeof(src->cp_res));
1427
+ memcpy(&dst->fh, &src->fh, sizeof(src->fh));
1428
+ dst->cp_clp = src->cp_clp;
1429
+ dst->nf_dst = nfsd_file_get(src->nf_dst);
1430
+ dst->cp_intra = src->cp_intra;
1431
+ if (src->cp_intra) /* for inter, file_src doesn't exist yet */
1432
+ dst->nf_src = nfsd_file_get(src->nf_src);
1433
+
1434
+ memcpy(&dst->cp_stateid, &src->cp_stateid, sizeof(src->cp_stateid));
1435
+ memcpy(&dst->cp_src, &src->cp_src, sizeof(struct nl4_server));
1436
+ memcpy(&dst->stateid, &src->stateid, sizeof(src->stateid));
1437
+ memcpy(&dst->c_fh, &src->c_fh, sizeof(src->c_fh));
1438
+ dst->ss_mnt = src->ss_mnt;
1439
+}
1440
+
1441
+static void cleanup_async_copy(struct nfsd4_copy *copy)
1442
+{
1443
+ nfs4_free_copy_state(copy);
1444
+ nfsd_file_put(copy->nf_dst);
1445
+ if (copy->cp_intra)
1446
+ nfsd_file_put(copy->nf_src);
1447
+ spin_lock(&copy->cp_clp->async_lock);
1448
+ list_del(&copy->copies);
1449
+ spin_unlock(&copy->cp_clp->async_lock);
1450
+ nfs4_put_copy(copy);
1451
+}
1452
+
1453
+static int nfsd4_do_async_copy(void *data)
1454
+{
1455
+ struct nfsd4_copy *copy = (struct nfsd4_copy *)data;
1456
+ struct nfsd4_copy *cb_copy;
1457
+
1458
+ if (!copy->cp_intra) { /* Inter server SSC */
1459
+ copy->nf_src = kzalloc(sizeof(struct nfsd_file), GFP_KERNEL);
1460
+ if (!copy->nf_src) {
1461
+ copy->nfserr = nfserr_serverfault;
1462
+ /* ss_mnt will be unmounted by the laundromat */
1463
+ goto do_callback;
1464
+ }
1465
+ copy->nf_src->nf_file = nfs42_ssc_open(copy->ss_mnt, &copy->c_fh,
1466
+ &copy->stateid);
1467
+ if (IS_ERR(copy->nf_src->nf_file)) {
1468
+ copy->nfserr = nfserr_offload_denied;
1469
+ /* ss_mnt will be unmounted by the laundromat */
1470
+ goto do_callback;
1471
+ }
1472
+ }
1473
+
1474
+ copy->nfserr = nfsd4_do_copy(copy, 0);
1475
+do_callback:
1476
+ cb_copy = kzalloc(sizeof(struct nfsd4_copy), GFP_KERNEL);
1477
+ if (!cb_copy)
1478
+ goto out;
1479
+ refcount_set(&cb_copy->refcount, 1);
1480
+ memcpy(&cb_copy->cp_res, &copy->cp_res, sizeof(copy->cp_res));
1481
+ cb_copy->cp_clp = copy->cp_clp;
1482
+ cb_copy->nfserr = copy->nfserr;
1483
+ memcpy(&cb_copy->fh, &copy->fh, sizeof(copy->fh));
1484
+ nfsd4_init_cb(&cb_copy->cp_cb, cb_copy->cp_clp,
1485
+ &nfsd4_cb_offload_ops, NFSPROC4_CLNT_CB_OFFLOAD);
1486
+ nfsd4_run_cb(&cb_copy->cp_cb);
1487
+out:
1488
+ if (!copy->cp_intra)
1489
+ kfree(copy->nf_src);
1490
+ cleanup_async_copy(copy);
1491
+ return 0;
10921492 }
10931493
10941494 static __be32
....@@ -1096,31 +1496,144 @@
10961496 union nfsd4_op_u *u)
10971497 {
10981498 struct nfsd4_copy *copy = &u->copy;
1099
- struct file *src, *dst;
11001499 __be32 status;
1101
- ssize_t bytes;
1500
+ struct nfsd4_copy *async_copy = NULL;
11021501
1103
- status = nfsd4_verify_copy(rqstp, cstate, &copy->cp_src_stateid, &src,
1104
- &copy->cp_dst_stateid, &dst);
1105
- if (status)
1106
- goto out;
1107
-
1108
- bytes = nfsd_copy_file_range(src, copy->cp_src_pos,
1109
- dst, copy->cp_dst_pos, copy->cp_count);
1110
-
1111
- if (bytes < 0)
1112
- status = nfserrno(bytes);
1113
- else {
1114
- copy->cp_res.wr_bytes_written = bytes;
1115
- copy->cp_res.wr_stable_how = NFS_UNSTABLE;
1116
- copy->cp_synchronous = 1;
1117
- gen_boot_verifier(&copy->cp_res.wr_verifier, SVC_NET(rqstp));
1118
- status = nfs_ok;
1502
+ if (!copy->cp_intra) { /* Inter server SSC */
1503
+ if (!inter_copy_offload_enable || copy->cp_synchronous) {
1504
+ status = nfserr_notsupp;
1505
+ goto out;
1506
+ }
1507
+ status = nfsd4_setup_inter_ssc(rqstp, cstate, copy,
1508
+ &copy->ss_mnt);
1509
+ if (status)
1510
+ return nfserr_offload_denied;
1511
+ } else {
1512
+ status = nfsd4_setup_intra_ssc(rqstp, cstate, copy);
1513
+ if (status)
1514
+ return status;
11191515 }
11201516
1121
- fput(src);
1122
- fput(dst);
1517
+ copy->cp_clp = cstate->clp;
1518
+ memcpy(&copy->fh, &cstate->current_fh.fh_handle,
1519
+ sizeof(struct knfsd_fh));
1520
+ if (!copy->cp_synchronous) {
1521
+ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
1522
+
1523
+ status = nfserrno(-ENOMEM);
1524
+ async_copy = kzalloc(sizeof(struct nfsd4_copy), GFP_KERNEL);
1525
+ if (!async_copy)
1526
+ goto out_err;
1527
+ if (!nfs4_init_copy_state(nn, copy))
1528
+ goto out_err;
1529
+ refcount_set(&async_copy->refcount, 1);
1530
+ memcpy(&copy->cp_res.cb_stateid, &copy->cp_stateid.stid,
1531
+ sizeof(copy->cp_res.cb_stateid));
1532
+ dup_copy_fields(copy, async_copy);
1533
+ async_copy->copy_task = kthread_create(nfsd4_do_async_copy,
1534
+ async_copy, "%s", "copy thread");
1535
+ if (IS_ERR(async_copy->copy_task))
1536
+ goto out_err;
1537
+ spin_lock(&async_copy->cp_clp->async_lock);
1538
+ list_add(&async_copy->copies,
1539
+ &async_copy->cp_clp->async_copies);
1540
+ spin_unlock(&async_copy->cp_clp->async_lock);
1541
+ wake_up_process(async_copy->copy_task);
1542
+ status = nfs_ok;
1543
+ } else {
1544
+ status = nfsd4_do_copy(copy, 1);
1545
+ }
11231546 out:
1547
+ return status;
1548
+out_err:
1549
+ if (async_copy)
1550
+ cleanup_async_copy(async_copy);
1551
+ status = nfserrno(-ENOMEM);
1552
+ /*
1553
+ * source's vfsmount of inter-copy will be unmounted
1554
+ * by the laundromat
1555
+ */
1556
+ goto out;
1557
+}
1558
+
1559
+struct nfsd4_copy *
1560
+find_async_copy(struct nfs4_client *clp, stateid_t *stateid)
1561
+{
1562
+ struct nfsd4_copy *copy;
1563
+
1564
+ spin_lock(&clp->async_lock);
1565
+ list_for_each_entry(copy, &clp->async_copies, copies) {
1566
+ if (memcmp(&copy->cp_stateid.stid, stateid, NFS4_STATEID_SIZE))
1567
+ continue;
1568
+ refcount_inc(&copy->refcount);
1569
+ spin_unlock(&clp->async_lock);
1570
+ return copy;
1571
+ }
1572
+ spin_unlock(&clp->async_lock);
1573
+ return NULL;
1574
+}
1575
+
1576
+static __be32
1577
+nfsd4_offload_cancel(struct svc_rqst *rqstp,
1578
+ struct nfsd4_compound_state *cstate,
1579
+ union nfsd4_op_u *u)
1580
+{
1581
+ struct nfsd4_offload_status *os = &u->offload_status;
1582
+ struct nfsd4_copy *copy;
1583
+ struct nfs4_client *clp = cstate->clp;
1584
+
1585
+ copy = find_async_copy(clp, &os->stateid);
1586
+ if (!copy) {
1587
+ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
1588
+
1589
+ return manage_cpntf_state(nn, &os->stateid, clp, NULL);
1590
+ } else
1591
+ nfsd4_stop_copy(copy);
1592
+
1593
+ return nfs_ok;
1594
+}
1595
+
1596
+static __be32
1597
+nfsd4_copy_notify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1598
+ union nfsd4_op_u *u)
1599
+{
1600
+ struct nfsd4_copy_notify *cn = &u->copy_notify;
1601
+ __be32 status;
1602
+ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
1603
+ struct nfs4_stid *stid;
1604
+ struct nfs4_cpntf_state *cps;
1605
+ struct nfs4_client *clp = cstate->clp;
1606
+
1607
+ status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
1608
+ &cn->cpn_src_stateid, RD_STATE, NULL,
1609
+ &stid);
1610
+ if (status)
1611
+ return status;
1612
+
1613
+ cn->cpn_sec = nn->nfsd4_lease;
1614
+ cn->cpn_nsec = 0;
1615
+
1616
+ status = nfserrno(-ENOMEM);
1617
+ cps = nfs4_alloc_init_cpntf_state(nn, stid);
1618
+ if (!cps)
1619
+ goto out;
1620
+ memcpy(&cn->cpn_cnr_stateid, &cps->cp_stateid.stid, sizeof(stateid_t));
1621
+ memcpy(&cps->cp_p_stateid, &stid->sc_stateid, sizeof(stateid_t));
1622
+ memcpy(&cps->cp_p_clid, &clp->cl_clientid, sizeof(clientid_t));
1623
+
1624
+ /* For now, only return one server address in cpn_src, the
1625
+ * address used by the client to connect to this server.
1626
+ */
1627
+ cn->cpn_src.nl4_type = NL4_NETADDR;
1628
+ status = nfsd4_set_netaddr((struct sockaddr *)&rqstp->rq_daddr,
1629
+ &cn->cpn_src.u.nl4_addr);
1630
+ WARN_ON_ONCE(status);
1631
+ if (status) {
1632
+ nfs4_put_cpntf_state(nn, cps);
1633
+ goto out;
1634
+ }
1635
+out:
1636
+ nfs4_put_stid(stid);
11241637 return status;
11251638 }
11261639
....@@ -1128,22 +1641,41 @@
11281641 nfsd4_fallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
11291642 struct nfsd4_fallocate *fallocate, int flags)
11301643 {
1131
- __be32 status = nfserr_notsupp;
1132
- struct file *file;
1644
+ __be32 status;
1645
+ struct nfsd_file *nf;
11331646
11341647 status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
11351648 &fallocate->falloc_stateid,
1136
- WR_STATE, &file, NULL);
1649
+ WR_STATE, &nf, NULL);
11371650 if (status != nfs_ok) {
11381651 dprintk("NFSD: nfsd4_fallocate: couldn't process stateid!\n");
11391652 return status;
11401653 }
11411654
1142
- status = nfsd4_vfs_fallocate(rqstp, &cstate->current_fh, file,
1655
+ status = nfsd4_vfs_fallocate(rqstp, &cstate->current_fh, nf->nf_file,
11431656 fallocate->falloc_offset,
11441657 fallocate->falloc_length,
11451658 flags);
1146
- fput(file);
1659
+ nfsd_file_put(nf);
1660
+ return status;
1661
+}
1662
+static __be32
1663
+nfsd4_offload_status(struct svc_rqst *rqstp,
1664
+ struct nfsd4_compound_state *cstate,
1665
+ union nfsd4_op_u *u)
1666
+{
1667
+ struct nfsd4_offload_status *os = &u->offload_status;
1668
+ __be32 status = 0;
1669
+ struct nfsd4_copy *copy;
1670
+ struct nfs4_client *clp = cstate->clp;
1671
+
1672
+ copy = find_async_copy(clp, &os->stateid);
1673
+ if (copy) {
1674
+ os->count = copy->cp_res.wr_bytes_written;
1675
+ nfs4_put_copy(copy);
1676
+ } else
1677
+ status = nfserr_bad_stateid;
1678
+
11471679 return status;
11481680 }
11491681
....@@ -1169,11 +1701,11 @@
11691701 struct nfsd4_seek *seek = &u->seek;
11701702 int whence;
11711703 __be32 status;
1172
- struct file *file;
1704
+ struct nfsd_file *nf;
11731705
11741706 status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
11751707 &seek->seek_stateid,
1176
- RD_STATE, &file, NULL);
1708
+ RD_STATE, &nf, NULL);
11771709 if (status) {
11781710 dprintk("NFSD: nfsd4_seek: couldn't process stateid!\n");
11791711 return status;
....@@ -1195,14 +1727,14 @@
11951727 * Note: This call does change file->f_pos, but nothing in NFSD
11961728 * should ever file->f_pos.
11971729 */
1198
- seek->seek_pos = vfs_llseek(file, seek->seek_offset, whence);
1730
+ seek->seek_pos = vfs_llseek(nf->nf_file, seek->seek_offset, whence);
11991731 if (seek->seek_pos < 0)
12001732 status = nfserrno(seek->seek_pos);
1201
- else if (seek->seek_pos >= i_size_read(file_inode(file)))
1733
+ else if (seek->seek_pos >= i_size_read(file_inode(nf->nf_file)))
12021734 seek->seek_eof = true;
12031735
12041736 out:
1205
- fput(file);
1737
+ nfsd_file_put(nf);
12061738 return status;
12071739 }
12081740
....@@ -1557,13 +2089,75 @@
15572089 }
15582090 #endif /* CONFIG_NFSD_PNFS */
15592091
2092
+static __be32
2093
+nfsd4_getxattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2094
+ union nfsd4_op_u *u)
2095
+{
2096
+ struct nfsd4_getxattr *getxattr = &u->getxattr;
2097
+
2098
+ return nfsd_getxattr(rqstp, &cstate->current_fh,
2099
+ getxattr->getxa_name, &getxattr->getxa_buf,
2100
+ &getxattr->getxa_len);
2101
+}
2102
+
2103
+static __be32
2104
+nfsd4_setxattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2105
+ union nfsd4_op_u *u)
2106
+{
2107
+ struct nfsd4_setxattr *setxattr = &u->setxattr;
2108
+ __be32 ret;
2109
+
2110
+ if (opens_in_grace(SVC_NET(rqstp)))
2111
+ return nfserr_grace;
2112
+
2113
+ ret = nfsd_setxattr(rqstp, &cstate->current_fh, setxattr->setxa_name,
2114
+ setxattr->setxa_buf, setxattr->setxa_len,
2115
+ setxattr->setxa_flags);
2116
+
2117
+ if (!ret)
2118
+ set_change_info(&setxattr->setxa_cinfo, &cstate->current_fh);
2119
+
2120
+ return ret;
2121
+}
2122
+
2123
+static __be32
2124
+nfsd4_listxattrs(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2125
+ union nfsd4_op_u *u)
2126
+{
2127
+ /*
2128
+ * Get the entire list, then copy out only the user attributes
2129
+ * in the encode function.
2130
+ */
2131
+ return nfsd_listxattr(rqstp, &cstate->current_fh,
2132
+ &u->listxattrs.lsxa_buf, &u->listxattrs.lsxa_len);
2133
+}
2134
+
2135
+static __be32
2136
+nfsd4_removexattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2137
+ union nfsd4_op_u *u)
2138
+{
2139
+ struct nfsd4_removexattr *removexattr = &u->removexattr;
2140
+ __be32 ret;
2141
+
2142
+ if (opens_in_grace(SVC_NET(rqstp)))
2143
+ return nfserr_grace;
2144
+
2145
+ ret = nfsd_removexattr(rqstp, &cstate->current_fh,
2146
+ removexattr->rmxa_name);
2147
+
2148
+ if (!ret)
2149
+ set_change_info(&removexattr->rmxa_cinfo, &cstate->current_fh);
2150
+
2151
+ return ret;
2152
+}
2153
+
15602154 /*
15612155 * NULL call.
15622156 */
15632157 static __be32
15642158 nfsd4_proc_null(struct svc_rqst *rqstp)
15652159 {
1566
- return nfs_ok;
2160
+ return rpc_success;
15672161 }
15682162
15692163 static inline void nfsd4_increment_op_stats(u32 opnum)
....@@ -1678,6 +2272,45 @@
16782272 - rqstp->rq_auth_slack;
16792273 }
16802274
2275
+#ifdef CONFIG_NFSD_V4_2_INTER_SSC
2276
+static void
2277
+check_if_stalefh_allowed(struct nfsd4_compoundargs *args)
2278
+{
2279
+ struct nfsd4_op *op, *current_op = NULL, *saved_op = NULL;
2280
+ struct nfsd4_copy *copy;
2281
+ struct nfsd4_putfh *putfh;
2282
+ int i;
2283
+
2284
+ /* traverse all operation and if it's a COPY compound, mark the
2285
+ * source filehandle to skip verification
2286
+ */
2287
+ for (i = 0; i < args->opcnt; i++) {
2288
+ op = &args->ops[i];
2289
+ if (op->opnum == OP_PUTFH)
2290
+ current_op = op;
2291
+ else if (op->opnum == OP_SAVEFH)
2292
+ saved_op = current_op;
2293
+ else if (op->opnum == OP_RESTOREFH)
2294
+ current_op = saved_op;
2295
+ else if (op->opnum == OP_COPY) {
2296
+ copy = (struct nfsd4_copy *)&op->u;
2297
+ if (!saved_op) {
2298
+ op->status = nfserr_nofilehandle;
2299
+ return;
2300
+ }
2301
+ putfh = (struct nfsd4_putfh *)&saved_op->u;
2302
+ if (!copy->cp_intra)
2303
+ putfh->no_verify = true;
2304
+ }
2305
+ }
2306
+}
2307
+#else
2308
+static void
2309
+check_if_stalefh_allowed(struct nfsd4_compoundargs *args)
2310
+{
2311
+}
2312
+#endif
2313
+
16812314 /*
16822315 * COMPOUND call.
16832316 */
....@@ -1690,6 +2323,7 @@
16902323 struct nfsd4_compound_state *cstate = &resp->cstate;
16912324 struct svc_fh *current_fh = &cstate->current_fh;
16922325 struct svc_fh *save_fh = &cstate->save_fh;
2326
+ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
16932327 __be32 status;
16942328
16952329 svcxdr_init_encode(rqstp, resp);
....@@ -1712,7 +2346,7 @@
17122346 * According to RFC3010, this takes precedence over all other errors.
17132347 */
17142348 status = nfserr_minor_vers_mismatch;
1715
- if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0)
2349
+ if (nfsd_minorversion(nn, args->minorversion, NFSD_TEST) <= 0)
17162350 goto out;
17172351 status = nfserr_resource;
17182352 if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
....@@ -1725,6 +2359,9 @@
17252359 resp->opcnt = 1;
17262360 goto encode_op;
17272361 }
2362
+ check_if_stalefh_allowed(args);
2363
+
2364
+ rqstp->rq_lease_breaker = (void **)&cstate->clp;
17282365
17292366 trace_nfsd_compound(rqstp, args->opcnt);
17302367 while (!status && resp->opcnt < args->opcnt) {
....@@ -1740,13 +2377,14 @@
17402377 op->status = nfsd4_open_omfg(rqstp, cstate, op);
17412378 goto encode_op;
17422379 }
1743
-
1744
- if (!current_fh->fh_dentry) {
2380
+ if (!current_fh->fh_dentry &&
2381
+ !HAS_FH_FLAG(current_fh, NFSD4_FH_FOREIGN)) {
17452382 if (!(op->opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
17462383 op->status = nfserr_nofilehandle;
17472384 goto encode_op;
17482385 }
1749
- } else if (current_fh->fh_export->ex_fslocs.migrated &&
2386
+ } else if (current_fh->fh_export &&
2387
+ current_fh->fh_export->ex_fslocs.migrated &&
17502388 !(op->opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
17512389 op->status = nfserr_moved;
17522390 goto encode_op;
....@@ -1790,7 +2428,8 @@
17902428 if (op->opdesc->op_flags & OP_CLEAR_STATEID)
17912429 clear_current_stateid(cstate);
17922430
1793
- if (need_wrongsec_check(rqstp))
2431
+ if (current_fh->fh_export &&
2432
+ need_wrongsec_check(rqstp))
17942433 op->status = check_nfsd_access(current_fh->fh_export, rqstp);
17952434 }
17962435 encode_op:
....@@ -1810,15 +2449,14 @@
18102449 nfsd4_increment_op_stats(op->opnum);
18112450 }
18122451
1813
- cstate->status = status;
18142452 fh_put(current_fh);
18152453 fh_put(save_fh);
18162454 BUG_ON(cstate->replay_owner);
18172455 out:
2456
+ cstate->status = status;
18182457 /* Reset deferral mechanism for RPC deferrals */
18192458 set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
1820
- dprintk("nfsv4 compound returned %d\n", ntohl(status));
1821
- return status;
2459
+ return rpc_success;
18222460 }
18232461
18242462 #define op_encode_hdr_size (2)
....@@ -1944,6 +2582,20 @@
19442582 return (op_encode_hdr_size + 2 + XDR_QUADLEN(rlen)) * sizeof(__be32);
19452583 }
19462584
2585
+static inline u32 nfsd4_read_plus_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
2586
+{
2587
+ u32 maxcount = svc_max_payload(rqstp);
2588
+ u32 rlen = min(op->u.read.rd_length, maxcount);
2589
+ /*
2590
+ * If we detect that the file changed during hole encoding, then we
2591
+ * recover by encoding the remaining reply as data. This means we need
2592
+ * to set aside enough room to encode two data segments.
2593
+ */
2594
+ u32 seg_len = 2 * (1 + 2 + 1);
2595
+
2596
+ return (op_encode_hdr_size + 2 + seg_len + XDR_QUADLEN(rlen)) * sizeof(__be32);
2597
+}
2598
+
19472599 static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
19482600 {
19492601 u32 maxcount = 0, rlen = 0;
....@@ -2049,6 +2701,29 @@
20492701 1 /* cr_synchronous */) * sizeof(__be32);
20502702 }
20512703
2704
+static inline u32 nfsd4_offload_status_rsize(struct svc_rqst *rqstp,
2705
+ struct nfsd4_op *op)
2706
+{
2707
+ return (op_encode_hdr_size +
2708
+ 2 /* osr_count */ +
2709
+ 1 /* osr_complete<1> optional 0 for now */) * sizeof(__be32);
2710
+}
2711
+
2712
+static inline u32 nfsd4_copy_notify_rsize(struct svc_rqst *rqstp,
2713
+ struct nfsd4_op *op)
2714
+{
2715
+ return (op_encode_hdr_size +
2716
+ 3 /* cnr_lease_time */ +
2717
+ 1 /* We support one cnr_source_server */ +
2718
+ 1 /* cnr_stateid seq */ +
2719
+ op_encode_stateid_maxsz /* cnr_stateid */ +
2720
+ 1 /* num cnr_source_server*/ +
2721
+ 1 /* nl4_type */ +
2722
+ 1 /* nl4 size */ +
2723
+ XDR_QUADLEN(NFS4_OPAQUE_LIMIT) /*nl4_loc + nl4_loc_sz */)
2724
+ * sizeof(__be32);
2725
+}
2726
+
20522727 #ifdef CONFIG_NFSD_PNFS
20532728 static inline u32 nfsd4_getdeviceinfo_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
20542729 {
....@@ -2097,6 +2772,42 @@
20972772 {
20982773 return (op_encode_hdr_size + 3) * sizeof(__be32);
20992774 }
2775
+
2776
+static inline u32 nfsd4_getxattr_rsize(struct svc_rqst *rqstp,
2777
+ struct nfsd4_op *op)
2778
+{
2779
+ u32 maxcount, rlen;
2780
+
2781
+ maxcount = svc_max_payload(rqstp);
2782
+ rlen = min_t(u32, XATTR_SIZE_MAX, maxcount);
2783
+
2784
+ return (op_encode_hdr_size + 1 + XDR_QUADLEN(rlen)) * sizeof(__be32);
2785
+}
2786
+
2787
+static inline u32 nfsd4_setxattr_rsize(struct svc_rqst *rqstp,
2788
+ struct nfsd4_op *op)
2789
+{
2790
+ return (op_encode_hdr_size + op_encode_change_info_maxsz)
2791
+ * sizeof(__be32);
2792
+}
2793
+static inline u32 nfsd4_listxattrs_rsize(struct svc_rqst *rqstp,
2794
+ struct nfsd4_op *op)
2795
+{
2796
+ u32 maxcount, rlen;
2797
+
2798
+ maxcount = svc_max_payload(rqstp);
2799
+ rlen = min(op->u.listxattrs.lsxa_maxcount, maxcount);
2800
+
2801
+ return (op_encode_hdr_size + 4 + XDR_QUADLEN(rlen)) * sizeof(__be32);
2802
+}
2803
+
2804
+static inline u32 nfsd4_removexattr_rsize(struct svc_rqst *rqstp,
2805
+ struct nfsd4_op *op)
2806
+{
2807
+ return (op_encode_hdr_size + op_encode_change_info_maxsz)
2808
+ * sizeof(__be32);
2809
+}
2810
+
21002811
21012812 static const struct nfsd4_operation nfsd4_ops[] = {
21022813 [OP_ACCESS] = {
....@@ -2435,32 +3146,78 @@
24353146 /* NFSv4.2 operations */
24363147 [OP_ALLOCATE] = {
24373148 .op_func = nfsd4_allocate,
2438
- .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
3149
+ .op_flags = OP_MODIFIES_SOMETHING,
24393150 .op_name = "OP_ALLOCATE",
24403151 .op_rsize_bop = nfsd4_only_status_rsize,
24413152 },
24423153 [OP_DEALLOCATE] = {
24433154 .op_func = nfsd4_deallocate,
2444
- .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
3155
+ .op_flags = OP_MODIFIES_SOMETHING,
24453156 .op_name = "OP_DEALLOCATE",
24463157 .op_rsize_bop = nfsd4_only_status_rsize,
24473158 },
24483159 [OP_CLONE] = {
24493160 .op_func = nfsd4_clone,
2450
- .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
3161
+ .op_flags = OP_MODIFIES_SOMETHING,
24513162 .op_name = "OP_CLONE",
24523163 .op_rsize_bop = nfsd4_only_status_rsize,
24533164 },
24543165 [OP_COPY] = {
24553166 .op_func = nfsd4_copy,
2456
- .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
3167
+ .op_flags = OP_MODIFIES_SOMETHING,
24573168 .op_name = "OP_COPY",
24583169 .op_rsize_bop = nfsd4_copy_rsize,
3170
+ },
3171
+ [OP_READ_PLUS] = {
3172
+ .op_func = nfsd4_read,
3173
+ .op_release = nfsd4_read_release,
3174
+ .op_name = "OP_READ_PLUS",
3175
+ .op_rsize_bop = nfsd4_read_plus_rsize,
3176
+ .op_get_currentstateid = nfsd4_get_readstateid,
24593177 },
24603178 [OP_SEEK] = {
24613179 .op_func = nfsd4_seek,
24623180 .op_name = "OP_SEEK",
24633181 .op_rsize_bop = nfsd4_seek_rsize,
3182
+ },
3183
+ [OP_OFFLOAD_STATUS] = {
3184
+ .op_func = nfsd4_offload_status,
3185
+ .op_name = "OP_OFFLOAD_STATUS",
3186
+ .op_rsize_bop = nfsd4_offload_status_rsize,
3187
+ },
3188
+ [OP_OFFLOAD_CANCEL] = {
3189
+ .op_func = nfsd4_offload_cancel,
3190
+ .op_flags = OP_MODIFIES_SOMETHING,
3191
+ .op_name = "OP_OFFLOAD_CANCEL",
3192
+ .op_rsize_bop = nfsd4_only_status_rsize,
3193
+ },
3194
+ [OP_COPY_NOTIFY] = {
3195
+ .op_func = nfsd4_copy_notify,
3196
+ .op_flags = OP_MODIFIES_SOMETHING,
3197
+ .op_name = "OP_COPY_NOTIFY",
3198
+ .op_rsize_bop = nfsd4_copy_notify_rsize,
3199
+ },
3200
+ [OP_GETXATTR] = {
3201
+ .op_func = nfsd4_getxattr,
3202
+ .op_name = "OP_GETXATTR",
3203
+ .op_rsize_bop = nfsd4_getxattr_rsize,
3204
+ },
3205
+ [OP_SETXATTR] = {
3206
+ .op_func = nfsd4_setxattr,
3207
+ .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
3208
+ .op_name = "OP_SETXATTR",
3209
+ .op_rsize_bop = nfsd4_setxattr_rsize,
3210
+ },
3211
+ [OP_LISTXATTRS] = {
3212
+ .op_func = nfsd4_listxattrs,
3213
+ .op_name = "OP_LISTXATTRS",
3214
+ .op_rsize_bop = nfsd4_listxattrs_rsize,
3215
+ },
3216
+ [OP_REMOVEXATTR] = {
3217
+ .op_func = nfsd4_removexattr,
3218
+ .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
3219
+ .op_name = "OP_REMOVEXATTR",
3220
+ .op_rsize_bop = nfsd4_removexattr_rsize,
24643221 },
24653222 };
24663223
....@@ -2486,7 +3243,7 @@
24863243 if (!cstate->minorversion)
24873244 return false;
24883245
2489
- if (cstate->spo_must_allowed == true)
3246
+ if (cstate->spo_must_allowed)
24903247 return true;
24913248
24923249 opiter = resp->opcnt;
....@@ -2534,6 +3291,7 @@
25343291 static const struct svc_procedure nfsd_procedures4[2] = {
25353292 [NFSPROC4_NULL] = {
25363293 .pc_func = nfsd4_proc_null,
3294
+ .pc_decode = nfs4svc_decode_voidarg,
25373295 .pc_encode = nfs4svc_encode_voidres,
25383296 .pc_argsize = sizeof(struct nfsd4_voidargs),
25393297 .pc_ressize = sizeof(struct nfsd4_voidres),