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 | |
| 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
| -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); |
