diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-01-17 22:04:26 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-01-31 19:28:07 -0500 |
commit | 536e43d12b9517bbbf6114cd1a12be27857a4d7a (patch) | |
tree | a40424a430fd651fe7b35232717f2201c608059a | |
parent | 48c22eb21071a3524f8b6e587371be35b5e86969 (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.c | 25 | ||||
-rw-r--r-- | fs/nfs/inode.c | 4 | ||||
-rw-r--r-- | 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 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 | ||
407 | int | 407 | int |
408 | nfs_setattr(struct dentry *dentry, struct iattr *attr) | 408 | nfs_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); |