summaryrefslogtreecommitdiffstats
path: root/fs/nfs/file.c
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2013-08-14 11:59:16 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-09-03 15:25:09 -0400
commitdc24826bfca8d788d05f625208f06d90be5560b3 (patch)
treecc6fa221202666ac694581061caf373b431ff9bd /fs/nfs/file.c
parent4de6caa270afaa381dd3373e9e6d148b1090e0ec (diff)
NFS avoid expired credential keys for buffered writes
We must avoid buffering a WRITE that is using a credential key (e.g. a GSS context key) that is about to expire or has expired. We currently will paint ourselves into a corner by returning success to the applciation for such a buffered WRITE, only to discover that we do not have permission when we attempt to flush the WRITE (and potentially associated COMMIT) to disk. Use the RPC layer credential key timeout and expire routines which use a a watermark, gss_key_expire_timeo. We test the key in nfs_file_write. If a WRITE is using a credential with a key that will expire within watermark seconds, flush the inode in nfs_write_end and send only NFS_FILE_SYNC WRITEs by adding nfs_ctx_key_to_expire to nfs_need_sync_write. Note that this results in single page NFS_FILE_SYNC WRITEs. Signed-off-by: Andy Adamson <andros@netapp.com> [Trond: removed a pr_warn_ratelimited() for now] Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r--fs/nfs/file.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index d6a9db0a8545..1e6bfdbc1aff 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -411,6 +411,7 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,
411 struct page *page, void *fsdata) 411 struct page *page, void *fsdata)
412{ 412{
413 unsigned offset = pos & (PAGE_CACHE_SIZE - 1); 413 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
414 struct nfs_open_context *ctx = nfs_file_open_context(file);
414 int status; 415 int status;
415 416
416 dfprintk(PAGECACHE, "NFS: write_end(%s/%s(%ld), %u@%lld)\n", 417 dfprintk(PAGECACHE, "NFS: write_end(%s/%s(%ld), %u@%lld)\n",
@@ -446,6 +447,13 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,
446 if (status < 0) 447 if (status < 0)
447 return status; 448 return status;
448 NFS_I(mapping->host)->write_io += copied; 449 NFS_I(mapping->host)->write_io += copied;
450
451 if (nfs_ctx_key_to_expire(ctx)) {
452 status = nfs_wb_all(mapping->host);
453 if (status < 0)
454 return status;
455 }
456
449 return copied; 457 return copied;
450} 458}
451 459
@@ -642,7 +650,8 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode)
642 if (IS_SYNC(inode) || (filp->f_flags & O_DSYNC)) 650 if (IS_SYNC(inode) || (filp->f_flags & O_DSYNC))
643 return 1; 651 return 1;
644 ctx = nfs_file_open_context(filp); 652 ctx = nfs_file_open_context(filp);
645 if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) 653 if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags) ||
654 nfs_ctx_key_to_expire(ctx))
646 return 1; 655 return 1;
647 return 0; 656 return 0;
648} 657}
@@ -656,6 +665,10 @@ ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
656 ssize_t result; 665 ssize_t result;
657 size_t count = iov_length(iov, nr_segs); 666 size_t count = iov_length(iov, nr_segs);
658 667
668 result = nfs_key_timeout_notify(iocb->ki_filp, inode);
669 if (result)
670 return result;
671
659 if (iocb->ki_filp->f_flags & O_DIRECT) 672 if (iocb->ki_filp->f_flags & O_DIRECT)
660 return nfs_file_direct_write(iocb, iov, nr_segs, pos, true); 673 return nfs_file_direct_write(iocb, iov, nr_segs, pos, true);
661 674