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