NFS client updates for Linux 3.11 (part 2)
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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.13 (GNU/Linux) iQIcBAABAgAGBQJR3vVIAAoJEGcL54qWCgDyBWEP/0blqSlJId4zZj4xDviRFqJ4 93C7b/Vn7LrAcNCgDQsPkkzTwAX5yTB1H5eNtMuyggAdGj89d4n0jXgBniIMHmqI Pjrr/XMQ65NddehrO491N01iJSfP9wE3CizJodnAv4VxMRO3xqiJG85lcnoLOFea V1FnEFUu9oi8e93cQt2fe6KdmTu/SuRqlqR7WPGyTFgS26x1l8nkp2OQgulit5Up lWuaxg4xbKOdj1jfUDXZhWUnDtkFjxyGxnKR63aA2X1DEGCUTJ6gB3tAl9pvnUb2 RTQF3GVj+Bm/E3gE6ULJvqOjhsgWYjLAZn6hDA3yNAIiFyV7aA6gwK4oKy/B47a6 tFEN2O1EupWzCqGyHhTArk+oEBLfUv/EgFyo7+Y0YIFV4sQTu5RbaZ0nQ2geY6LA 50q2GH57tkXTs859gtBPQgKzgRF1ulkF1FDY9EYQHyGiUbNxBfx+6/2OI04ubQt3 1gKUmm9w1WVzYGmHcHbxsXPT53NtAnHXW4ExcMgpaZ1YOPuIILm78ZuAw78XB/dd mvXRtbhVt/gs7qZAQQPp1iHIv+vnJ0KgjO62gbuTIRftw5jwWrpWcfYMUUZrMnyM kn326z3f4gn/vSDZI7J4tOfG1Uc7eNy+cJxStjtiNWTs3UzuWJKzJH0rZnoNZdei xAkLhjIUEybAqIpXJuGH =NqQf -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
1466b77a7b
|
@ -450,6 +450,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
|
|||
dentry = d_lookup(parent, &filename);
|
||||
if (dentry != NULL) {
|
||||
if (nfs_same_file(dentry, entry)) {
|
||||
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
||||
status = nfs_refresh_inode(dentry->d_inode, entry->fattr);
|
||||
if (!status)
|
||||
nfs_setsecurity(dentry->d_inode, entry->fattr, entry->label);
|
||||
|
@ -817,7 +818,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
|
|||
nfs_readdir_descriptor_t my_desc,
|
||||
*desc = &my_desc;
|
||||
struct nfs_open_dir_context *dir_ctx = file->private_data;
|
||||
int res;
|
||||
int res = 0;
|
||||
|
||||
dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
|
||||
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)
|
|||
desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0;
|
||||
|
||||
nfs_block_sillyrename(dentry);
|
||||
res = nfs_revalidate_mapping(inode, file->f_mapping);
|
||||
if (ctx->pos == 0 || nfs_attribute_cache_expired(inode))
|
||||
res = nfs_revalidate_mapping(inode, file->f_mapping);
|
||||
if (res < 0)
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -936,7 +936,7 @@ int nfs_attribute_timeout(struct inode *inode)
|
|||
return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo);
|
||||
}
|
||||
|
||||
static int nfs_attribute_cache_expired(struct inode *inode)
|
||||
int nfs_attribute_cache_expired(struct inode *inode)
|
||||
{
|
||||
if (nfs_have_delegated_attributes(inode))
|
||||
return 0;
|
||||
|
|
|
@ -888,6 +888,28 @@ out:
|
|||
return PageUptodate(page) != 0;
|
||||
}
|
||||
|
||||
/* If we know the page is up to date, and we're not using byte range locks (or
|
||||
* if we have the whole file locked for writing), it may be more efficient to
|
||||
* extend the write to cover the entire page in order to avoid fragmentation
|
||||
* inefficiencies.
|
||||
*
|
||||
* If the file is opened for synchronous writes or if we have a write delegation
|
||||
* from the server then we can just skip the rest of the checks.
|
||||
*/
|
||||
static int nfs_can_extend_write(struct file *file, struct page *page, struct inode *inode)
|
||||
{
|
||||
if (file->f_flags & O_DSYNC)
|
||||
return 0;
|
||||
if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE))
|
||||
return 1;
|
||||
if (nfs_write_pageuptodate(page, inode) && (inode->i_flock == NULL ||
|
||||
(inode->i_flock->fl_start == 0 &&
|
||||
inode->i_flock->fl_end == OFFSET_MAX &&
|
||||
inode->i_flock->fl_type != F_RDLCK)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update and possibly write a cached page of an NFS file.
|
||||
*
|
||||
|
@ -908,14 +930,7 @@ int nfs_updatepage(struct file *file, struct page *page,
|
|||
file->f_path.dentry->d_name.name, count,
|
||||
(long long)(page_file_offset(page) + offset));
|
||||
|
||||
/* If we're not using byte range locks, and we know the page
|
||||
* is up to date, it may be more efficient to extend the write
|
||||
* to cover the entire page in order to avoid fragmentation
|
||||
* inefficiencies.
|
||||
*/
|
||||
if (nfs_write_pageuptodate(page, inode) &&
|
||||
inode->i_flock == NULL &&
|
||||
!(file->f_flags & O_DSYNC)) {
|
||||
if (nfs_can_extend_write(file, page, inode)) {
|
||||
count = max(count + offset, nfs_page_length(page));
|
||||
offset = 0;
|
||||
}
|
||||
|
|
|
@ -348,6 +348,7 @@ extern int nfs_permission(struct inode *, int);
|
|||
extern int nfs_open(struct inode *, struct file *);
|
||||
extern int nfs_release(struct inode *, struct file *);
|
||||
extern int nfs_attribute_timeout(struct inode *inode);
|
||||
extern int nfs_attribute_cache_expired(struct inode *inode);
|
||||
extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
|
||||
extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
|
||||
extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue