Commit 636040b4 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 8874e812 b1027439
...@@ -207,7 +207,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ ...@@ -207,7 +207,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
static void nfs4_shutdown_session(struct nfs_client *clp) static void nfs4_shutdown_session(struct nfs_client *clp)
{ {
if (nfs4_has_session(clp)) { if (nfs4_has_session(clp)) {
nfs4_deviceid_purge_client(clp);
nfs4_destroy_session(clp->cl_session); nfs4_destroy_session(clp->cl_session);
nfs4_destroy_clientid(clp); nfs4_destroy_clientid(clp);
} }
......
...@@ -490,6 +490,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) ...@@ -490,6 +490,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
dreq->error = -EIO; dreq->error = -EIO;
spin_unlock(cinfo.lock); spin_unlock(cinfo.lock);
} }
nfs_release_request(req);
} }
nfs_pageio_complete(&desc); nfs_pageio_complete(&desc);
......
...@@ -57,6 +57,11 @@ unsigned int nfs_idmap_cache_timeout = 600; ...@@ -57,6 +57,11 @@ unsigned int nfs_idmap_cache_timeout = 600;
static const struct cred *id_resolver_cache; static const struct cred *id_resolver_cache;
static struct key_type key_type_id_resolver_legacy; static struct key_type key_type_id_resolver_legacy;
struct idmap {
struct rpc_pipe *idmap_pipe;
struct key_construction *idmap_key_cons;
struct mutex idmap_mutex;
};
/** /**
* nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields * 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,9 +315,11 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen,
name, namelen, type, data, name, namelen, type, data,
data_size, NULL); data_size, NULL);
if (ret < 0) { if (ret < 0) {
mutex_lock(&idmap->idmap_mutex);
ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, ret = nfs_idmap_request_key(&key_type_id_resolver_legacy,
name, namelen, type, data, name, namelen, type, data,
data_size, idmap); data_size, idmap);
mutex_unlock(&idmap->idmap_mutex);
} }
return ret; return ret;
} }
...@@ -354,11 +361,6 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *typ ...@@ -354,11 +361,6 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *typ
/* idmap classic begins here */ /* idmap classic begins here */
module_param(nfs_idmap_cache_timeout, int, 0644); module_param(nfs_idmap_cache_timeout, int, 0644);
struct idmap {
struct rpc_pipe *idmap_pipe;
struct key_construction *idmap_key_cons;
};
enum { enum {
Opt_find_uid, Opt_find_gid, Opt_find_user, Opt_find_group, Opt_find_err Opt_find_uid, Opt_find_gid, Opt_find_user, Opt_find_group, Opt_find_err
}; };
...@@ -469,6 +471,7 @@ nfs_idmap_new(struct nfs_client *clp) ...@@ -469,6 +471,7 @@ nfs_idmap_new(struct nfs_client *clp)
return error; return error;
} }
idmap->idmap_pipe = pipe; idmap->idmap_pipe = pipe;
mutex_init(&idmap->idmap_mutex);
clp->cl_idmap = idmap; clp->cl_idmap = idmap;
return 0; return 0;
......
...@@ -1530,7 +1530,6 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi) ...@@ -1530,7 +1530,6 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi)
nfsi->delegation_state = 0; nfsi->delegation_state = 0;
init_rwsem(&nfsi->rwsem); init_rwsem(&nfsi->rwsem);
nfsi->layout = NULL; nfsi->layout = NULL;
atomic_set(&nfsi->commit_info.rpcs_out, 0);
#endif #endif
} }
...@@ -1545,6 +1544,7 @@ static void init_once(void *foo) ...@@ -1545,6 +1544,7 @@ static void init_once(void *foo)
INIT_LIST_HEAD(&nfsi->commit_info.list); INIT_LIST_HEAD(&nfsi->commit_info.list);
nfsi->npages = 0; nfsi->npages = 0;
nfsi->commit_info.ncommit = 0; nfsi->commit_info.ncommit = 0;
atomic_set(&nfsi->commit_info.rpcs_out, 0);
atomic_set(&nfsi->silly_count, 1); atomic_set(&nfsi->silly_count, 1);
INIT_HLIST_HEAD(&nfsi->silly_list); INIT_HLIST_HEAD(&nfsi->silly_list);
init_waitqueue_head(&nfsi->waitqueue); init_waitqueue_head(&nfsi->waitqueue);
......
...@@ -70,6 +70,10 @@ find_pnfs_driver(u32 id) ...@@ -70,6 +70,10 @@ find_pnfs_driver(u32 id)
spin_lock(&pnfs_spinlock); spin_lock(&pnfs_spinlock);
local = find_pnfs_driver_locked(id); local = find_pnfs_driver_locked(id);
if (local != NULL && !try_module_get(local->owner)) {
dprintk("%s: Could not grab reference on module\n", __func__);
local = NULL;
}
spin_unlock(&pnfs_spinlock); spin_unlock(&pnfs_spinlock);
return local; return local;
} }
...@@ -80,6 +84,9 @@ unset_pnfs_layoutdriver(struct nfs_server *nfss) ...@@ -80,6 +84,9 @@ unset_pnfs_layoutdriver(struct nfs_server *nfss)
if (nfss->pnfs_curr_ld) { if (nfss->pnfs_curr_ld) {
if (nfss->pnfs_curr_ld->clear_layoutdriver) if (nfss->pnfs_curr_ld->clear_layoutdriver)
nfss->pnfs_curr_ld->clear_layoutdriver(nfss); nfss->pnfs_curr_ld->clear_layoutdriver(nfss);
/* Decrement the MDS count. Purge the deviceid cache if zero */
if (atomic_dec_and_test(&nfss->nfs_client->cl_mds_count))
nfs4_deviceid_purge_client(nfss->nfs_client);
module_put(nfss->pnfs_curr_ld->owner); module_put(nfss->pnfs_curr_ld->owner);
} }
nfss->pnfs_curr_ld = NULL; nfss->pnfs_curr_ld = NULL;
...@@ -115,10 +122,6 @@ set_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh, ...@@ -115,10 +122,6 @@ set_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh,
goto out_no_driver; goto out_no_driver;
} }
} }
if (!try_module_get(ld_type->owner)) {
dprintk("%s: Could not grab reference on module\n", __func__);
goto out_no_driver;
}
server->pnfs_curr_ld = ld_type; server->pnfs_curr_ld = ld_type;
if (ld_type->set_layoutdriver if (ld_type->set_layoutdriver
&& ld_type->set_layoutdriver(server, mntfh)) { && ld_type->set_layoutdriver(server, mntfh)) {
...@@ -127,6 +130,8 @@ set_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh, ...@@ -127,6 +130,8 @@ set_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh,
module_put(ld_type->owner); module_put(ld_type->owner);
goto out_no_driver; goto out_no_driver;
} }
/* Bump the MDS count */
atomic_inc(&server->nfs_client->cl_mds_count);
dprintk("%s: pNFS module for %u set\n", __func__, id); dprintk("%s: pNFS module for %u set\n", __func__, id);
return; return;
......
...@@ -25,6 +25,7 @@ struct nfs41_impl_id; ...@@ -25,6 +25,7 @@ struct nfs41_impl_id;
*/ */
struct nfs_client { struct nfs_client {
atomic_t cl_count; atomic_t cl_count;
atomic_t cl_mds_count;
int cl_cons_state; /* current construction state (-ve: init error) */ int cl_cons_state; /* current construction state (-ve: init error) */
#define NFS_CS_READY 0 /* ready to be used */ #define NFS_CS_READY 0 /* ready to be used */
#define NFS_CS_INITING 1 /* busy initialising */ #define NFS_CS_INITING 1 /* busy initialising */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment