diff options
-rw-r--r-- | fs/nfs/file.c | 15 | ||||
-rw-r--r-- | fs/nfs/internal.h | 2 | ||||
-rw-r--r-- | fs/nfs/write.c | 27 |
3 files changed, 43 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 | ||
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 50f7068903b9..2415198d29ad 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -431,6 +431,8 @@ void nfs_request_remove_commit_list(struct nfs_page *req, | |||
431 | void nfs_init_cinfo(struct nfs_commit_info *cinfo, | 431 | void nfs_init_cinfo(struct nfs_commit_info *cinfo, |
432 | struct inode *inode, | 432 | struct inode *inode, |
433 | struct nfs_direct_req *dreq); | 433 | struct nfs_direct_req *dreq); |
434 | int nfs_key_timeout_notify(struct file *filp, struct inode *inode); | ||
435 | bool nfs_ctx_key_to_expire(struct nfs_open_context *ctx); | ||
434 | 436 | ||
435 | #ifdef CONFIG_MIGRATION | 437 | #ifdef CONFIG_MIGRATION |
436 | extern int nfs_migrate_page(struct address_space *, | 438 | extern int nfs_migrate_page(struct address_space *, |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index d37e8ca9ab86..94eb4504731a 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -876,6 +876,33 @@ int nfs_flush_incompatible(struct file *file, struct page *page) | |||
876 | } | 876 | } |
877 | 877 | ||
878 | /* | 878 | /* |
879 | * Avoid buffered writes when a open context credential's key would | ||
880 | * expire soon. | ||
881 | * | ||
882 | * Returns -EACCES if the key will expire within RPC_KEY_EXPIRE_FAIL. | ||
883 | * | ||
884 | * Return 0 and set a credential flag which triggers the inode to flush | ||
885 | * and performs NFS_FILE_SYNC writes if the key will expired within | ||
886 | * RPC_KEY_EXPIRE_TIMEO. | ||
887 | */ | ||
888 | int | ||
889 | nfs_key_timeout_notify(struct file *filp, struct inode *inode) | ||
890 | { | ||
891 | struct nfs_open_context *ctx = nfs_file_open_context(filp); | ||
892 | struct rpc_auth *auth = NFS_SERVER(inode)->client->cl_auth; | ||
893 | |||
894 | return rpcauth_key_timeout_notify(auth, ctx->cred); | ||
895 | } | ||
896 | |||
897 | /* | ||
898 | * Test if the open context credential key is marked to expire soon. | ||
899 | */ | ||
900 | bool nfs_ctx_key_to_expire(struct nfs_open_context *ctx) | ||
901 | { | ||
902 | return rpcauth_cred_key_to_expire(ctx->cred); | ||
903 | } | ||
904 | |||
905 | /* | ||
879 | * If the page cache is marked as unsafe or invalid, then we can't rely on | 906 | * If the page cache is marked as unsafe or invalid, then we can't rely on |
880 | * the PageUptodate() flag. In this case, we will need to turn off | 907 | * the PageUptodate() flag. In this case, we will need to turn off |
881 | * write optimisations that depend on the page contents being correct. | 908 | * write optimisations that depend on the page contents being correct. |