diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-21 19:05:43 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-21 19:05:43 -0400 |
| commit | 636040b4eddf6152b5d0b2d574663809f898953b (patch) | |
| tree | 6f2e8124e531f88e264e53d5cc3ef52368659a69 | |
| parent | 8874e812feb4926f4a51a82c4fca75c7daa05fc5 (diff) | |
| parent | b1027439dff844675f6c0df97a1b1d190791a699 (diff) | |
Merge tag 'nfs-for-3.5-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust:
- Fix a write hang due to an uninitalised variable when
!defined(CONFIG_NFS_V4)
- Address upcall races in the legacy NFSv4 idmapper
- Remove an O_DIRECT refcounting issue
- Fix a pNFS refcounting bug when the file layout metadata server is
also acting as a data server
- Fix a pNFS module loading race.
* tag 'nfs-for-3.5-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
NFS: Force the legacy idmapper to be single threaded
NFS: Initialise commit_info.rpc_out when !defined(CONFIG_NFS_V4)
NFS: Fix a refcounting issue in O_DIRECT
NFSv4.1: Fix a race in set_pnfs_layoutdriver
NFSv4.1: Fix umount when filelayout DS is also the MDS
| -rw-r--r-- | fs/nfs/client.c | 1 | ||||
| -rw-r--r-- | fs/nfs/direct.c | 1 | ||||
| -rw-r--r-- | fs/nfs/idmap.c | 13 | ||||
| -rw-r--r-- | fs/nfs/inode.c | 2 | ||||
| -rw-r--r-- | fs/nfs/pnfs.c | 13 | ||||
| -rw-r--r-- | include/linux/nfs_fs_sb.h | 1 |
6 files changed, 20 insertions, 11 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 17ba6b995659..f005b5bebdc7 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -207,7 +207,6 @@ error_0: | |||
| 207 | static void nfs4_shutdown_session(struct nfs_client *clp) | 207 | static void nfs4_shutdown_session(struct nfs_client *clp) |
| 208 | { | 208 | { |
| 209 | if (nfs4_has_session(clp)) { | 209 | if (nfs4_has_session(clp)) { |
| 210 | nfs4_deviceid_purge_client(clp); | ||
| 211 | nfs4_destroy_session(clp->cl_session); | 210 | nfs4_destroy_session(clp->cl_session); |
| 212 | nfs4_destroy_clientid(clp); | 211 | nfs4_destroy_clientid(clp); |
| 213 | } | 212 | } |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 3168f6e3d4d4..9a4cbfc85d81 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
| @@ -490,6 +490,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
| 490 | dreq->error = -EIO; | 490 | dreq->error = -EIO; |
| 491 | spin_unlock(cinfo.lock); | 491 | spin_unlock(cinfo.lock); |
| 492 | } | 492 | } |
| 493 | nfs_release_request(req); | ||
| 493 | } | 494 | } |
| 494 | nfs_pageio_complete(&desc); | 495 | nfs_pageio_complete(&desc); |
| 495 | 496 | ||
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index b5b86a05059c..864c51e4b400 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
| @@ -57,6 +57,11 @@ unsigned int nfs_idmap_cache_timeout = 600; | |||
| 57 | static const struct cred *id_resolver_cache; | 57 | static const struct cred *id_resolver_cache; |
| 58 | static struct key_type key_type_id_resolver_legacy; | 58 | static struct key_type key_type_id_resolver_legacy; |
| 59 | 59 | ||
| 60 | struct idmap { | ||
| 61 | struct rpc_pipe *idmap_pipe; | ||
| 62 | struct key_construction *idmap_key_cons; | ||
| 63 | struct mutex idmap_mutex; | ||
| 64 | }; | ||
| 60 | 65 | ||
| 61 | /** | 66 | /** |
| 62 | * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields | 67 | * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields |
| @@ -310,9 +315,11 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, | |||
| 310 | name, namelen, type, data, | 315 | name, namelen, type, data, |
| 311 | data_size, NULL); | 316 | data_size, NULL); |
| 312 | if (ret < 0) { | 317 | if (ret < 0) { |
| 318 | mutex_lock(&idmap->idmap_mutex); | ||
| 313 | ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, | 319 | ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, |
| 314 | name, namelen, type, data, | 320 | name, namelen, type, data, |
| 315 | data_size, idmap); | 321 | data_size, idmap); |
| 322 | mutex_unlock(&idmap->idmap_mutex); | ||
| 316 | } | 323 | } |
| 317 | return ret; | 324 | return ret; |
| 318 | } | 325 | } |
| @@ -354,11 +361,6 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *typ | |||
| 354 | /* idmap classic begins here */ | 361 | /* idmap classic begins here */ |
| 355 | module_param(nfs_idmap_cache_timeout, int, 0644); | 362 | module_param(nfs_idmap_cache_timeout, int, 0644); |
| 356 | 363 | ||
| 357 | struct idmap { | ||
| 358 | struct rpc_pipe *idmap_pipe; | ||
| 359 | struct key_construction *idmap_key_cons; | ||
| 360 | }; | ||
| 361 | |||
| 362 | enum { | 364 | enum { |
| 363 | Opt_find_uid, Opt_find_gid, Opt_find_user, Opt_find_group, Opt_find_err | 365 | Opt_find_uid, Opt_find_gid, Opt_find_user, Opt_find_group, Opt_find_err |
| 364 | }; | 366 | }; |
| @@ -469,6 +471,7 @@ nfs_idmap_new(struct nfs_client *clp) | |||
| 469 | return error; | 471 | return error; |
| 470 | } | 472 | } |
| 471 | idmap->idmap_pipe = pipe; | 473 | idmap->idmap_pipe = pipe; |
| 474 | mutex_init(&idmap->idmap_mutex); | ||
| 472 | 475 | ||
| 473 | clp->cl_idmap = idmap; | 476 | clp->cl_idmap = idmap; |
| 474 | return 0; | 477 | return 0; |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e605d695dbcb..f7296983eba6 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -1530,7 +1530,6 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi) | |||
| 1530 | nfsi->delegation_state = 0; | 1530 | nfsi->delegation_state = 0; |
| 1531 | init_rwsem(&nfsi->rwsem); | 1531 | init_rwsem(&nfsi->rwsem); |
| 1532 | nfsi->layout = NULL; | 1532 | nfsi->layout = NULL; |
| 1533 | atomic_set(&nfsi->commit_info.rpcs_out, 0); | ||
| 1534 | #endif | 1533 | #endif |
| 1535 | } | 1534 | } |
| 1536 | 1535 | ||
| @@ -1545,6 +1544,7 @@ static void init_once(void *foo) | |||
| 1545 | INIT_LIST_HEAD(&nfsi->commit_info.list); | 1544 | INIT_LIST_HEAD(&nfsi->commit_info.list); |
| 1546 | nfsi->npages = 0; | 1545 | nfsi->npages = 0; |
| 1547 | nfsi->commit_info.ncommit = 0; | 1546 | nfsi->commit_info.ncommit = 0; |
| 1547 | atomic_set(&nfsi->commit_info.rpcs_out, 0); | ||
| 1548 | atomic_set(&nfsi->silly_count, 1); | 1548 | atomic_set(&nfsi->silly_count, 1); |
| 1549 | INIT_HLIST_HEAD(&nfsi->silly_list); | 1549 | INIT_HLIST_HEAD(&nfsi->silly_list); |
| 1550 | init_waitqueue_head(&nfsi->waitqueue); | 1550 | init_waitqueue_head(&nfsi->waitqueue); |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index b8323aa7b543..bbc49caa7a82 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
| @@ -70,6 +70,10 @@ find_pnfs_driver(u32 id) | |||
| 70 | 70 | ||
| 71 | spin_lock(&pnfs_spinlock); | 71 | spin_lock(&pnfs_spinlock); |
| 72 | local = find_pnfs_driver_locked(id); | 72 | local = find_pnfs_driver_locked(id); |
| 73 | if (local != NULL && !try_module_get(local->owner)) { | ||
| 74 | dprintk("%s: Could not grab reference on module\n", __func__); | ||
| 75 | local = NULL; | ||
| 76 | } | ||
| 73 | spin_unlock(&pnfs_spinlock); | 77 | spin_unlock(&pnfs_spinlock); |
| 74 | return local; | 78 | return local; |
| 75 | } | 79 | } |
| @@ -80,6 +84,9 @@ unset_pnfs_layoutdriver(struct nfs_server *nfss) | |||
| 80 | if (nfss->pnfs_curr_ld) { | 84 | if (nfss->pnfs_curr_ld) { |
| 81 | if (nfss->pnfs_curr_ld->clear_layoutdriver) | 85 | if (nfss->pnfs_curr_ld->clear_layoutdriver) |
| 82 | nfss->pnfs_curr_ld->clear_layoutdriver(nfss); | 86 | nfss->pnfs_curr_ld->clear_layoutdriver(nfss); |
| 87 | /* Decrement the MDS count. Purge the deviceid cache if zero */ | ||
| 88 | if (atomic_dec_and_test(&nfss->nfs_client->cl_mds_count)) | ||
| 89 | nfs4_deviceid_purge_client(nfss->nfs_client); | ||
| 83 | module_put(nfss->pnfs_curr_ld->owner); | 90 | module_put(nfss->pnfs_curr_ld->owner); |
| 84 | } | 91 | } |
| 85 | nfss->pnfs_curr_ld = NULL; | 92 | nfss->pnfs_curr_ld = NULL; |
| @@ -115,10 +122,6 @@ set_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh, | |||
| 115 | goto out_no_driver; | 122 | goto out_no_driver; |
| 116 | } | 123 | } |
| 117 | } | 124 | } |
| 118 | if (!try_module_get(ld_type->owner)) { | ||
| 119 | dprintk("%s: Could not grab reference on module\n", __func__); | ||
| 120 | goto out_no_driver; | ||
| 121 | } | ||
| 122 | server->pnfs_curr_ld = ld_type; | 125 | server->pnfs_curr_ld = ld_type; |
| 123 | if (ld_type->set_layoutdriver | 126 | if (ld_type->set_layoutdriver |
| 124 | && ld_type->set_layoutdriver(server, mntfh)) { | 127 | && ld_type->set_layoutdriver(server, mntfh)) { |
| @@ -127,6 +130,8 @@ set_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh, | |||
| 127 | module_put(ld_type->owner); | 130 | module_put(ld_type->owner); |
| 128 | goto out_no_driver; | 131 | goto out_no_driver; |
| 129 | } | 132 | } |
| 133 | /* Bump the MDS count */ | ||
| 134 | atomic_inc(&server->nfs_client->cl_mds_count); | ||
| 130 | 135 | ||
| 131 | dprintk("%s: pNFS module for %u set\n", __func__, id); | 136 | dprintk("%s: pNFS module for %u set\n", __func__, id); |
| 132 | return; | 137 | return; |
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index fbb78fb09bd2..f58325a1d8fb 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h | |||
| @@ -25,6 +25,7 @@ struct nfs41_impl_id; | |||
| 25 | */ | 25 | */ |
| 26 | struct nfs_client { | 26 | struct nfs_client { |
| 27 | atomic_t cl_count; | 27 | atomic_t cl_count; |
| 28 | atomic_t cl_mds_count; | ||
| 28 | int cl_cons_state; /* current construction state (-ve: init error) */ | 29 | int cl_cons_state; /* current construction state (-ve: init error) */ |
| 29 | #define NFS_CS_READY 0 /* ready to be used */ | 30 | #define NFS_CS_READY 0 /* ready to be used */ |
| 30 | #define NFS_CS_INITING 1 /* busy initialising */ | 31 | #define NFS_CS_INITING 1 /* busy initialising */ |
