aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-01-17 22:04:26 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-01-31 19:28:07 -0500
commit536e43d12b9517bbbf6114cd1a12be27857a4d7a (patch)
treea40424a430fd651fe7b35232717f2201c608059a
parent48c22eb21071a3524f8b6e587371be35b5e86969 (diff)
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>
-rw-r--r--fs/nfs/dir.c25
-rw-r--r--fs/nfs/inode.c4
-rw-r--r--fs/nfs/nfs4proc.c10
3 files changed, 28 insertions, 11 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index fd9a872fada0..bb132a88f4e8 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
1429 } 1429 }
1430 1430
1431 open_flags = nd->intent.open.flags; 1431 open_flags = nd->intent.open.flags;
1432 attr.ia_valid = 0;
1432 1433
1433 ctx = create_nfs_open_context(dentry, open_flags); 1434 ctx = create_nfs_open_context(dentry, open_flags);
1434 res = ERR_CAST(ctx); 1435 res = ERR_CAST(ctx);
@@ -1437,11 +1438,14 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
1437 1438
1438 if (nd->flags & LOOKUP_CREATE) { 1439 if (nd->flags & LOOKUP_CREATE) {
1439 attr.ia_mode = nd->intent.open.create_mode; 1440 attr.ia_mode = nd->intent.open.create_mode;
1440 attr.ia_valid = ATTR_MODE; 1441 attr.ia_valid |= ATTR_MODE;
1441 attr.ia_mode &= ~current_umask(); 1442 attr.ia_mode &= ~current_umask();
1442 } else { 1443 } else
1443 open_flags &= ~(O_EXCL | O_CREAT); 1444 open_flags &= ~(O_EXCL | O_CREAT);
1444 attr.ia_valid = 0; 1445
1446 if (open_flags & O_TRUNC) {
1447 attr.ia_valid |= ATTR_SIZE;
1448 attr.ia_size = 0;
1445 } 1449 }
1446 1450
1447 /* Open the file on the server */ 1451 /* Open the file on the server */
@@ -1495,6 +1499,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
1495 struct inode *inode; 1499 struct inode *inode;
1496 struct inode *dir; 1500 struct inode *dir;
1497 struct nfs_open_context *ctx; 1501 struct nfs_open_context *ctx;
1502 struct iattr attr;
1498 int openflags, ret = 0; 1503 int openflags, ret = 0;
1499 1504
1500 if (nd->flags & LOOKUP_RCU) 1505 if (nd->flags & LOOKUP_RCU)
@@ -1523,19 +1528,27 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
1523 /* We cannot do exclusive creation on a positive dentry */ 1528 /* We cannot do exclusive creation on a positive dentry */
1524 if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) 1529 if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
1525 goto no_open_dput; 1530 goto no_open_dput;
1526 /* We can't create new files, or truncate existing ones here */ 1531 /* We can't create new files here */
1527 openflags &= ~(O_CREAT|O_EXCL|O_TRUNC); 1532 openflags &= ~(O_CREAT|O_EXCL);
1528 1533
1529 ctx = create_nfs_open_context(dentry, openflags); 1534 ctx = create_nfs_open_context(dentry, openflags);
1530 ret = PTR_ERR(ctx); 1535 ret = PTR_ERR(ctx);
1531 if (IS_ERR(ctx)) 1536 if (IS_ERR(ctx))
1532 goto out; 1537 goto out;
1538
1539 attr.ia_valid = 0;
1540 if (openflags & O_TRUNC) {
1541 attr.ia_valid |= ATTR_SIZE;
1542 attr.ia_size = 0;
1543 nfs_wb_all(inode);
1544 }
1545
1533 /* 1546 /*
1534 * Note: we're not holding inode->i_mutex and so may be racing with 1547 * Note: we're not holding inode->i_mutex and so may be racing with
1535 * operations that change the directory. We therefore save the 1548 * operations that change the directory. We therefore save the
1536 * change attribute *before* we do the RPC call. 1549 * change attribute *before* we do the RPC call.
1537 */ 1550 */
1538 inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, NULL); 1551 inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr);
1539 if (IS_ERR(inode)) { 1552 if (IS_ERR(inode)) {
1540 ret = PTR_ERR(inode); 1553 ret = PTR_ERR(inode);
1541 switch (ret) { 1554 switch (ret) {
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 577ad5a72a24..65486e652943 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -402,7 +402,7 @@ out_no_inode:
402 goto out; 402 goto out;
403} 403}
404 404
405#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE) 405#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)
406 406
407int 407int
408nfs_setattr(struct dentry *dentry, struct iattr *attr) 408nfs_setattr(struct dentry *dentry, struct iattr *attr)
@@ -424,7 +424,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
424 424
425 /* Optimization: if the end result is no change, don't RPC */ 425 /* Optimization: if the end result is no change, don't RPC */
426 attr->ia_valid &= NFS_VALID_ATTRS; 426 attr->ia_valid &= NFS_VALID_ATTRS;
427 if ((attr->ia_valid & ~ATTR_FILE) == 0) 427 if ((attr->ia_valid & ~(ATTR_FILE|ATTR_OPEN)) == 0)
428 return 0; 428 return 0;
429 429
430 /* Write all dirty data */ 430 /* Write all dirty data */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 88a8b6999b4f..360240cc1e9b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -828,7 +828,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
828 p->o_arg.bitmask = server->attr_bitmask; 828 p->o_arg.bitmask = server->attr_bitmask;
829 p->o_arg.dir_bitmask = server->cache_consistency_bitmask; 829 p->o_arg.dir_bitmask = server->cache_consistency_bitmask;
830 p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; 830 p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
831 if (flags & O_CREAT) { 831 if (attrs != NULL && attrs->ia_valid != 0) {
832 u32 *s; 832 u32 *s;
833 833
834 p->o_arg.u.attrs = &p->attrs; 834 p->o_arg.u.attrs = &p->attrs;
@@ -885,7 +885,7 @@ static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode
885{ 885{
886 int ret = 0; 886 int ret = 0;
887 887
888 if (open_mode & O_EXCL) 888 if (open_mode & (O_EXCL|O_TRUNC))
889 goto out; 889 goto out;
890 switch (mode & (FMODE_READ|FMODE_WRITE)) { 890 switch (mode & (FMODE_READ|FMODE_WRITE)) {
891 case FMODE_READ: 891 case FMODE_READ:
@@ -1033,7 +1033,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
1033 struct nfs4_state *state = opendata->state; 1033 struct nfs4_state *state = opendata->state;
1034 struct nfs_inode *nfsi = NFS_I(state->inode); 1034 struct nfs_inode *nfsi = NFS_I(state->inode);
1035 struct nfs_delegation *delegation; 1035 struct nfs_delegation *delegation;
1036 int open_mode = opendata->o_arg.open_flags & O_EXCL; 1036 int open_mode = opendata->o_arg.open_flags & (O_EXCL|O_TRUNC);
1037 fmode_t fmode = opendata->o_arg.fmode; 1037 fmode_t fmode = opendata->o_arg.fmode;
1038 nfs4_stateid stateid; 1038 nfs4_stateid stateid;
1039 int ret = -EAGAIN; 1039 int ret = -EAGAIN;
@@ -2431,6 +2431,10 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
2431 } 2431 }
2432 } 2432 }
2433 2433
2434 /* Deal with open(O_TRUNC) */
2435 if (sattr->ia_valid & ATTR_OPEN)
2436 sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN);
2437
2434 status = nfs4_do_setattr(inode, cred, fattr, sattr, state); 2438 status = nfs4_do_setattr(inode, cred, fattr, sattr, state);
2435 if (status == 0) 2439 if (status == 0)
2436 nfs_setattr_update_inode(inode, sattr); 2440 nfs_setattr_update_inode(inode, sattr);