aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorFred Isaman <iisaman@netapp.com>2011-02-28 20:34:14 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-03-11 15:38:42 -0500
commit94ad1c80e28f9700c84b4d28d1e5302ddf63a6fd (patch)
tree2c600c1f8e85648c7693b5f0018b5d0b7e960b5f /fs/nfs
parentd684d2ae10a4f95d3035abf698d7d611ff2cd279 (diff)
NFSv4.1: coelesce across layout stripes
Add a pg_test layout driver hook which is used to avoid coelescing I/O across layout stripes. Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Andy Adamson <andros@citi.umich.edu> Signed-off-by: Dean Hildebrand <dhildeb@us.ibm.com> Signed-off-by: Fred Isaman <iisaman@citi.umich.edu> Signed-off-by: Fred Isaman <iisaman@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: Tao Guo <guotao@nrchpc.ac.cn> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4filelayout.c26
-rw-r--r--fs/nfs/pagelist.c12
-rw-r--r--fs/nfs/pnfs.c16
-rw-r--r--fs/nfs/pnfs.h12
-rw-r--r--fs/nfs/read.c1
-rw-r--r--fs/nfs/write.c3
6 files changed, 68 insertions, 2 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 23f930caf1e..0efe8cbd9e3 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 */
261int
262filelayout_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
255static struct pnfs_layoutdriver_type filelayout_type = { 280static 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
265static int __init nfs4filelayout_init(void) 291static int __init nfs4filelayout_init(void)
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index e1164e3f9e6..9b9a65c9bb4 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 */
242static int nfs_can_coalesce_requests(struct nfs_page *prev, 243static 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 3afa82e4543..330cee115de 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
861static void
862pnfs_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
870void
871pnfs_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 9a994bc9899..db52d965857 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
33enum { 35enum {
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
70struct pnfs_layout_hdr { 75struct 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);
152void set_pnfs_layoutdriver(struct nfs_server *, u32 id); 157void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
153void unset_pnfs_layoutdriver(struct nfs_server *); 158void unset_pnfs_layoutdriver(struct nfs_server *);
159void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *);
154int pnfs_layout_process(struct nfs4_layoutget *lgp); 160int pnfs_layout_process(struct nfs4_layoutget *lgp);
155void pnfs_free_lseg_list(struct list_head *tmp_list); 161void pnfs_free_lseg_list(struct list_head *tmp_list);
156void pnfs_destroy_layout(struct nfs_inode *); 162void 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
259static inline void
260pnfs_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 aedcaa7f291..2a2765975e1 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 ae528b98b80..40143c4747a 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