diff options
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 26 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 12 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 16 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 12 | ||||
-rw-r--r-- | fs/nfs/read.c | 1 | ||||
-rw-r--r-- | fs/nfs/write.c | 3 | ||||
-rw-r--r-- | include/linux/nfs_page.h | 2 |
7 files changed, 70 insertions, 2 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 23f930caf1e2..0efe8cbd9e3c 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -252,6 +252,31 @@ filelayout_free_lseg(struct pnfs_layout_segment *lseg) | |||
252 | _filelayout_free_lseg(fl); | 252 | _filelayout_free_lseg(fl); |
253 | } | 253 | } |
254 | 254 | ||
255 | /* | ||
256 | * filelayout_pg_test(). Called by nfs_can_coalesce_requests() | ||
257 | * | ||
258 | * return 1 : coalesce page | ||
259 | * return 0 : don't coalesce page | ||
260 | */ | ||
261 | int | ||
262 | filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, | ||
263 | struct nfs_page *req) | ||
264 | { | ||
265 | u64 p_stripe, r_stripe; | ||
266 | u32 stripe_unit; | ||
267 | |||
268 | if (!pgio->pg_lseg) | ||
269 | return 1; | ||
270 | p_stripe = (u64)prev->wb_index << PAGE_CACHE_SHIFT; | ||
271 | r_stripe = (u64)req->wb_index << PAGE_CACHE_SHIFT; | ||
272 | stripe_unit = FILELAYOUT_LSEG(pgio->pg_lseg)->stripe_unit; | ||
273 | |||
274 | do_div(p_stripe, stripe_unit); | ||
275 | do_div(r_stripe, stripe_unit); | ||
276 | |||
277 | return (p_stripe == r_stripe); | ||
278 | } | ||
279 | |||
255 | static struct pnfs_layoutdriver_type filelayout_type = { | 280 | static struct pnfs_layoutdriver_type filelayout_type = { |
256 | .id = LAYOUT_NFSV4_1_FILES, | 281 | .id = LAYOUT_NFSV4_1_FILES, |
257 | .name = "LAYOUT_NFSV4_1_FILES", | 282 | .name = "LAYOUT_NFSV4_1_FILES", |
@@ -260,6 +285,7 @@ static struct pnfs_layoutdriver_type filelayout_type = { | |||
260 | .clear_layoutdriver = filelayout_clear_layoutdriver, | 285 | .clear_layoutdriver = filelayout_clear_layoutdriver, |
261 | .alloc_lseg = filelayout_alloc_lseg, | 286 | .alloc_lseg = filelayout_alloc_lseg, |
262 | .free_lseg = filelayout_free_lseg, | 287 | .free_lseg = filelayout_free_lseg, |
288 | .pg_test = filelayout_pg_test, | ||
263 | }; | 289 | }; |
264 | 290 | ||
265 | static int __init nfs4filelayout_init(void) | 291 | static int __init nfs4filelayout_init(void) |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index e1164e3f9e69..9b9a65c9bb4f 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -226,6 +226,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | |||
226 | desc->pg_doio = doio; | 226 | desc->pg_doio = doio; |
227 | desc->pg_ioflags = io_flags; | 227 | desc->pg_ioflags = io_flags; |
228 | desc->pg_error = 0; | 228 | desc->pg_error = 0; |
229 | desc->pg_lseg = NULL; | ||
229 | } | 230 | } |
230 | 231 | ||
231 | /** | 232 | /** |
@@ -240,7 +241,8 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | |||
240 | * Return 'true' if this is the case, else return 'false'. | 241 | * Return 'true' if this is the case, else return 'false'. |
241 | */ | 242 | */ |
242 | static int nfs_can_coalesce_requests(struct nfs_page *prev, | 243 | static int nfs_can_coalesce_requests(struct nfs_page *prev, |
243 | struct nfs_page *req) | 244 | struct nfs_page *req, |
245 | struct nfs_pageio_descriptor *pgio) | ||
244 | { | 246 | { |
245 | if (req->wb_context->cred != prev->wb_context->cred) | 247 | if (req->wb_context->cred != prev->wb_context->cred) |
246 | return 0; | 248 | return 0; |
@@ -254,6 +256,12 @@ static int nfs_can_coalesce_requests(struct nfs_page *prev, | |||
254 | return 0; | 256 | return 0; |
255 | if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE) | 257 | if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE) |
256 | return 0; | 258 | return 0; |
259 | /* | ||
260 | * Non-whole file layouts need to check that req is inside of | ||
261 | * pgio->pg_lseg. | ||
262 | */ | ||
263 | if (pgio->pg_test && !pgio->pg_test(pgio, prev, req)) | ||
264 | return 0; | ||
257 | return 1; | 265 | return 1; |
258 | } | 266 | } |
259 | 267 | ||
@@ -286,7 +294,7 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc, | |||
286 | if (newlen > desc->pg_bsize) | 294 | if (newlen > desc->pg_bsize) |
287 | return 0; | 295 | return 0; |
288 | prev = nfs_list_entry(desc->pg_list.prev); | 296 | prev = nfs_list_entry(desc->pg_list.prev); |
289 | if (!nfs_can_coalesce_requests(prev, req)) | 297 | if (!nfs_can_coalesce_requests(prev, req, desc)) |
290 | return 0; | 298 | return 0; |
291 | } else | 299 | } else |
292 | desc->pg_base = req->wb_pgbase; | 300 | desc->pg_base = req->wb_pgbase; |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 3afa82e45438..330cee115de0 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -858,6 +858,22 @@ out_forget_reply: | |||
858 | goto out; | 858 | goto out; |
859 | } | 859 | } |
860 | 860 | ||
861 | static void | ||
862 | pnfs_set_pg_test(struct inode *inode, struct nfs_pageio_descriptor *pgio) | ||
863 | { | ||
864 | struct pnfs_layoutdriver_type *ld; | ||
865 | |||
866 | ld = NFS_SERVER(inode)->pnfs_curr_ld; | ||
867 | pgio->pg_test = (ld ? ld->pg_test : NULL); | ||
868 | } | ||
869 | |||
870 | void | ||
871 | pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, | ||
872 | struct inode *inode) | ||
873 | { | ||
874 | pnfs_set_pg_test(inode, pgio); | ||
875 | } | ||
876 | |||
861 | /* | 877 | /* |
862 | * Device ID cache. Currently supports one layout type per struct nfs_client. | 878 | * Device ID cache. Currently supports one layout type per struct nfs_client. |
863 | * Add layout type to the lookup key to expand to support multiple types. | 879 | * Add layout type to the lookup key to expand to support multiple types. |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 9a994bc9899f..db52d9658570 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -30,6 +30,8 @@ | |||
30 | #ifndef FS_NFS_PNFS_H | 30 | #ifndef FS_NFS_PNFS_H |
31 | #define FS_NFS_PNFS_H | 31 | #define FS_NFS_PNFS_H |
32 | 32 | ||
33 | #include <linux/nfs_page.h> | ||
34 | |||
33 | enum { | 35 | enum { |
34 | NFS_LSEG_VALID = 0, /* cleared when lseg is recalled/returned */ | 36 | NFS_LSEG_VALID = 0, /* cleared when lseg is recalled/returned */ |
35 | NFS_LSEG_ROC, /* roc bit received from server */ | 37 | NFS_LSEG_ROC, /* roc bit received from server */ |
@@ -65,6 +67,9 @@ struct pnfs_layoutdriver_type { | |||
65 | int (*clear_layoutdriver) (struct nfs_server *); | 67 | int (*clear_layoutdriver) (struct nfs_server *); |
66 | struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr); | 68 | struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr); |
67 | void (*free_lseg) (struct pnfs_layout_segment *lseg); | 69 | void (*free_lseg) (struct pnfs_layout_segment *lseg); |
70 | |||
71 | /* test for nfs page cache coalescing */ | ||
72 | int (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *); | ||
68 | }; | 73 | }; |
69 | 74 | ||
70 | struct pnfs_layout_hdr { | 75 | struct pnfs_layout_hdr { |
@@ -151,6 +156,7 @@ pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, | |||
151 | enum pnfs_iomode access_type); | 156 | enum pnfs_iomode access_type); |
152 | void set_pnfs_layoutdriver(struct nfs_server *, u32 id); | 157 | void set_pnfs_layoutdriver(struct nfs_server *, u32 id); |
153 | void unset_pnfs_layoutdriver(struct nfs_server *); | 158 | void unset_pnfs_layoutdriver(struct nfs_server *); |
159 | void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *); | ||
154 | int pnfs_layout_process(struct nfs4_layoutget *lgp); | 160 | int pnfs_layout_process(struct nfs4_layoutget *lgp); |
155 | void pnfs_free_lseg_list(struct list_head *tmp_list); | 161 | void pnfs_free_lseg_list(struct list_head *tmp_list); |
156 | void pnfs_destroy_layout(struct nfs_inode *); | 162 | void pnfs_destroy_layout(struct nfs_inode *); |
@@ -250,6 +256,12 @@ static inline void unset_pnfs_layoutdriver(struct nfs_server *s) | |||
250 | { | 256 | { |
251 | } | 257 | } |
252 | 258 | ||
259 | static inline void | ||
260 | pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *ino) | ||
261 | { | ||
262 | pgio->pg_test = NULL; | ||
263 | } | ||
264 | |||
253 | #endif /* CONFIG_NFS_V4_1 */ | 265 | #endif /* CONFIG_NFS_V4_1 */ |
254 | 266 | ||
255 | #endif /* FS_NFS_PNFS_H */ | 267 | #endif /* FS_NFS_PNFS_H */ |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index aedcaa7f291f..2a2765975e1f 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -626,6 +626,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, | |||
626 | goto read_complete; /* all pages were read */ | 626 | goto read_complete; /* all pages were read */ |
627 | 627 | ||
628 | pnfs_update_layout(inode, desc.ctx, IOMODE_READ); | 628 | pnfs_update_layout(inode, desc.ctx, IOMODE_READ); |
629 | pnfs_pageio_init_read(&pgio, inode); | ||
629 | if (rsize < PAGE_CACHE_SIZE) | 630 | if (rsize < PAGE_CACHE_SIZE) |
630 | nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0); | 631 | nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0); |
631 | else | 632 | else |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index ae528b98b804..40143c4747a5 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "iostat.h" | 28 | #include "iostat.h" |
29 | #include "nfs4_fs.h" | 29 | #include "nfs4_fs.h" |
30 | #include "fscache.h" | 30 | #include "fscache.h" |
31 | #include "pnfs.h" | ||
31 | 32 | ||
32 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE | 33 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE |
33 | 34 | ||
@@ -982,6 +983,8 @@ static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, | |||
982 | { | 983 | { |
983 | size_t wsize = NFS_SERVER(inode)->wsize; | 984 | size_t wsize = NFS_SERVER(inode)->wsize; |
984 | 985 | ||
986 | pgio->pg_test = NULL; | ||
987 | |||
985 | if (wsize < PAGE_CACHE_SIZE) | 988 | if (wsize < PAGE_CACHE_SIZE) |
986 | nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags); | 989 | nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags); |
987 | else | 990 | else |
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index d55cee73f634..4eaf27a1282d 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h | |||
@@ -62,6 +62,8 @@ struct nfs_pageio_descriptor { | |||
62 | int (*pg_doio)(struct inode *, struct list_head *, unsigned int, size_t, int); | 62 | int (*pg_doio)(struct inode *, struct list_head *, unsigned int, size_t, int); |
63 | int pg_ioflags; | 63 | int pg_ioflags; |
64 | int pg_error; | 64 | int pg_error; |
65 | struct pnfs_layout_segment *pg_lseg; | ||
66 | int (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *); | ||
65 | }; | 67 | }; |
66 | 68 | ||
67 | #define NFS_WBACK_BUSY(req) (test_bit(PG_BUSY,&(req)->wb_flags)) | 69 | #define NFS_WBACK_BUSY(req) (test_bit(PG_BUSY,&(req)->wb_flags)) |