diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-09-30 17:21:41 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-09-30 17:21:41 -0400 |
commit | 72c23f0819977d37924af92a42a9b7fbfd1c95d8 (patch) | |
tree | a0c10114d96c40f8e38887c346ec593a51321781 /fs/nfs | |
parent | 3fc3edf141fd78f624194eb89d7b37ff86138422 (diff) | |
parent | d1f456b0b9545f1606a54cd17c20775f159bd2ce (diff) |
Merge branch 'bugfixes' into linux-next
* bugfixes:
NFSv4.1: Fix an NFSv4.1 state renewal regression
NFSv4: fix open/lock state recovery error handling
NFSv4: Fix lock recovery when CREATE_SESSION/SETCLIENTID_CONFIRM fails
NFS: Fabricate fscache server index key correctly
SUNRPC: Add missing support for RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT
nfs: fix duplicate proc entries
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/client.c | 2 | ||||
-rw-r--r-- | fs/nfs/fscache-index.c | 3 | ||||
-rw-r--r-- | fs/nfs/nfs4client.c | 38 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 42 | ||||
-rw-r--r-- | fs/nfs/nfs4renewd.c | 12 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 17 |
6 files changed, 61 insertions, 53 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 8052020a0d0d..f9f4845db989 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -1320,7 +1320,7 @@ static int nfs_server_list_show(struct seq_file *m, void *v) | |||
1320 | */ | 1320 | */ |
1321 | static int nfs_volume_list_open(struct inode *inode, struct file *file) | 1321 | static int nfs_volume_list_open(struct inode *inode, struct file *file) |
1322 | { | 1322 | { |
1323 | return seq_open_net(inode, file, &nfs_server_list_ops, | 1323 | return seq_open_net(inode, file, &nfs_volume_list_ops, |
1324 | sizeof(struct seq_net_private)); | 1324 | sizeof(struct seq_net_private)); |
1325 | } | 1325 | } |
1326 | 1326 | ||
diff --git a/fs/nfs/fscache-index.c b/fs/nfs/fscache-index.c index 7cf2c4699b08..777b055063f6 100644 --- a/fs/nfs/fscache-index.c +++ b/fs/nfs/fscache-index.c | |||
@@ -74,11 +74,10 @@ static uint16_t nfs_server_get_key(const void *cookie_netfs_data, | |||
74 | struct nfs_server_key *key = buffer; | 74 | struct nfs_server_key *key = buffer; |
75 | uint16_t len = sizeof(struct nfs_server_key); | 75 | uint16_t len = sizeof(struct nfs_server_key); |
76 | 76 | ||
77 | memset(key, 0, len); | ||
77 | key->nfsversion = clp->rpc_ops->version; | 78 | key->nfsversion = clp->rpc_ops->version; |
78 | key->family = clp->cl_addr.ss_family; | 79 | key->family = clp->cl_addr.ss_family; |
79 | 80 | ||
80 | memset(key, 0, len); | ||
81 | |||
82 | switch (clp->cl_addr.ss_family) { | 81 | switch (clp->cl_addr.ss_family) { |
83 | case AF_INET: | 82 | case AF_INET: |
84 | key->port = sin->sin_port; | 83 | key->port = sin->sin_port; |
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 45bce9ed6791..5aa55c132aa2 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2234,9 +2234,13 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, | |||
2234 | ret = _nfs4_proc_open(opendata); | 2234 | ret = _nfs4_proc_open(opendata); |
2235 | if (ret != 0) { | 2235 | if (ret != 0) { |
2236 | if (ret == -ENOENT) { | 2236 | if (ret == -ENOENT) { |
2237 | d_drop(opendata->dentry); | 2237 | dentry = opendata->dentry; |
2238 | d_add(opendata->dentry, NULL); | 2238 | if (dentry->d_inode) |
2239 | nfs_set_verifier(opendata->dentry, | 2239 | d_delete(dentry); |
2240 | else if (d_unhashed(dentry)) | ||
2241 | d_add(dentry, NULL); | ||
2242 | |||
2243 | nfs_set_verifier(dentry, | ||
2240 | nfs_save_change_attribute(opendata->dir->d_inode)); | 2244 | nfs_save_change_attribute(opendata->dir->d_inode)); |
2241 | } | 2245 | } |
2242 | goto out; | 2246 | goto out; |
@@ -2622,23 +2626,23 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2622 | is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); | 2626 | is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); |
2623 | is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); | 2627 | is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); |
2624 | is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags); | 2628 | is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags); |
2625 | /* Calculate the current open share mode */ | ||
2626 | calldata->arg.fmode = 0; | ||
2627 | if (is_rdonly || is_rdwr) | ||
2628 | calldata->arg.fmode |= FMODE_READ; | ||
2629 | if (is_wronly || is_rdwr) | ||
2630 | calldata->arg.fmode |= FMODE_WRITE; | ||
2631 | /* Calculate the change in open mode */ | 2629 | /* Calculate the change in open mode */ |
2630 | calldata->arg.fmode = 0; | ||
2632 | if (state->n_rdwr == 0) { | 2631 | if (state->n_rdwr == 0) { |
2633 | if (state->n_rdonly == 0) { | 2632 | if (state->n_rdonly == 0) |
2634 | call_close |= is_rdonly || is_rdwr; | 2633 | call_close |= is_rdonly; |
2635 | calldata->arg.fmode &= ~FMODE_READ; | 2634 | else if (is_rdonly) |
2636 | } | 2635 | calldata->arg.fmode |= FMODE_READ; |
2637 | if (state->n_wronly == 0) { | 2636 | if (state->n_wronly == 0) |
2638 | call_close |= is_wronly || is_rdwr; | 2637 | call_close |= is_wronly; |
2639 | calldata->arg.fmode &= ~FMODE_WRITE; | 2638 | else if (is_wronly) |
2640 | } | 2639 | calldata->arg.fmode |= FMODE_WRITE; |
2641 | } | 2640 | } else if (is_rdwr) |
2641 | calldata->arg.fmode |= FMODE_READ|FMODE_WRITE; | ||
2642 | |||
2643 | if (calldata->arg.fmode == 0) | ||
2644 | call_close |= is_rdwr; | ||
2645 | |||
2642 | if (!nfs4_valid_open_stateid(state)) | 2646 | if (!nfs4_valid_open_stateid(state)) |
2643 | call_close = 0; | 2647 | call_close = 0; |
2644 | spin_unlock(&state->owner->so_lock); | 2648 | spin_unlock(&state->owner->so_lock); |
@@ -7368,7 +7372,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr | |||
7368 | int ret = 0; | 7372 | int ret = 0; |
7369 | 7373 | ||
7370 | if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) | 7374 | if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) |
7371 | return 0; | 7375 | return -EAGAIN; |
7372 | task = _nfs41_proc_sequence(clp, cred, false); | 7376 | task = _nfs41_proc_sequence(clp, cred, false); |
7373 | if (IS_ERR(task)) | 7377 | if (IS_ERR(task)) |
7374 | ret = PTR_ERR(task); | 7378 | ret = PTR_ERR(task); |
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c index 1720d32ffa54..e1ba58c3d1ad 100644 --- a/fs/nfs/nfs4renewd.c +++ b/fs/nfs/nfs4renewd.c | |||
@@ -88,10 +88,18 @@ nfs4_renew_state(struct work_struct *work) | |||
88 | } | 88 | } |
89 | nfs_expire_all_delegations(clp); | 89 | nfs_expire_all_delegations(clp); |
90 | } else { | 90 | } else { |
91 | int ret; | ||
92 | |||
91 | /* Queue an asynchronous RENEW. */ | 93 | /* Queue an asynchronous RENEW. */ |
92 | ops->sched_state_renewal(clp, cred, renew_flags); | 94 | ret = ops->sched_state_renewal(clp, cred, renew_flags); |
93 | put_rpccred(cred); | 95 | put_rpccred(cred); |
94 | goto out_exp; | 96 | switch (ret) { |
97 | default: | ||
98 | goto out_exp; | ||
99 | case -EAGAIN: | ||
100 | case -ENOMEM: | ||
101 | break; | ||
102 | } | ||
95 | } | 103 | } |
96 | } else { | 104 | } else { |
97 | dprintk("%s: failed to call renewd. Reason: lease not expired \n", | 105 | dprintk("%s: failed to call renewd. Reason: lease not expired \n", |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 6678769e1a54..5194933ed419 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1705,7 +1705,8 @@ restart: | |||
1705 | if (status < 0) { | 1705 | if (status < 0) { |
1706 | set_bit(ops->owner_flag_bit, &sp->so_flags); | 1706 | set_bit(ops->owner_flag_bit, &sp->so_flags); |
1707 | nfs4_put_state_owner(sp); | 1707 | nfs4_put_state_owner(sp); |
1708 | return nfs4_recovery_handle_error(clp, status); | 1708 | status = nfs4_recovery_handle_error(clp, status); |
1709 | return (status != 0) ? status : -EAGAIN; | ||
1709 | } | 1710 | } |
1710 | 1711 | ||
1711 | nfs4_put_state_owner(sp); | 1712 | nfs4_put_state_owner(sp); |
@@ -1714,7 +1715,7 @@ restart: | |||
1714 | spin_unlock(&clp->cl_lock); | 1715 | spin_unlock(&clp->cl_lock); |
1715 | } | 1716 | } |
1716 | rcu_read_unlock(); | 1717 | rcu_read_unlock(); |
1717 | return status; | 1718 | return 0; |
1718 | } | 1719 | } |
1719 | 1720 | ||
1720 | static int nfs4_check_lease(struct nfs_client *clp) | 1721 | static int nfs4_check_lease(struct nfs_client *clp) |
@@ -1761,7 +1762,6 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status) | |||
1761 | break; | 1762 | break; |
1762 | case -NFS4ERR_STALE_CLIENTID: | 1763 | case -NFS4ERR_STALE_CLIENTID: |
1763 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | 1764 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
1764 | nfs4_state_clear_reclaim_reboot(clp); | ||
1765 | nfs4_state_start_reclaim_reboot(clp); | 1765 | nfs4_state_start_reclaim_reboot(clp); |
1766 | break; | 1766 | break; |
1767 | case -NFS4ERR_CLID_INUSE: | 1767 | case -NFS4ERR_CLID_INUSE: |
@@ -2367,14 +2367,11 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
2367 | section = "reclaim reboot"; | 2367 | section = "reclaim reboot"; |
2368 | status = nfs4_do_reclaim(clp, | 2368 | status = nfs4_do_reclaim(clp, |
2369 | clp->cl_mvops->reboot_recovery_ops); | 2369 | clp->cl_mvops->reboot_recovery_ops); |
2370 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || | 2370 | if (status == -EAGAIN) |
2371 | test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) | ||
2372 | continue; | ||
2373 | nfs4_state_end_reclaim_reboot(clp); | ||
2374 | if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) | ||
2375 | continue; | 2371 | continue; |
2376 | if (status < 0) | 2372 | if (status < 0) |
2377 | goto out_error; | 2373 | goto out_error; |
2374 | nfs4_state_end_reclaim_reboot(clp); | ||
2378 | } | 2375 | } |
2379 | 2376 | ||
2380 | /* Now recover expired state... */ | 2377 | /* Now recover expired state... */ |
@@ -2382,9 +2379,7 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
2382 | section = "reclaim nograce"; | 2379 | section = "reclaim nograce"; |
2383 | status = nfs4_do_reclaim(clp, | 2380 | status = nfs4_do_reclaim(clp, |
2384 | clp->cl_mvops->nograce_recovery_ops); | 2381 | clp->cl_mvops->nograce_recovery_ops); |
2385 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || | 2382 | if (status == -EAGAIN) |
2386 | test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) || | ||
2387 | test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) | ||
2388 | continue; | 2383 | continue; |
2389 | if (status < 0) | 2384 | if (status < 0) |
2390 | goto out_error; | 2385 | goto out_error; |