aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2015-06-23 07:51:55 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2015-06-24 10:17:37 -0400
commitbe3a5d233922d73f27002ce2767f6ec03c3f473d (patch)
tree43a275fd1acfcdf22699db092d342627673abf67
parent1372a3130a3e0bfd38d82d476f0a907cc72ba816 (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.h9
-rw-r--r--fs/nfs/nfs42proc.c27
-rw-r--r--fs/nfs/nfs42xdr.c122
-rw-r--r--fs/nfs/nfs4_fs.h1
-rw-r--r--fs/nfs/nfs4proc.c4
-rw-r--r--fs/nfs/nfs4xdr.c1
-rw-r--r--include/linux/nfs4.h1
-rw-r--r--include/linux/nfs_xdr.h43
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 */
9int nfs42_proc_allocate(struct file *, loff_t, loff_t); 15int nfs42_proc_allocate(struct file *, loff_t, loff_t);
10int nfs42_proc_deallocate(struct file *, loff_t, loff_t); 16int nfs42_proc_deallocate(struct file *, loff_t, loff_t);
11loff_t nfs42_proc_llseek(struct file *, loff_t, int); 17loff_t nfs42_proc_llseek(struct file *, loff_t, int);
12 18int nfs42_proc_layoutstats_generic(struct nfs_server *,
19 struct nfs42_layoutstat_data *);
13/* nfs4.2xdr.h */ 20/* nfs4.2xdr.h */
14extern struct rpc_procinfo nfs4_2_procedures[]; 21extern 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
169static const struct rpc_call_ops nfs42_layoutstat_ops = {
170};
171
172int 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
50static void encode_fallocate(struct xdr_stream *xdr, 70static 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
104static 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 */
190static 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
140static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) 209static 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
241static 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
258out_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,
246out: 337out:
247 return status; 338 return status;
248} 339}
340
341/*
342 * Decode LAYOUTSTATS request
343 */
344static 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 }
366out:
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
233extern int nfs4_call_sync(struct rpc_clnt *, struct nfs_server *, 233extern 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);
236extern void nfs4_init_sequence(struct nfs4_sequence_args *, struct nfs4_sequence_res *, int);
236extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *); 237extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *);
237extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *); 238extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *);
238extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *, bool); 239extern 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
479static void nfs4_init_sequence(struct nfs4_sequence_args *args, 479void 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
321struct nfs42_layoutstat_args;
322struct nfs42_layoutstat_devinfo;
323typedef void (*layoutstats_encode_t)(struct xdr_stream *,
324 struct nfs42_layoutstat_args *,
325 struct nfs42_layoutstat_devinfo *);
326
327/* Per file per deviceid layoutstats */
328struct 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
341struct 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
350struct nfs42_layoutstat_res {
351 struct nfs4_sequence_res seq_res;
352 int num_dev;
353 int rpc_status;
354};
355
356struct nfs42_layoutstat_data {
357 struct inode *inode;
358 struct nfs42_layoutstat_args args;
359 struct nfs42_layoutstat_res res;
360};
361
319struct stateowner_id { 362struct stateowner_id {
320 __u64 create_time; 363 __u64 create_time;
321 __u32 uniquifier; 364 __u32 uniquifier;