diff options
author | Andy Adamson <andros@netapp.com> | 2011-02-28 20:34:16 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-03-11 15:38:42 -0500 |
commit | 64419a9b20938d9070fdd8c58c2fa23c911915f8 (patch) | |
tree | 182c1eaebcfb9b8e02fc75d807b346209757ace1 /fs/nfs | |
parent | bae724ef95b0d0a1f4518f5451e7c8aabc41f820 (diff) |
NFSv4.1: generic read
Separate the rpc run portion of nfs_read_rpcsetup into a new function
nfs_initiate_read that is called for normal NFS I/O.
Add a pNFS read_pagelist function that is called instead of nfs_intitate_read
for pNFS reads.
Signed-off-by: Andy Adamson <andros@citi.umich.edu>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
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: Mike Sager <sager@netapp.com>
Signed-off-by: Mingyang Guo <guomingyang@nrchpc.ac.cn>
Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
Signed-off-by: Tao Guo <guotao@nrchpc.ac.cn>
Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/pnfs.c | 28 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 20 | ||||
-rw-r--r-- | fs/nfs/read.c | 65 |
3 files changed, 88 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 | */ | ||
886 | enum pnfs_try_status | ||
887 | pnfs_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 | ||
48 | enum 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 | ||
75 | struct pnfs_layout_hdr { | 86 | struct 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); |
158 | void set_pnfs_layoutdriver(struct nfs_server *, u32 id); | 169 | void set_pnfs_layoutdriver(struct nfs_server *, u32 id); |
159 | void unset_pnfs_layoutdriver(struct nfs_server *); | 170 | void unset_pnfs_layoutdriver(struct nfs_server *); |
171 | enum pnfs_try_status pnfs_try_to_read_data(struct nfs_read_data *, | ||
172 | const struct rpc_call_ops *); | ||
160 | void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *); | 173 | void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *); |
161 | int pnfs_layout_process(struct nfs4_layoutget *lgp); | 174 | int pnfs_layout_process(struct nfs4_layoutget *lgp); |
162 | void pnfs_free_lseg_list(struct list_head *tmp_list); | 175 | void 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 | ||
243 | static inline enum pnfs_try_status | ||
244 | pnfs_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 | |||
230 | static inline bool | 250 | static inline bool |
231 | pnfs_roc(struct inode *ino) | 251 | pnfs_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 | /* | 160 | static 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 | */ | ||
161 | static 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 | */ | ||
202 | static 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 | ||
219 | static void | 234 | static void |