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