154 lines
5.0 KiB
Diff
154 lines
5.0 KiB
Diff
From: Trond Myklebust <Trond.Myklebust@netapp.com>
|
|
|
|
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>
|
|
---
|
|
fs/nfs/dir.c | 25 +++++++++++++++++++------
|
|
fs/nfs/inode.c | 4 ++--
|
|
fs/nfs/nfs4proc.c | 10 +++++++---
|
|
3 files changed, 28 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
|
|
index fd9a872..bb132a8 100644
|
|
--- a/fs/nfs/dir.c
|
|
+++ b/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) {
|
|
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
|
|
index f649fba..57d0abb 100644
|
|
--- a/fs/nfs/inode.c
|
|
+++ b/fs/nfs/inode.c
|
|
@@ -401,7 +401,7 @@ out_no_inode:
|
|
goto out;
|
|
}
|
|
|
|
-#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE)
|
|
+#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE|ATTR_OPEN)
|
|
|
|
int
|
|
nfs_setattr(struct dentry *dentry, struct iattr *attr)
|
|
@@ -423,7 +423,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
|
|
|
|
/* Optimization: if the end result is no change, don't RPC */
|
|
attr->ia_valid &= NFS_VALID_ATTRS;
|
|
- if ((attr->ia_valid & ~ATTR_FILE) == 0)
|
|
+ if ((attr->ia_valid & ~(ATTR_FILE|ATTR_OPEN)) == 0)
|
|
return 0;
|
|
|
|
/* Write all dirty data */
|
|
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
|
|
index 1515e45..c4c6b48 100644
|
|
--- a/fs/nfs/nfs4proc.c
|
|
+++ b/fs/nfs/nfs4proc.c
|
|
@@ -833,7 +833,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
|
|
p->o_arg.bitmask = server->attr_bitmask;
|
|
p->o_arg.dir_bitmask = server->cache_consistency_bitmask;
|
|
p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
|
|
- if (flags & O_CREAT) {
|
|
+ if (attrs != NULL && attrs->ia_valid != 0) {
|
|
u32 *s;
|
|
|
|
p->o_arg.u.attrs = &p->attrs;
|
|
@@ -890,7 +890,7 @@ static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode
|
|
{
|
|
int ret = 0;
|
|
|
|
- if (open_mode & O_EXCL)
|
|
+ if (open_mode & (O_EXCL|O_TRUNC))
|
|
goto out;
|
|
switch (mode & (FMODE_READ|FMODE_WRITE)) {
|
|
case FMODE_READ:
|
|
@@ -1038,7 +1038,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
|
|
struct nfs4_state *state = opendata->state;
|
|
struct nfs_inode *nfsi = NFS_I(state->inode);
|
|
struct nfs_delegation *delegation;
|
|
- int open_mode = opendata->o_arg.open_flags & O_EXCL;
|
|
+ int open_mode = opendata->o_arg.open_flags & (O_EXCL|O_TRUNC);
|
|
fmode_t fmode = opendata->o_arg.fmode;
|
|
nfs4_stateid stateid;
|
|
int ret = -EAGAIN;
|
|
@@ -2439,6 +2439,10 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
|
|
}
|
|
}
|
|
|
|
+ /* Deal with open(O_TRUNC) */
|
|
+ if (sattr->ia_valid & ATTR_OPEN)
|
|
+ sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN);
|
|
+
|
|
status = nfs4_do_setattr(inode, cred, fattr, sattr, state);
|
|
if (status == 0)
|
|
nfs_setattr_update_inode(inode, sattr);
|
|
--
|
|
1.7.7.6
|
|
|
|
_______________________________________________
|
|
kernel mailing list
|
|
kernel@lists.fedoraproject.org
|
|
https://admin.fedoraproject.org/mailman/listinfo/kernel
|