diff options
author | Scott Mayhew <smayhew@redhat.com> | 2013-07-05 17:33:19 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-07-09 19:32:50 -0400 |
commit | c7559663e42f4294ffe31fe159da6b6a66b35d61 (patch) | |
tree | 0b59b9bdc4a423efa64c79e9e9db1af68c27ff40 /fs | |
parent | 07b5ce8ef2d87f1914054804720d6facbaa3f4ce (diff) |
NFS: Allow nfs_updatepage to extend a write under additional circumstances
Currently nfs_updatepage allows a write to be extended to cover a full
page only if we don't have a byte range lock lock on the file... but if
we have a write delegation on the file or if we have the whole file
locked for writing then we should be allowed to extend the write as
well.
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
[Trond: fix up call to nfs_have_delegation()]
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/write.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index a2c7c28049d5..f1bdb7254776 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -888,6 +888,28 @@ out: | |||
888 | return PageUptodate(page) != 0; | 888 | return PageUptodate(page) != 0; |
889 | } | 889 | } |
890 | 890 | ||
891 | /* If we know the page is up to date, and we're not using byte range locks (or | ||
892 | * if we have the whole file locked for writing), it may be more efficient to | ||
893 | * extend the write to cover the entire page in order to avoid fragmentation | ||
894 | * inefficiencies. | ||
895 | * | ||
896 | * If the file is opened for synchronous writes or if we have a write delegation | ||
897 | * from the server then we can just skip the rest of the checks. | ||
898 | */ | ||
899 | static int nfs_can_extend_write(struct file *file, struct page *page, struct inode *inode) | ||
900 | { | ||
901 | if (file->f_flags & O_DSYNC) | ||
902 | return 0; | ||
903 | if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE)) | ||
904 | return 1; | ||
905 | if (nfs_write_pageuptodate(page, inode) && (inode->i_flock == NULL || | ||
906 | (inode->i_flock->fl_start == 0 && | ||
907 | inode->i_flock->fl_end == OFFSET_MAX && | ||
908 | inode->i_flock->fl_type != F_RDLCK))) | ||
909 | return 1; | ||
910 | return 0; | ||
911 | } | ||
912 | |||
891 | /* | 913 | /* |
892 | * Update and possibly write a cached page of an NFS file. | 914 | * Update and possibly write a cached page of an NFS file. |
893 | * | 915 | * |
@@ -908,14 +930,7 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
908 | file->f_path.dentry->d_name.name, count, | 930 | file->f_path.dentry->d_name.name, count, |
909 | (long long)(page_file_offset(page) + offset)); | 931 | (long long)(page_file_offset(page) + offset)); |
910 | 932 | ||
911 | /* If we're not using byte range locks, and we know the page | 933 | if (nfs_can_extend_write(file, page, inode)) { |
912 | * is up to date, it may be more efficient to extend the write | ||
913 | * to cover the entire page in order to avoid fragmentation | ||
914 | * inefficiencies. | ||
915 | */ | ||
916 | if (nfs_write_pageuptodate(page, inode) && | ||
917 | inode->i_flock == NULL && | ||
918 | !(file->f_flags & O_DSYNC)) { | ||
919 | count = max(count + offset, nfs_page_length(page)); | 934 | count = max(count + offset, nfs_page_length(page)); |
920 | offset = 0; | 935 | offset = 0; |
921 | } | 936 | } |