Commit 24a52e412ef22989b63c35428652598dc995812c
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
Merge tag 'nfs-for-3.20-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull more NFS client updates from Trond Myklebust: "Highlights include: - Fix a use-after-free in decode_cb_sequence_args() - Fix a compile error when #undef CONFIG_PROC_FS - NFSv4.1 backchannel spinlocking issue - Cleanups in the NFS unstable write code requested by Linus - NFSv4.1 fix issues when the server denies our backchannel request - Cleanups in create_session and bind_conn_to_session" * tag 'nfs-for-3.20-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFSv4.1: Clean up bind_conn_to_session NFSv4.1: Always set up a forward channel when binding the session NFSv4.1: Don't set up a backchannel if the server didn't agree to do so NFSv4.1: Clean up create_session pnfs: Refactor the *_layout_mark_request_commit to use pnfs_layout_mark_request_commit NFSv4: Kill unused nfs_inode->delegation_state field NFS: struct nfs_commit_info.lock must always point to inode->i_lock nfs: Can call nfs_clear_page_commit() instead nfs: Provide and use helper functions for marking a page as unstable SUNRPC: Always manipulate rpc_rqst::rq_bc_pa_list under xprt->bc_pa_lock SUNRPC: Fix a compile error when #undef CONFIG_PROC_FS NFSv4.1: Convert open-coded array allocation calls to kmalloc_array() NFSv4.1: Fix a kfree() of uninitialised pointers in decode_cb_sequence_args
Showing 19 changed files Side-by-side Diff
- fs/nfs/callback_proc.c
- fs/nfs/callback_xdr.c
- fs/nfs/delegation.c
- fs/nfs/direct.c
- fs/nfs/filelayout/filelayout.c
- fs/nfs/flexfilelayout/flexfilelayout.c
- fs/nfs/inode.c
- fs/nfs/internal.h
- fs/nfs/nfs4proc.c
- fs/nfs/nfs4session.c
- fs/nfs/nfs4session.h
- fs/nfs/nfs4xdr.c
- fs/nfs/pnfs.h
- fs/nfs/pnfs_nfs.c
- fs/nfs/write.c
- include/linux/nfs_fs.h
- include/linux/nfs_xdr.h
- include/linux/sunrpc/metrics.h
- net/sunrpc/backchannel_rqst.c
fs/nfs/callback_proc.c
fs/nfs/callback_xdr.c
... | ... | @@ -313,7 +313,7 @@ |
313 | 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 | 317 | if (!args->devs) { |
318 | 318 | status = htonl(NFS4ERR_DELAY); |
319 | 319 | goto out; |
... | ... | @@ -415,7 +415,7 @@ |
415 | 415 | rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t)); |
416 | 416 | if (unlikely(p == NULL)) |
417 | 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 | 419 | sizeof(*rc_list->rcl_refcalls), |
420 | 420 | GFP_KERNEL); |
421 | 421 | if (unlikely(rc_list->rcl_refcalls == NULL)) |
422 | 422 | |
... | ... | @@ -464,8 +464,10 @@ |
464 | 464 | |
465 | 465 | for (i = 0; i < args->csa_nrclists; i++) { |
466 | 466 | status = decode_rc_list(xdr, &args->csa_rclists[i]); |
467 | - if (status) | |
467 | + if (status) { | |
468 | + args->csa_nrclists = i; | |
468 | 469 | goto out_free; |
470 | + } | |
469 | 471 | } |
470 | 472 | } |
471 | 473 | status = 0; |
fs/nfs/delegation.c
... | ... | @@ -180,7 +180,6 @@ |
180 | 180 | delegation->cred = get_rpccred(cred); |
181 | 181 | clear_bit(NFS_DELEGATION_NEED_RECLAIM, |
182 | 182 | &delegation->flags); |
183 | - NFS_I(inode)->delegation_state = delegation->type; | |
184 | 183 | spin_unlock(&delegation->lock); |
185 | 184 | put_rpccred(oldcred); |
186 | 185 | rcu_read_unlock(); |
... | ... | @@ -275,7 +274,6 @@ |
275 | 274 | set_bit(NFS_DELEGATION_RETURNING, &delegation->flags); |
276 | 275 | list_del_rcu(&delegation->super_list); |
277 | 276 | delegation->inode = NULL; |
278 | - nfsi->delegation_state = 0; | |
279 | 277 | rcu_assign_pointer(nfsi->delegation, NULL); |
280 | 278 | spin_unlock(&delegation->lock); |
281 | 279 | return delegation; |
... | ... | @@ -355,7 +353,6 @@ |
355 | 353 | &delegation->stateid)) { |
356 | 354 | nfs_update_inplace_delegation(old_delegation, |
357 | 355 | delegation); |
358 | - nfsi->delegation_state = old_delegation->type; | |
359 | 356 | goto out; |
360 | 357 | } |
361 | 358 | /* |
... | ... | @@ -379,7 +376,6 @@ |
379 | 376 | goto out; |
380 | 377 | } |
381 | 378 | list_add_rcu(&delegation->super_list, &server->delegations); |
382 | - nfsi->delegation_state = delegation->type; | |
383 | 379 | rcu_assign_pointer(nfsi->delegation, delegation); |
384 | 380 | delegation = NULL; |
385 | 381 |
fs/nfs/direct.c
... | ... | @@ -283,7 +283,7 @@ |
283 | 283 | void nfs_init_cinfo_from_dreq(struct nfs_commit_info *cinfo, |
284 | 284 | struct nfs_direct_req *dreq) |
285 | 285 | { |
286 | - cinfo->lock = &dreq->lock; | |
286 | + cinfo->lock = &dreq->inode->i_lock; | |
287 | 287 | cinfo->mds = &dreq->mds_cinfo; |
288 | 288 | cinfo->ds = &dreq->ds_cinfo; |
289 | 289 | cinfo->dreq = dreq; |
fs/nfs/filelayout/filelayout.c
... | ... | @@ -960,52 +960,19 @@ |
960 | 960 | { |
961 | 961 | struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); |
962 | 962 | u32 i, j; |
963 | - struct list_head *list; | |
964 | - struct pnfs_commit_bucket *buckets; | |
965 | 963 | |
966 | 964 | if (fl->commit_through_mds) { |
967 | - list = &cinfo->mds->list; | |
968 | - spin_lock(cinfo->lock); | |
969 | - goto mds_commit; | |
970 | - } | |
971 | - | |
972 | - /* Note that we are calling nfs4_fl_calc_j_index on each page | |
973 | - * that ends up being committed to a data server. An attractive | |
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 | |
965 | + nfs_request_add_commit_list(req, &cinfo->mds->list, cinfo); | |
966 | + } else { | |
967 | + /* Note that we are calling nfs4_fl_calc_j_index on each page | |
968 | + * that ends up being committed to a data server. An attractive | |
969 | + * alternative is to add a field to nfs_write_data and nfs_page | |
970 | + * to store the value calculated in filelayout_write_pagelist | |
971 | + * and just use that here. | |
989 | 972 | */ |
990 | - buckets[i].wlseg = pnfs_get_lseg(lseg); | |
991 | - } | |
992 | - set_bit(PG_COMMIT_TO_DS, &req->wb_flags); | |
993 | - cinfo->ds->nwritten++; | |
994 | - | |
995 | -mds_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); | |
973 | + j = nfs4_fl_calc_j_index(lseg, req_offset(req)); | |
974 | + i = select_bucket_index(fl, j); | |
975 | + pnfs_layout_mark_request_commit(req, lseg, cinfo, i); | |
1009 | 976 | } |
1010 | 977 | } |
1011 | 978 |
fs/nfs/flexfilelayout/flexfilelayout.c
... | ... | @@ -1332,47 +1332,6 @@ |
1332 | 1332 | return PNFS_ATTEMPTED; |
1333 | 1333 | } |
1334 | 1334 | |
1335 | -static void | |
1336 | -ff_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 | - | |
1376 | 1335 | static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i) |
1377 | 1336 | { |
1378 | 1337 | return i; |
... | ... | @@ -1540,7 +1499,7 @@ |
1540 | 1499 | .pg_write_ops = &ff_layout_pg_write_ops, |
1541 | 1500 | .get_ds_info = ff_layout_get_ds_info, |
1542 | 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 | 1503 | .clear_request_commit = pnfs_generic_clear_request_commit, |
1545 | 1504 | .scan_commit_lists = pnfs_generic_scan_commit_lists, |
1546 | 1505 | .recover_commit_reqs = pnfs_generic_recover_commit_reqs, |
fs/nfs/inode.c
fs/nfs/internal.h
... | ... | @@ -598,6 +598,19 @@ |
598 | 598 | } |
599 | 599 | |
600 | 600 | /* |
601 | + * Record the page as unstable and mark its inode as dirty. | |
602 | + */ | |
603 | +static inline | |
604 | +void 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 | 614 | * Determine the number of bytes of data the page contains |
602 | 615 | */ |
603 | 616 | static inline |
fs/nfs/nfs4proc.c
... | ... | @@ -6648,47 +6648,47 @@ |
6648 | 6648 | int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred) |
6649 | 6649 | { |
6650 | 6650 | int status; |
6651 | + struct nfs41_bind_conn_to_session_args args = { | |
6652 | + .client = clp, | |
6653 | + .dir = NFS4_CDFC4_FORE_OR_BOTH, | |
6654 | + }; | |
6651 | 6655 | struct nfs41_bind_conn_to_session_res res; |
6652 | 6656 | struct rpc_message msg = { |
6653 | 6657 | .rpc_proc = |
6654 | 6658 | &nfs4_procedures[NFSPROC4_CLNT_BIND_CONN_TO_SESSION], |
6655 | - .rpc_argp = clp, | |
6659 | + .rpc_argp = &args, | |
6656 | 6660 | .rpc_resp = &res, |
6657 | 6661 | .rpc_cred = cred, |
6658 | 6662 | }; |
6659 | 6663 | |
6660 | 6664 | dprintk("--> %s\n", __func__); |
6661 | 6665 | |
6662 | - res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); | |
6663 | - if (unlikely(res.session == NULL)) { | |
6664 | - status = -ENOMEM; | |
6665 | - goto out; | |
6666 | - } | |
6666 | + nfs4_copy_sessionid(&args.sessionid, &clp->cl_session->sess_id); | |
6667 | + if (!(clp->cl_session->flags & SESSION4_BACK_CHAN)) | |
6668 | + args.dir = NFS4_CDFC4_FORE; | |
6667 | 6669 | |
6668 | 6670 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
6669 | 6671 | trace_nfs4_bind_conn_to_session(clp, status); |
6670 | 6672 | if (status == 0) { |
6671 | - if (memcmp(res.session->sess_id.data, | |
6673 | + if (memcmp(res.sessionid.data, | |
6672 | 6674 | clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) { |
6673 | 6675 | dprintk("NFS: %s: Session ID mismatch\n", __func__); |
6674 | 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 | 6680 | dprintk("NFS: %s: Unexpected direction from server\n", |
6679 | 6681 | __func__); |
6680 | 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 | 6686 | dprintk("NFS: %s: Server returned RDMA mode = true\n", |
6685 | 6687 | __func__); |
6686 | 6688 | status = -EIO; |
6687 | - goto out_session; | |
6689 | + goto out; | |
6688 | 6690 | } |
6689 | 6691 | } |
6690 | -out_session: | |
6691 | - kfree(res.session); | |
6692 | 6692 | out: |
6693 | 6693 | dprintk("<-- %s status= %d\n", __func__, status); |
6694 | 6694 | return status; |
6695 | 6695 | |
... | ... | @@ -7166,10 +7166,11 @@ |
7166 | 7166 | args->bc_attrs.max_reqs); |
7167 | 7167 | } |
7168 | 7168 | |
7169 | -static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session) | |
7169 | +static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args, | |
7170 | + struct nfs41_create_session_res *res) | |
7170 | 7171 | { |
7171 | 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 | 7175 | if (rcvd->max_resp_sz > sent->max_resp_sz) |
7175 | 7176 | return -EINVAL; |
7176 | 7177 | |
7177 | 7178 | |
... | ... | @@ -7188,11 +7189,14 @@ |
7188 | 7189 | return 0; |
7189 | 7190 | } |
7190 | 7191 | |
7191 | -static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session) | |
7192 | +static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args, | |
7193 | + struct nfs41_create_session_res *res) | |
7192 | 7194 | { |
7193 | 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 | 7200 | if (rcvd->max_rqst_sz > sent->max_rqst_sz) |
7197 | 7201 | return -EINVAL; |
7198 | 7202 | if (rcvd->max_resp_sz < sent->max_resp_sz) |
7199 | 7203 | |
7200 | 7204 | |
7201 | 7205 | |
7202 | 7206 | |
7203 | 7207 | |
7204 | 7208 | |
... | ... | @@ -7204,31 +7208,44 @@ |
7204 | 7208 | return -EINVAL; |
7205 | 7209 | if (rcvd->max_reqs != sent->max_reqs) |
7206 | 7210 | return -EINVAL; |
7211 | +out: | |
7207 | 7212 | return 0; |
7208 | 7213 | } |
7209 | 7214 | |
7210 | 7215 | static 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 | 7218 | int ret; |
7214 | 7219 | |
7215 | - ret = nfs4_verify_fore_channel_attrs(args, session); | |
7220 | + ret = nfs4_verify_fore_channel_attrs(args, res); | |
7216 | 7221 | if (ret) |
7217 | 7222 | return ret; |
7218 | - return nfs4_verify_back_channel_attrs(args, session); | |
7223 | + return nfs4_verify_back_channel_attrs(args, res); | |
7219 | 7224 | } |
7220 | 7225 | |
7226 | +static 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)); | |
7235 | +} | |
7236 | + | |
7221 | 7237 | static int _nfs4_proc_create_session(struct nfs_client *clp, |
7222 | 7238 | struct rpc_cred *cred) |
7223 | 7239 | { |
7224 | 7240 | struct nfs4_session *session = clp->cl_session; |
7225 | 7241 | struct nfs41_create_session_args args = { |
7226 | 7242 | .client = clp, |
7243 | + .clientid = clp->cl_clientid, | |
7244 | + .seqid = clp->cl_seqid, | |
7227 | 7245 | .cb_program = NFS4_CALLBACK, |
7228 | 7246 | }; |
7229 | - struct nfs41_create_session_res res = { | |
7230 | - .client = clp, | |
7231 | - }; | |
7247 | + struct nfs41_create_session_res res; | |
7248 | + | |
7232 | 7249 | struct rpc_message msg = { |
7233 | 7250 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION], |
7234 | 7251 | .rpc_argp = &args, |
7235 | 7252 | |
7236 | 7253 | |
... | ... | @@ -7245,11 +7262,15 @@ |
7245 | 7262 | |
7246 | 7263 | if (!status) { |
7247 | 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 | 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 | - | |
7273 | +out: | |
7253 | 7274 | return status; |
7254 | 7275 | } |
7255 | 7276 |
fs/nfs/nfs4session.c
... | ... | @@ -450,7 +450,7 @@ |
450 | 450 | tbl = &ses->fc_slot_table; |
451 | 451 | tbl->session = ses; |
452 | 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 | 454 | return status; |
455 | 455 | /* Back channel */ |
456 | 456 | tbl = &ses->bc_slot_table; |
fs/nfs/nfs4session.h
... | ... | @@ -118,6 +118,12 @@ |
118 | 118 | return 0; |
119 | 119 | } |
120 | 120 | |
121 | +static 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 | 127 | #ifdef CONFIG_CRC32 |
122 | 128 | /* |
123 | 129 | * nfs_session_id_hash - calculate the crc32 hash for the session id |
fs/nfs/nfs4xdr.c
... | ... | @@ -1715,17 +1715,17 @@ |
1715 | 1715 | #if defined(CONFIG_NFS_V4_1) |
1716 | 1716 | /* NFSv4.1 operations */ |
1717 | 1717 | static 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 | 1719 | struct compound_hdr *hdr) |
1720 | 1720 | { |
1721 | 1721 | __be32 *p; |
1722 | 1722 | |
1723 | 1723 | encode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION, |
1724 | 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 | 1726 | p = xdr_reserve_space(xdr, 8); |
1727 | - *p++ = cpu_to_be32(NFS4_CDFC4_BACK_OR_BOTH); | |
1728 | - *p = 0; /* use_conn_in_rdma_mode = False */ | |
1727 | + *p++ = cpu_to_be32(args->dir); | |
1728 | + *p = (args->use_conn_in_rdma_mode) ? cpu_to_be32(1) : cpu_to_be32(0); | |
1729 | 1729 | } |
1730 | 1730 | |
1731 | 1731 | static void encode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map) |
... | ... | @@ -1806,8 +1806,8 @@ |
1806 | 1806 | |
1807 | 1807 | encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr); |
1808 | 1808 | p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12); |
1809 | - p = xdr_encode_hyper(p, clp->cl_clientid); | |
1810 | - *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */ | |
1809 | + p = xdr_encode_hyper(p, args->clientid); | |
1810 | + *p++ = cpu_to_be32(args->seqid); /*Sequence id */ | |
1811 | 1811 | *p++ = cpu_to_be32(args->flags); /*flags */ |
1812 | 1812 | |
1813 | 1813 | /* Fore Channel */ |
1814 | 1814 | |
1815 | 1815 | |
... | ... | @@ -2734,14 +2734,14 @@ |
2734 | 2734 | */ |
2735 | 2735 | static void nfs4_xdr_enc_bind_conn_to_session(struct rpc_rqst *req, |
2736 | 2736 | struct xdr_stream *xdr, |
2737 | - struct nfs_client *clp) | |
2737 | + struct nfs41_bind_conn_to_session_args *args) | |
2738 | 2738 | { |
2739 | 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 | 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 | 2745 | encode_nops(&hdr); |
2746 | 2746 | } |
2747 | 2747 | |
... | ... | @@ -5613,7 +5613,7 @@ |
5613 | 5613 | |
5614 | 5614 | status = decode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION); |
5615 | 5615 | if (!status) |
5616 | - status = decode_sessionid(xdr, &res->session->sess_id); | |
5616 | + status = decode_sessionid(xdr, &res->sessionid); | |
5617 | 5617 | if (unlikely(status)) |
5618 | 5618 | return status; |
5619 | 5619 | |
5620 | 5620 | |
... | ... | @@ -5641,12 +5641,10 @@ |
5641 | 5641 | { |
5642 | 5642 | __be32 *p; |
5643 | 5643 | int status; |
5644 | - struct nfs_client *clp = res->client; | |
5645 | - struct nfs4_session *session = clp->cl_session; | |
5646 | 5644 | |
5647 | 5645 | status = decode_op_hdr(xdr, OP_CREATE_SESSION); |
5648 | 5646 | if (!status) |
5649 | - status = decode_sessionid(xdr, &session->sess_id); | |
5647 | + status = decode_sessionid(xdr, &res->sessionid); | |
5650 | 5648 | if (unlikely(status)) |
5651 | 5649 | return status; |
5652 | 5650 | |
5653 | 5651 | |
5654 | 5652 | |
... | ... | @@ -5654,13 +5652,13 @@ |
5654 | 5652 | p = xdr_inline_decode(xdr, 8); |
5655 | 5653 | if (unlikely(!p)) |
5656 | 5654 | goto out_overflow; |
5657 | - clp->cl_seqid = be32_to_cpup(p++); | |
5658 | - session->flags = be32_to_cpup(p); | |
5655 | + res->seqid = be32_to_cpup(p++); | |
5656 | + res->flags = be32_to_cpup(p); | |
5659 | 5657 | |
5660 | 5658 | /* Channel attributes */ |
5661 | - status = decode_chan_attrs(xdr, &session->fc_attrs); | |
5659 | + status = decode_chan_attrs(xdr, &res->fc_attrs); | |
5662 | 5660 | if (!status) |
5663 | - status = decode_chan_attrs(xdr, &session->bc_attrs); | |
5661 | + status = decode_chan_attrs(xdr, &res->bc_attrs); | |
5664 | 5662 | return status; |
5665 | 5663 | out_overflow: |
5666 | 5664 | print_overflow_msg(__func__, xdr); |
fs/nfs/pnfs.h
... | ... | @@ -344,6 +344,10 @@ |
344 | 344 | struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net, |
345 | 345 | struct xdr_stream *xdr, |
346 | 346 | gfp_t gfp_flags); |
347 | +void 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 | |
348 | 352 | static inline bool nfs_have_layout(struct inode *inode) |
349 | 353 | { |
fs/nfs/pnfs_nfs.c
... | ... | @@ -838,4 +838,34 @@ |
838 | 838 | return NULL; |
839 | 839 | } |
840 | 840 | EXPORT_SYMBOL_GPL(nfs4_decode_mp_ds_addr); |
841 | + | |
842 | +void | |
843 | +pnfs_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 | +} | |
870 | +EXPORT_SYMBOL_GPL(pnfs_layout_mark_request_commit); |
fs/nfs/write.c
... | ... | @@ -789,13 +789,8 @@ |
789 | 789 | nfs_list_add_request(req, dst); |
790 | 790 | cinfo->mds->ncommit++; |
791 | 791 | spin_unlock(cinfo->lock); |
792 | - if (!cinfo->dreq) { | |
793 | - inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | |
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 | - } | |
792 | + if (!cinfo->dreq) | |
793 | + nfs_mark_page_unstable(req->wb_page); | |
799 | 794 | } |
800 | 795 | EXPORT_SYMBOL_GPL(nfs_request_add_commit_list); |
801 | 796 | |
... | ... | @@ -1605,11 +1600,8 @@ |
1605 | 1600 | req = nfs_list_entry(page_list->next); |
1606 | 1601 | nfs_list_remove_request(req); |
1607 | 1602 | nfs_mark_request_commit(req, lseg, cinfo, ds_commit_idx); |
1608 | - if (!cinfo->dreq) { | |
1609 | - dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | |
1610 | - dec_bdi_stat(inode_to_bdi(page_file_mapping(req->wb_page)->host), | |
1611 | - BDI_RECLAIMABLE); | |
1612 | - } | |
1603 | + if (!cinfo->dreq) | |
1604 | + nfs_clear_page_commit(req->wb_page); | |
1613 | 1605 | nfs_unlock_and_release_request(req); |
1614 | 1606 | } |
1615 | 1607 | } |
include/linux/nfs_fs.h
include/linux/nfs_xdr.h
... | ... | @@ -1167,8 +1167,15 @@ |
1167 | 1167 | struct nfstime4 date; |
1168 | 1168 | }; |
1169 | 1169 | |
1170 | +struct 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 | + | |
1170 | 1177 | struct nfs41_bind_conn_to_session_res { |
1171 | - struct nfs4_session *session; | |
1178 | + struct nfs4_sessionid sessionid; | |
1172 | 1179 | u32 dir; |
1173 | 1180 | bool use_conn_in_rdma_mode; |
1174 | 1181 | }; |
... | ... | @@ -1185,6 +1192,8 @@ |
1185 | 1192 | |
1186 | 1193 | struct nfs41_create_session_args { |
1187 | 1194 | struct nfs_client *client; |
1195 | + u64 clientid; | |
1196 | + uint32_t seqid; | |
1188 | 1197 | uint32_t flags; |
1189 | 1198 | uint32_t cb_program; |
1190 | 1199 | struct nfs4_channel_attrs fc_attrs; /* Fore Channel */ |
... | ... | @@ -1192,7 +1201,11 @@ |
1192 | 1201 | }; |
1193 | 1202 | |
1194 | 1203 | struct 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 | |
1198 | 1211 | struct nfs41_reclaim_complete_args { |
... | ... | @@ -1351,7 +1364,7 @@ |
1351 | 1364 | }; |
1352 | 1365 | |
1353 | 1366 | struct nfs_commit_info { |
1354 | - spinlock_t *lock; | |
1367 | + spinlock_t *lock; /* inode->i_lock */ | |
1355 | 1368 | struct nfs_mds_commit_info *mds; |
1356 | 1369 | struct pnfs_ds_commit_info *ds; |
1357 | 1370 | struct nfs_direct_req *dreq; /* O_DIRECT request */ |
include/linux/sunrpc/metrics.h
... | ... | @@ -89,8 +89,11 @@ |
89 | 89 | static inline struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt) { return NULL; } |
90 | 90 | static inline void rpc_count_iostats(const struct rpc_task *task, |
91 | 91 | struct rpc_iostats *stats) {} |
92 | -static inline void rpc_count_iostats_metrics(const struct rpc_task *, | |
93 | - struct rpc_iostats *) {} | |
92 | +static inline void rpc_count_iostats_metrics(const struct rpc_task *task, | |
93 | + struct rpc_iostats *stats) | |
94 | +{ | |
95 | +} | |
96 | + | |
94 | 97 | static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {} |
95 | 98 | static inline void rpc_free_iostats(struct rpc_iostats *stats) {} |
96 | 99 |
net/sunrpc/backchannel_rqst.c
... | ... | @@ -309,12 +309,15 @@ |
309 | 309 | struct rpc_xprt *xprt = req->rq_xprt; |
310 | 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 | 316 | req->rq_private_buf.len = copied; |
313 | 317 | set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); |
314 | 318 | |
315 | 319 | dprintk("RPC: add callback request to list\n"); |
316 | 320 | spin_lock(&bc_serv->sv_cb_lock); |
317 | - list_del(&req->rq_bc_pa_list); | |
318 | 321 | list_add(&req->rq_bc_list, &bc_serv->sv_cb_list); |
319 | 322 | wake_up(&bc_serv->sv_cb_waitq); |
320 | 323 | spin_unlock(&bc_serv->sv_cb_lock); |