diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-11 21:11:35 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-11 21:11:35 +0200 |
commit | 1466b77a7be75144dee1cb09839be3435854dd0b (patch) | |
tree | 977a0b6c1cd69ff98e5027359bb7de7b8897276a /net | |
parent | Merge tag 'for-linus-3.11-merge-window-part-2' of git://git.kernel.org/pub/sc... (diff) | |
parent | SUNRPC: Fix a deadlock in rpc_client_register() (diff) | |
download | linux-1466b77a7be75144dee1cb09839be3435854dd0b.tar.xz linux-1466b77a7be75144dee1cb09839be3435854dd0b.zip |
Merge tag 'nfs-for-3.11-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull second set of NFS client updates from Trond Myklebust:
"This mainly contains some small readdir optimisations that had
dependencies on Al Viro's readdir rewrite. There is also a fix for a
nasty deadlock which surfaced earlier in this merge window.
Highlights include:
- Fix an_rpc pipefs regression that causes a deadlock on mount
- Readdir optimisations by Scott Mayhew and Jeff Layton
- clean up the rpc_pipefs dentry operation setup"
* tag 'nfs-for-3.11-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
SUNRPC: Fix a deadlock in rpc_client_register()
rpc_pipe: rpc_dir_inode_operations can be static
NFS: Allow nfs_updatepage to extend a write under additional circumstances
NFS: Make nfs_readdir revalidate less often
NFS: Make nfs_attribute_cache_expired() non-static
rpc_pipe: set dentry operations at d_alloc time
nfs: set verifier on existing dentries in nfs_prime_dcache
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/clnt.c | 16 | ||||
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 25 |
2 files changed, 29 insertions, 12 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index f0339ae9bf37..aa401560777b 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -290,7 +290,7 @@ static int rpc_client_register(const struct rpc_create_args *args, struct rpc_auth *auth; struct net *net = rpc_net_ns(clnt); struct super_block *pipefs_sb; - int err = 0; + int err; pipefs_sb = rpc_get_sb_net(net); if (pipefs_sb) { @@ -299,6 +299,10 @@ static int rpc_client_register(const struct rpc_create_args *args, goto out; } + rpc_register_client(clnt); + if (pipefs_sb) + rpc_put_sb_net(net); + auth = rpcauth_create(args->authflavor, clnt); if (IS_ERR(auth)) { dprintk("RPC: Couldn't create auth handle (flavor %u)\n", @@ -306,16 +310,14 @@ static int rpc_client_register(const struct rpc_create_args *args, err = PTR_ERR(auth); goto err_auth; } - - rpc_register_client(clnt); + return 0; +err_auth: + pipefs_sb = rpc_get_sb_net(net); + __rpc_clnt_remove_pipedir(clnt); out: if (pipefs_sb) rpc_put_sb_net(net); return err; - -err_auth: - __rpc_clnt_remove_pipedir(clnt); - goto out; } static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 4679df5a6d50..61239a2cb786 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -480,6 +480,23 @@ static const struct dentry_operations rpc_dentry_operations = { .d_delete = rpc_delete_dentry, }; +/* + * Lookup the data. This is trivial - if the dentry didn't already + * exist, we know it is negative. + */ +static struct dentry * +rpc_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) +{ + if (dentry->d_name.len > NAME_MAX) + return ERR_PTR(-ENAMETOOLONG); + d_add(dentry, NULL); + return NULL; +} + +static const struct inode_operations rpc_dir_inode_operations = { + .lookup = rpc_lookup, +}; + static struct inode * rpc_get_inode(struct super_block *sb, umode_t mode) { @@ -492,7 +509,7 @@ rpc_get_inode(struct super_block *sb, umode_t mode) switch (mode & S_IFMT) { case S_IFDIR: inode->i_fop = &simple_dir_operations; - inode->i_op = &simple_dir_inode_operations; + inode->i_op = &rpc_dir_inode_operations; inc_nlink(inode); default: break; @@ -666,11 +683,8 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, if (!dentry) return ERR_PTR(-ENOMEM); } - if (dentry->d_inode == NULL) { - if (!dentry->d_op) - d_set_d_op(dentry, &rpc_dentry_operations); + if (dentry->d_inode == NULL) return dentry; - } dput(dentry); return ERR_PTR(-EEXIST); } @@ -1117,6 +1131,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = RPCAUTH_GSSMAGIC; sb->s_op = &s_ops; + sb->s_d_op = &rpc_dentry_operations; sb->s_time_gran = 1; inode = rpc_get_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO); |