Skip to content

Commit 81770f4

Browse files
committed
Merge tag 'nfs-for-3.17-5' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client fixes from Trond Myklebust: "Highligts: - fix an Oops in nfs4_open_and_get_state - fix an Oops in the nfs4_state_manager - fix another bug in the close/open_downgrade code" * tag 'nfs-for-3.17-5' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFSv4: Fix another bug in the close/open_downgrade code NFSv4: nfs4_state_manager() vs. nfs_server_remove_lists() NFS: remove BUG possibility in nfs4_open_and_get_state
2 parents b29f83a + cd9288f commit 81770f4

File tree

2 files changed

+42
-36
lines changed

2 files changed

+42
-36
lines changed

fs/nfs/nfs4client.c

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,16 @@ int nfs40_walk_client_list(struct nfs_client *new,
482482

483483
spin_lock(&nn->nfs_client_lock);
484484
list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
485+
486+
if (pos->rpc_ops != new->rpc_ops)
487+
continue;
488+
489+
if (pos->cl_proto != new->cl_proto)
490+
continue;
491+
492+
if (pos->cl_minorversion != new->cl_minorversion)
493+
continue;
494+
485495
/* If "pos" isn't marked ready, we can't trust the
486496
* remaining fields in "pos" */
487497
if (pos->cl_cons_state > NFS_CS_READY) {
@@ -501,15 +511,6 @@ int nfs40_walk_client_list(struct nfs_client *new,
501511
if (pos->cl_cons_state != NFS_CS_READY)
502512
continue;
503513

504-
if (pos->rpc_ops != new->rpc_ops)
505-
continue;
506-
507-
if (pos->cl_proto != new->cl_proto)
508-
continue;
509-
510-
if (pos->cl_minorversion != new->cl_minorversion)
511-
continue;
512-
513514
if (pos->cl_clientid != new->cl_clientid)
514515
continue;
515516

@@ -622,6 +623,16 @@ int nfs41_walk_client_list(struct nfs_client *new,
622623

623624
spin_lock(&nn->nfs_client_lock);
624625
list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
626+
627+
if (pos->rpc_ops != new->rpc_ops)
628+
continue;
629+
630+
if (pos->cl_proto != new->cl_proto)
631+
continue;
632+
633+
if (pos->cl_minorversion != new->cl_minorversion)
634+
continue;
635+
625636
/* If "pos" isn't marked ready, we can't trust the
626637
* remaining fields in "pos", especially the client
627638
* ID and serverowner fields. Wait for CREATE_SESSION
@@ -647,15 +658,6 @@ int nfs41_walk_client_list(struct nfs_client *new,
647658
if (pos->cl_cons_state != NFS_CS_READY)
648659
continue;
649660

650-
if (pos->rpc_ops != new->rpc_ops)
651-
continue;
652-
653-
if (pos->cl_proto != new->cl_proto)
654-
continue;
655-
656-
if (pos->cl_minorversion != new->cl_minorversion)
657-
continue;
658-
659661
if (!nfs4_match_clientids(pos, new))
660662
continue;
661663

fs/nfs/nfs4proc.c

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2226,9 +2226,13 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
22262226
ret = _nfs4_proc_open(opendata);
22272227
if (ret != 0) {
22282228
if (ret == -ENOENT) {
2229-
d_drop(opendata->dentry);
2230-
d_add(opendata->dentry, NULL);
2231-
nfs_set_verifier(opendata->dentry,
2229+
dentry = opendata->dentry;
2230+
if (dentry->d_inode)
2231+
d_delete(dentry);
2232+
else if (d_unhashed(dentry))
2233+
d_add(dentry, NULL);
2234+
2235+
nfs_set_verifier(dentry,
22322236
nfs_save_change_attribute(opendata->dir->d_inode));
22332237
}
22342238
goto out;
@@ -2614,23 +2618,23 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
26142618
is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags);
26152619
is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags);
26162620
is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags);
2617-
/* Calculate the current open share mode */
2618-
calldata->arg.fmode = 0;
2619-
if (is_rdonly || is_rdwr)
2620-
calldata->arg.fmode |= FMODE_READ;
2621-
if (is_wronly || is_rdwr)
2622-
calldata->arg.fmode |= FMODE_WRITE;
26232621
/* Calculate the change in open mode */
2622+
calldata->arg.fmode = 0;
26242623
if (state->n_rdwr == 0) {
2625-
if (state->n_rdonly == 0) {
2626-
call_close |= is_rdonly || is_rdwr;
2627-
calldata->arg.fmode &= ~FMODE_READ;
2628-
}
2629-
if (state->n_wronly == 0) {
2630-
call_close |= is_wronly || is_rdwr;
2631-
calldata->arg.fmode &= ~FMODE_WRITE;
2632-
}
2633-
}
2624+
if (state->n_rdonly == 0)
2625+
call_close |= is_rdonly;
2626+
else if (is_rdonly)
2627+
calldata->arg.fmode |= FMODE_READ;
2628+
if (state->n_wronly == 0)
2629+
call_close |= is_wronly;
2630+
else if (is_wronly)
2631+
calldata->arg.fmode |= FMODE_WRITE;
2632+
} else if (is_rdwr)
2633+
calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;
2634+
2635+
if (calldata->arg.fmode == 0)
2636+
call_close |= is_rdwr;
2637+
26342638
if (!nfs4_valid_open_stateid(state))
26352639
call_close = 0;
26362640
spin_unlock(&state->owner->so_lock);

0 commit comments

Comments
 (0)