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 | |
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')
-rw-r--r-- | fs/nfs/blocklayout/blocklayout.c | 38 | ||||
-rw-r--r-- | fs/nfs/direct.c | 7 | ||||
-rw-r--r-- | fs/nfs/internal.h | 1 | ||||
-rw-r--r-- | fs/nfs/objlayout/objio_osd.c | 9 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 6 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 3 |
6 files changed, 57 insertions, 7 deletions
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index a34014a7f9a..f1027b06a1a 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 |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 4be8673ee18..cae26cbd59e 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/kref.h> | 46 | #include <linux/kref.h> |
47 | #include <linux/slab.h> | 47 | #include <linux/slab.h> |
48 | #include <linux/task_io_accounting_ops.h> | 48 | #include <linux/task_io_accounting_ops.h> |
49 | #include <linux/module.h> | ||
49 | 50 | ||
50 | #include <linux/nfs_fs.h> | 51 | #include <linux/nfs_fs.h> |
51 | #include <linux/nfs_page.h> | 52 | #include <linux/nfs_page.h> |
@@ -191,6 +192,12 @@ static void nfs_direct_req_release(struct nfs_direct_req *dreq) | |||
191 | kref_put(&dreq->kref, nfs_direct_req_free); | 192 | kref_put(&dreq->kref, nfs_direct_req_free); |
192 | } | 193 | } |
193 | 194 | ||
195 | ssize_t nfs_dreq_bytes_left(struct nfs_direct_req *dreq) | ||
196 | { | ||
197 | return dreq->bytes_left; | ||
198 | } | ||
199 | EXPORT_SYMBOL_GPL(nfs_dreq_bytes_left); | ||
200 | |||
194 | /* | 201 | /* |
195 | * Collects and returns the final error value/byte-count. | 202 | * Collects and returns the final error value/byte-count. |
196 | */ | 203 | */ |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 89a795dc302..59b133c5d65 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -464,6 +464,7 @@ static inline void nfs_inode_dio_wait(struct inode *inode) | |||
464 | { | 464 | { |
465 | inode_dio_wait(inode); | 465 | inode_dio_wait(inode); |
466 | } | 466 | } |
467 | extern ssize_t nfs_dreq_bytes_left(struct nfs_direct_req *dreq); | ||
467 | 468 | ||
468 | /* nfs4proc.c */ | 469 | /* nfs4proc.c */ |
469 | extern void __nfs4_read_done_cb(struct nfs_read_data *); | 470 | extern void __nfs4_read_done_cb(struct nfs_read_data *); |
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index ea6d111b03e..be731e6b7b9 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <scsi/osd_ore.h> | 41 | #include <scsi/osd_ore.h> |
42 | 42 | ||
43 | #include "objlayout.h" | 43 | #include "objlayout.h" |
44 | #include "../internal.h" | ||
44 | 45 | ||
45 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD | 46 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD |
46 | 47 | ||
@@ -606,8 +607,14 @@ static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout, | |||
606 | void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) | 607 | void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) |
607 | { | 608 | { |
608 | unsigned long stripe_end = 0; | 609 | unsigned long stripe_end = 0; |
610 | u64 wb_size; | ||
609 | 611 | ||
610 | pnfs_generic_pg_init_write(pgio, req); | 612 | if (pgio->pg_dreq == NULL) |
613 | wb_size = i_size_read(pgio->pg_inode) - req_offset(req); | ||
614 | else | ||
615 | wb_size = nfs_dreq_bytes_left(pgio->pg_dreq); | ||
616 | |||
617 | pnfs_generic_pg_init_write(pgio, req, wb_size); | ||
611 | if (unlikely(pgio->pg_lseg == NULL)) | 618 | if (unlikely(pgio->pg_lseg == NULL)) |
612 | return; /* Not pNFS */ | 619 | return; /* Not pNFS */ |
613 | 620 | ||
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index bd9769296e4..9a2bcce4528 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -1240,7 +1240,8 @@ pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *r | |||
1240 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_read); | 1240 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_read); |
1241 | 1241 | ||
1242 | void | 1242 | void |
1243 | pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) | 1243 | pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, |
1244 | struct nfs_page *req, u64 wb_size) | ||
1244 | { | 1245 | { |
1245 | BUG_ON(pgio->pg_lseg != NULL); | 1246 | BUG_ON(pgio->pg_lseg != NULL); |
1246 | 1247 | ||
@@ -1248,10 +1249,11 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page * | |||
1248 | nfs_pageio_reset_write_mds(pgio); | 1249 | nfs_pageio_reset_write_mds(pgio); |
1249 | return; | 1250 | return; |
1250 | } | 1251 | } |
1252 | |||
1251 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 1253 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
1252 | req->wb_context, | 1254 | req->wb_context, |
1253 | req_offset(req), | 1255 | req_offset(req), |
1254 | req->wb_bytes, | 1256 | wb_size, |
1255 | IOMODE_RW, | 1257 | IOMODE_RW, |
1256 | GFP_NOFS); | 1258 | GFP_NOFS); |
1257 | /* If no lseg, fall back to write through mds */ | 1259 | /* If no lseg, fall back to write through mds */ |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 6cede2c6c96..2d722dba111 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -186,7 +186,8 @@ void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32); | |||
186 | void unset_pnfs_layoutdriver(struct nfs_server *); | 186 | void unset_pnfs_layoutdriver(struct nfs_server *); |
187 | void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *); | 187 | void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *); |
188 | int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc); | 188 | int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc); |
189 | void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *, struct nfs_page *); | 189 | void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, |
190 | struct nfs_page *req, u64 wb_size); | ||
190 | int pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc); | 191 | int pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc); |
191 | bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req); | 192 | bool pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, struct nfs_page *req); |
192 | void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg); | 193 | void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg); |