aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/pnfs.c28
-rw-r--r--fs/nfs/pnfs.h20
-rw-r--r--fs/nfs/read.c65
-rw-r--r--include/linux/nfs_iostat.h1
-rw-r--r--include/linux/nfs_xdr.h1
5 files changed, 90 insertions, 25 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 77966ecb0a2c..86c154bad5db 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -30,6 +30,7 @@
30#include <linux/nfs_fs.h> 30#include <linux/nfs_fs.h>
31#include "internal.h" 31#include "internal.h"
32#include "pnfs.h" 32#include "pnfs.h"
33#include "iostat.h"
33 34
34#define NFSDBG_FACILITY NFSDBG_PNFS 35#define NFSDBG_FACILITY NFSDBG_PNFS
35 36
@@ -880,6 +881,33 @@ pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode)
880} 881}
881 882
882/* 883/*
884 * Call the appropriate parallel I/O subsystem read function.
885 */
886enum pnfs_try_status
887pnfs_try_to_read_data(struct nfs_read_data *rdata,
888 const struct rpc_call_ops *call_ops)
889{
890 struct inode *inode = rdata->inode;
891 struct nfs_server *nfss = NFS_SERVER(inode);
892 enum pnfs_try_status trypnfs;
893
894 rdata->mds_ops = call_ops;
895
896 dprintk("%s: Reading ino:%lu %u@%llu\n",
897 __func__, inode->i_ino, rdata->args.count, rdata->args.offset);
898
899 trypnfs = nfss->pnfs_curr_ld->read_pagelist(rdata);
900 if (trypnfs == PNFS_NOT_ATTEMPTED) {
901 put_lseg(rdata->lseg);
902 rdata->lseg = NULL;
903 } else {
904 nfs_inc_stats(inode, NFSIOS_PNFS_READ);
905 }
906 dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs);
907 return trypnfs;
908}
909
910/*
883 * Device ID cache. Currently supports one layout type per struct nfs_client. 911 * Device ID cache. Currently supports one layout type per struct nfs_client.
884 * Add layout type to the lookup key to expand to support multiple types. 912 * Add layout type to the lookup key to expand to support multiple types.
885 */ 913 */
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 5107d14db485..585023fabb55 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -45,6 +45,11 @@ struct pnfs_layout_segment {
45 struct pnfs_layout_hdr *pls_layout; 45 struct pnfs_layout_hdr *pls_layout;
46}; 46};
47 47
48enum pnfs_try_status {
49 PNFS_ATTEMPTED = 0,
50 PNFS_NOT_ATTEMPTED = 1,
51};
52
48#ifdef CONFIG_NFS_V4_1 53#ifdef CONFIG_NFS_V4_1
49 54
50#define LAYOUT_NFSV4_1_MODULE_PREFIX "nfs-layouttype4" 55#define LAYOUT_NFSV4_1_MODULE_PREFIX "nfs-layouttype4"
@@ -70,6 +75,12 @@ struct pnfs_layoutdriver_type {
70 75
71 /* test for nfs page cache coalescing */ 76 /* test for nfs page cache coalescing */
72 int (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *); 77 int (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *);
78
79 /*
80 * Return PNFS_ATTEMPTED to indicate the layout code has attempted
81 * I/O, else return PNFS_NOT_ATTEMPTED to fall back to normal NFS
82 */
83 enum pnfs_try_status (*read_pagelist) (struct nfs_read_data *nfs_data);
73}; 84};
74 85
75struct pnfs_layout_hdr { 86struct pnfs_layout_hdr {
@@ -157,6 +168,8 @@ pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
157 enum pnfs_iomode access_type); 168 enum pnfs_iomode access_type);
158void set_pnfs_layoutdriver(struct nfs_server *, u32 id); 169void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
159void unset_pnfs_layoutdriver(struct nfs_server *); 170void unset_pnfs_layoutdriver(struct nfs_server *);
171enum pnfs_try_status pnfs_try_to_read_data(struct nfs_read_data *,
172 const struct rpc_call_ops *);
160void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *); 173void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *);
161int pnfs_layout_process(struct nfs4_layoutget *lgp); 174int pnfs_layout_process(struct nfs4_layoutget *lgp);
162void pnfs_free_lseg_list(struct list_head *tmp_list); 175void pnfs_free_lseg_list(struct list_head *tmp_list);
@@ -227,6 +240,13 @@ pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
227 return NULL; 240 return NULL;
228} 241}
229 242
243static inline enum pnfs_try_status
244pnfs_try_to_read_data(struct nfs_read_data *data,
245 const struct rpc_call_ops *call_ops)
246{
247 return PNFS_NOT_ATTEMPTED;
248}
249
230static inline bool 250static inline bool
231pnfs_roc(struct inode *ino) 251pnfs_roc(struct inode *ino)
232{ 252{
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 6dc9eaf00e5c..4127a1c0eec6 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -18,6 +18,8 @@
18#include <linux/sunrpc/clnt.h> 18#include <linux/sunrpc/clnt.h>
19#include <linux/nfs_fs.h> 19#include <linux/nfs_fs.h>
20#include <linux/nfs_page.h> 20#include <linux/nfs_page.h>
21#include <linux/smp_lock.h>
22#include <linux/module.h>
21 23
22#include <asm/system.h> 24#include <asm/system.h>
23#include "pnfs.h" 25#include "pnfs.h"
@@ -155,25 +157,20 @@ static void nfs_readpage_release(struct nfs_page *req)
155 nfs_release_request(req); 157 nfs_release_request(req);
156} 158}
157 159
158/* 160static int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt,
159 * Set up the NFS read request struct 161 const struct rpc_call_ops *call_ops)
160 */
161static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
162 const struct rpc_call_ops *call_ops,
163 unsigned int count, unsigned int offset,
164 struct pnfs_layout_segment *lseg)
165{ 162{
166 struct inode *inode = req->wb_context->path.dentry->d_inode; 163 struct inode *inode = data->inode;
167 int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0; 164 int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0;
168 struct rpc_task *task; 165 struct rpc_task *task;
169 struct rpc_message msg = { 166 struct rpc_message msg = {
170 .rpc_argp = &data->args, 167 .rpc_argp = &data->args,
171 .rpc_resp = &data->res, 168 .rpc_resp = &data->res,
172 .rpc_cred = req->wb_context->cred, 169 .rpc_cred = data->cred,
173 }; 170 };
174 struct rpc_task_setup task_setup_data = { 171 struct rpc_task_setup task_setup_data = {
175 .task = &data->task, 172 .task = &data->task,
176 .rpc_client = NFS_CLIENT(inode), 173 .rpc_client = clnt,
177 .rpc_message = &msg, 174 .rpc_message = &msg,
178 .callback_ops = call_ops, 175 .callback_ops = call_ops,
179 .callback_data = data, 176 .callback_data = data,
@@ -181,9 +178,37 @@ static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
181 .flags = RPC_TASK_ASYNC | swap_flags, 178 .flags = RPC_TASK_ASYNC | swap_flags,
182 }; 179 };
183 180
181 /* Set up the initial task struct. */
182 NFS_PROTO(inode)->read_setup(data, &msg);
183
184 dprintk("NFS: %5u initiated read call (req %s/%lld, %u bytes @ "
185 "offset %llu)\n",
186 data->task.tk_pid,
187 inode->i_sb->s_id,
188 (long long)NFS_FILEID(inode),
189 data->args.count,
190 (unsigned long long)data->args.offset);
191
192 task = rpc_run_task(&task_setup_data);
193 if (IS_ERR(task))
194 return PTR_ERR(task);
195 rpc_put_task(task);
196 return 0;
197}
198
199/*
200 * Set up the NFS read request struct
201 */
202static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
203 const struct rpc_call_ops *call_ops,
204 unsigned int count, unsigned int offset,
205 struct pnfs_layout_segment *lseg)
206{
207 struct inode *inode = req->wb_context->path.dentry->d_inode;
208
184 data->req = req; 209 data->req = req;
185 data->inode = inode; 210 data->inode = inode;
186 data->cred = msg.rpc_cred; 211 data->cred = req->wb_context->cred;
187 data->lseg = get_lseg(lseg); 212 data->lseg = get_lseg(lseg);
188 213
189 data->args.fh = NFS_FH(inode); 214 data->args.fh = NFS_FH(inode);
@@ -199,21 +224,11 @@ static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
199 data->res.eof = 0; 224 data->res.eof = 0;
200 nfs_fattr_init(&data->fattr); 225 nfs_fattr_init(&data->fattr);
201 226
202 /* Set up the initial task struct. */ 227 if (data->lseg &&
203 NFS_PROTO(inode)->read_setup(data, &msg); 228 (pnfs_try_to_read_data(data, call_ops) == PNFS_ATTEMPTED))
204 229 return 0;
205 dprintk("NFS: %5u initiated read call (req %s/%Ld, %u bytes @ offset %Lu)\n",
206 data->task.tk_pid,
207 inode->i_sb->s_id,
208 (long long)NFS_FILEID(inode),
209 count,
210 (unsigned long long)data->args.offset);
211 230
212 task = rpc_run_task(&task_setup_data); 231 return nfs_initiate_read(data, NFS_CLIENT(inode), call_ops);
213 if (IS_ERR(task))
214 return PTR_ERR(task);
215 rpc_put_task(task);
216 return 0;
217} 232}
218 233
219static void 234static void
diff --git a/include/linux/nfs_iostat.h b/include/linux/nfs_iostat.h
index 68b10f5f8907..37a143732d02 100644
--- a/include/linux/nfs_iostat.h
+++ b/include/linux/nfs_iostat.h
@@ -113,6 +113,7 @@ enum nfs_stat_eventcounters {
113 NFSIOS_SHORTREAD, 113 NFSIOS_SHORTREAD,
114 NFSIOS_SHORTWRITE, 114 NFSIOS_SHORTWRITE,
115 NFSIOS_DELAY, 115 NFSIOS_DELAY,
116 NFSIOS_PNFS_READ,
116 __NFSIOS_COUNTSMAX, 117 __NFSIOS_COUNTSMAX,
117}; 118};
118 119
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 560923e28723..9d2b9dae277d 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1018,6 +1018,7 @@ struct nfs_read_data {
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 pnfs_layout_segment *lseg;
1021 const struct rpc_call_ops *mds_ops;
1021 struct page *page_array[NFS_PAGEVEC_SIZE]; 1022 struct page *page_array[NFS_PAGEVEC_SIZE];
1022}; 1023};
1023 1024