aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-11 15:11:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-11 15:11:35 -0400
commit1466b77a7be75144dee1cb09839be3435854dd0b (patch)
tree977a0b6c1cd69ff98e5027359bb7de7b8897276a
parent19d2f8e0fb7bba99cc585d2467e9fa54a84c8557 (diff)
parenteeee245268c951262b861bc1be4e9dc812352499 (diff)
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
-rw-r--r--fs/nfs/dir.c6
-rw-r--r--fs/nfs/inode.c2
-rw-r--r--fs/nfs/write.c31
-rw-r--r--include/linux/nfs_fs.h1
-rw-r--r--net/sunrpc/clnt.c16
-rw-r--r--net/sunrpc/rpc_pipe.c25
6 files changed, 58 insertions, 23 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 0fac2cb1ea18..e474ca2b2bfe 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -450,6 +450,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
450 dentry = d_lookup(parent, &filename); 450 dentry = d_lookup(parent, &filename);
451 if (dentry != NULL) { 451 if (dentry != NULL) {
452 if (nfs_same_file(dentry, entry)) { 452 if (nfs_same_file(dentry, entry)) {
453 nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
453 status = nfs_refresh_inode(dentry->d_inode, entry->fattr); 454 status = nfs_refresh_inode(dentry->d_inode, entry->fattr);
454 if (!status) 455 if (!status)
455 nfs_setsecurity(dentry->d_inode, entry->fattr, entry->label); 456 nfs_setsecurity(dentry->d_inode, entry->fattr, entry->label);
@@ -817,7 +818,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
817 nfs_readdir_descriptor_t my_desc, 818 nfs_readdir_descriptor_t my_desc,
818 *desc = &my_desc; 819 *desc = &my_desc;
819 struct nfs_open_dir_context *dir_ctx = file->private_data; 820 struct nfs_open_dir_context *dir_ctx = file->private_data;
820 int res; 821 int res = 0;
821 822
822 dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", 823 dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
823 dentry->d_parent->d_name.name, dentry->d_name.name, 824 dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -839,7 +840,8 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
839 desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0; 840 desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0;
840 841
841 nfs_block_sillyrename(dentry); 842 nfs_block_sillyrename(dentry);
842 res = nfs_revalidate_mapping(inode, file->f_mapping); 843 if (ctx->pos == 0 || nfs_attribute_cache_expired(inode))
844 res = nfs_revalidate_mapping(inode, file->f_mapping);
843 if (res < 0) 845 if (res < 0)
844 goto out; 846 goto out;
845 847
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index c93639e6cf68..af6e806044d7 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -936,7 +936,7 @@ int nfs_attribute_timeout(struct inode *inode)
936 return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo); 936 return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo);
937} 937}
938 938
939static int nfs_attribute_cache_expired(struct inode *inode) 939int nfs_attribute_cache_expired(struct inode *inode)
940{ 940{
941 if (nfs_have_delegated_attributes(inode)) 941 if (nfs_have_delegated_attributes(inode))
942 return 0; 942 return 0;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index a2c7c28049d5..f1bdb7254776 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -888,6 +888,28 @@ out:
888 return PageUptodate(page) != 0; 888 return PageUptodate(page) != 0;
889} 889}
890 890
891/* If we know the page is up to date, and we're not using byte range locks (or
892 * if we have the whole file locked for writing), it may be more efficient to
893 * extend the write to cover the entire page in order to avoid fragmentation
894 * inefficiencies.
895 *
896 * If the file is opened for synchronous writes or if we have a write delegation
897 * from the server then we can just skip the rest of the checks.
898 */
899static int nfs_can_extend_write(struct file *file, struct page *page, struct inode *inode)
900{
901 if (file->f_flags & O_DSYNC)
902 return 0;
903 if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE))
904 return 1;
905 if (nfs_write_pageuptodate(page, inode) && (inode->i_flock == NULL ||
906 (inode->i_flock->fl_start == 0 &&
907 inode->i_flock->fl_end == OFFSET_MAX &&
908 inode->i_flock->fl_type != F_RDLCK)))
909 return 1;
910 return 0;
911}
912
891/* 913/*
892 * Update and possibly write a cached page of an NFS file. 914 * Update and possibly write a cached page of an NFS file.
893 * 915 *
@@ -908,14 +930,7 @@ int nfs_updatepage(struct file *file, struct page *page,
908 file->f_path.dentry->d_name.name, count, 930 file->f_path.dentry->d_name.name, count,
909 (long long)(page_file_offset(page) + offset)); 931 (long long)(page_file_offset(page) + offset));
910 932
911 /* If we're not using byte range locks, and we know the page 933 if (nfs_can_extend_write(file, page, inode)) {
912 * is up to date, it may be more efficient to extend the write
913 * to cover the entire page in order to avoid fragmentation
914 * inefficiencies.
915 */
916 if (nfs_write_pageuptodate(page, inode) &&
917 inode->i_flock == NULL &&
918 !(file->f_flags & O_DSYNC)) {
919 count = max(count + offset, nfs_page_length(page)); 934 count = max(count + offset, nfs_page_length(page));
920 offset = 0; 935 offset = 0;
921 } 936 }
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 0b176297aaf6..7125cef74164 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -348,6 +348,7 @@ extern int nfs_permission(struct inode *, int);
348extern int nfs_open(struct inode *, struct file *); 348extern int nfs_open(struct inode *, struct file *);
349extern int nfs_release(struct inode *, struct file *); 349extern int nfs_release(struct inode *, struct file *);
350extern int nfs_attribute_timeout(struct inode *inode); 350extern int nfs_attribute_timeout(struct inode *inode);
351extern int nfs_attribute_cache_expired(struct inode *inode);
351extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode); 352extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
352extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); 353extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
353extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); 354extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
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,
290 struct rpc_auth *auth; 290 struct rpc_auth *auth;
291 struct net *net = rpc_net_ns(clnt); 291 struct net *net = rpc_net_ns(clnt);
292 struct super_block *pipefs_sb; 292 struct super_block *pipefs_sb;
293 int err = 0; 293 int err;
294 294
295 pipefs_sb = rpc_get_sb_net(net); 295 pipefs_sb = rpc_get_sb_net(net);
296 if (pipefs_sb) { 296 if (pipefs_sb) {
@@ -299,6 +299,10 @@ static int rpc_client_register(const struct rpc_create_args *args,
299 goto out; 299 goto out;
300 } 300 }
301 301
302 rpc_register_client(clnt);
303 if (pipefs_sb)
304 rpc_put_sb_net(net);
305
302 auth = rpcauth_create(args->authflavor, clnt); 306 auth = rpcauth_create(args->authflavor, clnt);
303 if (IS_ERR(auth)) { 307 if (IS_ERR(auth)) {
304 dprintk("RPC: Couldn't create auth handle (flavor %u)\n", 308 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,
306 err = PTR_ERR(auth); 310 err = PTR_ERR(auth);
307 goto err_auth; 311 goto err_auth;
308 } 312 }
309 313 return 0;
310 rpc_register_client(clnt); 314err_auth:
315 pipefs_sb = rpc_get_sb_net(net);
316 __rpc_clnt_remove_pipedir(clnt);
311out: 317out:
312 if (pipefs_sb) 318 if (pipefs_sb)
313 rpc_put_sb_net(net); 319 rpc_put_sb_net(net);
314 return err; 320 return err;
315
316err_auth:
317 __rpc_clnt_remove_pipedir(clnt);
318 goto out;
319} 321}
320 322
321static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) 323static 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 = {
480 .d_delete = rpc_delete_dentry, 480 .d_delete = rpc_delete_dentry,
481}; 481};
482 482
483/*
484 * Lookup the data. This is trivial - if the dentry didn't already
485 * exist, we know it is negative.
486 */
487static struct dentry *
488rpc_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
489{
490 if (dentry->d_name.len > NAME_MAX)
491 return ERR_PTR(-ENAMETOOLONG);
492 d_add(dentry, NULL);
493 return NULL;
494}
495
496static const struct inode_operations rpc_dir_inode_operations = {
497 .lookup = rpc_lookup,
498};
499
483static struct inode * 500static struct inode *
484rpc_get_inode(struct super_block *sb, umode_t mode) 501rpc_get_inode(struct super_block *sb, umode_t mode)
485{ 502{
@@ -492,7 +509,7 @@ rpc_get_inode(struct super_block *sb, umode_t mode)
492 switch (mode & S_IFMT) { 509 switch (mode & S_IFMT) {
493 case S_IFDIR: 510 case S_IFDIR:
494 inode->i_fop = &simple_dir_operations; 511 inode->i_fop = &simple_dir_operations;
495 inode->i_op = &simple_dir_inode_operations; 512 inode->i_op = &rpc_dir_inode_operations;
496 inc_nlink(inode); 513 inc_nlink(inode);
497 default: 514 default:
498 break; 515 break;
@@ -666,11 +683,8 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent,
666 if (!dentry) 683 if (!dentry)
667 return ERR_PTR(-ENOMEM); 684 return ERR_PTR(-ENOMEM);
668 } 685 }
669 if (dentry->d_inode == NULL) { 686 if (dentry->d_inode == NULL)
670 if (!dentry->d_op)
671 d_set_d_op(dentry, &rpc_dentry_operations);
672 return dentry; 687 return dentry;
673 }
674 dput(dentry); 688 dput(dentry);
675 return ERR_PTR(-EEXIST); 689 return ERR_PTR(-EEXIST);
676} 690}
@@ -1117,6 +1131,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
1117 sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 1131 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
1118 sb->s_magic = RPCAUTH_GSSMAGIC; 1132 sb->s_magic = RPCAUTH_GSSMAGIC;
1119 sb->s_op = &s_ops; 1133 sb->s_op = &s_ops;
1134 sb->s_d_op = &rpc_dentry_operations;
1120 sb->s_time_gran = 1; 1135 sb->s_time_gran = 1;
1121 1136
1122 inode = rpc_get_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO); 1137 inode = rpc_get_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO);