Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

NFSv4: Don't free slots prematurely if requesting a directory delegation

When requesting a directory delegation, it is imperative to hold the
slot until the delegation state has been recorded. Otherwise, if a
recall comes in, the call to referring_call_exists() will assume the
processing is done, and when it doesn't find a delegation, it will
assume it has been returned.

Fixes: 156b09482933 ("NFS: Request a directory delegation on ACCESS, CREATE, and UNLINK")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>

+39 -8
+39 -8
fs/nfs/nfs4proc.c
··· 4494 4494 } 4495 4495 #endif /* CONFIG_NFS_V4_1 */ 4496 4496 4497 + static void nfs4_call_getattr_prepare(struct rpc_task *task, void *calldata) 4498 + { 4499 + struct nfs4_call_sync_data *data = calldata; 4500 + nfs4_setup_sequence(data->seq_server->nfs_client, data->seq_args, 4501 + data->seq_res, task); 4502 + } 4503 + 4504 + static void nfs4_call_getattr_done(struct rpc_task *task, void *calldata) 4505 + { 4506 + struct nfs4_call_sync_data *data = calldata; 4507 + 4508 + nfs4_sequence_process(task, data->seq_res); 4509 + } 4510 + 4511 + static const struct rpc_call_ops nfs4_call_getattr_ops = { 4512 + .rpc_call_prepare = nfs4_call_getattr_prepare, 4513 + .rpc_call_done = nfs4_call_getattr_done, 4514 + }; 4515 + 4497 4516 static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, 4498 4517 struct nfs_fattr *fattr, struct inode *inode) 4499 4518 { ··· 4530 4511 .rpc_argp = &args, 4531 4512 .rpc_resp = &res, 4532 4513 }; 4514 + struct nfs4_call_sync_data data = { 4515 + .seq_server = server, 4516 + .seq_args = &args.seq_args, 4517 + .seq_res = &res.seq_res, 4518 + }; 4519 + struct rpc_task_setup task_setup = { 4520 + .rpc_client = server->client, 4521 + .rpc_message = &msg, 4522 + .callback_ops = &nfs4_call_getattr_ops, 4523 + .callback_data = &data, 4524 + }; 4533 4525 struct nfs4_gdd_res gdd_res; 4534 - unsigned short task_flags = 0; 4535 4526 int status; 4536 4527 4537 4528 if (nfs4_has_session(server->nfs_client)) 4538 - task_flags = RPC_TASK_MOVEABLE; 4529 + task_setup.flags = RPC_TASK_MOVEABLE; 4539 4530 4540 4531 /* Is this is an attribute revalidation, subject to softreval? */ 4541 4532 if (inode && (server->flags & NFS_MOUNT_SOFTREVAL)) 4542 - task_flags |= RPC_TASK_TIMEOUT; 4533 + task_setup.flags |= RPC_TASK_TIMEOUT; 4543 4534 4544 4535 args.get_dir_deleg = should_request_dir_deleg(inode); 4545 4536 if (args.get_dir_deleg) ··· 4559 4530 nfs_fattr_init(fattr); 4560 4531 nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 0); 4561 4532 4562 - status = nfs4_do_call_sync(server->client, server, &msg, 4563 - &args.seq_args, &res.seq_res, task_flags); 4533 + status = nfs4_call_sync_custom(&task_setup); 4534 + 4564 4535 if (args.get_dir_deleg) { 4565 4536 switch (status) { 4566 4537 case 0: 4567 4538 if (gdd_res.status != GDD4_OK) 4568 4539 break; 4569 - status = nfs_inode_set_delegation( 4570 - inode, current_cred(), FMODE_READ, 4571 - &gdd_res.deleg, 0, NFS4_OPEN_DELEGATE_READ); 4540 + nfs_inode_set_delegation(inode, current_cred(), 4541 + FMODE_READ, &gdd_res.deleg, 0, 4542 + NFS4_OPEN_DELEGATE_READ); 4572 4543 break; 4573 4544 case -ENOTSUPP: 4574 4545 case -EOPNOTSUPP: 4575 4546 server->caps &= ~NFS_CAP_DIR_DELEG; 4576 4547 } 4577 4548 } 4549 + 4550 + nfs4_sequence_free_slot(&res.seq_res); 4578 4551 return status; 4579 4552 } 4580 4553