aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/callback_proc.c2
-rw-r--r--fs/nfs/callback_xdr.c8
-rw-r--r--fs/nfs/delegation.c4
-rw-r--r--fs/nfs/direct.c2
-rw-r--r--fs/nfs/filelayout/filelayout.c53
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c43
-rw-r--r--fs/nfs/inode.c1
-rw-r--r--fs/nfs/internal.h13
-rw-r--r--fs/nfs/nfs4proc.c75
-rw-r--r--fs/nfs/nfs4session.c2
-rw-r--r--fs/nfs/nfs4session.h6
-rw-r--r--fs/nfs/nfs4xdr.c32
-rw-r--r--fs/nfs/pnfs.h4
-rw-r--r--fs/nfs/pnfs_nfs.c30
-rw-r--r--fs/nfs/write.c16
-rw-r--r--include/linux/nfs_fs.h1
-rw-r--r--include/linux/nfs_xdr.h19
-rw-r--r--include/linux/sunrpc/metrics.h7
-rw-r--r--net/sunrpc/backchannel_rqst.c5
19 files changed, 165 insertions, 158 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index e36a9d78ea49..197806fb87ff 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -427,6 +427,8 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
427 if (clp == NULL) 427 if (clp == NULL)
428 goto out; 428 goto out;
429 429
430 if (!(clp->cl_session->flags & SESSION4_BACK_CHAN))
431 goto out;
430 tbl = &clp->cl_session->bc_slot_table; 432 tbl = &clp->cl_session->bc_slot_table;
431 433
432 spin_lock(&tbl->slot_tbl_lock); 434 spin_lock(&tbl->slot_tbl_lock);
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index f4ccfe6521ec..19ca95cdfd9b 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -313,7 +313,7 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp,
313 goto out; 313 goto out;
314 } 314 }
315 315
316 args->devs = kmalloc(n * sizeof(*args->devs), GFP_KERNEL); 316 args->devs = kmalloc_array(n, sizeof(*args->devs), GFP_KERNEL);
317 if (!args->devs) { 317 if (!args->devs) {
318 status = htonl(NFS4ERR_DELAY); 318 status = htonl(NFS4ERR_DELAY);
319 goto out; 319 goto out;
@@ -415,7 +415,7 @@ static __be32 decode_rc_list(struct xdr_stream *xdr,
415 rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t)); 415 rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t));
416 if (unlikely(p == NULL)) 416 if (unlikely(p == NULL))
417 goto out; 417 goto out;
418 rc_list->rcl_refcalls = kmalloc(rc_list->rcl_nrefcalls * 418 rc_list->rcl_refcalls = kmalloc_array(rc_list->rcl_nrefcalls,
419 sizeof(*rc_list->rcl_refcalls), 419 sizeof(*rc_list->rcl_refcalls),
420 GFP_KERNEL); 420 GFP_KERNEL);
421 if (unlikely(rc_list->rcl_refcalls == NULL)) 421 if (unlikely(rc_list->rcl_refcalls == NULL))
@@ -464,8 +464,10 @@ static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp,
464 464
465 for (i = 0; i < args->csa_nrclists; i++) { 465 for (i = 0; i < args->csa_nrclists; i++) {
466 status = decode_rc_list(xdr, &args->csa_rclists[i]); 466 status = decode_rc_list(xdr, &args->csa_rclists[i]);
467 if (status) 467 if (status) {
468 args->csa_nrclists = i;
468 goto out_free; 469 goto out_free;
470 }
469 } 471 }
470 } 472 }
471 status = 0; 473 status = 0;
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index da5433230bb1..a1f0685b42ff 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -180,7 +180,6 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred,
180 delegation->cred = get_rpccred(cred); 180 delegation->cred = get_rpccred(cred);
181 clear_bit(NFS_DELEGATION_NEED_RECLAIM, 181 clear_bit(NFS_DELEGATION_NEED_RECLAIM,
182 &delegation->flags); 182 &delegation->flags);
183 NFS_I(inode)->delegation_state = delegation->type;
184 spin_unlock(&delegation->lock); 183 spin_unlock(&delegation->lock);
185 put_rpccred(oldcred); 184 put_rpccred(oldcred);
186 rcu_read_unlock(); 185 rcu_read_unlock();
@@ -275,7 +274,6 @@ nfs_detach_delegation_locked(struct nfs_inode *nfsi,
275 set_bit(NFS_DELEGATION_RETURNING, &delegation->flags); 274 set_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
276 list_del_rcu(&delegation->super_list); 275 list_del_rcu(&delegation->super_list);
277 delegation->inode = NULL; 276 delegation->inode = NULL;
278 nfsi->delegation_state = 0;
279 rcu_assign_pointer(nfsi->delegation, NULL); 277 rcu_assign_pointer(nfsi->delegation, NULL);
280 spin_unlock(&delegation->lock); 278 spin_unlock(&delegation->lock);
281 return delegation; 279 return delegation;
@@ -355,7 +353,6 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
355 &delegation->stateid)) { 353 &delegation->stateid)) {
356 nfs_update_inplace_delegation(old_delegation, 354 nfs_update_inplace_delegation(old_delegation,
357 delegation); 355 delegation);
358 nfsi->delegation_state = old_delegation->type;
359 goto out; 356 goto out;
360 } 357 }
361 /* 358 /*
@@ -379,7 +376,6 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
379 goto out; 376 goto out;
380 } 377 }
381 list_add_rcu(&delegation->super_list, &server->delegations); 378 list_add_rcu(&delegation->super_list, &server->delegations);
382 nfsi->delegation_state = delegation->type;
383 rcu_assign_pointer(nfsi->delegation, delegation); 379 rcu_assign_pointer(nfsi->delegation, delegation);
384 delegation = NULL; 380 delegation = NULL;
385 381
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 7077521acdf4..e907c8cf732e 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -283,7 +283,7 @@ static void nfs_direct_release_pages(struct page **pages, unsigned int npages)
283void nfs_init_cinfo_from_dreq(struct nfs_commit_info *cinfo, 283void nfs_init_cinfo_from_dreq(struct nfs_commit_info *cinfo,
284 struct nfs_direct_req *dreq) 284 struct nfs_direct_req *dreq)
285{ 285{
286 cinfo->lock = &dreq->lock; 286 cinfo->lock = &dreq->inode->i_lock;
287 cinfo->mds = &dreq->mds_cinfo; 287 cinfo->mds = &dreq->mds_cinfo;
288 cinfo->ds = &dreq->ds_cinfo; 288 cinfo->ds = &dreq->ds_cinfo;
289 cinfo->dreq = dreq; 289 cinfo->dreq = dreq;
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c
index 7ae1c263c5cf..91e88a7ecef0 100644
--- a/fs/nfs/filelayout/filelayout.c
+++ b/fs/nfs/filelayout/filelayout.c
@@ -960,52 +960,19 @@ filelayout_mark_request_commit(struct nfs_page *req,
960{ 960{
961 struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); 961 struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
962 u32 i, j; 962 u32 i, j;
963 struct list_head *list;
964 struct pnfs_commit_bucket *buckets;
965 963
966 if (fl->commit_through_mds) { 964 if (fl->commit_through_mds) {
967 list = &cinfo->mds->list; 965 nfs_request_add_commit_list(req, &cinfo->mds->list, cinfo);
968 spin_lock(cinfo->lock); 966 } else {
969 goto mds_commit; 967 /* Note that we are calling nfs4_fl_calc_j_index on each page
970 } 968 * that ends up being committed to a data server. An attractive
971 969 * alternative is to add a field to nfs_write_data and nfs_page
972 /* Note that we are calling nfs4_fl_calc_j_index on each page 970 * to store the value calculated in filelayout_write_pagelist
973 * that ends up being committed to a data server. An attractive 971 * and just use that here.
974 * alternative is to add a field to nfs_write_data and nfs_page
975 * to store the value calculated in filelayout_write_pagelist
976 * and just use that here.
977 */
978 j = nfs4_fl_calc_j_index(lseg, req_offset(req));
979 i = select_bucket_index(fl, j);
980 spin_lock(cinfo->lock);
981 buckets = cinfo->ds->buckets;
982 list = &buckets[i].written;
983 if (list_empty(list)) {
984 /* Non-empty buckets hold a reference on the lseg. That ref
985 * is normally transferred to the COMMIT call and released
986 * there. It could also be released if the last req is pulled
987 * off due to a rewrite, in which case it will be done in
988 * pnfs_generic_clear_request_commit
989 */ 972 */
990 buckets[i].wlseg = pnfs_get_lseg(lseg); 973 j = nfs4_fl_calc_j_index(lseg, req_offset(req));
991 } 974 i = select_bucket_index(fl, j);
992 set_bit(PG_COMMIT_TO_DS, &req->wb_flags); 975 pnfs_layout_mark_request_commit(req, lseg, cinfo, i);
993 cinfo->ds->nwritten++;
994
995mds_commit:
996 /* nfs_request_add_commit_list(). We need to add req to list without
997 * dropping cinfo lock.
998 */
999 set_bit(PG_CLEAN, &(req)->wb_flags);
1000 nfs_list_add_request(req, list);
1001 cinfo->mds->ncommit++;
1002 spin_unlock(cinfo->lock);
1003 if (!cinfo->dreq) {
1004 inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
1005 inc_bdi_stat(inode_to_bdi(page_file_mapping(req->wb_page)->host),
1006 BDI_RECLAIMABLE);
1007 __mark_inode_dirty(req->wb_context->dentry->d_inode,
1008 I_DIRTY_DATASYNC);
1009 } 976 }
1010} 977}
1011 978
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index c22ecaa86c1c..315cc68945b9 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -1332,47 +1332,6 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
1332 return PNFS_ATTEMPTED; 1332 return PNFS_ATTEMPTED;
1333} 1333}
1334 1334
1335static void
1336ff_layout_mark_request_commit(struct nfs_page *req,
1337 struct pnfs_layout_segment *lseg,
1338 struct nfs_commit_info *cinfo,
1339 u32 ds_commit_idx)
1340{
1341 struct list_head *list;
1342 struct pnfs_commit_bucket *buckets;
1343
1344 spin_lock(cinfo->lock);
1345 buckets = cinfo->ds->buckets;
1346 list = &buckets[ds_commit_idx].written;
1347 if (list_empty(list)) {
1348 /* Non-empty buckets hold a reference on the lseg. That ref
1349 * is normally transferred to the COMMIT call and released
1350 * there. It could also be released if the last req is pulled
1351 * off due to a rewrite, in which case it will be done in
1352 * pnfs_common_clear_request_commit
1353 */
1354 WARN_ON_ONCE(buckets[ds_commit_idx].wlseg != NULL);
1355 buckets[ds_commit_idx].wlseg = pnfs_get_lseg(lseg);
1356 }
1357 set_bit(PG_COMMIT_TO_DS, &req->wb_flags);
1358 cinfo->ds->nwritten++;
1359
1360 /* nfs_request_add_commit_list(). We need to add req to list without
1361 * dropping cinfo lock.
1362 */
1363 set_bit(PG_CLEAN, &(req)->wb_flags);
1364 nfs_list_add_request(req, list);
1365 cinfo->mds->ncommit++;
1366 spin_unlock(cinfo->lock);
1367 if (!cinfo->dreq) {
1368 inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
1369 inc_bdi_stat(inode_to_bdi(page_file_mapping(req->wb_page)->host),
1370 BDI_RECLAIMABLE);
1371 __mark_inode_dirty(req->wb_context->dentry->d_inode,
1372 I_DIRTY_DATASYNC);
1373 }
1374}
1375
1376static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i) 1335static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i)
1377{ 1336{
1378 return i; 1337 return i;
@@ -1540,7 +1499,7 @@ static struct pnfs_layoutdriver_type flexfilelayout_type = {
1540 .pg_write_ops = &ff_layout_pg_write_ops, 1499 .pg_write_ops = &ff_layout_pg_write_ops,
1541 .get_ds_info = ff_layout_get_ds_info, 1500 .get_ds_info = ff_layout_get_ds_info,
1542 .free_deviceid_node = ff_layout_free_deveiceid_node, 1501 .free_deviceid_node = ff_layout_free_deveiceid_node,
1543 .mark_request_commit = ff_layout_mark_request_commit, 1502 .mark_request_commit = pnfs_layout_mark_request_commit,
1544 .clear_request_commit = pnfs_generic_clear_request_commit, 1503 .clear_request_commit = pnfs_generic_clear_request_commit,
1545 .scan_commit_lists = pnfs_generic_scan_commit_lists, 1504 .scan_commit_lists = pnfs_generic_scan_commit_lists,
1546 .recover_commit_reqs = pnfs_generic_recover_commit_reqs, 1505 .recover_commit_reqs = pnfs_generic_recover_commit_reqs,
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index e4f0dcef8f54..83107be3dd01 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1775,7 +1775,6 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi)
1775#if IS_ENABLED(CONFIG_NFS_V4) 1775#if IS_ENABLED(CONFIG_NFS_V4)
1776 INIT_LIST_HEAD(&nfsi->open_states); 1776 INIT_LIST_HEAD(&nfsi->open_states);
1777 nfsi->delegation = NULL; 1777 nfsi->delegation = NULL;
1778 nfsi->delegation_state = 0;
1779 init_rwsem(&nfsi->rwsem); 1778 init_rwsem(&nfsi->rwsem);
1780 nfsi->layout = NULL; 1779 nfsi->layout = NULL;
1781#endif 1780#endif
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 212b8c883d22..b802fb3a2d99 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -598,6 +598,19 @@ void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize)
598} 598}
599 599
600/* 600/*
601 * Record the page as unstable and mark its inode as dirty.
602 */
603static inline
604void nfs_mark_page_unstable(struct page *page)
605{
606 struct inode *inode = page_file_mapping(page)->host;
607
608 inc_zone_page_state(page, NR_UNSTABLE_NFS);
609 inc_bdi_stat(inode_to_bdi(inode), BDI_RECLAIMABLE);
610 __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
611}
612
613/*
601 * Determine the number of bytes of data the page contains 614 * Determine the number of bytes of data the page contains
602 */ 615 */
603static inline 616static inline
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 2e7c9f7a6f7c..88180ac5ea0e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6648,47 +6648,47 @@ nfs41_same_server_scope(struct nfs41_server_scope *a,
6648int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred) 6648int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred)
6649{ 6649{
6650 int status; 6650 int status;
6651 struct nfs41_bind_conn_to_session_args args = {
6652 .client = clp,
6653 .dir = NFS4_CDFC4_FORE_OR_BOTH,
6654 };
6651 struct nfs41_bind_conn_to_session_res res; 6655 struct nfs41_bind_conn_to_session_res res;
6652 struct rpc_message msg = { 6656 struct rpc_message msg = {
6653 .rpc_proc = 6657 .rpc_proc =
6654 &nfs4_procedures[NFSPROC4_CLNT_BIND_CONN_TO_SESSION], 6658 &nfs4_procedures[NFSPROC4_CLNT_BIND_CONN_TO_SESSION],
6655 .rpc_argp = clp, 6659 .rpc_argp = &args,
6656 .rpc_resp = &res, 6660 .rpc_resp = &res,
6657 .rpc_cred = cred, 6661 .rpc_cred = cred,
6658 }; 6662 };
6659 6663
6660 dprintk("--> %s\n", __func__); 6664 dprintk("--> %s\n", __func__);
6661 6665
6662 res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); 6666 nfs4_copy_sessionid(&args.sessionid, &clp->cl_session->sess_id);
6663 if (unlikely(res.session == NULL)) { 6667 if (!(clp->cl_session->flags & SESSION4_BACK_CHAN))
6664 status = -ENOMEM; 6668 args.dir = NFS4_CDFC4_FORE;
6665 goto out;
6666 }
6667 6669
6668 status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); 6670 status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
6669 trace_nfs4_bind_conn_to_session(clp, status); 6671 trace_nfs4_bind_conn_to_session(clp, status);
6670 if (status == 0) { 6672 if (status == 0) {
6671 if (memcmp(res.session->sess_id.data, 6673 if (memcmp(res.sessionid.data,
6672 clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) { 6674 clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) {
6673 dprintk("NFS: %s: Session ID mismatch\n", __func__); 6675 dprintk("NFS: %s: Session ID mismatch\n", __func__);
6674 status = -EIO; 6676 status = -EIO;
6675 goto out_session; 6677 goto out;
6676 } 6678 }
6677 if (res.dir != NFS4_CDFS4_BOTH) { 6679 if ((res.dir & args.dir) != res.dir || res.dir == 0) {
6678 dprintk("NFS: %s: Unexpected direction from server\n", 6680 dprintk("NFS: %s: Unexpected direction from server\n",
6679 __func__); 6681 __func__);
6680 status = -EIO; 6682 status = -EIO;
6681 goto out_session; 6683 goto out;
6682 } 6684 }
6683 if (res.use_conn_in_rdma_mode) { 6685 if (res.use_conn_in_rdma_mode != args.use_conn_in_rdma_mode) {
6684 dprintk("NFS: %s: Server returned RDMA mode = true\n", 6686 dprintk("NFS: %s: Server returned RDMA mode = true\n",
6685 __func__); 6687 __func__);
6686 status = -EIO; 6688 status = -EIO;
6687 goto out_session; 6689 goto out;
6688 } 6690 }
6689 } 6691 }
6690out_session:
6691 kfree(res.session);
6692out: 6692out:
6693 dprintk("<-- %s status= %d\n", __func__, status); 6693 dprintk("<-- %s status= %d\n", __func__, status);
6694 return status; 6694 return status;
@@ -7166,10 +7166,11 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
7166 args->bc_attrs.max_reqs); 7166 args->bc_attrs.max_reqs);
7167} 7167}
7168 7168
7169static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session) 7169static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args,
7170 struct nfs41_create_session_res *res)
7170{ 7171{
7171 struct nfs4_channel_attrs *sent = &args->fc_attrs; 7172 struct nfs4_channel_attrs *sent = &args->fc_attrs;
7172 struct nfs4_channel_attrs *rcvd = &session->fc_attrs; 7173 struct nfs4_channel_attrs *rcvd = &res->fc_attrs;
7173 7174
7174 if (rcvd->max_resp_sz > sent->max_resp_sz) 7175 if (rcvd->max_resp_sz > sent->max_resp_sz)
7175 return -EINVAL; 7176 return -EINVAL;
@@ -7188,11 +7189,14 @@ static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args
7188 return 0; 7189 return 0;
7189} 7190}
7190 7191
7191static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session) 7192static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args,
7193 struct nfs41_create_session_res *res)
7192{ 7194{
7193 struct nfs4_channel_attrs *sent = &args->bc_attrs; 7195 struct nfs4_channel_attrs *sent = &args->bc_attrs;
7194 struct nfs4_channel_attrs *rcvd = &session->bc_attrs; 7196 struct nfs4_channel_attrs *rcvd = &res->bc_attrs;
7195 7197
7198 if (!(res->flags & SESSION4_BACK_CHAN))
7199 goto out;
7196 if (rcvd->max_rqst_sz > sent->max_rqst_sz) 7200 if (rcvd->max_rqst_sz > sent->max_rqst_sz)
7197 return -EINVAL; 7201 return -EINVAL;
7198 if (rcvd->max_resp_sz < sent->max_resp_sz) 7202 if (rcvd->max_resp_sz < sent->max_resp_sz)
@@ -7204,18 +7208,30 @@ static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args
7204 return -EINVAL; 7208 return -EINVAL;
7205 if (rcvd->max_reqs != sent->max_reqs) 7209 if (rcvd->max_reqs != sent->max_reqs)
7206 return -EINVAL; 7210 return -EINVAL;
7211out:
7207 return 0; 7212 return 0;
7208} 7213}
7209 7214
7210static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args, 7215static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args,
7211 struct nfs4_session *session) 7216 struct nfs41_create_session_res *res)
7212{ 7217{
7213 int ret; 7218 int ret;
7214 7219
7215 ret = nfs4_verify_fore_channel_attrs(args, session); 7220 ret = nfs4_verify_fore_channel_attrs(args, res);
7216 if (ret) 7221 if (ret)
7217 return ret; 7222 return ret;
7218 return nfs4_verify_back_channel_attrs(args, session); 7223 return nfs4_verify_back_channel_attrs(args, res);
7224}
7225
7226static void nfs4_update_session(struct nfs4_session *session,
7227 struct nfs41_create_session_res *res)
7228{
7229 nfs4_copy_sessionid(&session->sess_id, &res->sessionid);
7230 session->flags = res->flags;
7231 memcpy(&session->fc_attrs, &res->fc_attrs, sizeof(session->fc_attrs));
7232 if (res->flags & SESSION4_BACK_CHAN)
7233 memcpy(&session->bc_attrs, &res->bc_attrs,
7234 sizeof(session->bc_attrs));
7219} 7235}
7220 7236
7221static int _nfs4_proc_create_session(struct nfs_client *clp, 7237static int _nfs4_proc_create_session(struct nfs_client *clp,
@@ -7224,11 +7240,12 @@ static int _nfs4_proc_create_session(struct nfs_client *clp,
7224 struct nfs4_session *session = clp->cl_session; 7240 struct nfs4_session *session = clp->cl_session;
7225 struct nfs41_create_session_args args = { 7241 struct nfs41_create_session_args args = {
7226 .client = clp, 7242 .client = clp,
7243 .clientid = clp->cl_clientid,
7244 .seqid = clp->cl_seqid,
7227 .cb_program = NFS4_CALLBACK, 7245 .cb_program = NFS4_CALLBACK,
7228 }; 7246 };
7229 struct nfs41_create_session_res res = { 7247 struct nfs41_create_session_res res;
7230 .client = clp, 7248
7231 };
7232 struct rpc_message msg = { 7249 struct rpc_message msg = {
7233 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION], 7250 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION],
7234 .rpc_argp = &args, 7251 .rpc_argp = &args,
@@ -7245,11 +7262,15 @@ static int _nfs4_proc_create_session(struct nfs_client *clp,
7245 7262
7246 if (!status) { 7263 if (!status) {
7247 /* Verify the session's negotiated channel_attrs values */ 7264 /* Verify the session's negotiated channel_attrs values */
7248 status = nfs4_verify_channel_attrs(&args, session); 7265 status = nfs4_verify_channel_attrs(&args, &res);
7249 /* Increment the clientid slot sequence id */ 7266 /* Increment the clientid slot sequence id */
7250 clp->cl_seqid++; 7267 if (clp->cl_seqid == res.seqid)
7268 clp->cl_seqid++;
7269 if (status)
7270 goto out;
7271 nfs4_update_session(session, &res);
7251 } 7272 }
7252 7273out:
7253 return status; 7274 return status;
7254} 7275}
7255 7276
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c
index e799dc3c3b1d..e23366effcfb 100644
--- a/fs/nfs/nfs4session.c
+++ b/fs/nfs/nfs4session.c
@@ -450,7 +450,7 @@ int nfs4_setup_session_slot_tables(struct nfs4_session *ses)
450 tbl = &ses->fc_slot_table; 450 tbl = &ses->fc_slot_table;
451 tbl->session = ses; 451 tbl->session = ses;
452 status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1); 452 status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1);
453 if (status) /* -ENOMEM */ 453 if (status || !(ses->flags & SESSION4_BACK_CHAN)) /* -ENOMEM */
454 return status; 454 return status;
455 /* Back channel */ 455 /* Back channel */
456 tbl = &ses->bc_slot_table; 456 tbl = &ses->bc_slot_table;
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h
index b34ada9bc6a2..fc46c7455898 100644
--- a/fs/nfs/nfs4session.h
+++ b/fs/nfs/nfs4session.h
@@ -118,6 +118,12 @@ static inline int nfs4_has_persistent_session(const struct nfs_client *clp)
118 return 0; 118 return 0;
119} 119}
120 120
121static inline void nfs4_copy_sessionid(struct nfs4_sessionid *dst,
122 const struct nfs4_sessionid *src)
123{
124 memcpy(dst->data, src->data, NFS4_MAX_SESSIONID_LEN);
125}
126
121#ifdef CONFIG_CRC32 127#ifdef CONFIG_CRC32
122/* 128/*
123 * nfs_session_id_hash - calculate the crc32 hash for the session id 129 * nfs_session_id_hash - calculate the crc32 hash for the session id
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index e23a0a664e12..5c399ec41079 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1715,17 +1715,17 @@ static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, stru
1715#if defined(CONFIG_NFS_V4_1) 1715#if defined(CONFIG_NFS_V4_1)
1716/* NFSv4.1 operations */ 1716/* NFSv4.1 operations */
1717static void encode_bind_conn_to_session(struct xdr_stream *xdr, 1717static void encode_bind_conn_to_session(struct xdr_stream *xdr,
1718 struct nfs4_session *session, 1718 struct nfs41_bind_conn_to_session_args *args,
1719 struct compound_hdr *hdr) 1719 struct compound_hdr *hdr)
1720{ 1720{
1721 __be32 *p; 1721 __be32 *p;
1722 1722
1723 encode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION, 1723 encode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION,
1724 decode_bind_conn_to_session_maxsz, hdr); 1724 decode_bind_conn_to_session_maxsz, hdr);
1725 encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN); 1725 encode_opaque_fixed(xdr, args->sessionid.data, NFS4_MAX_SESSIONID_LEN);
1726 p = xdr_reserve_space(xdr, 8); 1726 p = xdr_reserve_space(xdr, 8);
1727 *p++ = cpu_to_be32(NFS4_CDFC4_BACK_OR_BOTH); 1727 *p++ = cpu_to_be32(args->dir);
1728 *p = 0; /* use_conn_in_rdma_mode = False */ 1728 *p = (args->use_conn_in_rdma_mode) ? cpu_to_be32(1) : cpu_to_be32(0);
1729} 1729}
1730 1730
1731static void encode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map) 1731static void encode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map)
@@ -1806,8 +1806,8 @@ static void encode_create_session(struct xdr_stream *xdr,
1806 1806
1807 encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr); 1807 encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr);
1808 p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12); 1808 p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12);
1809 p = xdr_encode_hyper(p, clp->cl_clientid); 1809 p = xdr_encode_hyper(p, args->clientid);
1810 *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */ 1810 *p++ = cpu_to_be32(args->seqid); /*Sequence id */
1811 *p++ = cpu_to_be32(args->flags); /*flags */ 1811 *p++ = cpu_to_be32(args->flags); /*flags */
1812 1812
1813 /* Fore Channel */ 1813 /* Fore Channel */
@@ -2734,14 +2734,14 @@ static void nfs4_xdr_enc_fsid_present(struct rpc_rqst *req,
2734 */ 2734 */
2735static void nfs4_xdr_enc_bind_conn_to_session(struct rpc_rqst *req, 2735static void nfs4_xdr_enc_bind_conn_to_session(struct rpc_rqst *req,
2736 struct xdr_stream *xdr, 2736 struct xdr_stream *xdr,
2737 struct nfs_client *clp) 2737 struct nfs41_bind_conn_to_session_args *args)
2738{ 2738{
2739 struct compound_hdr hdr = { 2739 struct compound_hdr hdr = {
2740 .minorversion = clp->cl_mvops->minor_version, 2740 .minorversion = args->client->cl_mvops->minor_version,
2741 }; 2741 };
2742 2742
2743 encode_compound_hdr(xdr, req, &hdr); 2743 encode_compound_hdr(xdr, req, &hdr);
2744 encode_bind_conn_to_session(xdr, clp->cl_session, &hdr); 2744 encode_bind_conn_to_session(xdr, args, &hdr);
2745 encode_nops(&hdr); 2745 encode_nops(&hdr);
2746} 2746}
2747 2747
@@ -5613,7 +5613,7 @@ static int decode_bind_conn_to_session(struct xdr_stream *xdr,
5613 5613
5614 status = decode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION); 5614 status = decode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION);
5615 if (!status) 5615 if (!status)
5616 status = decode_sessionid(xdr, &res->session->sess_id); 5616 status = decode_sessionid(xdr, &res->sessionid);
5617 if (unlikely(status)) 5617 if (unlikely(status))
5618 return status; 5618 return status;
5619 5619
@@ -5641,12 +5641,10 @@ static int decode_create_session(struct xdr_stream *xdr,
5641{ 5641{
5642 __be32 *p; 5642 __be32 *p;
5643 int status; 5643 int status;
5644 struct nfs_client *clp = res->client;
5645 struct nfs4_session *session = clp->cl_session;
5646 5644
5647 status = decode_op_hdr(xdr, OP_CREATE_SESSION); 5645 status = decode_op_hdr(xdr, OP_CREATE_SESSION);
5648 if (!status) 5646 if (!status)
5649 status = decode_sessionid(xdr, &session->sess_id); 5647 status = decode_sessionid(xdr, &res->sessionid);
5650 if (unlikely(status)) 5648 if (unlikely(status))
5651 return status; 5649 return status;
5652 5650
@@ -5654,13 +5652,13 @@ static int decode_create_session(struct xdr_stream *xdr,
5654 p = xdr_inline_decode(xdr, 8); 5652 p = xdr_inline_decode(xdr, 8);
5655 if (unlikely(!p)) 5653 if (unlikely(!p))
5656 goto out_overflow; 5654 goto out_overflow;
5657 clp->cl_seqid = be32_to_cpup(p++); 5655 res->seqid = be32_to_cpup(p++);
5658 session->flags = be32_to_cpup(p); 5656 res->flags = be32_to_cpup(p);
5659 5657
5660 /* Channel attributes */ 5658 /* Channel attributes */
5661 status = decode_chan_attrs(xdr, &session->fc_attrs); 5659 status = decode_chan_attrs(xdr, &res->fc_attrs);
5662 if (!status) 5660 if (!status)
5663 status = decode_chan_attrs(xdr, &session->bc_attrs); 5661 status = decode_chan_attrs(xdr, &res->bc_attrs);
5664 return status; 5662 return status;
5665out_overflow: 5663out_overflow:
5666 print_overflow_msg(__func__, xdr); 5664 print_overflow_msg(__func__, xdr);
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 797cd6253adf..635f0865671c 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -344,6 +344,10 @@ void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
344struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net, 344struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net,
345 struct xdr_stream *xdr, 345 struct xdr_stream *xdr,
346 gfp_t gfp_flags); 346 gfp_t gfp_flags);
347void pnfs_layout_mark_request_commit(struct nfs_page *req,
348 struct pnfs_layout_segment *lseg,
349 struct nfs_commit_info *cinfo,
350 u32 ds_commit_idx);
347 351
348static inline bool nfs_have_layout(struct inode *inode) 352static inline bool nfs_have_layout(struct inode *inode)
349{ 353{
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c
index fdc4f6562bb7..54e36b38fb5f 100644
--- a/fs/nfs/pnfs_nfs.c
+++ b/fs/nfs/pnfs_nfs.c
@@ -838,3 +838,33 @@ out_err:
838 return NULL; 838 return NULL;
839} 839}
840EXPORT_SYMBOL_GPL(nfs4_decode_mp_ds_addr); 840EXPORT_SYMBOL_GPL(nfs4_decode_mp_ds_addr);
841
842void
843pnfs_layout_mark_request_commit(struct nfs_page *req,
844 struct pnfs_layout_segment *lseg,
845 struct nfs_commit_info *cinfo,
846 u32 ds_commit_idx)
847{
848 struct list_head *list;
849 struct pnfs_commit_bucket *buckets;
850
851 spin_lock(cinfo->lock);
852 buckets = cinfo->ds->buckets;
853 list = &buckets[ds_commit_idx].written;
854 if (list_empty(list)) {
855 /* Non-empty buckets hold a reference on the lseg. That ref
856 * is normally transferred to the COMMIT call and released
857 * there. It could also be released if the last req is pulled
858 * off due to a rewrite, in which case it will be done in
859 * pnfs_common_clear_request_commit
860 */
861 WARN_ON_ONCE(buckets[ds_commit_idx].wlseg != NULL);
862 buckets[ds_commit_idx].wlseg = pnfs_get_lseg(lseg);
863 }
864 set_bit(PG_COMMIT_TO_DS, &req->wb_flags);
865 cinfo->ds->nwritten++;
866 spin_unlock(cinfo->lock);
867
868 nfs_request_add_commit_list(req, list, cinfo);
869}
870EXPORT_SYMBOL_GPL(pnfs_layout_mark_request_commit);
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 88a6d2196ece..595d81e354d1 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -789,13 +789,8 @@ nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst,
789 nfs_list_add_request(req, dst); 789 nfs_list_add_request(req, dst);
790 cinfo->mds->ncommit++; 790 cinfo->mds->ncommit++;
791 spin_unlock(cinfo->lock); 791 spin_unlock(cinfo->lock);
792 if (!cinfo->dreq) { 792 if (!cinfo->dreq)
793 inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); 793 nfs_mark_page_unstable(req->wb_page);
794 inc_bdi_stat(inode_to_bdi(page_file_mapping(req->wb_page)->host),
795 BDI_RECLAIMABLE);
796 __mark_inode_dirty(req->wb_context->dentry->d_inode,
797 I_DIRTY_DATASYNC);
798 }
799} 794}
800EXPORT_SYMBOL_GPL(nfs_request_add_commit_list); 795EXPORT_SYMBOL_GPL(nfs_request_add_commit_list);
801 796
@@ -1605,11 +1600,8 @@ void nfs_retry_commit(struct list_head *page_list,
1605 req = nfs_list_entry(page_list->next); 1600 req = nfs_list_entry(page_list->next);
1606 nfs_list_remove_request(req); 1601 nfs_list_remove_request(req);
1607 nfs_mark_request_commit(req, lseg, cinfo, ds_commit_idx); 1602 nfs_mark_request_commit(req, lseg, cinfo, ds_commit_idx);
1608 if (!cinfo->dreq) { 1603 if (!cinfo->dreq)
1609 dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); 1604 nfs_clear_page_commit(req->wb_page);
1610 dec_bdi_stat(inode_to_bdi(page_file_mapping(req->wb_page)->host),
1611 BDI_RECLAIMABLE);
1612 }
1613 nfs_unlock_and_release_request(req); 1605 nfs_unlock_and_release_request(req);
1614 } 1606 }
1615} 1607}
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 6d627b92df53..2f77e0c651c8 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -180,7 +180,6 @@ struct nfs_inode {
180 /* NFSv4 state */ 180 /* NFSv4 state */
181 struct list_head open_states; 181 struct list_head open_states;
182 struct nfs_delegation __rcu *delegation; 182 struct nfs_delegation __rcu *delegation;
183 fmode_t delegation_state;
184 struct rw_semaphore rwsem; 183 struct rw_semaphore rwsem;
185 184
186 /* pNFS layout information */ 185 /* pNFS layout information */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 38d96ba935c2..4cb3eaa89cf7 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1167,8 +1167,15 @@ struct nfs41_impl_id {
1167 struct nfstime4 date; 1167 struct nfstime4 date;
1168}; 1168};
1169 1169
1170struct nfs41_bind_conn_to_session_args {
1171 struct nfs_client *client;
1172 struct nfs4_sessionid sessionid;
1173 u32 dir;
1174 bool use_conn_in_rdma_mode;
1175};
1176
1170struct nfs41_bind_conn_to_session_res { 1177struct nfs41_bind_conn_to_session_res {
1171 struct nfs4_session *session; 1178 struct nfs4_sessionid sessionid;
1172 u32 dir; 1179 u32 dir;
1173 bool use_conn_in_rdma_mode; 1180 bool use_conn_in_rdma_mode;
1174}; 1181};
@@ -1185,6 +1192,8 @@ struct nfs41_exchange_id_res {
1185 1192
1186struct nfs41_create_session_args { 1193struct nfs41_create_session_args {
1187 struct nfs_client *client; 1194 struct nfs_client *client;
1195 u64 clientid;
1196 uint32_t seqid;
1188 uint32_t flags; 1197 uint32_t flags;
1189 uint32_t cb_program; 1198 uint32_t cb_program;
1190 struct nfs4_channel_attrs fc_attrs; /* Fore Channel */ 1199 struct nfs4_channel_attrs fc_attrs; /* Fore Channel */
@@ -1192,7 +1201,11 @@ struct nfs41_create_session_args {
1192}; 1201};
1193 1202
1194struct nfs41_create_session_res { 1203struct nfs41_create_session_res {
1195 struct nfs_client *client; 1204 struct nfs4_sessionid sessionid;
1205 uint32_t seqid;
1206 uint32_t flags;
1207 struct nfs4_channel_attrs fc_attrs; /* Fore Channel */
1208 struct nfs4_channel_attrs bc_attrs; /* Back Channel */
1196}; 1209};
1197 1210
1198struct nfs41_reclaim_complete_args { 1211struct nfs41_reclaim_complete_args {
@@ -1351,7 +1364,7 @@ struct nfs_commit_completion_ops {
1351}; 1364};
1352 1365
1353struct nfs_commit_info { 1366struct nfs_commit_info {
1354 spinlock_t *lock; 1367 spinlock_t *lock; /* inode->i_lock */
1355 struct nfs_mds_commit_info *mds; 1368 struct nfs_mds_commit_info *mds;
1356 struct pnfs_ds_commit_info *ds; 1369 struct pnfs_ds_commit_info *ds;
1357 struct nfs_direct_req *dreq; /* O_DIRECT request */ 1370 struct nfs_direct_req *dreq; /* O_DIRECT request */
diff --git a/include/linux/sunrpc/metrics.h b/include/linux/sunrpc/metrics.h
index 7e61a17030a4..694eecb2f1b5 100644
--- a/include/linux/sunrpc/metrics.h
+++ b/include/linux/sunrpc/metrics.h
@@ -89,8 +89,11 @@ void rpc_free_iostats(struct rpc_iostats *);
89static inline struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt) { return NULL; } 89static inline struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt) { return NULL; }
90static inline void rpc_count_iostats(const struct rpc_task *task, 90static inline void rpc_count_iostats(const struct rpc_task *task,
91 struct rpc_iostats *stats) {} 91 struct rpc_iostats *stats) {}
92static inline void rpc_count_iostats_metrics(const struct rpc_task *, 92static inline void rpc_count_iostats_metrics(const struct rpc_task *task,
93 struct rpc_iostats *) {} 93 struct rpc_iostats *stats)
94{
95}
96
94static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {} 97static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {}
95static inline void rpc_free_iostats(struct rpc_iostats *stats) {} 98static inline void rpc_free_iostats(struct rpc_iostats *stats) {}
96 99
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c
index 651f49ab601f..9dd0ea8db463 100644
--- a/net/sunrpc/backchannel_rqst.c
+++ b/net/sunrpc/backchannel_rqst.c
@@ -309,12 +309,15 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied)
309 struct rpc_xprt *xprt = req->rq_xprt; 309 struct rpc_xprt *xprt = req->rq_xprt;
310 struct svc_serv *bc_serv = xprt->bc_serv; 310 struct svc_serv *bc_serv = xprt->bc_serv;
311 311
312 spin_lock(&xprt->bc_pa_lock);
313 list_del(&req->rq_bc_pa_list);
314 spin_unlock(&xprt->bc_pa_lock);
315
312 req->rq_private_buf.len = copied; 316 req->rq_private_buf.len = copied;
313 set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); 317 set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
314 318
315 dprintk("RPC: add callback request to list\n"); 319 dprintk("RPC: add callback request to list\n");
316 spin_lock(&bc_serv->sv_cb_lock); 320 spin_lock(&bc_serv->sv_cb_lock);
317 list_del(&req->rq_bc_pa_list);
318 list_add(&req->rq_bc_list, &bc_serv->sv_cb_list); 321 list_add(&req->rq_bc_list, &bc_serv->sv_cb_list);
319 wake_up(&bc_serv->sv_cb_waitq); 322 wake_up(&bc_serv->sv_cb_waitq);
320 spin_unlock(&bc_serv->sv_cb_lock); 323 spin_unlock(&bc_serv->sv_cb_lock);