diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-09-19 16:07:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-09-19 16:07:49 -0400 |
commit | 81770f41447bb2534d29b58a14ab501c0fb1e671 (patch) | |
tree | 45f69c2a4a46923406efbe584bc67cc004185d7f /fs | |
parent | b29f83aa8b7018cdbe687dd57b239160e25889f0 (diff) | |
parent | cd9288ffaea4359d5cfe2b8d264911506aed26a4 (diff) |
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
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/nfs4client.c | 38 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 40 |
2 files changed, 42 insertions, 36 deletions
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 53e435a95260..ffdb28d86cf8 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -482,6 +482,16 @@ int nfs40_walk_client_list(struct nfs_client *new, | |||
482 | 482 | ||
483 | spin_lock(&nn->nfs_client_lock); | 483 | spin_lock(&nn->nfs_client_lock); |
484 | list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { | 484 | 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 | |||
485 | /* If "pos" isn't marked ready, we can't trust the | 495 | /* If "pos" isn't marked ready, we can't trust the |
486 | * remaining fields in "pos" */ | 496 | * remaining fields in "pos" */ |
487 | if (pos->cl_cons_state > NFS_CS_READY) { | 497 | if (pos->cl_cons_state > NFS_CS_READY) { |
@@ -501,15 +511,6 @@ int nfs40_walk_client_list(struct nfs_client *new, | |||
501 | if (pos->cl_cons_state != NFS_CS_READY) | 511 | if (pos->cl_cons_state != NFS_CS_READY) |
502 | continue; | 512 | continue; |
503 | 513 | ||
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 | |||
513 | if (pos->cl_clientid != new->cl_clientid) | 514 | if (pos->cl_clientid != new->cl_clientid) |
514 | continue; | 515 | continue; |
515 | 516 | ||
@@ -622,6 +623,16 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
622 | 623 | ||
623 | spin_lock(&nn->nfs_client_lock); | 624 | spin_lock(&nn->nfs_client_lock); |
624 | list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { | 625 | 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 | |||
625 | /* If "pos" isn't marked ready, we can't trust the | 636 | /* If "pos" isn't marked ready, we can't trust the |
626 | * remaining fields in "pos", especially the client | 637 | * remaining fields in "pos", especially the client |
627 | * ID and serverowner fields. Wait for CREATE_SESSION | 638 | * ID and serverowner fields. Wait for CREATE_SESSION |
@@ -647,15 +658,6 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
647 | if (pos->cl_cons_state != NFS_CS_READY) | 658 | if (pos->cl_cons_state != NFS_CS_READY) |
648 | continue; | 659 | continue; |
649 | 660 | ||
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 | |||
659 | if (!nfs4_match_clientids(pos, new)) | 661 | if (!nfs4_match_clientids(pos, new)) |
660 | continue; | 662 | continue; |
661 | 663 | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 7dd8aca31c29..6ca0c8e7a945 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2226,9 +2226,13 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, | |||
2226 | ret = _nfs4_proc_open(opendata); | 2226 | ret = _nfs4_proc_open(opendata); |
2227 | if (ret != 0) { | 2227 | if (ret != 0) { |
2228 | if (ret == -ENOENT) { | 2228 | if (ret == -ENOENT) { |
2229 | d_drop(opendata->dentry); | 2229 | dentry = opendata->dentry; |
2230 | d_add(opendata->dentry, NULL); | 2230 | if (dentry->d_inode) |
2231 | nfs_set_verifier(opendata->dentry, | 2231 | d_delete(dentry); |
2232 | else if (d_unhashed(dentry)) | ||
2233 | d_add(dentry, NULL); | ||
2234 | |||
2235 | nfs_set_verifier(dentry, | ||
2232 | nfs_save_change_attribute(opendata->dir->d_inode)); | 2236 | nfs_save_change_attribute(opendata->dir->d_inode)); |
2233 | } | 2237 | } |
2234 | goto out; | 2238 | goto out; |
@@ -2614,23 +2618,23 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2614 | is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); | 2618 | is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); |
2615 | is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); | 2619 | is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); |
2616 | is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags); | 2620 | 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; | ||
2623 | /* Calculate the change in open mode */ | 2621 | /* Calculate the change in open mode */ |
2622 | calldata->arg.fmode = 0; | ||
2624 | if (state->n_rdwr == 0) { | 2623 | if (state->n_rdwr == 0) { |
2625 | if (state->n_rdonly == 0) { | 2624 | if (state->n_rdonly == 0) |
2626 | call_close |= is_rdonly || is_rdwr; | 2625 | call_close |= is_rdonly; |
2627 | calldata->arg.fmode &= ~FMODE_READ; | 2626 | else if (is_rdonly) |
2628 | } | 2627 | calldata->arg.fmode |= FMODE_READ; |
2629 | if (state->n_wronly == 0) { | 2628 | if (state->n_wronly == 0) |
2630 | call_close |= is_wronly || is_rdwr; | 2629 | call_close |= is_wronly; |
2631 | calldata->arg.fmode &= ~FMODE_WRITE; | 2630 | else if (is_wronly) |
2632 | } | 2631 | calldata->arg.fmode |= FMODE_WRITE; |
2633 | } | 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 | |||
2634 | if (!nfs4_valid_open_stateid(state)) | 2638 | if (!nfs4_valid_open_stateid(state)) |
2635 | call_close = 0; | 2639 | call_close = 0; |
2636 | spin_unlock(&state->owner->so_lock); | 2640 | spin_unlock(&state->owner->so_lock); |