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 d6a9db0a854..1e6bfdbc1af 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,
struct page *page, void *fsdata)
{
unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
+ struct nfs_open_context *ctx = nfs_file_open_context(file);
int status;
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,
if (status < 0)
return status;
NFS_I(mapping->host)->write_io += copied;
+
+ if (nfs_ctx_key_to_expire(ctx)) {
+ status = nfs_wb_all(mapping->host);
+ if (status < 0)
+ return status;
+ }
+
return copied;
}
@@ -642,7 +650,8 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode)
if (IS_SYNC(inode) || (filp->f_flags & O_DSYNC))
return 1;
ctx = nfs_file_open_context(filp);
- if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags))
+ if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags) ||
+ nfs_ctx_key_to_expire(ctx))
return 1;
return 0;
}
@@ -656,6 +665,10 @@ ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
ssize_t result;
size_t count = iov_length(iov, nr_segs);
+ result = nfs_key_timeout_notify(iocb->ki_filp, inode);
+ if (result)
+ return result;
+
if (iocb->ki_filp->f_flags & O_DIRECT)
return nfs_file_direct_write(iocb, iov, nr_segs, pos, true);