NFS: Optimise away unnecessary setattrs for open(O_TRUNC);
Currently, we will correctly optimise away a truncate that doesn't change the file size. However, in the case of open(O_TRUNC), we also want to optimise away the time changes. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
25
fs/nfs/dir.c
25
fs/nfs/dir.c
@@ -1429,6 +1429,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
|
||||
}
|
||||
|
||||
open_flags = nd->intent.open.flags;
|
||||
attr.ia_valid = 0;
|
||||
|
||||
ctx = create_nfs_open_context(dentry, open_flags);
|
||||
res = ERR_CAST(ctx);
|
||||
@@ -1437,11 +1438,14 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
|
||||
|
||||
if (nd->flags & LOOKUP_CREATE) {
|
||||
attr.ia_mode = nd->intent.open.create_mode;
|
||||
attr.ia_valid = ATTR_MODE;
|
||||
attr.ia_valid |= ATTR_MODE;
|
||||
attr.ia_mode &= ~current_umask();
|
||||
} else {
|
||||
} else
|
||||
open_flags &= ~(O_EXCL | O_CREAT);
|
||||
attr.ia_valid = 0;
|
||||
|
||||
if (open_flags & O_TRUNC) {
|
||||
attr.ia_valid |= ATTR_SIZE;
|
||||
attr.ia_size = 0;
|
||||
}
|
||||
|
||||
/* Open the file on the server */
|
||||
@@ -1495,6 +1499,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
struct inode *inode;
|
||||
struct inode *dir;
|
||||
struct nfs_open_context *ctx;
|
||||
struct iattr attr;
|
||||
int openflags, ret = 0;
|
||||
|
||||
if (nd->flags & LOOKUP_RCU)
|
||||
@@ -1523,19 +1528,27 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
|
||||
/* We cannot do exclusive creation on a positive dentry */
|
||||
if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
|
||||
goto no_open_dput;
|
||||
/* We can't create new files, or truncate existing ones here */
|
||||
openflags &= ~(O_CREAT|O_EXCL|O_TRUNC);
|
||||
/* We can't create new files here */
|
||||
openflags &= ~(O_CREAT|O_EXCL);
|
||||
|
||||
ctx = create_nfs_open_context(dentry, openflags);
|
||||
ret = PTR_ERR(ctx);
|
||||
if (IS_ERR(ctx))
|
||||
goto out;
|
||||
|
||||
attr.ia_valid = 0;
|
||||
if (openflags & O_TRUNC) {
|
||||
attr.ia_valid |= ATTR_SIZE;
|
||||
attr.ia_size = 0;
|
||||
nfs_wb_all(inode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: we're not holding inode->i_mutex and so may be racing with
|
||||
* operations that change the directory. We therefore save the
|
||||
* change attribute *before* we do the RPC call.
|
||||
*/
|
||||
inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, NULL);
|
||||
inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr);
|
||||
if (IS_ERR(inode)) {
|
||||
ret = PTR_ERR(inode);
|
||||
switch (ret) {
|
||||
|
Reference in New Issue
Block a user