diff options
author | Andy Adamson <andros@netapp.com> | 2011-02-28 20:34:19 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-03-11 15:38:43 -0500 |
commit | dc70d7b3189597f313df7bd2da849cfc39063b15 (patch) | |
tree | c739f2c3a2213b1bc028f1599ee0efcbeabd9b81 /fs | |
parent | cfe7f4120f8b1b9465c333d1e42efd4669b1799f (diff) |
NFSv4.1: filelayout read
Attempt a pNFS file layout read by setting up the nfs_read_data struct and
calling nfs_initiate_read with the data server rpc client and the
filelayout rpc call ops.
Error handling is implemented in a subsequent patch.
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: Mingyang Guo <guomingyang@nrchpc.ac.cn>
Signed-off-by: Oleg Drokin <green@linuxhacker.ru>
Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
Tested-by: Guo Mingyang <guomingyang@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')
-rw-r--r-- | fs/nfs/internal.h | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 3 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 82 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 3 | ||||
-rw-r--r-- | fs/nfs/read.c | 3 |
5 files changed, 91 insertions, 2 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 5cc92014259e..5e9df992cd73 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -271,6 +271,8 @@ extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); | |||
271 | #endif | 271 | #endif |
272 | 272 | ||
273 | /* read.c */ | 273 | /* read.c */ |
274 | extern int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt, | ||
275 | const struct rpc_call_ops *call_ops); | ||
274 | extern void nfs_read_prepare(struct rpc_task *task, void *calldata); | 276 | extern void nfs_read_prepare(struct rpc_task *task, void *calldata); |
275 | 277 | ||
276 | /* write.c */ | 278 | /* write.c */ |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 7058a9f75e7f..c64be1cff080 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -252,6 +252,9 @@ static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *ser | |||
252 | extern int nfs4_setup_sequence(const struct nfs_server *server, | 252 | extern int nfs4_setup_sequence(const struct nfs_server *server, |
253 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, | 253 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, |
254 | int cache_reply, struct rpc_task *task); | 254 | int cache_reply, struct rpc_task *task); |
255 | extern int nfs41_setup_sequence(struct nfs4_session *session, | ||
256 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, | ||
257 | int cache_reply, struct rpc_task *task); | ||
255 | extern void nfs4_destroy_session(struct nfs4_session *session); | 258 | extern void nfs4_destroy_session(struct nfs4_session *session); |
256 | extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); | 259 | extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); |
257 | extern int nfs4_proc_create_session(struct nfs_client *); | 260 | extern int nfs4_proc_create_session(struct nfs_client *); |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index ed833705dcee..3608411653dc 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -101,6 +101,87 @@ filelayout_get_dserver_offset(struct pnfs_layout_segment *lseg, loff_t offset) | |||
101 | } | 101 | } |
102 | 102 | ||
103 | /* | 103 | /* |
104 | * Call ops for the async read/write cases | ||
105 | * In the case of dense layouts, the offset needs to be reset to its | ||
106 | * original value. | ||
107 | */ | ||
108 | static void filelayout_read_prepare(struct rpc_task *task, void *data) | ||
109 | { | ||
110 | struct nfs_read_data *rdata = (struct nfs_read_data *)data; | ||
111 | |||
112 | if (nfs41_setup_sequence(rdata->ds_clp->cl_session, | ||
113 | &rdata->args.seq_args, &rdata->res.seq_res, | ||
114 | 0, task)) | ||
115 | return; | ||
116 | |||
117 | rpc_call_start(task); | ||
118 | } | ||
119 | |||
120 | static void filelayout_read_call_done(struct rpc_task *task, void *data) | ||
121 | { | ||
122 | struct nfs_read_data *rdata = (struct nfs_read_data *)data; | ||
123 | |||
124 | dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status); | ||
125 | |||
126 | /* Note this may cause RPC to be resent */ | ||
127 | rdata->mds_ops->rpc_call_done(task, data); | ||
128 | } | ||
129 | |||
130 | static void filelayout_read_release(void *data) | ||
131 | { | ||
132 | struct nfs_read_data *rdata = (struct nfs_read_data *)data; | ||
133 | |||
134 | rdata->mds_ops->rpc_release(data); | ||
135 | } | ||
136 | |||
137 | struct rpc_call_ops filelayout_read_call_ops = { | ||
138 | .rpc_call_prepare = filelayout_read_prepare, | ||
139 | .rpc_call_done = filelayout_read_call_done, | ||
140 | .rpc_release = filelayout_read_release, | ||
141 | }; | ||
142 | |||
143 | static enum pnfs_try_status | ||
144 | filelayout_read_pagelist(struct nfs_read_data *data) | ||
145 | { | ||
146 | struct pnfs_layout_segment *lseg = data->lseg; | ||
147 | struct nfs4_pnfs_ds *ds; | ||
148 | loff_t offset = data->args.offset; | ||
149 | u32 j, idx; | ||
150 | struct nfs_fh *fh; | ||
151 | int status; | ||
152 | |||
153 | dprintk("--> %s ino %lu pgbase %u req %Zu@%llu\n", | ||
154 | __func__, data->inode->i_ino, | ||
155 | data->args.pgbase, (size_t)data->args.count, offset); | ||
156 | |||
157 | /* Retrieve the correct rpc_client for the byte range */ | ||
158 | j = nfs4_fl_calc_j_index(lseg, offset); | ||
159 | idx = nfs4_fl_calc_ds_index(lseg, j); | ||
160 | ds = nfs4_fl_prepare_ds(lseg, idx); | ||
161 | if (!ds) { | ||
162 | printk(KERN_ERR "%s: prepare_ds failed, use MDS\n", __func__); | ||
163 | return PNFS_NOT_ATTEMPTED; | ||
164 | } | ||
165 | dprintk("%s USE DS:ip %x %hu\n", __func__, | ||
166 | ntohl(ds->ds_ip_addr), ntohs(ds->ds_port)); | ||
167 | |||
168 | /* No multipath support. Use first DS */ | ||
169 | data->ds_clp = ds->ds_clp; | ||
170 | fh = nfs4_fl_select_ds_fh(lseg, j); | ||
171 | if (fh) | ||
172 | data->args.fh = fh; | ||
173 | |||
174 | data->args.offset = filelayout_get_dserver_offset(lseg, offset); | ||
175 | data->mds_offset = offset; | ||
176 | |||
177 | /* Perform an asynchronous read to ds */ | ||
178 | status = nfs_initiate_read(data, ds->ds_clp->cl_rpcclient, | ||
179 | &filelayout_read_call_ops); | ||
180 | BUG_ON(status != 0); | ||
181 | return PNFS_ATTEMPTED; | ||
182 | } | ||
183 | |||
184 | /* | ||
104 | * filelayout_check_layout() | 185 | * filelayout_check_layout() |
105 | * | 186 | * |
106 | * Make sure layout segment parameters are sane WRT the device. | 187 | * Make sure layout segment parameters are sane WRT the device. |
@@ -320,6 +401,7 @@ static struct pnfs_layoutdriver_type filelayout_type = { | |||
320 | .alloc_lseg = filelayout_alloc_lseg, | 401 | .alloc_lseg = filelayout_alloc_lseg, |
321 | .free_lseg = filelayout_free_lseg, | 402 | .free_lseg = filelayout_free_lseg, |
322 | .pg_test = filelayout_pg_test, | 403 | .pg_test = filelayout_pg_test, |
404 | .read_pagelist = filelayout_read_pagelist, | ||
323 | }; | 405 | }; |
324 | 406 | ||
325 | static int __init nfs4filelayout_init(void) | 407 | static int __init nfs4filelayout_init(void) |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 07d1a43f40f5..d09623933302 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -505,7 +505,7 @@ out: | |||
505 | return ret_id; | 505 | return ret_id; |
506 | } | 506 | } |
507 | 507 | ||
508 | static int nfs41_setup_sequence(struct nfs4_session *session, | 508 | int nfs41_setup_sequence(struct nfs4_session *session, |
509 | struct nfs4_sequence_args *args, | 509 | struct nfs4_sequence_args *args, |
510 | struct nfs4_sequence_res *res, | 510 | struct nfs4_sequence_res *res, |
511 | int cache_reply, | 511 | int cache_reply, |
@@ -571,6 +571,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session, | |||
571 | res->sr_status = 1; | 571 | res->sr_status = 1; |
572 | return 0; | 572 | return 0; |
573 | } | 573 | } |
574 | EXPORT_SYMBOL_GPL(nfs41_setup_sequence); | ||
574 | 575 | ||
575 | int nfs4_setup_sequence(const struct nfs_server *server, | 576 | int nfs4_setup_sequence(const struct nfs_server *server, |
576 | struct nfs4_sequence_args *args, | 577 | struct nfs4_sequence_args *args, |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 4127a1c0eec6..f4d0fcffcb5a 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -157,7 +157,7 @@ static void nfs_readpage_release(struct nfs_page *req) | |||
157 | nfs_release_request(req); | 157 | nfs_release_request(req); |
158 | } | 158 | } |
159 | 159 | ||
160 | static int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt, | 160 | int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt, |
161 | const struct rpc_call_ops *call_ops) | 161 | const struct rpc_call_ops *call_ops) |
162 | { | 162 | { |
163 | struct inode *inode = data->inode; | 163 | struct inode *inode = data->inode; |
@@ -195,6 +195,7 @@ static int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt, | |||
195 | rpc_put_task(task); | 195 | rpc_put_task(task); |
196 | return 0; | 196 | return 0; |
197 | } | 197 | } |
198 | EXPORT_SYMBOL_GPL(nfs_initiate_read); | ||
198 | 199 | ||
199 | /* | 200 | /* |
200 | * Set up the NFS read request struct | 201 | * Set up the NFS read request struct |