diff options
| author | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-06-23 07:51:55 -0400 |
|---|---|---|
| committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-06-24 10:17:37 -0400 |
| commit | be3a5d233922d73f27002ce2767f6ec03c3f473d (patch) | |
| tree | 43a275fd1acfcdf22699db092d342627673abf67 | |
| parent | 1372a3130a3e0bfd38d82d476f0a907cc72ba816 (diff) | |
NFSv.2/pnfs Add a LAYOUTSTATS rpc function
Reviewed-by: Jeff Layton <jeff.layton@primarydata.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Peng Tao <tao.peng@primarydata.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
| -rw-r--r-- | fs/nfs/nfs42.h | 9 | ||||
| -rw-r--r-- | fs/nfs/nfs42proc.c | 27 | ||||
| -rw-r--r-- | fs/nfs/nfs42xdr.c | 122 | ||||
| -rw-r--r-- | fs/nfs/nfs4_fs.h | 1 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 4 | ||||
| -rw-r--r-- | fs/nfs/nfs4xdr.c | 1 | ||||
| -rw-r--r-- | include/linux/nfs4.h | 1 | ||||
| -rw-r--r-- | include/linux/nfs_xdr.h | 43 |
8 files changed, 205 insertions, 3 deletions
diff --git a/fs/nfs/nfs42.h b/fs/nfs/nfs42.h index 7afb8947dfdf..ff66ae700b89 100644 --- a/fs/nfs/nfs42.h +++ b/fs/nfs/nfs42.h | |||
| @@ -5,11 +5,18 @@ | |||
| 5 | #ifndef __LINUX_FS_NFS_NFS4_2_H | 5 | #ifndef __LINUX_FS_NFS_NFS4_2_H |
| 6 | #define __LINUX_FS_NFS_NFS4_2_H | 6 | #define __LINUX_FS_NFS_NFS4_2_H |
| 7 | 7 | ||
| 8 | /* | ||
| 9 | * FIXME: four LAYOUTSTATS calls per compound at most! Do we need to support | ||
| 10 | * more? Need to consider not to pre-alloc too much for a compound. | ||
| 11 | */ | ||
| 12 | #define PNFS_LAYOUTSTATS_MAXDEV (4) | ||
| 13 | |||
| 8 | /* nfs4.2proc.c */ | 14 | /* nfs4.2proc.c */ |
| 9 | int nfs42_proc_allocate(struct file *, loff_t, loff_t); | 15 | int nfs42_proc_allocate(struct file *, loff_t, loff_t); |
| 10 | int nfs42_proc_deallocate(struct file *, loff_t, loff_t); | 16 | int nfs42_proc_deallocate(struct file *, loff_t, loff_t); |
| 11 | loff_t nfs42_proc_llseek(struct file *, loff_t, int); | 17 | loff_t nfs42_proc_llseek(struct file *, loff_t, int); |
| 12 | 18 | int nfs42_proc_layoutstats_generic(struct nfs_server *, | |
| 19 | struct nfs42_layoutstat_data *); | ||
| 13 | /* nfs4.2xdr.h */ | 20 | /* nfs4.2xdr.h */ |
| 14 | extern struct rpc_procinfo nfs4_2_procedures[]; | 21 | extern struct rpc_procinfo nfs4_2_procedures[]; |
| 15 | 22 | ||
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index 3a9e75235f30..ac929685350b 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c | |||
| @@ -165,3 +165,30 @@ loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence) | |||
| 165 | 165 | ||
| 166 | return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes); | 166 | return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes); |
| 167 | } | 167 | } |
| 168 | |||
| 169 | static const struct rpc_call_ops nfs42_layoutstat_ops = { | ||
| 170 | }; | ||
| 171 | |||
| 172 | int nfs42_proc_layoutstats_generic(struct nfs_server *server, | ||
| 173 | struct nfs42_layoutstat_data *data) | ||
| 174 | { | ||
| 175 | struct rpc_message msg = { | ||
| 176 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTSTATS], | ||
| 177 | .rpc_argp = &data->args, | ||
| 178 | .rpc_resp = &data->res, | ||
| 179 | }; | ||
| 180 | struct rpc_task_setup task_setup = { | ||
| 181 | .rpc_client = server->client, | ||
| 182 | .rpc_message = &msg, | ||
| 183 | .callback_ops = &nfs42_layoutstat_ops, | ||
| 184 | .callback_data = data, | ||
| 185 | .flags = RPC_TASK_ASYNC, | ||
| 186 | }; | ||
| 187 | struct rpc_task *task; | ||
| 188 | |||
| 189 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); | ||
| 190 | task = rpc_run_task(&task_setup); | ||
| 191 | if (IS_ERR(task)) | ||
| 192 | return PTR_ERR(task); | ||
| 193 | return 0; | ||
| 194 | } | ||
diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c index 1a25b27248f2..9aae0205ef11 100644 --- a/fs/nfs/nfs42xdr.c +++ b/fs/nfs/nfs42xdr.c | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | #ifndef __LINUX_FS_NFS_NFS4_2XDR_H | 4 | #ifndef __LINUX_FS_NFS_NFS4_2XDR_H |
| 5 | #define __LINUX_FS_NFS_NFS4_2XDR_H | 5 | #define __LINUX_FS_NFS_NFS4_2XDR_H |
| 6 | 6 | ||
| 7 | #include "nfs42.h" | ||
| 8 | |||
| 7 | #define encode_fallocate_maxsz (encode_stateid_maxsz + \ | 9 | #define encode_fallocate_maxsz (encode_stateid_maxsz + \ |
| 8 | 2 /* offset */ + \ | 10 | 2 /* offset */ + \ |
| 9 | 2 /* length */) | 11 | 2 /* length */) |
| @@ -22,6 +24,16 @@ | |||
| 22 | 1 /* whence */ + \ | 24 | 1 /* whence */ + \ |
| 23 | 2 /* offset */ + \ | 25 | 2 /* offset */ + \ |
| 24 | 2 /* length */) | 26 | 2 /* length */) |
| 27 | #define encode_io_info_maxsz 4 | ||
| 28 | #define encode_layoutstats_maxsz (op_decode_hdr_maxsz + \ | ||
| 29 | 2 /* offset */ + \ | ||
| 30 | 2 /* length */ + \ | ||
| 31 | encode_stateid_maxsz + \ | ||
| 32 | encode_io_info_maxsz + \ | ||
| 33 | encode_io_info_maxsz + \ | ||
| 34 | 1 /* opaque devaddr4 length */ + \ | ||
| 35 | XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE)) | ||
| 36 | #define decode_layoutstats_maxsz (op_decode_hdr_maxsz) | ||
| 25 | 37 | ||
| 26 | #define NFS4_enc_allocate_sz (compound_encode_hdr_maxsz + \ | 38 | #define NFS4_enc_allocate_sz (compound_encode_hdr_maxsz + \ |
| 27 | encode_putfh_maxsz + \ | 39 | encode_putfh_maxsz + \ |
| @@ -45,6 +57,14 @@ | |||
| 45 | #define NFS4_dec_seek_sz (compound_decode_hdr_maxsz + \ | 57 | #define NFS4_dec_seek_sz (compound_decode_hdr_maxsz + \ |
| 46 | decode_putfh_maxsz + \ | 58 | decode_putfh_maxsz + \ |
| 47 | decode_seek_maxsz) | 59 | decode_seek_maxsz) |
| 60 | #define NFS4_enc_layoutstats_sz (compound_encode_hdr_maxsz + \ | ||
| 61 | encode_sequence_maxsz + \ | ||
| 62 | encode_putfh_maxsz + \ | ||
| 63 | PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz) | ||
| 64 | #define NFS4_dec_layoutstats_sz (compound_decode_hdr_maxsz + \ | ||
| 65 | decode_sequence_maxsz + \ | ||
| 66 | decode_putfh_maxsz + \ | ||
| 67 | PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz) | ||
| 48 | 68 | ||
| 49 | 69 | ||
| 50 | static void encode_fallocate(struct xdr_stream *xdr, | 70 | static void encode_fallocate(struct xdr_stream *xdr, |
| @@ -81,6 +101,33 @@ static void encode_seek(struct xdr_stream *xdr, | |||
| 81 | encode_uint32(xdr, args->sa_what); | 101 | encode_uint32(xdr, args->sa_what); |
| 82 | } | 102 | } |
| 83 | 103 | ||
| 104 | static void encode_layoutstats(struct xdr_stream *xdr, | ||
| 105 | struct nfs42_layoutstat_args *args, | ||
| 106 | struct nfs42_layoutstat_devinfo *devinfo, | ||
| 107 | struct compound_hdr *hdr) | ||
| 108 | { | ||
| 109 | __be32 *p; | ||
| 110 | |||
| 111 | encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr); | ||
| 112 | p = reserve_space(xdr, 8 + 8); | ||
| 113 | p = xdr_encode_hyper(p, devinfo->offset); | ||
| 114 | p = xdr_encode_hyper(p, devinfo->length); | ||
| 115 | encode_nfs4_stateid(xdr, &args->stateid); | ||
| 116 | p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4); | ||
| 117 | p = xdr_encode_hyper(p, devinfo->read_count); | ||
| 118 | p = xdr_encode_hyper(p, devinfo->read_bytes); | ||
| 119 | p = xdr_encode_hyper(p, devinfo->write_count); | ||
| 120 | p = xdr_encode_hyper(p, devinfo->write_bytes); | ||
| 121 | p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data, | ||
| 122 | NFS4_DEVICEID4_SIZE); | ||
| 123 | /* Encode layoutupdate4 */ | ||
| 124 | *p++ = cpu_to_be32(devinfo->layout_type); | ||
| 125 | if (devinfo->layoutstats_encode != NULL) | ||
| 126 | devinfo->layoutstats_encode(xdr, args, devinfo); | ||
| 127 | else | ||
| 128 | encode_uint32(xdr, 0); | ||
| 129 | } | ||
| 130 | |||
| 84 | /* | 131 | /* |
| 85 | * Encode ALLOCATE request | 132 | * Encode ALLOCATE request |
| 86 | */ | 133 | */ |
| @@ -137,6 +184,28 @@ static void nfs4_xdr_enc_seek(struct rpc_rqst *req, | |||
| 137 | encode_nops(&hdr); | 184 | encode_nops(&hdr); |
| 138 | } | 185 | } |
| 139 | 186 | ||
| 187 | /* | ||
| 188 | * Encode LAYOUTSTATS request | ||
| 189 | */ | ||
| 190 | static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req, | ||
| 191 | struct xdr_stream *xdr, | ||
| 192 | struct nfs42_layoutstat_args *args) | ||
| 193 | { | ||
| 194 | int i; | ||
| 195 | |||
| 196 | struct compound_hdr hdr = { | ||
| 197 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | ||
| 198 | }; | ||
| 199 | |||
| 200 | encode_compound_hdr(xdr, req, &hdr); | ||
| 201 | encode_sequence(xdr, &args->seq_args, &hdr); | ||
| 202 | encode_putfh(xdr, args->fh, &hdr); | ||
| 203 | WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV); | ||
| 204 | for (i = 0; i < args->num_dev; i++) | ||
| 205 | encode_layoutstats(xdr, args, &args->devinfo[i], &hdr); | ||
| 206 | encode_nops(&hdr); | ||
| 207 | } | ||
| 208 | |||
| 140 | static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) | 209 | static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) |
| 141 | { | 210 | { |
| 142 | return decode_op_hdr(xdr, OP_ALLOCATE); | 211 | return decode_op_hdr(xdr, OP_ALLOCATE); |
| @@ -169,6 +238,28 @@ out_overflow: | |||
| 169 | return -EIO; | 238 | return -EIO; |
| 170 | } | 239 | } |
| 171 | 240 | ||
| 241 | static int decode_layoutstats(struct xdr_stream *xdr, | ||
| 242 | struct nfs42_layoutstat_res *res) | ||
| 243 | { | ||
| 244 | int status; | ||
| 245 | __be32 *p; | ||
| 246 | |||
| 247 | status = decode_op_hdr(xdr, OP_LAYOUTSTATS); | ||
| 248 | if (status) | ||
| 249 | return status; | ||
| 250 | |||
| 251 | p = xdr_inline_decode(xdr, 4); | ||
| 252 | if (unlikely(!p)) | ||
| 253 | goto out_overflow; | ||
| 254 | |||
| 255 | res->rpc_status = be32_to_cpup(p++); | ||
| 256 | return 0; | ||
| 257 | |||
| 258 | out_overflow: | ||
| 259 | print_overflow_msg(__func__, xdr); | ||
| 260 | return -EIO; | ||
| 261 | } | ||
| 262 | |||
| 172 | /* | 263 | /* |
| 173 | * Decode ALLOCATE request | 264 | * Decode ALLOCATE request |
| 174 | */ | 265 | */ |
| @@ -246,4 +337,35 @@ static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp, | |||
| 246 | out: | 337 | out: |
| 247 | return status; | 338 | return status; |
| 248 | } | 339 | } |
| 340 | |||
| 341 | /* | ||
| 342 | * Decode LAYOUTSTATS request | ||
| 343 | */ | ||
| 344 | static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp, | ||
| 345 | struct xdr_stream *xdr, | ||
| 346 | struct nfs42_layoutstat_res *res) | ||
| 347 | { | ||
| 348 | struct compound_hdr hdr; | ||
| 349 | int status, i; | ||
| 350 | |||
| 351 | status = decode_compound_hdr(xdr, &hdr); | ||
| 352 | if (status) | ||
| 353 | goto out; | ||
| 354 | status = decode_sequence(xdr, &res->seq_res, rqstp); | ||
| 355 | if (status) | ||
| 356 | goto out; | ||
| 357 | status = decode_putfh(xdr); | ||
| 358 | if (status) | ||
| 359 | goto out; | ||
| 360 | WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV); | ||
| 361 | for (i = 0; i < res->num_dev; i++) { | ||
| 362 | status = decode_layoutstats(xdr, res); | ||
| 363 | if (status) | ||
| 364 | goto out; | ||
| 365 | } | ||
| 366 | out: | ||
| 367 | res->rpc_status = status; | ||
| 368 | return status; | ||
| 369 | } | ||
| 370 | |||
| 249 | #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */ | 371 | #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */ |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index fdef424b0cd3..ea3bee919a76 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
| @@ -233,6 +233,7 @@ extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception | |||
| 233 | extern int nfs4_call_sync(struct rpc_clnt *, struct nfs_server *, | 233 | extern int nfs4_call_sync(struct rpc_clnt *, struct nfs_server *, |
| 234 | struct rpc_message *, struct nfs4_sequence_args *, | 234 | struct rpc_message *, struct nfs4_sequence_args *, |
| 235 | struct nfs4_sequence_res *, int); | 235 | struct nfs4_sequence_res *, int); |
| 236 | extern void nfs4_init_sequence(struct nfs4_sequence_args *, struct nfs4_sequence_res *, int); | ||
| 236 | extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *); | 237 | extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *); |
| 237 | extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *); | 238 | extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *); |
| 238 | extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *, bool); | 239 | extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *, bool); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index e9cd45f1d60f..643ce3a91b22 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -476,8 +476,8 @@ struct nfs4_call_sync_data { | |||
| 476 | struct nfs4_sequence_res *seq_res; | 476 | struct nfs4_sequence_res *seq_res; |
| 477 | }; | 477 | }; |
| 478 | 478 | ||
| 479 | static void nfs4_init_sequence(struct nfs4_sequence_args *args, | 479 | void nfs4_init_sequence(struct nfs4_sequence_args *args, |
| 480 | struct nfs4_sequence_res *res, int cache_reply) | 480 | struct nfs4_sequence_res *res, int cache_reply) |
| 481 | { | 481 | { |
| 482 | args->sa_slot = NULL; | 482 | args->sa_slot = NULL; |
| 483 | args->sa_cache_this = cache_reply; | 483 | args->sa_cache_this = cache_reply; |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index a07555d6968c..558cd65dbdb7 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
| @@ -7431,6 +7431,7 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
| 7431 | PROC(SEEK, enc_seek, dec_seek), | 7431 | PROC(SEEK, enc_seek, dec_seek), |
| 7432 | PROC(ALLOCATE, enc_allocate, dec_allocate), | 7432 | PROC(ALLOCATE, enc_allocate, dec_allocate), |
| 7433 | PROC(DEALLOCATE, enc_deallocate, dec_deallocate), | 7433 | PROC(DEALLOCATE, enc_deallocate, dec_deallocate), |
| 7434 | PROC(LAYOUTSTATS, enc_layoutstats, dec_layoutstats), | ||
| 7434 | #endif /* CONFIG_NFS_V4_2 */ | 7435 | #endif /* CONFIG_NFS_V4_2 */ |
| 7435 | }; | 7436 | }; |
| 7436 | 7437 | ||
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 32201c269890..b8e72aad919c 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h | |||
| @@ -500,6 +500,7 @@ enum { | |||
| 500 | NFSPROC4_CLNT_SEEK, | 500 | NFSPROC4_CLNT_SEEK, |
| 501 | NFSPROC4_CLNT_ALLOCATE, | 501 | NFSPROC4_CLNT_ALLOCATE, |
| 502 | NFSPROC4_CLNT_DEALLOCATE, | 502 | NFSPROC4_CLNT_DEALLOCATE, |
| 503 | NFSPROC4_CLNT_LAYOUTSTATS, | ||
| 503 | }; | 504 | }; |
| 504 | 505 | ||
| 505 | /* nfs41 types */ | 506 | /* nfs41 types */ |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index c959e7eb5bd4..7bbe50504211 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
| @@ -316,6 +316,49 @@ struct nfs4_layoutreturn { | |||
| 316 | int rpc_status; | 316 | int rpc_status; |
| 317 | }; | 317 | }; |
| 318 | 318 | ||
| 319 | #define PNFS_LAYOUTSTATS_MAXSIZE 256 | ||
| 320 | |||
| 321 | struct nfs42_layoutstat_args; | ||
| 322 | struct nfs42_layoutstat_devinfo; | ||
| 323 | typedef void (*layoutstats_encode_t)(struct xdr_stream *, | ||
| 324 | struct nfs42_layoutstat_args *, | ||
| 325 | struct nfs42_layoutstat_devinfo *); | ||
| 326 | |||
| 327 | /* Per file per deviceid layoutstats */ | ||
| 328 | struct nfs42_layoutstat_devinfo { | ||
| 329 | struct nfs4_deviceid dev_id; | ||
| 330 | __u64 offset; | ||
| 331 | __u64 length; | ||
| 332 | __u64 read_count; | ||
| 333 | __u64 read_bytes; | ||
| 334 | __u64 write_count; | ||
| 335 | __u64 write_bytes; | ||
| 336 | __u32 layout_type; | ||
| 337 | layoutstats_encode_t layoutstats_encode; | ||
| 338 | void *layout_private; | ||
| 339 | }; | ||
| 340 | |||
| 341 | struct nfs42_layoutstat_args { | ||
| 342 | struct nfs4_sequence_args seq_args; | ||
| 343 | struct nfs_fh *fh; | ||
| 344 | struct inode *inode; | ||
| 345 | nfs4_stateid stateid; | ||
| 346 | int num_dev; | ||
| 347 | struct nfs42_layoutstat_devinfo *devinfo; | ||
| 348 | }; | ||
| 349 | |||
| 350 | struct nfs42_layoutstat_res { | ||
| 351 | struct nfs4_sequence_res seq_res; | ||
| 352 | int num_dev; | ||
| 353 | int rpc_status; | ||
| 354 | }; | ||
| 355 | |||
| 356 | struct nfs42_layoutstat_data { | ||
| 357 | struct inode *inode; | ||
| 358 | struct nfs42_layoutstat_args args; | ||
| 359 | struct nfs42_layoutstat_res res; | ||
| 360 | }; | ||
| 361 | |||
| 319 | struct stateowner_id { | 362 | struct stateowner_id { |
| 320 | __u64 create_time; | 363 | __u64 create_time; |
| 321 | __u32 uniquifier; | 364 | __u32 uniquifier; |
