diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-03-19 15:35:50 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-03-19 15:35:50 -0400 |
commit | 7fe5c398fc2186ed586db11106a6692d871d0d58 (patch) | |
tree | 1133bd775a23fb07ca759e4d6c44132c14576b75 /fs/nfs/inode.c | |
parent | b1e4adf4ea41bb8b5a7bfc1a7001f137e65495df (diff) |
NFS: Optimise NFS close()
Close-to-open cache consistency rules really only require us to flush out
writes on calls to close(), and require us to revalidate attributes on the
very last close of the file.
Currently we appear to be doing a lot of extra attribute revalidation
and cache flushes.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index c40adc5dd609..a834d1d850b7 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -541,6 +541,32 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
541 | return err; | 541 | return err; |
542 | } | 542 | } |
543 | 543 | ||
544 | /** | ||
545 | * nfs_close_context - Common close_context() routine NFSv2/v3 | ||
546 | * @ctx: pointer to context | ||
547 | * @is_sync: is this a synchronous close | ||
548 | * | ||
549 | * always ensure that the attributes are up to date if we're mounted | ||
550 | * with close-to-open semantics | ||
551 | */ | ||
552 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync) | ||
553 | { | ||
554 | struct inode *inode; | ||
555 | struct nfs_server *server; | ||
556 | |||
557 | if (!(ctx->mode & FMODE_WRITE)) | ||
558 | return; | ||
559 | if (!is_sync) | ||
560 | return; | ||
561 | inode = ctx->path.dentry->d_inode; | ||
562 | if (!list_empty(&NFS_I(inode)->open_files)) | ||
563 | return; | ||
564 | server = NFS_SERVER(inode); | ||
565 | if (server->flags & NFS_MOUNT_NOCTO) | ||
566 | return; | ||
567 | nfs_revalidate_inode(server, inode); | ||
568 | } | ||
569 | |||
544 | static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred) | 570 | static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred) |
545 | { | 571 | { |
546 | struct nfs_open_context *ctx; | 572 | struct nfs_open_context *ctx; |
@@ -567,24 +593,15 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) | |||
567 | return ctx; | 593 | return ctx; |
568 | } | 594 | } |
569 | 595 | ||
570 | static void __put_nfs_open_context(struct nfs_open_context *ctx, int wait) | 596 | static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync) |
571 | { | 597 | { |
572 | struct inode *inode; | 598 | struct inode *inode = ctx->path.dentry->d_inode; |
573 | 599 | ||
574 | if (ctx == NULL) | ||
575 | return; | ||
576 | |||
577 | inode = ctx->path.dentry->d_inode; | ||
578 | if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock)) | 600 | if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock)) |
579 | return; | 601 | return; |
580 | list_del(&ctx->list); | 602 | list_del(&ctx->list); |
581 | spin_unlock(&inode->i_lock); | 603 | spin_unlock(&inode->i_lock); |
582 | if (ctx->state != NULL) { | 604 | NFS_PROTO(inode)->close_context(ctx, is_sync); |
583 | if (wait) | ||
584 | nfs4_close_sync(&ctx->path, ctx->state, ctx->mode); | ||
585 | else | ||
586 | nfs4_close_state(&ctx->path, ctx->state, ctx->mode); | ||
587 | } | ||
588 | if (ctx->cred != NULL) | 605 | if (ctx->cred != NULL) |
589 | put_rpccred(ctx->cred); | 606 | put_rpccred(ctx->cred); |
590 | path_put(&ctx->path); | 607 | path_put(&ctx->path); |