forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
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,8 +874,7 @@
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,
....@@ -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,9 @@
10631074 out:
10641075 return status;
10651076 out_put_dst:
1066
- fput(*dst);
1077
+ nfsd_file_put(*dst);
10671078 out_put_src:
1068
- fput(*src);
1079
+ nfsd_file_put(*src);
10691080 goto out;
10701081 }
10711082
....@@ -1074,7 +1085,7 @@
10741085 union nfsd4_op_u *u)
10751086 {
10761087 struct nfsd4_clone *clone = &u->clone;
1077
- struct file *src, *dst;
1088
+ struct nfsd_file *src, *dst;
10781089 __be32 status;
10791090
10801091 status = nfsd4_verify_copy(rqstp, cstate, &clone->cl_src_stateid, &src,
....@@ -1083,12 +1094,411 @@
10831094 goto out;
10841095
10851096 status = nfsd4_clone_file_range(src, clone->cl_src_pos,
1086
- dst, clone->cl_dst_pos, clone->cl_count);
1097
+ dst, clone->cl_dst_pos, clone->cl_count,
1098
+ EX_ISSYNC(cstate->current_fh.fh_export));
10871099
1088
- fput(dst);
1089
- fput(src);
1100
+ nfsd_file_put(dst);
1101
+ nfsd_file_put(src);
10901102 out:
10911103 return status;
1104
+}
1105
+
1106
+void nfs4_put_copy(struct nfsd4_copy *copy)
1107
+{
1108
+ if (!refcount_dec_and_test(&copy->refcount))
1109
+ return;
1110
+ kfree(copy);
1111
+}
1112
+
1113
+static bool
1114
+check_and_set_stop_copy(struct nfsd4_copy *copy)
1115
+{
1116
+ bool value;
1117
+
1118
+ spin_lock(&copy->cp_clp->async_lock);
1119
+ value = copy->stopped;
1120
+ if (!copy->stopped)
1121
+ copy->stopped = true;
1122
+ spin_unlock(&copy->cp_clp->async_lock);
1123
+ return value;
1124
+}
1125
+
1126
+static void nfsd4_stop_copy(struct nfsd4_copy *copy)
1127
+{
1128
+ /* only 1 thread should stop the copy */
1129
+ if (!check_and_set_stop_copy(copy))
1130
+ kthread_stop(copy->copy_task);
1131
+ nfs4_put_copy(copy);
1132
+}
1133
+
1134
+static struct nfsd4_copy *nfsd4_get_copy(struct nfs4_client *clp)
1135
+{
1136
+ struct nfsd4_copy *copy = NULL;
1137
+
1138
+ spin_lock(&clp->async_lock);
1139
+ if (!list_empty(&clp->async_copies)) {
1140
+ copy = list_first_entry(&clp->async_copies, struct nfsd4_copy,
1141
+ copies);
1142
+ refcount_inc(&copy->refcount);
1143
+ }
1144
+ spin_unlock(&clp->async_lock);
1145
+ return copy;
1146
+}
1147
+
1148
+void nfsd4_shutdown_copy(struct nfs4_client *clp)
1149
+{
1150
+ struct nfsd4_copy *copy;
1151
+
1152
+ while ((copy = nfsd4_get_copy(clp)) != NULL)
1153
+ nfsd4_stop_copy(copy);
1154
+}
1155
+#ifdef CONFIG_NFSD_V4_2_INTER_SSC
1156
+
1157
+extern struct file *nfs42_ssc_open(struct vfsmount *ss_mnt,
1158
+ struct nfs_fh *src_fh,
1159
+ nfs4_stateid *stateid);
1160
+extern void nfs42_ssc_close(struct file *filep);
1161
+
1162
+extern void nfs_sb_deactive(struct super_block *sb);
1163
+
1164
+#define NFSD42_INTERSSC_MOUNTOPS "vers=4.2,addr=%s,sec=sys"
1165
+
1166
+/*
1167
+ * Support one copy source server for now.
1168
+ */
1169
+static __be32
1170
+nfsd4_interssc_connect(struct nl4_server *nss, struct svc_rqst *rqstp,
1171
+ struct vfsmount **mount)
1172
+{
1173
+ struct file_system_type *type;
1174
+ struct vfsmount *ss_mnt;
1175
+ struct nfs42_netaddr *naddr;
1176
+ struct sockaddr_storage tmp_addr;
1177
+ size_t tmp_addrlen, match_netid_len = 3;
1178
+ char *startsep = "", *endsep = "", *match_netid = "tcp";
1179
+ char *ipaddr, *dev_name, *raw_data;
1180
+ int len, raw_len;
1181
+ __be32 status = nfserr_inval;
1182
+
1183
+ naddr = &nss->u.nl4_addr;
1184
+ tmp_addrlen = rpc_uaddr2sockaddr(SVC_NET(rqstp), naddr->addr,
1185
+ naddr->addr_len,
1186
+ (struct sockaddr *)&tmp_addr,
1187
+ sizeof(tmp_addr));
1188
+ if (tmp_addrlen == 0)
1189
+ goto out_err;
1190
+
1191
+ if (tmp_addr.ss_family == AF_INET6) {
1192
+ startsep = "[";
1193
+ endsep = "]";
1194
+ match_netid = "tcp6";
1195
+ match_netid_len = 4;
1196
+ }
1197
+
1198
+ if (naddr->netid_len != match_netid_len ||
1199
+ strncmp(naddr->netid, match_netid, naddr->netid_len))
1200
+ goto out_err;
1201
+
1202
+ /* Construct the raw data for the vfs_kern_mount call */
1203
+ len = RPC_MAX_ADDRBUFLEN + 1;
1204
+ ipaddr = kzalloc(len, GFP_KERNEL);
1205
+ if (!ipaddr)
1206
+ goto out_err;
1207
+
1208
+ rpc_ntop((struct sockaddr *)&tmp_addr, ipaddr, len);
1209
+
1210
+ /* 2 for ipv6 endsep and startsep. 3 for ":/" and trailing '/0'*/
1211
+
1212
+ raw_len = strlen(NFSD42_INTERSSC_MOUNTOPS) + strlen(ipaddr);
1213
+ raw_data = kzalloc(raw_len, GFP_KERNEL);
1214
+ if (!raw_data)
1215
+ goto out_free_ipaddr;
1216
+
1217
+ snprintf(raw_data, raw_len, NFSD42_INTERSSC_MOUNTOPS, ipaddr);
1218
+
1219
+ status = nfserr_nodev;
1220
+ type = get_fs_type("nfs");
1221
+ if (!type)
1222
+ goto out_free_rawdata;
1223
+
1224
+ /* Set the server:<export> for the vfs_kern_mount call */
1225
+ dev_name = kzalloc(len + 5, GFP_KERNEL);
1226
+ if (!dev_name)
1227
+ goto out_free_rawdata;
1228
+ snprintf(dev_name, len + 5, "%s%s%s:/", startsep, ipaddr, endsep);
1229
+
1230
+ /* Use an 'internal' mount: SB_KERNMOUNT -> MNT_INTERNAL */
1231
+ ss_mnt = vfs_kern_mount(type, SB_KERNMOUNT, dev_name, raw_data);
1232
+ module_put(type->owner);
1233
+ if (IS_ERR(ss_mnt))
1234
+ goto out_free_devname;
1235
+
1236
+ status = 0;
1237
+ *mount = ss_mnt;
1238
+
1239
+out_free_devname:
1240
+ kfree(dev_name);
1241
+out_free_rawdata:
1242
+ kfree(raw_data);
1243
+out_free_ipaddr:
1244
+ kfree(ipaddr);
1245
+out_err:
1246
+ return status;
1247
+}
1248
+
1249
+static void
1250
+nfsd4_interssc_disconnect(struct vfsmount *ss_mnt)
1251
+{
1252
+ nfs_do_sb_deactive(ss_mnt->mnt_sb);
1253
+ mntput(ss_mnt);
1254
+}
1255
+
1256
+/*
1257
+ * Verify COPY destination stateid.
1258
+ *
1259
+ * Connect to the source server with NFSv4.1.
1260
+ * Create the source struct file for nfsd_copy_range.
1261
+ * Called with COPY cstate:
1262
+ * SAVED_FH: source filehandle
1263
+ * CURRENT_FH: destination filehandle
1264
+ */
1265
+static __be32
1266
+nfsd4_setup_inter_ssc(struct svc_rqst *rqstp,
1267
+ struct nfsd4_compound_state *cstate,
1268
+ struct nfsd4_copy *copy, struct vfsmount **mount)
1269
+{
1270
+ struct svc_fh *s_fh = NULL;
1271
+ stateid_t *s_stid = &copy->cp_src_stateid;
1272
+ __be32 status = nfserr_inval;
1273
+
1274
+ /* Verify the destination stateid and set dst struct file*/
1275
+ status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
1276
+ &copy->cp_dst_stateid,
1277
+ WR_STATE, &copy->nf_dst, NULL);
1278
+ if (status)
1279
+ goto out;
1280
+
1281
+ status = nfsd4_interssc_connect(&copy->cp_src, rqstp, mount);
1282
+ if (status)
1283
+ goto out;
1284
+
1285
+ s_fh = &cstate->save_fh;
1286
+
1287
+ copy->c_fh.size = s_fh->fh_handle.fh_size;
1288
+ memcpy(copy->c_fh.data, &s_fh->fh_handle.fh_base, copy->c_fh.size);
1289
+ copy->stateid.seqid = cpu_to_be32(s_stid->si_generation);
1290
+ memcpy(copy->stateid.other, (void *)&s_stid->si_opaque,
1291
+ sizeof(stateid_opaque_t));
1292
+
1293
+ status = 0;
1294
+out:
1295
+ return status;
1296
+}
1297
+
1298
+static void
1299
+nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct nfsd_file *src,
1300
+ struct nfsd_file *dst)
1301
+{
1302
+ nfs42_ssc_close(src->nf_file);
1303
+ fput(src->nf_file);
1304
+ nfsd_file_put(dst);
1305
+ mntput(ss_mnt);
1306
+}
1307
+
1308
+#else /* CONFIG_NFSD_V4_2_INTER_SSC */
1309
+
1310
+static __be32
1311
+nfsd4_setup_inter_ssc(struct svc_rqst *rqstp,
1312
+ struct nfsd4_compound_state *cstate,
1313
+ struct nfsd4_copy *copy,
1314
+ struct vfsmount **mount)
1315
+{
1316
+ *mount = NULL;
1317
+ return nfserr_inval;
1318
+}
1319
+
1320
+static void
1321
+nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct nfsd_file *src,
1322
+ struct nfsd_file *dst)
1323
+{
1324
+}
1325
+
1326
+static void
1327
+nfsd4_interssc_disconnect(struct vfsmount *ss_mnt)
1328
+{
1329
+}
1330
+
1331
+static struct file *nfs42_ssc_open(struct vfsmount *ss_mnt,
1332
+ struct nfs_fh *src_fh,
1333
+ nfs4_stateid *stateid)
1334
+{
1335
+ return NULL;
1336
+}
1337
+#endif /* CONFIG_NFSD_V4_2_INTER_SSC */
1338
+
1339
+static __be32
1340
+nfsd4_setup_intra_ssc(struct svc_rqst *rqstp,
1341
+ struct nfsd4_compound_state *cstate,
1342
+ struct nfsd4_copy *copy)
1343
+{
1344
+ return nfsd4_verify_copy(rqstp, cstate, &copy->cp_src_stateid,
1345
+ &copy->nf_src, &copy->cp_dst_stateid,
1346
+ &copy->nf_dst);
1347
+}
1348
+
1349
+static void
1350
+nfsd4_cleanup_intra_ssc(struct nfsd_file *src, struct nfsd_file *dst)
1351
+{
1352
+ nfsd_file_put(src);
1353
+ nfsd_file_put(dst);
1354
+}
1355
+
1356
+static void nfsd4_cb_offload_release(struct nfsd4_callback *cb)
1357
+{
1358
+ struct nfsd4_copy *copy = container_of(cb, struct nfsd4_copy, cp_cb);
1359
+
1360
+ nfs4_put_copy(copy);
1361
+}
1362
+
1363
+static int nfsd4_cb_offload_done(struct nfsd4_callback *cb,
1364
+ struct rpc_task *task)
1365
+{
1366
+ return 1;
1367
+}
1368
+
1369
+static const struct nfsd4_callback_ops nfsd4_cb_offload_ops = {
1370
+ .release = nfsd4_cb_offload_release,
1371
+ .done = nfsd4_cb_offload_done
1372
+};
1373
+
1374
+static void nfsd4_init_copy_res(struct nfsd4_copy *copy, bool sync)
1375
+{
1376
+ copy->cp_res.wr_stable_how = NFS_UNSTABLE;
1377
+ copy->cp_synchronous = sync;
1378
+ gen_boot_verifier(&copy->cp_res.wr_verifier, copy->cp_clp->net);
1379
+}
1380
+
1381
+static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy)
1382
+{
1383
+ struct file *dst = copy->nf_dst->nf_file;
1384
+ struct file *src = copy->nf_src->nf_file;
1385
+ ssize_t bytes_copied = 0;
1386
+ size_t bytes_total = copy->cp_count;
1387
+ u64 src_pos = copy->cp_src_pos;
1388
+ u64 dst_pos = copy->cp_dst_pos;
1389
+
1390
+ do {
1391
+ if (kthread_should_stop())
1392
+ break;
1393
+ bytes_copied = nfsd_copy_file_range(src, src_pos, dst, dst_pos,
1394
+ bytes_total);
1395
+ if (bytes_copied <= 0)
1396
+ break;
1397
+ bytes_total -= bytes_copied;
1398
+ copy->cp_res.wr_bytes_written += bytes_copied;
1399
+ src_pos += bytes_copied;
1400
+ dst_pos += bytes_copied;
1401
+ } while (bytes_total > 0 && !copy->cp_synchronous);
1402
+ return bytes_copied;
1403
+}
1404
+
1405
+static __be32 nfsd4_do_copy(struct nfsd4_copy *copy, bool sync)
1406
+{
1407
+ __be32 status;
1408
+ ssize_t bytes;
1409
+
1410
+ bytes = _nfsd_copy_file_range(copy);
1411
+ /* for async copy, we ignore the error, client can always retry
1412
+ * to get the error
1413
+ */
1414
+ if (bytes < 0 && !copy->cp_res.wr_bytes_written)
1415
+ status = nfserrno(bytes);
1416
+ else {
1417
+ nfsd4_init_copy_res(copy, sync);
1418
+ status = nfs_ok;
1419
+ }
1420
+
1421
+ if (!copy->cp_intra) /* Inter server SSC */
1422
+ nfsd4_cleanup_inter_ssc(copy->ss_mnt, copy->nf_src,
1423
+ copy->nf_dst);
1424
+ else
1425
+ nfsd4_cleanup_intra_ssc(copy->nf_src, copy->nf_dst);
1426
+
1427
+ return status;
1428
+}
1429
+
1430
+static void dup_copy_fields(struct nfsd4_copy *src, struct nfsd4_copy *dst)
1431
+{
1432
+ dst->cp_src_pos = src->cp_src_pos;
1433
+ dst->cp_dst_pos = src->cp_dst_pos;
1434
+ dst->cp_count = src->cp_count;
1435
+ dst->cp_synchronous = src->cp_synchronous;
1436
+ memcpy(&dst->cp_res, &src->cp_res, sizeof(src->cp_res));
1437
+ memcpy(&dst->fh, &src->fh, sizeof(src->fh));
1438
+ dst->cp_clp = src->cp_clp;
1439
+ dst->nf_dst = nfsd_file_get(src->nf_dst);
1440
+ dst->cp_intra = src->cp_intra;
1441
+ if (src->cp_intra) /* for inter, file_src doesn't exist yet */
1442
+ dst->nf_src = nfsd_file_get(src->nf_src);
1443
+
1444
+ memcpy(&dst->cp_stateid, &src->cp_stateid, sizeof(src->cp_stateid));
1445
+ memcpy(&dst->cp_src, &src->cp_src, sizeof(struct nl4_server));
1446
+ memcpy(&dst->stateid, &src->stateid, sizeof(src->stateid));
1447
+ memcpy(&dst->c_fh, &src->c_fh, sizeof(src->c_fh));
1448
+ dst->ss_mnt = src->ss_mnt;
1449
+}
1450
+
1451
+static void cleanup_async_copy(struct nfsd4_copy *copy)
1452
+{
1453
+ nfs4_free_copy_state(copy);
1454
+ nfsd_file_put(copy->nf_dst);
1455
+ if (copy->cp_intra)
1456
+ nfsd_file_put(copy->nf_src);
1457
+ spin_lock(&copy->cp_clp->async_lock);
1458
+ list_del(&copy->copies);
1459
+ spin_unlock(&copy->cp_clp->async_lock);
1460
+ nfs4_put_copy(copy);
1461
+}
1462
+
1463
+static int nfsd4_do_async_copy(void *data)
1464
+{
1465
+ struct nfsd4_copy *copy = (struct nfsd4_copy *)data;
1466
+ struct nfsd4_copy *cb_copy;
1467
+
1468
+ if (!copy->cp_intra) { /* Inter server SSC */
1469
+ copy->nf_src = kzalloc(sizeof(struct nfsd_file), GFP_KERNEL);
1470
+ if (!copy->nf_src) {
1471
+ copy->nfserr = nfserr_serverfault;
1472
+ nfsd4_interssc_disconnect(copy->ss_mnt);
1473
+ goto do_callback;
1474
+ }
1475
+ copy->nf_src->nf_file = nfs42_ssc_open(copy->ss_mnt, &copy->c_fh,
1476
+ &copy->stateid);
1477
+ if (IS_ERR(copy->nf_src->nf_file)) {
1478
+ copy->nfserr = nfserr_offload_denied;
1479
+ nfsd4_interssc_disconnect(copy->ss_mnt);
1480
+ goto do_callback;
1481
+ }
1482
+ }
1483
+
1484
+ copy->nfserr = nfsd4_do_copy(copy, 0);
1485
+do_callback:
1486
+ cb_copy = kzalloc(sizeof(struct nfsd4_copy), GFP_KERNEL);
1487
+ if (!cb_copy)
1488
+ goto out;
1489
+ refcount_set(&cb_copy->refcount, 1);
1490
+ memcpy(&cb_copy->cp_res, &copy->cp_res, sizeof(copy->cp_res));
1491
+ cb_copy->cp_clp = copy->cp_clp;
1492
+ cb_copy->nfserr = copy->nfserr;
1493
+ memcpy(&cb_copy->fh, &copy->fh, sizeof(copy->fh));
1494
+ nfsd4_init_cb(&cb_copy->cp_cb, cb_copy->cp_clp,
1495
+ &nfsd4_cb_offload_ops, NFSPROC4_CLNT_CB_OFFLOAD);
1496
+ nfsd4_run_cb(&cb_copy->cp_cb);
1497
+out:
1498
+ if (!copy->cp_intra)
1499
+ kfree(copy->nf_src);
1500
+ cleanup_async_copy(copy);
1501
+ return 0;
10921502 }
10931503
10941504 static __be32
....@@ -1096,31 +1506,142 @@
10961506 union nfsd4_op_u *u)
10971507 {
10981508 struct nfsd4_copy *copy = &u->copy;
1099
- struct file *src, *dst;
11001509 __be32 status;
1101
- ssize_t bytes;
1510
+ struct nfsd4_copy *async_copy = NULL;
11021511
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;
1512
+ if (!copy->cp_intra) { /* Inter server SSC */
1513
+ if (!inter_copy_offload_enable || copy->cp_synchronous) {
1514
+ status = nfserr_notsupp;
1515
+ goto out;
1516
+ }
1517
+ status = nfsd4_setup_inter_ssc(rqstp, cstate, copy,
1518
+ &copy->ss_mnt);
1519
+ if (status)
1520
+ return nfserr_offload_denied;
1521
+ } else {
1522
+ status = nfsd4_setup_intra_ssc(rqstp, cstate, copy);
1523
+ if (status)
1524
+ return status;
11191525 }
11201526
1121
- fput(src);
1122
- fput(dst);
1527
+ copy->cp_clp = cstate->clp;
1528
+ memcpy(&copy->fh, &cstate->current_fh.fh_handle,
1529
+ sizeof(struct knfsd_fh));
1530
+ if (!copy->cp_synchronous) {
1531
+ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
1532
+
1533
+ status = nfserrno(-ENOMEM);
1534
+ async_copy = kzalloc(sizeof(struct nfsd4_copy), GFP_KERNEL);
1535
+ if (!async_copy)
1536
+ goto out_err;
1537
+ if (!nfs4_init_copy_state(nn, copy))
1538
+ goto out_err;
1539
+ refcount_set(&async_copy->refcount, 1);
1540
+ memcpy(&copy->cp_res.cb_stateid, &copy->cp_stateid.stid,
1541
+ sizeof(copy->cp_res.cb_stateid));
1542
+ dup_copy_fields(copy, async_copy);
1543
+ async_copy->copy_task = kthread_create(nfsd4_do_async_copy,
1544
+ async_copy, "%s", "copy thread");
1545
+ if (IS_ERR(async_copy->copy_task))
1546
+ goto out_err;
1547
+ spin_lock(&async_copy->cp_clp->async_lock);
1548
+ list_add(&async_copy->copies,
1549
+ &async_copy->cp_clp->async_copies);
1550
+ spin_unlock(&async_copy->cp_clp->async_lock);
1551
+ wake_up_process(async_copy->copy_task);
1552
+ status = nfs_ok;
1553
+ } else {
1554
+ status = nfsd4_do_copy(copy, 1);
1555
+ }
11231556 out:
1557
+ return status;
1558
+out_err:
1559
+ if (async_copy)
1560
+ cleanup_async_copy(async_copy);
1561
+ status = nfserrno(-ENOMEM);
1562
+ if (!copy->cp_intra)
1563
+ nfsd4_interssc_disconnect(copy->ss_mnt);
1564
+ goto out;
1565
+}
1566
+
1567
+struct nfsd4_copy *
1568
+find_async_copy(struct nfs4_client *clp, stateid_t *stateid)
1569
+{
1570
+ struct nfsd4_copy *copy;
1571
+
1572
+ spin_lock(&clp->async_lock);
1573
+ list_for_each_entry(copy, &clp->async_copies, copies) {
1574
+ if (memcmp(&copy->cp_stateid.stid, stateid, NFS4_STATEID_SIZE))
1575
+ continue;
1576
+ refcount_inc(&copy->refcount);
1577
+ spin_unlock(&clp->async_lock);
1578
+ return copy;
1579
+ }
1580
+ spin_unlock(&clp->async_lock);
1581
+ return NULL;
1582
+}
1583
+
1584
+static __be32
1585
+nfsd4_offload_cancel(struct svc_rqst *rqstp,
1586
+ struct nfsd4_compound_state *cstate,
1587
+ union nfsd4_op_u *u)
1588
+{
1589
+ struct nfsd4_offload_status *os = &u->offload_status;
1590
+ struct nfsd4_copy *copy;
1591
+ struct nfs4_client *clp = cstate->clp;
1592
+
1593
+ copy = find_async_copy(clp, &os->stateid);
1594
+ if (!copy) {
1595
+ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
1596
+
1597
+ return manage_cpntf_state(nn, &os->stateid, clp, NULL);
1598
+ } else
1599
+ nfsd4_stop_copy(copy);
1600
+
1601
+ return nfs_ok;
1602
+}
1603
+
1604
+static __be32
1605
+nfsd4_copy_notify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1606
+ union nfsd4_op_u *u)
1607
+{
1608
+ struct nfsd4_copy_notify *cn = &u->copy_notify;
1609
+ __be32 status;
1610
+ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
1611
+ struct nfs4_stid *stid;
1612
+ struct nfs4_cpntf_state *cps;
1613
+ struct nfs4_client *clp = cstate->clp;
1614
+
1615
+ status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
1616
+ &cn->cpn_src_stateid, RD_STATE, NULL,
1617
+ &stid);
1618
+ if (status)
1619
+ return status;
1620
+
1621
+ cn->cpn_sec = nn->nfsd4_lease;
1622
+ cn->cpn_nsec = 0;
1623
+
1624
+ status = nfserrno(-ENOMEM);
1625
+ cps = nfs4_alloc_init_cpntf_state(nn, stid);
1626
+ if (!cps)
1627
+ goto out;
1628
+ memcpy(&cn->cpn_cnr_stateid, &cps->cp_stateid.stid, sizeof(stateid_t));
1629
+ memcpy(&cps->cp_p_stateid, &stid->sc_stateid, sizeof(stateid_t));
1630
+ memcpy(&cps->cp_p_clid, &clp->cl_clientid, sizeof(clientid_t));
1631
+
1632
+ /* For now, only return one server address in cpn_src, the
1633
+ * address used by the client to connect to this server.
1634
+ */
1635
+ cn->cpn_src.nl4_type = NL4_NETADDR;
1636
+ status = nfsd4_set_netaddr((struct sockaddr *)&rqstp->rq_daddr,
1637
+ &cn->cpn_src.u.nl4_addr);
1638
+ WARN_ON_ONCE(status);
1639
+ if (status) {
1640
+ nfs4_put_cpntf_state(nn, cps);
1641
+ goto out;
1642
+ }
1643
+out:
1644
+ nfs4_put_stid(stid);
11241645 return status;
11251646 }
11261647
....@@ -1128,22 +1649,41 @@
11281649 nfsd4_fallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
11291650 struct nfsd4_fallocate *fallocate, int flags)
11301651 {
1131
- __be32 status = nfserr_notsupp;
1132
- struct file *file;
1652
+ __be32 status;
1653
+ struct nfsd_file *nf;
11331654
11341655 status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
11351656 &fallocate->falloc_stateid,
1136
- WR_STATE, &file, NULL);
1657
+ WR_STATE, &nf, NULL);
11371658 if (status != nfs_ok) {
11381659 dprintk("NFSD: nfsd4_fallocate: couldn't process stateid!\n");
11391660 return status;
11401661 }
11411662
1142
- status = nfsd4_vfs_fallocate(rqstp, &cstate->current_fh, file,
1663
+ status = nfsd4_vfs_fallocate(rqstp, &cstate->current_fh, nf->nf_file,
11431664 fallocate->falloc_offset,
11441665 fallocate->falloc_length,
11451666 flags);
1146
- fput(file);
1667
+ nfsd_file_put(nf);
1668
+ return status;
1669
+}
1670
+static __be32
1671
+nfsd4_offload_status(struct svc_rqst *rqstp,
1672
+ struct nfsd4_compound_state *cstate,
1673
+ union nfsd4_op_u *u)
1674
+{
1675
+ struct nfsd4_offload_status *os = &u->offload_status;
1676
+ __be32 status = 0;
1677
+ struct nfsd4_copy *copy;
1678
+ struct nfs4_client *clp = cstate->clp;
1679
+
1680
+ copy = find_async_copy(clp, &os->stateid);
1681
+ if (copy) {
1682
+ os->count = copy->cp_res.wr_bytes_written;
1683
+ nfs4_put_copy(copy);
1684
+ } else
1685
+ status = nfserr_bad_stateid;
1686
+
11471687 return status;
11481688 }
11491689
....@@ -1169,11 +1709,11 @@
11691709 struct nfsd4_seek *seek = &u->seek;
11701710 int whence;
11711711 __be32 status;
1172
- struct file *file;
1712
+ struct nfsd_file *nf;
11731713
11741714 status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
11751715 &seek->seek_stateid,
1176
- RD_STATE, &file, NULL);
1716
+ RD_STATE, &nf, NULL);
11771717 if (status) {
11781718 dprintk("NFSD: nfsd4_seek: couldn't process stateid!\n");
11791719 return status;
....@@ -1195,14 +1735,14 @@
11951735 * Note: This call does change file->f_pos, but nothing in NFSD
11961736 * should ever file->f_pos.
11971737 */
1198
- seek->seek_pos = vfs_llseek(file, seek->seek_offset, whence);
1738
+ seek->seek_pos = vfs_llseek(nf->nf_file, seek->seek_offset, whence);
11991739 if (seek->seek_pos < 0)
12001740 status = nfserrno(seek->seek_pos);
1201
- else if (seek->seek_pos >= i_size_read(file_inode(file)))
1741
+ else if (seek->seek_pos >= i_size_read(file_inode(nf->nf_file)))
12021742 seek->seek_eof = true;
12031743
12041744 out:
1205
- fput(file);
1745
+ nfsd_file_put(nf);
12061746 return status;
12071747 }
12081748
....@@ -1557,13 +2097,75 @@
15572097 }
15582098 #endif /* CONFIG_NFSD_PNFS */
15592099
2100
+static __be32
2101
+nfsd4_getxattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2102
+ union nfsd4_op_u *u)
2103
+{
2104
+ struct nfsd4_getxattr *getxattr = &u->getxattr;
2105
+
2106
+ return nfsd_getxattr(rqstp, &cstate->current_fh,
2107
+ getxattr->getxa_name, &getxattr->getxa_buf,
2108
+ &getxattr->getxa_len);
2109
+}
2110
+
2111
+static __be32
2112
+nfsd4_setxattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2113
+ union nfsd4_op_u *u)
2114
+{
2115
+ struct nfsd4_setxattr *setxattr = &u->setxattr;
2116
+ __be32 ret;
2117
+
2118
+ if (opens_in_grace(SVC_NET(rqstp)))
2119
+ return nfserr_grace;
2120
+
2121
+ ret = nfsd_setxattr(rqstp, &cstate->current_fh, setxattr->setxa_name,
2122
+ setxattr->setxa_buf, setxattr->setxa_len,
2123
+ setxattr->setxa_flags);
2124
+
2125
+ if (!ret)
2126
+ set_change_info(&setxattr->setxa_cinfo, &cstate->current_fh);
2127
+
2128
+ return ret;
2129
+}
2130
+
2131
+static __be32
2132
+nfsd4_listxattrs(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2133
+ union nfsd4_op_u *u)
2134
+{
2135
+ /*
2136
+ * Get the entire list, then copy out only the user attributes
2137
+ * in the encode function.
2138
+ */
2139
+ return nfsd_listxattr(rqstp, &cstate->current_fh,
2140
+ &u->listxattrs.lsxa_buf, &u->listxattrs.lsxa_len);
2141
+}
2142
+
2143
+static __be32
2144
+nfsd4_removexattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2145
+ union nfsd4_op_u *u)
2146
+{
2147
+ struct nfsd4_removexattr *removexattr = &u->removexattr;
2148
+ __be32 ret;
2149
+
2150
+ if (opens_in_grace(SVC_NET(rqstp)))
2151
+ return nfserr_grace;
2152
+
2153
+ ret = nfsd_removexattr(rqstp, &cstate->current_fh,
2154
+ removexattr->rmxa_name);
2155
+
2156
+ if (!ret)
2157
+ set_change_info(&removexattr->rmxa_cinfo, &cstate->current_fh);
2158
+
2159
+ return ret;
2160
+}
2161
+
15602162 /*
15612163 * NULL call.
15622164 */
15632165 static __be32
15642166 nfsd4_proc_null(struct svc_rqst *rqstp)
15652167 {
1566
- return nfs_ok;
2168
+ return rpc_success;
15672169 }
15682170
15692171 static inline void nfsd4_increment_op_stats(u32 opnum)
....@@ -1678,6 +2280,45 @@
16782280 - rqstp->rq_auth_slack;
16792281 }
16802282
2283
+#ifdef CONFIG_NFSD_V4_2_INTER_SSC
2284
+static void
2285
+check_if_stalefh_allowed(struct nfsd4_compoundargs *args)
2286
+{
2287
+ struct nfsd4_op *op, *current_op = NULL, *saved_op = NULL;
2288
+ struct nfsd4_copy *copy;
2289
+ struct nfsd4_putfh *putfh;
2290
+ int i;
2291
+
2292
+ /* traverse all operation and if it's a COPY compound, mark the
2293
+ * source filehandle to skip verification
2294
+ */
2295
+ for (i = 0; i < args->opcnt; i++) {
2296
+ op = &args->ops[i];
2297
+ if (op->opnum == OP_PUTFH)
2298
+ current_op = op;
2299
+ else if (op->opnum == OP_SAVEFH)
2300
+ saved_op = current_op;
2301
+ else if (op->opnum == OP_RESTOREFH)
2302
+ current_op = saved_op;
2303
+ else if (op->opnum == OP_COPY) {
2304
+ copy = (struct nfsd4_copy *)&op->u;
2305
+ if (!saved_op) {
2306
+ op->status = nfserr_nofilehandle;
2307
+ return;
2308
+ }
2309
+ putfh = (struct nfsd4_putfh *)&saved_op->u;
2310
+ if (!copy->cp_intra)
2311
+ putfh->no_verify = true;
2312
+ }
2313
+ }
2314
+}
2315
+#else
2316
+static void
2317
+check_if_stalefh_allowed(struct nfsd4_compoundargs *args)
2318
+{
2319
+}
2320
+#endif
2321
+
16812322 /*
16822323 * COMPOUND call.
16832324 */
....@@ -1690,6 +2331,7 @@
16902331 struct nfsd4_compound_state *cstate = &resp->cstate;
16912332 struct svc_fh *current_fh = &cstate->current_fh;
16922333 struct svc_fh *save_fh = &cstate->save_fh;
2334
+ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
16932335 __be32 status;
16942336
16952337 svcxdr_init_encode(rqstp, resp);
....@@ -1712,7 +2354,7 @@
17122354 * According to RFC3010, this takes precedence over all other errors.
17132355 */
17142356 status = nfserr_minor_vers_mismatch;
1715
- if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0)
2357
+ if (nfsd_minorversion(nn, args->minorversion, NFSD_TEST) <= 0)
17162358 goto out;
17172359 status = nfserr_resource;
17182360 if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
....@@ -1725,6 +2367,9 @@
17252367 resp->opcnt = 1;
17262368 goto encode_op;
17272369 }
2370
+ check_if_stalefh_allowed(args);
2371
+
2372
+ rqstp->rq_lease_breaker = (void **)&cstate->clp;
17282373
17292374 trace_nfsd_compound(rqstp, args->opcnt);
17302375 while (!status && resp->opcnt < args->opcnt) {
....@@ -1740,13 +2385,14 @@
17402385 op->status = nfsd4_open_omfg(rqstp, cstate, op);
17412386 goto encode_op;
17422387 }
1743
-
1744
- if (!current_fh->fh_dentry) {
2388
+ if (!current_fh->fh_dentry &&
2389
+ !HAS_FH_FLAG(current_fh, NFSD4_FH_FOREIGN)) {
17452390 if (!(op->opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
17462391 op->status = nfserr_nofilehandle;
17472392 goto encode_op;
17482393 }
1749
- } else if (current_fh->fh_export->ex_fslocs.migrated &&
2394
+ } else if (current_fh->fh_export &&
2395
+ current_fh->fh_export->ex_fslocs.migrated &&
17502396 !(op->opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
17512397 op->status = nfserr_moved;
17522398 goto encode_op;
....@@ -1790,7 +2436,8 @@
17902436 if (op->opdesc->op_flags & OP_CLEAR_STATEID)
17912437 clear_current_stateid(cstate);
17922438
1793
- if (need_wrongsec_check(rqstp))
2439
+ if (current_fh->fh_export &&
2440
+ need_wrongsec_check(rqstp))
17942441 op->status = check_nfsd_access(current_fh->fh_export, rqstp);
17952442 }
17962443 encode_op:
....@@ -1810,15 +2457,14 @@
18102457 nfsd4_increment_op_stats(op->opnum);
18112458 }
18122459
1813
- cstate->status = status;
18142460 fh_put(current_fh);
18152461 fh_put(save_fh);
18162462 BUG_ON(cstate->replay_owner);
18172463 out:
2464
+ cstate->status = status;
18182465 /* Reset deferral mechanism for RPC deferrals */
18192466 set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
1820
- dprintk("nfsv4 compound returned %d\n", ntohl(status));
1821
- return status;
2467
+ return rpc_success;
18222468 }
18232469
18242470 #define op_encode_hdr_size (2)
....@@ -1944,6 +2590,20 @@
19442590 return (op_encode_hdr_size + 2 + XDR_QUADLEN(rlen)) * sizeof(__be32);
19452591 }
19462592
2593
+static inline u32 nfsd4_read_plus_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
2594
+{
2595
+ u32 maxcount = svc_max_payload(rqstp);
2596
+ u32 rlen = min(op->u.read.rd_length, maxcount);
2597
+ /*
2598
+ * If we detect that the file changed during hole encoding, then we
2599
+ * recover by encoding the remaining reply as data. This means we need
2600
+ * to set aside enough room to encode two data segments.
2601
+ */
2602
+ u32 seg_len = 2 * (1 + 2 + 1);
2603
+
2604
+ return (op_encode_hdr_size + 2 + seg_len + XDR_QUADLEN(rlen)) * sizeof(__be32);
2605
+}
2606
+
19472607 static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
19482608 {
19492609 u32 maxcount = 0, rlen = 0;
....@@ -2049,6 +2709,29 @@
20492709 1 /* cr_synchronous */) * sizeof(__be32);
20502710 }
20512711
2712
+static inline u32 nfsd4_offload_status_rsize(struct svc_rqst *rqstp,
2713
+ struct nfsd4_op *op)
2714
+{
2715
+ return (op_encode_hdr_size +
2716
+ 2 /* osr_count */ +
2717
+ 1 /* osr_complete<1> optional 0 for now */) * sizeof(__be32);
2718
+}
2719
+
2720
+static inline u32 nfsd4_copy_notify_rsize(struct svc_rqst *rqstp,
2721
+ struct nfsd4_op *op)
2722
+{
2723
+ return (op_encode_hdr_size +
2724
+ 3 /* cnr_lease_time */ +
2725
+ 1 /* We support one cnr_source_server */ +
2726
+ 1 /* cnr_stateid seq */ +
2727
+ op_encode_stateid_maxsz /* cnr_stateid */ +
2728
+ 1 /* num cnr_source_server*/ +
2729
+ 1 /* nl4_type */ +
2730
+ 1 /* nl4 size */ +
2731
+ XDR_QUADLEN(NFS4_OPAQUE_LIMIT) /*nl4_loc + nl4_loc_sz */)
2732
+ * sizeof(__be32);
2733
+}
2734
+
20522735 #ifdef CONFIG_NFSD_PNFS
20532736 static inline u32 nfsd4_getdeviceinfo_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
20542737 {
....@@ -2097,6 +2780,42 @@
20972780 {
20982781 return (op_encode_hdr_size + 3) * sizeof(__be32);
20992782 }
2783
+
2784
+static inline u32 nfsd4_getxattr_rsize(struct svc_rqst *rqstp,
2785
+ struct nfsd4_op *op)
2786
+{
2787
+ u32 maxcount, rlen;
2788
+
2789
+ maxcount = svc_max_payload(rqstp);
2790
+ rlen = min_t(u32, XATTR_SIZE_MAX, maxcount);
2791
+
2792
+ return (op_encode_hdr_size + 1 + XDR_QUADLEN(rlen)) * sizeof(__be32);
2793
+}
2794
+
2795
+static inline u32 nfsd4_setxattr_rsize(struct svc_rqst *rqstp,
2796
+ struct nfsd4_op *op)
2797
+{
2798
+ return (op_encode_hdr_size + op_encode_change_info_maxsz)
2799
+ * sizeof(__be32);
2800
+}
2801
+static inline u32 nfsd4_listxattrs_rsize(struct svc_rqst *rqstp,
2802
+ struct nfsd4_op *op)
2803
+{
2804
+ u32 maxcount, rlen;
2805
+
2806
+ maxcount = svc_max_payload(rqstp);
2807
+ rlen = min(op->u.listxattrs.lsxa_maxcount, maxcount);
2808
+
2809
+ return (op_encode_hdr_size + 4 + XDR_QUADLEN(rlen)) * sizeof(__be32);
2810
+}
2811
+
2812
+static inline u32 nfsd4_removexattr_rsize(struct svc_rqst *rqstp,
2813
+ struct nfsd4_op *op)
2814
+{
2815
+ return (op_encode_hdr_size + op_encode_change_info_maxsz)
2816
+ * sizeof(__be32);
2817
+}
2818
+
21002819
21012820 static const struct nfsd4_operation nfsd4_ops[] = {
21022821 [OP_ACCESS] = {
....@@ -2435,32 +3154,78 @@
24353154 /* NFSv4.2 operations */
24363155 [OP_ALLOCATE] = {
24373156 .op_func = nfsd4_allocate,
2438
- .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
3157
+ .op_flags = OP_MODIFIES_SOMETHING,
24393158 .op_name = "OP_ALLOCATE",
24403159 .op_rsize_bop = nfsd4_only_status_rsize,
24413160 },
24423161 [OP_DEALLOCATE] = {
24433162 .op_func = nfsd4_deallocate,
2444
- .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
3163
+ .op_flags = OP_MODIFIES_SOMETHING,
24453164 .op_name = "OP_DEALLOCATE",
24463165 .op_rsize_bop = nfsd4_only_status_rsize,
24473166 },
24483167 [OP_CLONE] = {
24493168 .op_func = nfsd4_clone,
2450
- .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
3169
+ .op_flags = OP_MODIFIES_SOMETHING,
24513170 .op_name = "OP_CLONE",
24523171 .op_rsize_bop = nfsd4_only_status_rsize,
24533172 },
24543173 [OP_COPY] = {
24553174 .op_func = nfsd4_copy,
2456
- .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
3175
+ .op_flags = OP_MODIFIES_SOMETHING,
24573176 .op_name = "OP_COPY",
24583177 .op_rsize_bop = nfsd4_copy_rsize,
3178
+ },
3179
+ [OP_READ_PLUS] = {
3180
+ .op_func = nfsd4_read,
3181
+ .op_release = nfsd4_read_release,
3182
+ .op_name = "OP_READ_PLUS",
3183
+ .op_rsize_bop = nfsd4_read_plus_rsize,
3184
+ .op_get_currentstateid = nfsd4_get_readstateid,
24593185 },
24603186 [OP_SEEK] = {
24613187 .op_func = nfsd4_seek,
24623188 .op_name = "OP_SEEK",
24633189 .op_rsize_bop = nfsd4_seek_rsize,
3190
+ },
3191
+ [OP_OFFLOAD_STATUS] = {
3192
+ .op_func = nfsd4_offload_status,
3193
+ .op_name = "OP_OFFLOAD_STATUS",
3194
+ .op_rsize_bop = nfsd4_offload_status_rsize,
3195
+ },
3196
+ [OP_OFFLOAD_CANCEL] = {
3197
+ .op_func = nfsd4_offload_cancel,
3198
+ .op_flags = OP_MODIFIES_SOMETHING,
3199
+ .op_name = "OP_OFFLOAD_CANCEL",
3200
+ .op_rsize_bop = nfsd4_only_status_rsize,
3201
+ },
3202
+ [OP_COPY_NOTIFY] = {
3203
+ .op_func = nfsd4_copy_notify,
3204
+ .op_flags = OP_MODIFIES_SOMETHING,
3205
+ .op_name = "OP_COPY_NOTIFY",
3206
+ .op_rsize_bop = nfsd4_copy_notify_rsize,
3207
+ },
3208
+ [OP_GETXATTR] = {
3209
+ .op_func = nfsd4_getxattr,
3210
+ .op_name = "OP_GETXATTR",
3211
+ .op_rsize_bop = nfsd4_getxattr_rsize,
3212
+ },
3213
+ [OP_SETXATTR] = {
3214
+ .op_func = nfsd4_setxattr,
3215
+ .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
3216
+ .op_name = "OP_SETXATTR",
3217
+ .op_rsize_bop = nfsd4_setxattr_rsize,
3218
+ },
3219
+ [OP_LISTXATTRS] = {
3220
+ .op_func = nfsd4_listxattrs,
3221
+ .op_name = "OP_LISTXATTRS",
3222
+ .op_rsize_bop = nfsd4_listxattrs_rsize,
3223
+ },
3224
+ [OP_REMOVEXATTR] = {
3225
+ .op_func = nfsd4_removexattr,
3226
+ .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
3227
+ .op_name = "OP_REMOVEXATTR",
3228
+ .op_rsize_bop = nfsd4_removexattr_rsize,
24643229 },
24653230 };
24663231
....@@ -2486,7 +3251,7 @@
24863251 if (!cstate->minorversion)
24873252 return false;
24883253
2489
- if (cstate->spo_must_allowed == true)
3254
+ if (cstate->spo_must_allowed)
24903255 return true;
24913256
24923257 opiter = resp->opcnt;
....@@ -2534,6 +3299,7 @@
25343299 static const struct svc_procedure nfsd_procedures4[2] = {
25353300 [NFSPROC4_NULL] = {
25363301 .pc_func = nfsd4_proc_null,
3302
+ .pc_decode = nfs4svc_decode_voidarg,
25373303 .pc_encode = nfs4svc_encode_voidres,
25383304 .pc_argsize = sizeof(struct nfsd4_voidargs),
25393305 .pc_ressize = sizeof(struct nfsd4_voidres),