diff options
author | Peng Tao <bergwolf@gmail.com> | 2012-09-25 02:55:57 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-10-08 19:32:22 -0400 |
commit | 6296556f0b31eaff29f2a3aee2c17b7eae895b98 (patch) | |
tree | 19f39cac9cff045e8c753ab8908deadc1c9c6bab /fs/nfs/blocklayout | |
parent | 35754bc00e94e598c432ad02f7a3d3063c4402e3 (diff) |
NFS41: send real write size in layoutget
For buffer write, block layout client scan inode mapping to find
next hole and use offset-to-hole as layoutget length. Object
layout client uses offset-to-isize as layoutget length.
For direct write, both block layout and object layout use dreq->bytes_left.
Signed-off-by: Peng Tao <tao.peng@emc.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/blocklayout')
-rw-r--r-- | fs/nfs/blocklayout/blocklayout.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index a34014a7f9a5..f1027b06a1a9 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/bio.h> /* struct bio */ | 37 | #include <linux/bio.h> /* struct bio */ |
38 | #include <linux/buffer_head.h> /* various write calls */ | 38 | #include <linux/buffer_head.h> /* various write calls */ |
39 | #include <linux/prefetch.h> | 39 | #include <linux/prefetch.h> |
40 | #include <linux/pagevec.h> | ||
40 | 41 | ||
41 | #include "../pnfs.h" | 42 | #include "../pnfs.h" |
42 | #include "../internal.h" | 43 | #include "../internal.h" |
@@ -1204,14 +1205,45 @@ bl_pg_test_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, | |||
1204 | return pnfs_generic_pg_test(pgio, prev, req); | 1205 | return pnfs_generic_pg_test(pgio, prev, req); |
1205 | } | 1206 | } |
1206 | 1207 | ||
1208 | /* | ||
1209 | * Return the number of contiguous bytes for a given inode | ||
1210 | * starting at page frame idx. | ||
1211 | */ | ||
1212 | static u64 pnfs_num_cont_bytes(struct inode *inode, pgoff_t idx) | ||
1213 | { | ||
1214 | struct address_space *mapping = inode->i_mapping; | ||
1215 | pgoff_t end; | ||
1216 | |||
1217 | /* Optimize common case that writes from 0 to end of file */ | ||
1218 | end = DIV_ROUND_UP(i_size_read(inode), PAGE_CACHE_SIZE); | ||
1219 | if (end != NFS_I(inode)->npages) { | ||
1220 | rcu_read_lock(); | ||
1221 | end = radix_tree_next_hole(&mapping->page_tree, idx + 1, ULONG_MAX); | ||
1222 | rcu_read_unlock(); | ||
1223 | } | ||
1224 | |||
1225 | if (!end) | ||
1226 | return i_size_read(inode) - (idx << PAGE_CACHE_SHIFT); | ||
1227 | else | ||
1228 | return (end - idx) << PAGE_CACHE_SHIFT; | ||
1229 | } | ||
1230 | |||
1207 | static void | 1231 | static void |
1208 | bl_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) | 1232 | bl_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) |
1209 | { | 1233 | { |
1210 | if (pgio->pg_dreq != NULL && | 1234 | if (pgio->pg_dreq != NULL && |
1211 | !is_aligned_req(req, PAGE_CACHE_SIZE)) | 1235 | !is_aligned_req(req, PAGE_CACHE_SIZE)) { |
1212 | nfs_pageio_reset_write_mds(pgio); | 1236 | nfs_pageio_reset_write_mds(pgio); |
1213 | else | 1237 | } else { |
1214 | pnfs_generic_pg_init_write(pgio, req); | 1238 | u64 wb_size; |
1239 | if (pgio->pg_dreq == NULL) | ||
1240 | wb_size = pnfs_num_cont_bytes(pgio->pg_inode, | ||
1241 | req->wb_index); | ||
1242 | else | ||
1243 | wb_size = nfs_dreq_bytes_left(pgio->pg_dreq); | ||
1244 | |||
1245 | pnfs_generic_pg_init_write(pgio, req, wb_size); | ||
1246 | } | ||
1215 | } | 1247 | } |
1216 | 1248 | ||
1217 | static bool | 1249 | static bool |