diff options
-rw-r--r-- | fs/nfs/file.c | 4 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 7 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 27 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 1 | ||||
-rw-r--r-- | fs/nfs/read.c | 40 | ||||
-rw-r--r-- | fs/nfs/write.c | 4 | ||||
-rw-r--r-- | include/linux/nfs_page.h | 4 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 1 |
8 files changed, 51 insertions, 37 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 7bf029ef4084..d85a534b15cd 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -387,10 +387,6 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping, | |||
387 | file->f_path.dentry->d_name.name, | 387 | file->f_path.dentry->d_name.name, |
388 | mapping->host->i_ino, len, (long long) pos); | 388 | mapping->host->i_ino, len, (long long) pos); |
389 | 389 | ||
390 | pnfs_update_layout(mapping->host, | ||
391 | nfs_file_open_context(file), | ||
392 | IOMODE_RW); | ||
393 | |||
394 | start: | 390 | start: |
395 | /* | 391 | /* |
396 | * Prevent starvation issues if someone is doing a consistency | 392 | * Prevent starvation issues if someone is doing a consistency |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 9b9a65c9bb4f..45b0fb8add39 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/nfs_mount.h> | 20 | #include <linux/nfs_mount.h> |
21 | 21 | ||
22 | #include "internal.h" | 22 | #include "internal.h" |
23 | #include "pnfs.h" | ||
23 | 24 | ||
24 | static struct kmem_cache *nfs_page_cachep; | 25 | static struct kmem_cache *nfs_page_cachep; |
25 | 26 | ||
@@ -213,7 +214,7 @@ nfs_wait_on_request(struct nfs_page *req) | |||
213 | */ | 214 | */ |
214 | void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | 215 | void nfs_pageio_init(struct nfs_pageio_descriptor *desc, |
215 | struct inode *inode, | 216 | struct inode *inode, |
216 | int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int), | 217 | int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int, struct pnfs_layout_segment *), |
217 | size_t bsize, | 218 | size_t bsize, |
218 | int io_flags) | 219 | int io_flags) |
219 | { | 220 | { |
@@ -315,7 +316,9 @@ static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc) | |||
315 | nfs_page_array_len(desc->pg_base, | 316 | nfs_page_array_len(desc->pg_base, |
316 | desc->pg_count), | 317 | desc->pg_count), |
317 | desc->pg_count, | 318 | desc->pg_count, |
318 | desc->pg_ioflags); | 319 | desc->pg_ioflags, |
320 | desc->pg_lseg); | ||
321 | desc->pg_lseg = NULL; | ||
319 | if (error < 0) | 322 | if (error < 0) |
320 | desc->pg_error = error; | 323 | desc->pg_error = error; |
321 | else | 324 | else |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 330cee115de0..77966ecb0a2c 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -245,7 +245,7 @@ put_lseg_common(struct pnfs_layout_segment *lseg) | |||
245 | rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq); | 245 | rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq); |
246 | } | 246 | } |
247 | 247 | ||
248 | static void | 248 | void |
249 | put_lseg(struct pnfs_layout_segment *lseg) | 249 | put_lseg(struct pnfs_layout_segment *lseg) |
250 | { | 250 | { |
251 | struct inode *inode; | 251 | struct inode *inode; |
@@ -784,7 +784,6 @@ pnfs_update_layout(struct inode *ino, | |||
784 | out: | 784 | out: |
785 | dprintk("%s end, state 0x%lx lseg %p\n", __func__, | 785 | dprintk("%s end, state 0x%lx lseg %p\n", __func__, |
786 | nfsi->layout ? nfsi->layout->plh_flags : -1, lseg); | 786 | nfsi->layout ? nfsi->layout->plh_flags : -1, lseg); |
787 | put_lseg(lseg); /* STUB - callers currently ignore return value */ | ||
788 | return lseg; | 787 | return lseg; |
789 | out_unlock: | 788 | out_unlock: |
790 | spin_unlock(&ino->i_lock); | 789 | spin_unlock(&ino->i_lock); |
@@ -858,20 +857,26 @@ out_forget_reply: | |||
858 | goto out; | 857 | goto out; |
859 | } | 858 | } |
860 | 859 | ||
861 | static void | 860 | static int pnfs_read_pg_test(struct nfs_pageio_descriptor *pgio, |
862 | pnfs_set_pg_test(struct inode *inode, struct nfs_pageio_descriptor *pgio) | 861 | struct nfs_page *prev, |
862 | struct nfs_page *req) | ||
863 | { | 863 | { |
864 | struct pnfs_layoutdriver_type *ld; | 864 | if (pgio->pg_count == prev->wb_bytes) { |
865 | 865 | /* This is first coelesce call for a series of nfs_pages */ | |
866 | ld = NFS_SERVER(inode)->pnfs_curr_ld; | 866 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
867 | pgio->pg_test = (ld ? ld->pg_test : NULL); | 867 | prev->wb_context, |
868 | IOMODE_READ); | ||
869 | } | ||
870 | return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req); | ||
868 | } | 871 | } |
869 | 872 | ||
870 | void | 873 | void |
871 | pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, | 874 | pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode) |
872 | struct inode *inode) | ||
873 | { | 875 | { |
874 | pnfs_set_pg_test(inode, pgio); | 876 | struct pnfs_layoutdriver_type *ld; |
877 | |||
878 | ld = NFS_SERVER(inode)->pnfs_curr_ld; | ||
879 | pgio->pg_test = (ld && ld->pg_test) ? pnfs_read_pg_test : NULL; | ||
875 | } | 880 | } |
876 | 881 | ||
877 | /* | 882 | /* |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index db52d9658570..5107d14db485 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -151,6 +151,7 @@ extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp); | |||
151 | 151 | ||
152 | /* pnfs.c */ | 152 | /* pnfs.c */ |
153 | void get_layout_hdr(struct pnfs_layout_hdr *lo); | 153 | void get_layout_hdr(struct pnfs_layout_hdr *lo); |
154 | void put_lseg(struct pnfs_layout_segment *lseg); | ||
154 | struct pnfs_layout_segment * | 155 | struct pnfs_layout_segment * |
155 | pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, | 156 | pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, |
156 | enum pnfs_iomode access_type); | 157 | enum pnfs_iomode access_type); |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 2a2765975e1f..6dc9eaf00e5c 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -20,17 +20,17 @@ | |||
20 | #include <linux/nfs_page.h> | 20 | #include <linux/nfs_page.h> |
21 | 21 | ||
22 | #include <asm/system.h> | 22 | #include <asm/system.h> |
23 | #include "pnfs.h" | ||
23 | 24 | ||
24 | #include "nfs4_fs.h" | 25 | #include "nfs4_fs.h" |
25 | #include "internal.h" | 26 | #include "internal.h" |
26 | #include "iostat.h" | 27 | #include "iostat.h" |
27 | #include "fscache.h" | 28 | #include "fscache.h" |
28 | #include "pnfs.h" | ||
29 | 29 | ||
30 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE | 30 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE |
31 | 31 | ||
32 | static int nfs_pagein_multi(struct inode *, struct list_head *, unsigned int, size_t, int); | 32 | static int nfs_pagein_multi(struct inode *, struct list_head *, unsigned int, size_t, int, struct pnfs_layout_segment *); |
33 | static int nfs_pagein_one(struct inode *, struct list_head *, unsigned int, size_t, int); | 33 | static int nfs_pagein_one(struct inode *, struct list_head *, unsigned int, size_t, int, struct pnfs_layout_segment *); |
34 | static const struct rpc_call_ops nfs_read_partial_ops; | 34 | static const struct rpc_call_ops nfs_read_partial_ops; |
35 | static const struct rpc_call_ops nfs_read_full_ops; | 35 | static const struct rpc_call_ops nfs_read_full_ops; |
36 | 36 | ||
@@ -69,6 +69,7 @@ void nfs_readdata_free(struct nfs_read_data *p) | |||
69 | 69 | ||
70 | static void nfs_readdata_release(struct nfs_read_data *rdata) | 70 | static void nfs_readdata_release(struct nfs_read_data *rdata) |
71 | { | 71 | { |
72 | put_lseg(rdata->lseg); | ||
72 | put_nfs_open_context(rdata->args.context); | 73 | put_nfs_open_context(rdata->args.context); |
73 | nfs_readdata_free(rdata); | 74 | nfs_readdata_free(rdata); |
74 | } | 75 | } |
@@ -121,7 +122,6 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, | |||
121 | len = nfs_page_length(page); | 122 | len = nfs_page_length(page); |
122 | if (len == 0) | 123 | if (len == 0) |
123 | return nfs_return_empty_page(page); | 124 | return nfs_return_empty_page(page); |
124 | pnfs_update_layout(inode, ctx, IOMODE_READ); | ||
125 | new = nfs_create_request(ctx, inode, page, 0, len); | 125 | new = nfs_create_request(ctx, inode, page, 0, len); |
126 | if (IS_ERR(new)) { | 126 | if (IS_ERR(new)) { |
127 | unlock_page(page); | 127 | unlock_page(page); |
@@ -132,9 +132,9 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, | |||
132 | 132 | ||
133 | nfs_list_add_request(new, &one_request); | 133 | nfs_list_add_request(new, &one_request); |
134 | if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE) | 134 | if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE) |
135 | nfs_pagein_multi(inode, &one_request, 1, len, 0); | 135 | nfs_pagein_multi(inode, &one_request, 1, len, 0, NULL); |
136 | else | 136 | else |
137 | nfs_pagein_one(inode, &one_request, 1, len, 0); | 137 | nfs_pagein_one(inode, &one_request, 1, len, 0, NULL); |
138 | return 0; | 138 | return 0; |
139 | } | 139 | } |
140 | 140 | ||
@@ -160,7 +160,8 @@ static void nfs_readpage_release(struct nfs_page *req) | |||
160 | */ | 160 | */ |
161 | static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | 161 | static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, |
162 | const struct rpc_call_ops *call_ops, | 162 | const struct rpc_call_ops *call_ops, |
163 | unsigned int count, unsigned int offset) | 163 | unsigned int count, unsigned int offset, |
164 | struct pnfs_layout_segment *lseg) | ||
164 | { | 165 | { |
165 | struct inode *inode = req->wb_context->path.dentry->d_inode; | 166 | struct inode *inode = req->wb_context->path.dentry->d_inode; |
166 | int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0; | 167 | int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0; |
@@ -183,6 +184,7 @@ static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | |||
183 | data->req = req; | 184 | data->req = req; |
184 | data->inode = inode; | 185 | data->inode = inode; |
185 | data->cred = msg.rpc_cred; | 186 | data->cred = msg.rpc_cred; |
187 | data->lseg = get_lseg(lseg); | ||
186 | 188 | ||
187 | data->args.fh = NFS_FH(inode); | 189 | data->args.fh = NFS_FH(inode); |
188 | data->args.offset = req_offset(req) + offset; | 190 | data->args.offset = req_offset(req) + offset; |
@@ -240,7 +242,7 @@ nfs_async_read_error(struct list_head *head) | |||
240 | * won't see the new data until our attribute cache is updated. This is more | 242 | * won't see the new data until our attribute cache is updated. This is more |
241 | * or less conventional NFS client behavior. | 243 | * or less conventional NFS client behavior. |
242 | */ | 244 | */ |
243 | static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int flags) | 245 | static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int flags, struct pnfs_layout_segment *lseg) |
244 | { | 246 | { |
245 | struct nfs_page *req = nfs_list_entry(head->next); | 247 | struct nfs_page *req = nfs_list_entry(head->next); |
246 | struct page *page = req->wb_page; | 248 | struct page *page = req->wb_page; |
@@ -266,6 +268,8 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne | |||
266 | } while(nbytes != 0); | 268 | } while(nbytes != 0); |
267 | atomic_set(&req->wb_complete, requests); | 269 | atomic_set(&req->wb_complete, requests); |
268 | 270 | ||
271 | /* We know lseg==NULL */ | ||
272 | lseg = pnfs_update_layout(inode, req->wb_context, IOMODE_READ); | ||
269 | ClearPageError(page); | 273 | ClearPageError(page); |
270 | offset = 0; | 274 | offset = 0; |
271 | nbytes = count; | 275 | nbytes = count; |
@@ -280,12 +284,13 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne | |||
280 | if (nbytes < rsize) | 284 | if (nbytes < rsize) |
281 | rsize = nbytes; | 285 | rsize = nbytes; |
282 | ret2 = nfs_read_rpcsetup(req, data, &nfs_read_partial_ops, | 286 | ret2 = nfs_read_rpcsetup(req, data, &nfs_read_partial_ops, |
283 | rsize, offset); | 287 | rsize, offset, lseg); |
284 | if (ret == 0) | 288 | if (ret == 0) |
285 | ret = ret2; | 289 | ret = ret2; |
286 | offset += rsize; | 290 | offset += rsize; |
287 | nbytes -= rsize; | 291 | nbytes -= rsize; |
288 | } while (nbytes != 0); | 292 | } while (nbytes != 0); |
293 | put_lseg(lseg); | ||
289 | 294 | ||
290 | return ret; | 295 | return ret; |
291 | 296 | ||
@@ -300,7 +305,7 @@ out_bad: | |||
300 | return -ENOMEM; | 305 | return -ENOMEM; |
301 | } | 306 | } |
302 | 307 | ||
303 | static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int flags) | 308 | static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int flags, struct pnfs_layout_segment *lseg) |
304 | { | 309 | { |
305 | struct nfs_page *req; | 310 | struct nfs_page *req; |
306 | struct page **pages; | 311 | struct page **pages; |
@@ -308,8 +313,10 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned | |||
308 | int ret = -ENOMEM; | 313 | int ret = -ENOMEM; |
309 | 314 | ||
310 | data = nfs_readdata_alloc(npages); | 315 | data = nfs_readdata_alloc(npages); |
311 | if (!data) | 316 | if (!data) { |
312 | goto out_bad; | 317 | nfs_async_read_error(head); |
318 | goto out; | ||
319 | } | ||
313 | 320 | ||
314 | pages = data->pagevec; | 321 | pages = data->pagevec; |
315 | while (!list_empty(head)) { | 322 | while (!list_empty(head)) { |
@@ -320,10 +327,12 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned | |||
320 | *pages++ = req->wb_page; | 327 | *pages++ = req->wb_page; |
321 | } | 328 | } |
322 | req = nfs_list_entry(data->pages.next); | 329 | req = nfs_list_entry(data->pages.next); |
330 | if ((!lseg) && list_is_singular(&data->pages)) | ||
331 | lseg = pnfs_update_layout(inode, req->wb_context, IOMODE_READ); | ||
323 | 332 | ||
324 | return nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0); | 333 | ret = nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0, lseg); |
325 | out_bad: | 334 | out: |
326 | nfs_async_read_error(head); | 335 | put_lseg(lseg); |
327 | return ret; | 336 | return ret; |
328 | } | 337 | } |
329 | 338 | ||
@@ -625,7 +634,6 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, | |||
625 | if (ret == 0) | 634 | if (ret == 0) |
626 | goto read_complete; /* all pages were read */ | 635 | goto read_complete; /* all pages were read */ |
627 | 636 | ||
628 | pnfs_update_layout(inode, desc.ctx, IOMODE_READ); | ||
629 | pnfs_pageio_init_read(&pgio, inode); | 637 | pnfs_pageio_init_read(&pgio, inode); |
630 | if (rsize < PAGE_CACHE_SIZE) | 638 | if (rsize < PAGE_CACHE_SIZE) |
631 | nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0); | 639 | nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0); |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 40143c4747a5..f033fa0d7d33 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -880,7 +880,7 @@ static void nfs_redirty_request(struct nfs_page *req) | |||
880 | * Generate multiple small requests to write out a single | 880 | * Generate multiple small requests to write out a single |
881 | * contiguous dirty area on one page. | 881 | * contiguous dirty area on one page. |
882 | */ | 882 | */ |
883 | static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int how) | 883 | static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int how, struct pnfs_layout_segment *lseg) |
884 | { | 884 | { |
885 | struct nfs_page *req = nfs_list_entry(head->next); | 885 | struct nfs_page *req = nfs_list_entry(head->next); |
886 | struct page *page = req->wb_page; | 886 | struct page *page = req->wb_page; |
@@ -947,7 +947,7 @@ out_bad: | |||
947 | * This is the case if nfs_updatepage detects a conflicting request | 947 | * This is the case if nfs_updatepage detects a conflicting request |
948 | * that has been written but not committed. | 948 | * that has been written but not committed. |
949 | */ | 949 | */ |
950 | static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int how) | 950 | static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int how, struct pnfs_layout_segment *lseg) |
951 | { | 951 | { |
952 | struct nfs_page *req; | 952 | struct nfs_page *req; |
953 | struct page **pages; | 953 | struct page **pages; |
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index 4eaf27a1282d..ba88ff4f8186 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h | |||
@@ -59,7 +59,7 @@ struct nfs_pageio_descriptor { | |||
59 | unsigned int pg_base; | 59 | unsigned int pg_base; |
60 | 60 | ||
61 | struct inode *pg_inode; | 61 | struct inode *pg_inode; |
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, struct pnfs_layout_segment *); |
63 | int pg_ioflags; | 63 | int pg_ioflags; |
64 | int pg_error; | 64 | int pg_error; |
65 | struct pnfs_layout_segment *pg_lseg; | 65 | struct pnfs_layout_segment *pg_lseg; |
@@ -81,7 +81,7 @@ extern int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *dst, | |||
81 | pgoff_t idx_start, unsigned int npages, int tag); | 81 | pgoff_t idx_start, unsigned int npages, int tag); |
82 | extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | 82 | extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc, |
83 | struct inode *inode, | 83 | struct inode *inode, |
84 | int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int), | 84 | int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int, struct pnfs_layout_segment *), |
85 | size_t bsize, | 85 | size_t bsize, |
86 | int how); | 86 | int how); |
87 | extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *, | 87 | extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *, |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index d159fe733381..560923e28723 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -1017,6 +1017,7 @@ struct nfs_read_data { | |||
1017 | struct nfs_readargs args; | 1017 | struct nfs_readargs args; |
1018 | struct nfs_readres res; | 1018 | struct nfs_readres res; |
1019 | unsigned long timestamp; /* For lease renewal */ | 1019 | unsigned long timestamp; /* For lease renewal */ |
1020 | struct pnfs_layout_segment *lseg; | ||
1020 | struct page *page_array[NFS_PAGEVEC_SIZE]; | 1021 | struct page *page_array[NFS_PAGEVEC_SIZE]; |
1021 | }; | 1022 | }; |
1022 | 1023 | ||