Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Andy Adamson and committed by
Trond Myklebust
dc70d7b3 cfe7f412

+92 -2
+2
fs/nfs/internal.h
··· 271 271 #endif 272 272 273 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 276 extern void nfs_read_prepare(struct rpc_task *task, void *calldata); 275 277 276 278 /* write.c */
+3
fs/nfs/nfs4_fs.h
··· 252 252 extern int nfs4_setup_sequence(const struct nfs_server *server, 253 253 struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, 254 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 258 extern void nfs4_destroy_session(struct nfs4_session *session); 256 259 extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); 257 260 extern int nfs4_proc_create_session(struct nfs_client *);
+82
fs/nfs/nfs4filelayout.c
··· 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 185 * filelayout_check_layout() 105 186 * 106 187 * Make sure layout segment parameters are sane WRT the device. ··· 401 320 .alloc_lseg = filelayout_alloc_lseg, 402 321 .free_lseg = filelayout_free_lseg, 403 322 .pg_test = filelayout_pg_test, 323 + .read_pagelist = filelayout_read_pagelist, 404 324 }; 405 325 406 326 static int __init nfs4filelayout_init(void)
+2 -1
fs/nfs/nfs4proc.c
··· 505 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 509 struct nfs4_sequence_args *args, 510 510 struct nfs4_sequence_res *res, 511 511 int cache_reply, ··· 571 571 res->sr_status = 1; 572 572 return 0; 573 573 } 574 + EXPORT_SYMBOL_GPL(nfs41_setup_sequence); 574 575 575 576 int nfs4_setup_sequence(const struct nfs_server *server, 576 577 struct nfs4_sequence_args *args,
+2 -1
fs/nfs/read.c
··· 157 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 161 const struct rpc_call_ops *call_ops) 162 162 { 163 163 struct inode *inode = data->inode; ··· 195 195 rpc_put_task(task); 196 196 return 0; 197 197 } 198 + EXPORT_SYMBOL_GPL(nfs_initiate_read); 198 199 199 200 /* 200 201 * Set up the NFS read request struct
+1
include/linux/nfs_xdr.h
··· 1020 1020 struct pnfs_layout_segment *lseg; 1021 1021 struct nfs_client *ds_clp; /* pNFS data server */ 1022 1022 const struct rpc_call_ops *mds_ops; 1023 + __u64 mds_offset; 1023 1024 struct page *page_array[NFS_PAGEVEC_SIZE]; 1024 1025 }; 1025 1026