GNU Linux-libre 4.19.211-gnu1
[releases.git] / fs / orangefs / orangefs-sysfs.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Documentation/ABI/stable/sysfs-fs-orangefs:
4  *
5  * What:                /sys/fs/orangefs/perf_counter_reset
6  * Date:                June 2015
7  * Contact:             Mike Marshall <hubcap@omnibond.com>
8  * Description:
9  *                      echo a 0 or a 1 into perf_counter_reset to
10  *                      reset all the counters in
11  *                      /sys/fs/orangefs/perf_counters
12  *                      except ones with PINT_PERF_PRESERVE set.
13  *
14  *
15  * What:                /sys/fs/orangefs/perf_counters/...
16  * Date:                Jun 2015
17  * Contact:             Mike Marshall <hubcap@omnibond.com>
18  * Description:
19  *                      Counters and settings for various caches.
20  *                      Read only.
21  *
22  *
23  * What:                /sys/fs/orangefs/perf_time_interval_secs
24  * Date:                Jun 2015
25  * Contact:             Mike Marshall <hubcap@omnibond.com>
26  * Description:
27  *                      Length of perf counter intervals in
28  *                      seconds.
29  *
30  *
31  * What:                /sys/fs/orangefs/perf_history_size
32  * Date:                Jun 2015
33  * Contact:             Mike Marshall <hubcap@omnibond.com>
34  * Description:
35  *                      The perf_counters cache statistics have N, or
36  *                      perf_history_size, samples. The default is
37  *                      one.
38  *
39  *                      Every perf_time_interval_secs the (first)
40  *                      samples are reset.
41  *
42  *                      If N is greater than one, the "current" set
43  *                      of samples is reset, and the samples from the
44  *                      other N-1 intervals remain available.
45  *
46  *
47  * What:                /sys/fs/orangefs/op_timeout_secs
48  * Date:                Jun 2015
49  * Contact:             Mike Marshall <hubcap@omnibond.com>
50  * Description:
51  *                      Service operation timeout in seconds.
52  *
53  *
54  * What:                /sys/fs/orangefs/slot_timeout_secs
55  * Date:                Jun 2015
56  * Contact:             Mike Marshall <hubcap@omnibond.com>
57  * Description:
58  *                      "Slot" timeout in seconds. A "slot"
59  *                      is an indexed buffer in the shared
60  *                      memory segment used for communication
61  *                      between the kernel module and userspace.
62  *                      Slots are requested and waited for,
63  *                      the wait times out after slot_timeout_secs.
64  *
65  * What:                /sys/fs/orangefs/dcache_timeout_msecs
66  * Date:                Jul 2016
67  * Contact:             Martin Brandenburg <martin@omnibond.com>
68  * Description:
69  *                      Time lookup is valid in milliseconds.
70  *
71  * What:                /sys/fs/orangefs/getattr_timeout_msecs
72  * Date:                Jul 2016
73  * Contact:             Martin Brandenburg <martin@omnibond.com>
74  * Description:
75  *                      Time getattr is valid in milliseconds.
76  *
77  * What:                /sys/fs/orangefs/readahead_count
78  * Date:                Aug 2016
79  * Contact:             Martin Brandenburg <martin@omnibond.com>
80  * Description:
81  *                      Readahead cache buffer count.
82  *
83  * What:                /sys/fs/orangefs/readahead_size
84  * Date:                Aug 2016
85  * Contact:             Martin Brandenburg <martin@omnibond.com>
86  * Description:
87  *                      Readahead cache buffer size.
88  *
89  * What:                /sys/fs/orangefs/readahead_count_size
90  * Date:                Aug 2016
91  * Contact:             Martin Brandenburg <martin@omnibond.com>
92  * Description:
93  *                      Readahead cache buffer count and size.
94  *
95  * What:                /sys/fs/orangefs/readahead_readcnt
96  * Date:                Jan 2017
97  * Contact:             Martin Brandenburg <martin@omnibond.com>
98  * Description:
99  *                      Number of buffers (in multiples of readahead_size)
100  *                      which can be read ahead for a single file at once.
101  *
102  * What:                /sys/fs/orangefs/acache/...
103  * Date:                Jun 2015
104  * Contact:             Martin Brandenburg <martin@omnibond.com>
105  * Description:
106  *                      Attribute cache configurable settings.
107  *
108  *
109  * What:                /sys/fs/orangefs/ncache/...
110  * Date:                Jun 2015
111  * Contact:             Mike Marshall <hubcap@omnibond.com>
112  * Description:
113  *                      Name cache configurable settings.
114  *
115  *
116  * What:                /sys/fs/orangefs/capcache/...
117  * Date:                Jun 2015
118  * Contact:             Mike Marshall <hubcap@omnibond.com>
119  * Description:
120  *                      Capability cache configurable settings.
121  *
122  *
123  * What:                /sys/fs/orangefs/ccache/...
124  * Date:                Jun 2015
125  * Contact:             Mike Marshall <hubcap@omnibond.com>
126  * Description:
127  *                      Credential cache configurable settings.
128  *
129  */
130
131 #include <linux/fs.h>
132 #include <linux/kobject.h>
133 #include <linux/string.h>
134 #include <linux/sysfs.h>
135 #include <linux/module.h>
136 #include <linux/init.h>
137
138 #include "protocol.h"
139 #include "orangefs-kernel.h"
140 #include "orangefs-sysfs.h"
141
142 #define ORANGEFS_KOBJ_ID "orangefs"
143 #define ACACHE_KOBJ_ID "acache"
144 #define CAPCACHE_KOBJ_ID "capcache"
145 #define CCACHE_KOBJ_ID "ccache"
146 #define NCACHE_KOBJ_ID "ncache"
147 #define PC_KOBJ_ID "pc"
148 #define STATS_KOBJ_ID "stats"
149
150 /*
151  * Every item calls orangefs_attr_show and orangefs_attr_store through
152  * orangefs_sysfs_ops. They look at the orangefs_attributes further below to
153  * call one of sysfs_int_show, sysfs_int_store, sysfs_service_op_show, or
154  * sysfs_service_op_store.
155  */
156
157 struct orangefs_attribute {
158         struct attribute attr;
159         ssize_t (*show)(struct kobject *kobj,
160                         struct orangefs_attribute *attr,
161                         char *buf);
162         ssize_t (*store)(struct kobject *kobj,
163                          struct orangefs_attribute *attr,
164                          const char *buf,
165                          size_t count);
166 };
167
168 static ssize_t orangefs_attr_show(struct kobject *kobj,
169                                   struct attribute *attr,
170                                   char *buf)
171 {
172         struct orangefs_attribute *attribute;
173
174         attribute = container_of(attr, struct orangefs_attribute, attr);
175         if (!attribute->show)
176                 return -EIO;
177         return attribute->show(kobj, attribute, buf);
178 }
179
180 static ssize_t orangefs_attr_store(struct kobject *kobj,
181                                    struct attribute *attr,
182                                    const char *buf,
183                                    size_t len)
184 {
185         struct orangefs_attribute *attribute;
186
187         if (!strcmp(kobj->name, PC_KOBJ_ID) ||
188             !strcmp(kobj->name, STATS_KOBJ_ID))
189                 return -EPERM;
190
191         attribute = container_of(attr, struct orangefs_attribute, attr);
192         if (!attribute->store)
193                 return -EIO;
194         return attribute->store(kobj, attribute, buf, len);
195 }
196
197 static const struct sysfs_ops orangefs_sysfs_ops = {
198         .show = orangefs_attr_show,
199         .store = orangefs_attr_store,
200 };
201
202 static ssize_t sysfs_int_show(struct kobject *kobj,
203     struct orangefs_attribute *attr, char *buf)
204 {
205         int rc = -EIO;
206
207         gossip_debug(GOSSIP_SYSFS_DEBUG, "sysfs_int_show: id:%s:\n",
208             kobj->name);
209
210         if (!strcmp(kobj->name, ORANGEFS_KOBJ_ID)) {
211                 if (!strcmp(attr->attr.name, "op_timeout_secs")) {
212                         rc = scnprintf(buf,
213                                        PAGE_SIZE,
214                                        "%d\n",
215                                        op_timeout_secs);
216                         goto out;
217                 } else if (!strcmp(attr->attr.name,
218                                    "slot_timeout_secs")) {
219                         rc = scnprintf(buf,
220                                        PAGE_SIZE,
221                                        "%d\n",
222                                        slot_timeout_secs);
223                         goto out;
224                 } else if (!strcmp(attr->attr.name,
225                                    "dcache_timeout_msecs")) {
226                         rc = scnprintf(buf,
227                                        PAGE_SIZE,
228                                        "%d\n",
229                                        orangefs_dcache_timeout_msecs);
230                         goto out;
231                 } else if (!strcmp(attr->attr.name,
232                                    "getattr_timeout_msecs")) {
233                         rc = scnprintf(buf,
234                                        PAGE_SIZE,
235                                        "%d\n",
236                                        orangefs_getattr_timeout_msecs);
237                         goto out;
238                 } else {
239                         goto out;
240                 }
241
242         } else if (!strcmp(kobj->name, STATS_KOBJ_ID)) {
243                 if (!strcmp(attr->attr.name, "reads")) {
244                         rc = scnprintf(buf,
245                                        PAGE_SIZE,
246                                        "%lu\n",
247                                        orangefs_stats.reads);
248                         goto out;
249                 } else if (!strcmp(attr->attr.name, "writes")) {
250                         rc = scnprintf(buf,
251                                        PAGE_SIZE,
252                                        "%lu\n",
253                                        orangefs_stats.writes);
254                         goto out;
255                 } else {
256                         goto out;
257                 }
258         }
259
260 out:
261
262         return rc;
263 }
264
265 static ssize_t sysfs_int_store(struct kobject *kobj,
266     struct orangefs_attribute *attr, const char *buf, size_t count)
267 {
268         int rc = 0;
269
270         gossip_debug(GOSSIP_SYSFS_DEBUG,
271                      "sysfs_int_store: start attr->attr.name:%s: buf:%s:\n",
272                      attr->attr.name, buf);
273
274         if (!strcmp(attr->attr.name, "op_timeout_secs")) {
275                 rc = kstrtoint(buf, 0, &op_timeout_secs);
276                 goto out;
277         } else if (!strcmp(attr->attr.name, "slot_timeout_secs")) {
278                 rc = kstrtoint(buf, 0, &slot_timeout_secs);
279                 goto out;
280         } else if (!strcmp(attr->attr.name, "dcache_timeout_msecs")) {
281                 rc = kstrtoint(buf, 0, &orangefs_dcache_timeout_msecs);
282                 goto out;
283         } else if (!strcmp(attr->attr.name, "getattr_timeout_msecs")) {
284                 rc = kstrtoint(buf, 0, &orangefs_getattr_timeout_msecs);
285                 goto out;
286         } else {
287                 goto out;
288         }
289
290 out:
291         if (rc)
292                 rc = -EINVAL;
293         else
294                 rc = count;
295
296         return rc;
297 }
298
299 /*
300  * obtain attribute values from userspace with a service operation.
301  */
302 static ssize_t sysfs_service_op_show(struct kobject *kobj,
303     struct orangefs_attribute *attr, char *buf)
304 {
305         struct orangefs_kernel_op_s *new_op = NULL;
306         int rc = 0;
307         char *ser_op_type = NULL;
308         __u32 op_alloc_type;
309
310         gossip_debug(GOSSIP_SYSFS_DEBUG,
311                      "sysfs_service_op_show: id:%s:\n",
312                      kobj->name);
313
314         if (strcmp(kobj->name, PC_KOBJ_ID))
315                 op_alloc_type = ORANGEFS_VFS_OP_PARAM;
316         else
317                 op_alloc_type = ORANGEFS_VFS_OP_PERF_COUNT;
318
319         new_op = op_alloc(op_alloc_type);
320         if (!new_op)
321                 return -ENOMEM;
322
323         /* Can't do a service_operation if the client is not running... */
324         rc = is_daemon_in_service();
325         if (rc) {
326                 pr_info_ratelimited("%s: Client not running :%d:\n",
327                         __func__,
328                         is_daemon_in_service());
329                 goto out;
330         }
331
332         if (strcmp(kobj->name, PC_KOBJ_ID))
333                 new_op->upcall.req.param.type = ORANGEFS_PARAM_REQUEST_GET;
334
335         if (!strcmp(kobj->name, ORANGEFS_KOBJ_ID)) {
336                 /* Drop unsupported requests first. */
337                 if (!(orangefs_features & ORANGEFS_FEATURE_READAHEAD) &&
338                     (!strcmp(attr->attr.name, "readahead_count") ||
339                     !strcmp(attr->attr.name, "readahead_size") ||
340                     !strcmp(attr->attr.name, "readahead_count_size") ||
341                     !strcmp(attr->attr.name, "readahead_readcnt"))) {
342                         rc = -EINVAL;
343                         goto out;
344                 }
345
346                 if (!strcmp(attr->attr.name, "perf_history_size"))
347                         new_op->upcall.req.param.op =
348                                 ORANGEFS_PARAM_REQUEST_OP_PERF_HISTORY_SIZE;
349                 else if (!strcmp(attr->attr.name,
350                                  "perf_time_interval_secs"))
351                         new_op->upcall.req.param.op =
352                                 ORANGEFS_PARAM_REQUEST_OP_PERF_TIME_INTERVAL_SECS;
353                 else if (!strcmp(attr->attr.name,
354                                  "perf_counter_reset"))
355                         new_op->upcall.req.param.op =
356                                 ORANGEFS_PARAM_REQUEST_OP_PERF_RESET;
357
358                 else if (!strcmp(attr->attr.name,
359                                  "readahead_count"))
360                         new_op->upcall.req.param.op =
361                                 ORANGEFS_PARAM_REQUEST_OP_READAHEAD_COUNT;
362
363                 else if (!strcmp(attr->attr.name,
364                                  "readahead_size"))
365                         new_op->upcall.req.param.op =
366                                 ORANGEFS_PARAM_REQUEST_OP_READAHEAD_SIZE;
367
368                 else if (!strcmp(attr->attr.name,
369                                  "readahead_count_size"))
370                         new_op->upcall.req.param.op =
371                                 ORANGEFS_PARAM_REQUEST_OP_READAHEAD_COUNT_SIZE;
372
373                 else if (!strcmp(attr->attr.name,
374                                  "readahead_readcnt"))
375                         new_op->upcall.req.param.op =
376                                 ORANGEFS_PARAM_REQUEST_OP_READAHEAD_READCNT;
377         } else if (!strcmp(kobj->name, ACACHE_KOBJ_ID)) {
378                 if (!strcmp(attr->attr.name, "timeout_msecs"))
379                         new_op->upcall.req.param.op =
380                                 ORANGEFS_PARAM_REQUEST_OP_ACACHE_TIMEOUT_MSECS;
381
382                 if (!strcmp(attr->attr.name, "hard_limit"))
383                         new_op->upcall.req.param.op =
384                                 ORANGEFS_PARAM_REQUEST_OP_ACACHE_HARD_LIMIT;
385
386                 if (!strcmp(attr->attr.name, "soft_limit"))
387                         new_op->upcall.req.param.op =
388                                 ORANGEFS_PARAM_REQUEST_OP_ACACHE_SOFT_LIMIT;
389
390                 if (!strcmp(attr->attr.name, "reclaim_percentage"))
391                         new_op->upcall.req.param.op =
392                           ORANGEFS_PARAM_REQUEST_OP_ACACHE_RECLAIM_PERCENTAGE;
393
394         } else if (!strcmp(kobj->name, CAPCACHE_KOBJ_ID)) {
395                 if (!strcmp(attr->attr.name, "timeout_secs"))
396                         new_op->upcall.req.param.op =
397                                 ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_TIMEOUT_SECS;
398
399                 if (!strcmp(attr->attr.name, "hard_limit"))
400                         new_op->upcall.req.param.op =
401                                 ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_HARD_LIMIT;
402
403                 if (!strcmp(attr->attr.name, "soft_limit"))
404                         new_op->upcall.req.param.op =
405                                 ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_SOFT_LIMIT;
406
407                 if (!strcmp(attr->attr.name, "reclaim_percentage"))
408                         new_op->upcall.req.param.op =
409                           ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_RECLAIM_PERCENTAGE;
410
411         } else if (!strcmp(kobj->name, CCACHE_KOBJ_ID)) {
412                 if (!strcmp(attr->attr.name, "timeout_secs"))
413                         new_op->upcall.req.param.op =
414                                 ORANGEFS_PARAM_REQUEST_OP_CCACHE_TIMEOUT_SECS;
415
416                 if (!strcmp(attr->attr.name, "hard_limit"))
417                         new_op->upcall.req.param.op =
418                                 ORANGEFS_PARAM_REQUEST_OP_CCACHE_HARD_LIMIT;
419
420                 if (!strcmp(attr->attr.name, "soft_limit"))
421                         new_op->upcall.req.param.op =
422                                 ORANGEFS_PARAM_REQUEST_OP_CCACHE_SOFT_LIMIT;
423
424                 if (!strcmp(attr->attr.name, "reclaim_percentage"))
425                         new_op->upcall.req.param.op =
426                           ORANGEFS_PARAM_REQUEST_OP_CCACHE_RECLAIM_PERCENTAGE;
427
428         } else if (!strcmp(kobj->name, NCACHE_KOBJ_ID)) {
429                 if (!strcmp(attr->attr.name, "timeout_msecs"))
430                         new_op->upcall.req.param.op =
431                                 ORANGEFS_PARAM_REQUEST_OP_NCACHE_TIMEOUT_MSECS;
432
433                 if (!strcmp(attr->attr.name, "hard_limit"))
434                         new_op->upcall.req.param.op =
435                                 ORANGEFS_PARAM_REQUEST_OP_NCACHE_HARD_LIMIT;
436
437                 if (!strcmp(attr->attr.name, "soft_limit"))
438                         new_op->upcall.req.param.op =
439                                 ORANGEFS_PARAM_REQUEST_OP_NCACHE_SOFT_LIMIT;
440
441                 if (!strcmp(attr->attr.name, "reclaim_percentage"))
442                         new_op->upcall.req.param.op =
443                           ORANGEFS_PARAM_REQUEST_OP_NCACHE_RECLAIM_PERCENTAGE;
444
445         } else if (!strcmp(kobj->name, PC_KOBJ_ID)) {
446                 if (!strcmp(attr->attr.name, ACACHE_KOBJ_ID))
447                         new_op->upcall.req.perf_count.type =
448                                 ORANGEFS_PERF_COUNT_REQUEST_ACACHE;
449
450                 if (!strcmp(attr->attr.name, CAPCACHE_KOBJ_ID))
451                         new_op->upcall.req.perf_count.type =
452                                 ORANGEFS_PERF_COUNT_REQUEST_CAPCACHE;
453
454                 if (!strcmp(attr->attr.name, NCACHE_KOBJ_ID))
455                         new_op->upcall.req.perf_count.type =
456                                 ORANGEFS_PERF_COUNT_REQUEST_NCACHE;
457
458         } else {
459                 gossip_err("sysfs_service_op_show: unknown kobj_id:%s:\n",
460                            kobj->name);
461                 rc = -EINVAL;
462                 goto out;
463         }
464
465
466         if (strcmp(kobj->name, PC_KOBJ_ID))
467                 ser_op_type = "orangefs_param";
468         else
469                 ser_op_type = "orangefs_perf_count";
470
471         /*
472          * The service_operation will return an errno return code on
473          * error, and zero on success.
474          */
475         rc = service_operation(new_op, ser_op_type, ORANGEFS_OP_INTERRUPTIBLE);
476
477 out:
478         if (!rc) {
479                 if (strcmp(kobj->name, PC_KOBJ_ID)) {
480                         if (new_op->upcall.req.param.op ==
481                             ORANGEFS_PARAM_REQUEST_OP_READAHEAD_COUNT_SIZE) {
482                                 rc = scnprintf(buf, PAGE_SIZE, "%d %d\n",
483                                     (int)new_op->downcall.resp.param.u.
484                                     value32[0],
485                                     (int)new_op->downcall.resp.param.u.
486                                     value32[1]);
487                         } else {
488                                 rc = scnprintf(buf, PAGE_SIZE, "%d\n",
489                                     (int)new_op->downcall.resp.param.u.value64);
490                         }
491                 } else {
492                         rc = scnprintf(
493                                 buf,
494                                 PAGE_SIZE,
495                                 "%s",
496                                 new_op->downcall.resp.perf_count.buffer);
497                 }
498         }
499
500         op_release(new_op);
501
502         return rc;
503
504 }
505
506 /*
507  * pass attribute values back to userspace with a service operation.
508  *
509  * We have to do a memory allocation, an sscanf and a service operation.
510  * And we have to evaluate what the user entered, to make sure the
511  * value is within the range supported by the attribute. So, there's
512  * a lot of return code checking and mapping going on here.
513  *
514  * We want to return 1 if we think everything went OK, and
515  * EINVAL if not.
516  */
517 static ssize_t sysfs_service_op_store(struct kobject *kobj,
518     struct orangefs_attribute *attr, const char *buf, size_t count)
519 {
520         struct orangefs_kernel_op_s *new_op = NULL;
521         int val = 0;
522         int rc = 0;
523
524         gossip_debug(GOSSIP_SYSFS_DEBUG,
525                      "sysfs_service_op_store: id:%s:\n",
526                      kobj->name);
527
528         new_op = op_alloc(ORANGEFS_VFS_OP_PARAM);
529         if (!new_op)
530                 return -EINVAL; /* sic */
531
532         /* Can't do a service_operation if the client is not running... */
533         rc = is_daemon_in_service();
534         if (rc) {
535                 pr_info("%s: Client not running :%d:\n",
536                         __func__,
537                         is_daemon_in_service());
538                 goto out;
539         }
540
541         /*
542          * The value we want to send back to userspace is in buf, unless this
543          * there are two parameters, which is specially handled below.
544          */
545         if (strcmp(kobj->name, ORANGEFS_KOBJ_ID) ||
546             strcmp(attr->attr.name, "readahead_count_size")) {
547                 rc = kstrtoint(buf, 0, &val);
548                 if (rc)
549                         goto out;
550         }
551
552         new_op->upcall.req.param.type = ORANGEFS_PARAM_REQUEST_SET;
553
554         if (!strcmp(kobj->name, ORANGEFS_KOBJ_ID)) {
555                 /* Drop unsupported requests first. */
556                 if (!(orangefs_features & ORANGEFS_FEATURE_READAHEAD) &&
557                     (!strcmp(attr->attr.name, "readahead_count") ||
558                     !strcmp(attr->attr.name, "readahead_size") ||
559                     !strcmp(attr->attr.name, "readahead_count_size") ||
560                     !strcmp(attr->attr.name, "readahead_readcnt"))) {
561                         rc = -EINVAL;
562                         goto out;
563                 }
564
565                 if (!strcmp(attr->attr.name, "perf_history_size")) {
566                         if (val > 0) {
567                                 new_op->upcall.req.param.op =
568                                   ORANGEFS_PARAM_REQUEST_OP_PERF_HISTORY_SIZE;
569                         } else {
570                                 rc = 0;
571                                 goto out;
572                         }
573                 } else if (!strcmp(attr->attr.name,
574                                    "perf_time_interval_secs")) {
575                         if (val > 0) {
576                                 new_op->upcall.req.param.op =
577                                 ORANGEFS_PARAM_REQUEST_OP_PERF_TIME_INTERVAL_SECS;
578                         } else {
579                                 rc = 0;
580                                 goto out;
581                         }
582                 } else if (!strcmp(attr->attr.name,
583                                    "perf_counter_reset")) {
584                         if ((val == 0) || (val == 1)) {
585                                 new_op->upcall.req.param.op =
586                                         ORANGEFS_PARAM_REQUEST_OP_PERF_RESET;
587                         } else {
588                                 rc = 0;
589                                 goto out;
590                         }
591                 } else if (!strcmp(attr->attr.name,
592                                    "readahead_count")) {
593                         if ((val >= 0)) {
594                                 new_op->upcall.req.param.op =
595                                 ORANGEFS_PARAM_REQUEST_OP_READAHEAD_COUNT;
596                         } else {
597                                 rc = 0;
598                                 goto out;
599                         }
600                 } else if (!strcmp(attr->attr.name,
601                                    "readahead_size")) {
602                         if ((val >= 0)) {
603                                 new_op->upcall.req.param.op =
604                                 ORANGEFS_PARAM_REQUEST_OP_READAHEAD_SIZE;
605                         } else {
606                                 rc = 0;
607                                 goto out;
608                         }
609                 } else if (!strcmp(attr->attr.name,
610                                    "readahead_count_size")) {
611                         int val1, val2;
612                         rc = sscanf(buf, "%d %d", &val1, &val2);
613                         if (rc < 2) {
614                                 rc = 0;
615                                 goto out;
616                         }
617                         if ((val1 >= 0) && (val2 >= 0)) {
618                                 new_op->upcall.req.param.op =
619                                 ORANGEFS_PARAM_REQUEST_OP_READAHEAD_COUNT_SIZE;
620                         } else {
621                                 rc = 0;
622                                 goto out;
623                         }
624                         new_op->upcall.req.param.u.value32[0] = val1;
625                         new_op->upcall.req.param.u.value32[1] = val2;
626                         goto value_set;
627                 } else if (!strcmp(attr->attr.name,
628                                    "readahead_readcnt")) {
629                         if ((val >= 0)) {
630                                 new_op->upcall.req.param.op =
631                                 ORANGEFS_PARAM_REQUEST_OP_READAHEAD_READCNT;
632                         } else {
633                                 rc = 0;
634                                 goto out;
635                         }
636                 }
637
638         } else if (!strcmp(kobj->name, ACACHE_KOBJ_ID)) {
639                 if (!strcmp(attr->attr.name, "hard_limit")) {
640                         if (val > -1) {
641                                 new_op->upcall.req.param.op =
642                                   ORANGEFS_PARAM_REQUEST_OP_ACACHE_HARD_LIMIT;
643                         } else {
644                                 rc = 0;
645                                 goto out;
646                         }
647                 } else if (!strcmp(attr->attr.name, "soft_limit")) {
648                         if (val > -1) {
649                                 new_op->upcall.req.param.op =
650                                   ORANGEFS_PARAM_REQUEST_OP_ACACHE_SOFT_LIMIT;
651                         } else {
652                                 rc = 0;
653                                 goto out;
654                         }
655                 } else if (!strcmp(attr->attr.name,
656                                    "reclaim_percentage")) {
657                         if ((val > -1) && (val < 101)) {
658                                 new_op->upcall.req.param.op =
659                                   ORANGEFS_PARAM_REQUEST_OP_ACACHE_RECLAIM_PERCENTAGE;
660                         } else {
661                                 rc = 0;
662                                 goto out;
663                         }
664                 } else if (!strcmp(attr->attr.name, "timeout_msecs")) {
665                         if (val > -1) {
666                                 new_op->upcall.req.param.op =
667                                   ORANGEFS_PARAM_REQUEST_OP_ACACHE_TIMEOUT_MSECS;
668                         } else {
669                                 rc = 0;
670                                 goto out;
671                         }
672                 }
673
674         } else if (!strcmp(kobj->name, CAPCACHE_KOBJ_ID)) {
675                 if (!strcmp(attr->attr.name, "hard_limit")) {
676                         if (val > -1) {
677                                 new_op->upcall.req.param.op =
678                                   ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_HARD_LIMIT;
679                         } else {
680                                 rc = 0;
681                                 goto out;
682                         }
683                 } else if (!strcmp(attr->attr.name, "soft_limit")) {
684                         if (val > -1) {
685                                 new_op->upcall.req.param.op =
686                                   ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_SOFT_LIMIT;
687                         } else {
688                                 rc = 0;
689                                 goto out;
690                         }
691                 } else if (!strcmp(attr->attr.name,
692                                    "reclaim_percentage")) {
693                         if ((val > -1) && (val < 101)) {
694                                 new_op->upcall.req.param.op =
695                                   ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_RECLAIM_PERCENTAGE;
696                         } else {
697                                 rc = 0;
698                                 goto out;
699                         }
700                 } else if (!strcmp(attr->attr.name, "timeout_secs")) {
701                         if (val > -1) {
702                                 new_op->upcall.req.param.op =
703                                   ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_TIMEOUT_SECS;
704                         } else {
705                                 rc = 0;
706                                 goto out;
707                         }
708                 }
709
710         } else if (!strcmp(kobj->name, CCACHE_KOBJ_ID)) {
711                 if (!strcmp(attr->attr.name, "hard_limit")) {
712                         if (val > -1) {
713                                 new_op->upcall.req.param.op =
714                                   ORANGEFS_PARAM_REQUEST_OP_CCACHE_HARD_LIMIT;
715                         } else {
716                                 rc = 0;
717                                 goto out;
718                         }
719                 } else if (!strcmp(attr->attr.name, "soft_limit")) {
720                         if (val > -1) {
721                                 new_op->upcall.req.param.op =
722                                   ORANGEFS_PARAM_REQUEST_OP_CCACHE_SOFT_LIMIT;
723                         } else {
724                                 rc = 0;
725                                 goto out;
726                         }
727                 } else if (!strcmp(attr->attr.name,
728                                    "reclaim_percentage")) {
729                         if ((val > -1) && (val < 101)) {
730                                 new_op->upcall.req.param.op =
731                                   ORANGEFS_PARAM_REQUEST_OP_CCACHE_RECLAIM_PERCENTAGE;
732                         } else {
733                                 rc = 0;
734                                 goto out;
735                         }
736                 } else if (!strcmp(attr->attr.name, "timeout_secs")) {
737                         if (val > -1) {
738                                 new_op->upcall.req.param.op =
739                                   ORANGEFS_PARAM_REQUEST_OP_CCACHE_TIMEOUT_SECS;
740                         } else {
741                                 rc = 0;
742                                 goto out;
743                         }
744                 }
745
746         } else if (!strcmp(kobj->name, NCACHE_KOBJ_ID)) {
747                 if (!strcmp(attr->attr.name, "hard_limit")) {
748                         if (val > -1) {
749                                 new_op->upcall.req.param.op =
750                                   ORANGEFS_PARAM_REQUEST_OP_NCACHE_HARD_LIMIT;
751                         } else {
752                                 rc = 0;
753                                 goto out;
754                         }
755                 } else if (!strcmp(attr->attr.name, "soft_limit")) {
756                         if (val > -1) {
757                                 new_op->upcall.req.param.op =
758                                   ORANGEFS_PARAM_REQUEST_OP_NCACHE_SOFT_LIMIT;
759                         } else {
760                                 rc = 0;
761                                 goto out;
762                         }
763                 } else if (!strcmp(attr->attr.name,
764                                    "reclaim_percentage")) {
765                         if ((val > -1) && (val < 101)) {
766                                 new_op->upcall.req.param.op =
767                                         ORANGEFS_PARAM_REQUEST_OP_NCACHE_RECLAIM_PERCENTAGE;
768                         } else {
769                                 rc = 0;
770                                 goto out;
771                         }
772                 } else if (!strcmp(attr->attr.name, "timeout_msecs")) {
773                         if (val > -1) {
774                                 new_op->upcall.req.param.op =
775                                   ORANGEFS_PARAM_REQUEST_OP_NCACHE_TIMEOUT_MSECS;
776                         } else {
777                                 rc = 0;
778                                 goto out;
779                         }
780                 }
781
782         } else {
783                 gossip_err("sysfs_service_op_store: unknown kobj_id:%s:\n",
784                            kobj->name);
785                 rc = -EINVAL;
786                 goto out;
787         }
788
789         new_op->upcall.req.param.u.value64 = val;
790 value_set:
791
792         /*
793          * The service_operation will return a errno return code on
794          * error, and zero on success.
795          */
796         rc = service_operation(new_op, "orangefs_param", ORANGEFS_OP_INTERRUPTIBLE);
797
798         if (rc < 0) {
799                 gossip_err("sysfs_service_op_store: service op returned:%d:\n",
800                         rc);
801                 rc = 0;
802         } else {
803                 rc = count;
804         }
805
806 out:
807         op_release(new_op);
808
809         if (rc == -ENOMEM || rc == 0)
810                 rc = -EINVAL;
811
812         return rc;
813 }
814
815 static struct orangefs_attribute op_timeout_secs_attribute =
816         __ATTR(op_timeout_secs, 0664, sysfs_int_show, sysfs_int_store);
817
818 static struct orangefs_attribute slot_timeout_secs_attribute =
819         __ATTR(slot_timeout_secs, 0664, sysfs_int_show, sysfs_int_store);
820
821 static struct orangefs_attribute dcache_timeout_msecs_attribute =
822         __ATTR(dcache_timeout_msecs, 0664, sysfs_int_show, sysfs_int_store);
823
824 static struct orangefs_attribute getattr_timeout_msecs_attribute =
825         __ATTR(getattr_timeout_msecs, 0664, sysfs_int_show, sysfs_int_store);
826
827 static struct orangefs_attribute readahead_count_attribute =
828         __ATTR(readahead_count, 0664, sysfs_service_op_show,
829                sysfs_service_op_store);
830
831 static struct orangefs_attribute readahead_size_attribute =
832         __ATTR(readahead_size, 0664, sysfs_service_op_show,
833                sysfs_service_op_store);
834
835 static struct orangefs_attribute readahead_count_size_attribute =
836         __ATTR(readahead_count_size, 0664, sysfs_service_op_show,
837                sysfs_service_op_store);
838
839 static struct orangefs_attribute readahead_readcnt_attribute =
840         __ATTR(readahead_readcnt, 0664, sysfs_service_op_show,
841                sysfs_service_op_store);
842
843 static struct orangefs_attribute perf_counter_reset_attribute =
844         __ATTR(perf_counter_reset,
845                0664,
846                sysfs_service_op_show,
847                sysfs_service_op_store);
848
849 static struct orangefs_attribute perf_history_size_attribute =
850         __ATTR(perf_history_size,
851                0664,
852                sysfs_service_op_show,
853                sysfs_service_op_store);
854
855 static struct orangefs_attribute perf_time_interval_secs_attribute =
856         __ATTR(perf_time_interval_secs,
857                0664,
858                sysfs_service_op_show,
859                sysfs_service_op_store);
860
861 static struct attribute *orangefs_default_attrs[] = {
862         &op_timeout_secs_attribute.attr,
863         &slot_timeout_secs_attribute.attr,
864         &dcache_timeout_msecs_attribute.attr,
865         &getattr_timeout_msecs_attribute.attr,
866         &readahead_count_attribute.attr,
867         &readahead_size_attribute.attr,
868         &readahead_count_size_attribute.attr,
869         &readahead_readcnt_attribute.attr,
870         &perf_counter_reset_attribute.attr,
871         &perf_history_size_attribute.attr,
872         &perf_time_interval_secs_attribute.attr,
873         NULL,
874 };
875
876 static struct kobj_type orangefs_ktype = {
877         .sysfs_ops = &orangefs_sysfs_ops,
878         .default_attrs = orangefs_default_attrs,
879 };
880
881 static struct orangefs_attribute acache_hard_limit_attribute =
882         __ATTR(hard_limit,
883                0664,
884                sysfs_service_op_show,
885                sysfs_service_op_store);
886
887 static struct orangefs_attribute acache_reclaim_percent_attribute =
888         __ATTR(reclaim_percentage,
889                0664,
890                sysfs_service_op_show,
891                sysfs_service_op_store);
892
893 static struct orangefs_attribute acache_soft_limit_attribute =
894         __ATTR(soft_limit,
895                0664,
896                sysfs_service_op_show,
897                sysfs_service_op_store);
898
899 static struct orangefs_attribute acache_timeout_msecs_attribute =
900         __ATTR(timeout_msecs,
901                0664,
902                sysfs_service_op_show,
903                sysfs_service_op_store);
904
905 static struct attribute *acache_orangefs_default_attrs[] = {
906         &acache_hard_limit_attribute.attr,
907         &acache_reclaim_percent_attribute.attr,
908         &acache_soft_limit_attribute.attr,
909         &acache_timeout_msecs_attribute.attr,
910         NULL,
911 };
912
913 static struct kobj_type acache_orangefs_ktype = {
914         .sysfs_ops = &orangefs_sysfs_ops,
915         .default_attrs = acache_orangefs_default_attrs,
916 };
917
918 static struct orangefs_attribute capcache_hard_limit_attribute =
919         __ATTR(hard_limit,
920                0664,
921                sysfs_service_op_show,
922                sysfs_service_op_store);
923
924 static struct orangefs_attribute capcache_reclaim_percent_attribute =
925         __ATTR(reclaim_percentage,
926                0664,
927                sysfs_service_op_show,
928                sysfs_service_op_store);
929
930 static struct orangefs_attribute capcache_soft_limit_attribute =
931         __ATTR(soft_limit,
932                0664,
933                sysfs_service_op_show,
934                sysfs_service_op_store);
935
936 static struct orangefs_attribute capcache_timeout_secs_attribute =
937         __ATTR(timeout_secs,
938                0664,
939                sysfs_service_op_show,
940                sysfs_service_op_store);
941
942 static struct attribute *capcache_orangefs_default_attrs[] = {
943         &capcache_hard_limit_attribute.attr,
944         &capcache_reclaim_percent_attribute.attr,
945         &capcache_soft_limit_attribute.attr,
946         &capcache_timeout_secs_attribute.attr,
947         NULL,
948 };
949
950 static struct kobj_type capcache_orangefs_ktype = {
951         .sysfs_ops = &orangefs_sysfs_ops,
952         .default_attrs = capcache_orangefs_default_attrs,
953 };
954
955 static struct orangefs_attribute ccache_hard_limit_attribute =
956         __ATTR(hard_limit,
957                0664,
958                sysfs_service_op_show,
959                sysfs_service_op_store);
960
961 static struct orangefs_attribute ccache_reclaim_percent_attribute =
962         __ATTR(reclaim_percentage,
963                0664,
964                sysfs_service_op_show,
965                sysfs_service_op_store);
966
967 static struct orangefs_attribute ccache_soft_limit_attribute =
968         __ATTR(soft_limit,
969                0664,
970                sysfs_service_op_show,
971                sysfs_service_op_store);
972
973 static struct orangefs_attribute ccache_timeout_secs_attribute =
974         __ATTR(timeout_secs,
975                0664,
976                sysfs_service_op_show,
977                sysfs_service_op_store);
978
979 static struct attribute *ccache_orangefs_default_attrs[] = {
980         &ccache_hard_limit_attribute.attr,
981         &ccache_reclaim_percent_attribute.attr,
982         &ccache_soft_limit_attribute.attr,
983         &ccache_timeout_secs_attribute.attr,
984         NULL,
985 };
986
987 static struct kobj_type ccache_orangefs_ktype = {
988         .sysfs_ops = &orangefs_sysfs_ops,
989         .default_attrs = ccache_orangefs_default_attrs,
990 };
991
992 static struct orangefs_attribute ncache_hard_limit_attribute =
993         __ATTR(hard_limit,
994                0664,
995                sysfs_service_op_show,
996                sysfs_service_op_store);
997
998 static struct orangefs_attribute ncache_reclaim_percent_attribute =
999         __ATTR(reclaim_percentage,
1000                0664,
1001                sysfs_service_op_show,
1002                sysfs_service_op_store);
1003
1004 static struct orangefs_attribute ncache_soft_limit_attribute =
1005         __ATTR(soft_limit,
1006                0664,
1007                sysfs_service_op_show,
1008                sysfs_service_op_store);
1009
1010 static struct orangefs_attribute ncache_timeout_msecs_attribute =
1011         __ATTR(timeout_msecs,
1012                0664,
1013                sysfs_service_op_show,
1014                sysfs_service_op_store);
1015
1016 static struct attribute *ncache_orangefs_default_attrs[] = {
1017         &ncache_hard_limit_attribute.attr,
1018         &ncache_reclaim_percent_attribute.attr,
1019         &ncache_soft_limit_attribute.attr,
1020         &ncache_timeout_msecs_attribute.attr,
1021         NULL,
1022 };
1023
1024 static struct kobj_type ncache_orangefs_ktype = {
1025         .sysfs_ops = &orangefs_sysfs_ops,
1026         .default_attrs = ncache_orangefs_default_attrs,
1027 };
1028
1029 static struct orangefs_attribute pc_acache_attribute =
1030         __ATTR(acache,
1031                0664,
1032                sysfs_service_op_show,
1033                NULL);
1034
1035 static struct orangefs_attribute pc_capcache_attribute =
1036         __ATTR(capcache,
1037                0664,
1038                sysfs_service_op_show,
1039                NULL);
1040
1041 static struct orangefs_attribute pc_ncache_attribute =
1042         __ATTR(ncache,
1043                0664,
1044                sysfs_service_op_show,
1045                NULL);
1046
1047 static struct attribute *pc_orangefs_default_attrs[] = {
1048         &pc_acache_attribute.attr,
1049         &pc_capcache_attribute.attr,
1050         &pc_ncache_attribute.attr,
1051         NULL,
1052 };
1053
1054 static struct kobj_type pc_orangefs_ktype = {
1055         .sysfs_ops = &orangefs_sysfs_ops,
1056         .default_attrs = pc_orangefs_default_attrs,
1057 };
1058
1059 static struct orangefs_attribute stats_reads_attribute =
1060         __ATTR(reads,
1061                0664,
1062                sysfs_int_show,
1063                NULL);
1064
1065 static struct orangefs_attribute stats_writes_attribute =
1066         __ATTR(writes,
1067                0664,
1068                sysfs_int_show,
1069                NULL);
1070
1071 static struct attribute *stats_orangefs_default_attrs[] = {
1072         &stats_reads_attribute.attr,
1073         &stats_writes_attribute.attr,
1074         NULL,
1075 };
1076
1077 static struct kobj_type stats_orangefs_ktype = {
1078         .sysfs_ops = &orangefs_sysfs_ops,
1079         .default_attrs = stats_orangefs_default_attrs,
1080 };
1081
1082 static struct kobject *orangefs_obj;
1083 static struct kobject *acache_orangefs_obj;
1084 static struct kobject *capcache_orangefs_obj;
1085 static struct kobject *ccache_orangefs_obj;
1086 static struct kobject *ncache_orangefs_obj;
1087 static struct kobject *pc_orangefs_obj;
1088 static struct kobject *stats_orangefs_obj;
1089
1090 int orangefs_sysfs_init(void)
1091 {
1092         int rc = -EINVAL;
1093
1094         gossip_debug(GOSSIP_SYSFS_DEBUG, "orangefs_sysfs_init: start\n");
1095
1096         /* create /sys/fs/orangefs. */
1097         orangefs_obj = kzalloc(sizeof(*orangefs_obj), GFP_KERNEL);
1098         if (!orangefs_obj)
1099                 goto out;
1100
1101         rc = kobject_init_and_add(orangefs_obj,
1102                                   &orangefs_ktype,
1103                                   fs_kobj,
1104                                   ORANGEFS_KOBJ_ID);
1105
1106         if (rc)
1107                 goto ofs_obj_bail;
1108
1109         kobject_uevent(orangefs_obj, KOBJ_ADD);
1110
1111         /* create /sys/fs/orangefs/acache. */
1112         acache_orangefs_obj = kzalloc(sizeof(*acache_orangefs_obj), GFP_KERNEL);
1113         if (!acache_orangefs_obj) {
1114                 rc = -EINVAL;
1115                 goto ofs_obj_bail;
1116         }
1117
1118         rc = kobject_init_and_add(acache_orangefs_obj,
1119                                   &acache_orangefs_ktype,
1120                                   orangefs_obj,
1121                                   ACACHE_KOBJ_ID);
1122
1123         if (rc)
1124                 goto acache_obj_bail;
1125
1126         kobject_uevent(acache_orangefs_obj, KOBJ_ADD);
1127
1128         /* create /sys/fs/orangefs/capcache. */
1129         capcache_orangefs_obj =
1130                 kzalloc(sizeof(*capcache_orangefs_obj), GFP_KERNEL);
1131         if (!capcache_orangefs_obj) {
1132                 rc = -EINVAL;
1133                 goto acache_obj_bail;
1134         }
1135
1136         rc = kobject_init_and_add(capcache_orangefs_obj,
1137                                   &capcache_orangefs_ktype,
1138                                   orangefs_obj,
1139                                   CAPCACHE_KOBJ_ID);
1140         if (rc)
1141                 goto capcache_obj_bail;
1142
1143         kobject_uevent(capcache_orangefs_obj, KOBJ_ADD);
1144
1145         /* create /sys/fs/orangefs/ccache. */
1146         ccache_orangefs_obj =
1147                 kzalloc(sizeof(*ccache_orangefs_obj), GFP_KERNEL);
1148         if (!ccache_orangefs_obj) {
1149                 rc = -EINVAL;
1150                 goto capcache_obj_bail;
1151         }
1152
1153         rc = kobject_init_and_add(ccache_orangefs_obj,
1154                                   &ccache_orangefs_ktype,
1155                                   orangefs_obj,
1156                                   CCACHE_KOBJ_ID);
1157         if (rc)
1158                 goto ccache_obj_bail;
1159
1160         kobject_uevent(ccache_orangefs_obj, KOBJ_ADD);
1161
1162         /* create /sys/fs/orangefs/ncache. */
1163         ncache_orangefs_obj = kzalloc(sizeof(*ncache_orangefs_obj), GFP_KERNEL);
1164         if (!ncache_orangefs_obj) {
1165                 rc = -EINVAL;
1166                 goto ccache_obj_bail;
1167         }
1168
1169         rc = kobject_init_and_add(ncache_orangefs_obj,
1170                                   &ncache_orangefs_ktype,
1171                                   orangefs_obj,
1172                                   NCACHE_KOBJ_ID);
1173
1174         if (rc)
1175                 goto ncache_obj_bail;
1176
1177         kobject_uevent(ncache_orangefs_obj, KOBJ_ADD);
1178
1179         /* create /sys/fs/orangefs/perf_counters. */
1180         pc_orangefs_obj = kzalloc(sizeof(*pc_orangefs_obj), GFP_KERNEL);
1181         if (!pc_orangefs_obj) {
1182                 rc = -EINVAL;
1183                 goto ncache_obj_bail;
1184         }
1185
1186         rc = kobject_init_and_add(pc_orangefs_obj,
1187                                   &pc_orangefs_ktype,
1188                                   orangefs_obj,
1189                                   "perf_counters");
1190
1191         if (rc)
1192                 goto pc_obj_bail;
1193
1194         kobject_uevent(pc_orangefs_obj, KOBJ_ADD);
1195
1196         /* create /sys/fs/orangefs/stats. */
1197         stats_orangefs_obj = kzalloc(sizeof(*stats_orangefs_obj), GFP_KERNEL);
1198         if (!stats_orangefs_obj) {
1199                 rc = -EINVAL;
1200                 goto pc_obj_bail;
1201         }
1202
1203         rc = kobject_init_and_add(stats_orangefs_obj,
1204                                   &stats_orangefs_ktype,
1205                                   orangefs_obj,
1206                                   STATS_KOBJ_ID);
1207
1208         if (rc)
1209                 goto stats_obj_bail;
1210
1211         kobject_uevent(stats_orangefs_obj, KOBJ_ADD);
1212         goto out;
1213
1214 stats_obj_bail:
1215                 kobject_put(stats_orangefs_obj);
1216 pc_obj_bail:
1217                 kobject_put(pc_orangefs_obj);
1218 ncache_obj_bail:
1219                 kobject_put(ncache_orangefs_obj);
1220 ccache_obj_bail:
1221                 kobject_put(ccache_orangefs_obj);
1222 capcache_obj_bail:
1223                 kobject_put(capcache_orangefs_obj);
1224 acache_obj_bail:
1225                 kobject_put(acache_orangefs_obj);
1226 ofs_obj_bail:
1227                 kobject_put(orangefs_obj);
1228 out:
1229         return rc;
1230 }
1231
1232 void orangefs_sysfs_exit(void)
1233 {
1234         gossip_debug(GOSSIP_SYSFS_DEBUG, "orangefs_sysfs_exit: start\n");
1235         kobject_put(acache_orangefs_obj);
1236         kobject_put(capcache_orangefs_obj);
1237         kobject_put(ccache_orangefs_obj);
1238         kobject_put(ncache_orangefs_obj);
1239         kobject_put(pc_orangefs_obj);
1240         kobject_put(stats_orangefs_obj);
1241         kobject_put(orangefs_obj);
1242 }