Whamcloud - gitweb
LU-5614 build: use %kernel_module_package in rpm spec
[fs/lustre-release.git] / lustre / ptlrpc / nodemap_lproc.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (C) 2013, Trustees of Indiana University
24  *
25  * Copyright (c) 2014, 2015, Intel Corporation.
26  *
27  * Author: Joshua Walgenbach <jjw@iu.edu>
28  */
29
30 #define NODEMAP_LPROC_ID_LEN 16
31 #define NODEMAP_LPROC_FLAG_LEN 2
32
33 #include <lprocfs_status.h>
34 #include <lustre_net.h>
35 #include <lustre_export.h>
36 #include <obd_class.h>
37 #include <interval_tree.h>
38 #include "nodemap_internal.h"
39
40 static LIST_HEAD(nodemap_pde_list);
41
42 /**
43  * Reads and prints the idmap for the given nodemap.
44  *
45  * \param       m               seq file in proc fs
46  * \param       data            unused
47  * \retval      0               success
48  */
49 static int nodemap_idmap_show(struct seq_file *m, void *data)
50 {
51         struct lu_nodemap       *nodemap;
52         struct lu_idmap         *idmap;
53         struct rb_node          *node;
54         bool                    cont = 0;
55         int rc;
56
57         mutex_lock(&active_config_lock);
58         nodemap = nodemap_lookup(m->private);
59         mutex_unlock(&active_config_lock);
60         if (IS_ERR(nodemap)) {
61                 rc = PTR_ERR(nodemap);
62                 CERROR("cannot find nodemap '%s': rc = %d\n",
63                         (char *)m->private, rc);
64                 return rc;
65         }
66
67         seq_printf(m, "[\n");
68         read_lock(&nodemap->nm_idmap_lock);
69         for (node = rb_first(&nodemap->nm_client_to_fs_uidmap); node;
70                                 node = rb_next(node)) {
71                 if (cont)
72                         seq_printf(m, ",\n");
73                 cont = 1;
74                 idmap = rb_entry(node, struct lu_idmap, id_client_to_fs);
75                 if (idmap != NULL)
76                         seq_printf(m, " { idtype: uid, client_id: %u, "
77                                    "fs_id: %u }", idmap->id_client,
78                                    idmap->id_fs);
79         }
80         for (node = rb_first(&nodemap->nm_client_to_fs_gidmap);
81                                 node; node = rb_next(node)) {
82                 if (cont)
83                         seq_printf(m, ",\n");
84                 idmap = rb_entry(node, struct lu_idmap, id_client_to_fs);
85                 if (idmap != NULL)
86                         seq_printf(m, " { idtype: gid, client_id: %u, "
87                                    "fs_id: %u }", idmap->id_client,
88                                    idmap->id_fs);
89         }
90         read_unlock(&nodemap->nm_idmap_lock);
91         seq_printf(m, "\n");
92         seq_printf(m, "]\n");
93
94         nodemap_putref(nodemap);
95         return 0;
96 }
97
98 /**
99  * Attaches nodemap_idmap_show to proc file.
100  *
101  * \param       inode           inode of seq file in proc fs
102  * \param       file            seq file
103  * \retval      0               success
104  */
105 static int nodemap_idmap_open(struct inode *inode, struct file *file)
106 {
107         return single_open(file, nodemap_idmap_show, PDE_DATA(inode));
108 }
109
110 /**
111  * Reads and prints the NID ranges for the given nodemap.
112  *
113  * \param       m               seq file in proc fs
114  * \param       data            unused
115  * \retval      0               success
116  */
117 static int nodemap_ranges_show(struct seq_file *m, void *data)
118 {
119         struct lu_nodemap               *nodemap;
120         struct lu_nid_range             *range;
121         struct interval_node_extent     ext;
122         char                            start_nidstr[LNET_NIDSTR_SIZE];
123         char                            end_nidstr[LNET_NIDSTR_SIZE];
124         bool                            cont = false;
125         int rc;
126
127         mutex_lock(&active_config_lock);
128         nodemap = nodemap_lookup(m->private);
129         if (IS_ERR(nodemap)) {
130                 mutex_unlock(&active_config_lock);
131                 rc = PTR_ERR(nodemap);
132                 CERROR("cannot find nodemap '%s': rc = %d\n",
133                         (char *)m->private, rc);
134                 return rc;
135         }
136
137         seq_printf(m, "[\n");
138         down_read(&active_config->nmc_range_tree_lock);
139         list_for_each_entry(range, &nodemap->nm_ranges, rn_list) {
140                 if (cont)
141                         seq_printf(m, ",\n");
142                 cont = 1;
143                 ext = range->rn_node.in_extent;
144                 libcfs_nid2str_r(ext.start, start_nidstr, sizeof(start_nidstr));
145                 libcfs_nid2str_r(ext.end, end_nidstr, sizeof(end_nidstr));
146                 seq_printf(m, " { id: %u, start_nid: %s, end_nid: %s }",
147                            range->rn_id, start_nidstr, end_nidstr);
148         }
149         up_read(&active_config->nmc_range_tree_lock);
150         mutex_unlock(&active_config_lock);
151         seq_printf(m, "\n");
152         seq_printf(m, "]\n");
153
154         nodemap_putref(nodemap);
155         return 0;
156 }
157
158 /**
159  * Connects nodemap_idmap_show to proc file.
160  *
161  * \param       inode           inode of seq file in proc fs
162  * \param       file            seq file
163  * \retval      0               success
164  */
165 static int nodemap_ranges_open(struct inode *inode, struct file *file)
166 {
167         return single_open(file, nodemap_ranges_show, PDE_DATA(inode));
168 }
169
170 /**
171  * Reads and prints the fileset for the given nodemap.
172  *
173  * \param       m               seq file in proc fs
174  * \param       data            unused
175  * \retval      0               success
176  */
177 static int nodemap_fileset_seq_show(struct seq_file *m, void *data)
178 {
179         struct lu_nodemap *nodemap;
180         int rc;
181
182         mutex_lock(&active_config_lock);
183         nodemap = nodemap_lookup(m->private);
184         mutex_unlock(&active_config_lock);
185         if (IS_ERR(nodemap)) {
186                 rc = PTR_ERR(nodemap);
187                 CERROR("cannot find nodemap '%s': rc = %d\n",
188                         (char *)m->private, rc);
189                 return rc;
190         }
191
192         rc = seq_printf(m, "%s\n", nodemap->nm_fileset);
193         nodemap_putref(nodemap);
194         return rc;
195 }
196
197 /**
198  * Set a fileset on a nodemap.
199  *
200  * \param[in] file      proc file
201  * \param[in] buffer    string, "<fileset>"
202  * \param[in] count     \a buffer length
203  * \param[in] off       unused
204  * \retval              \a count on success
205  * \retval              negative number on error
206  */
207 static ssize_t
208 nodemap_fileset_seq_write(struct file *file,
209                                       const char __user *buffer,
210                                       size_t count, loff_t *off)
211 {
212         struct seq_file *m = file->private_data;
213         int rc = 0;
214
215         if (count > 0)
216                 rc = nodemap_set_fileset(m->private, buffer);
217
218         if (rc != 0)
219                 return -EINVAL;
220
221         return count;
222 }
223 LPROC_SEQ_FOPS(nodemap_fileset);
224
225 /**
226  * Reads and prints the exports attached to the given nodemap.
227  *
228  * \param       m               seq file in proc fs, stores nodemap
229  * \param       data            unused
230  * \retval      0               success
231  */
232 static int nodemap_exports_show(struct seq_file *m, void *data)
233 {
234         struct lu_nodemap *nodemap;
235         struct obd_export *exp;
236         char nidstr[LNET_NIDSTR_SIZE] = "<unknown>";
237         int rc;
238
239         mutex_lock(&active_config_lock);
240         nodemap = nodemap_lookup(m->private);
241         mutex_unlock(&active_config_lock);
242         if (IS_ERR(nodemap)) {
243                 rc = PTR_ERR(nodemap);
244                 CERROR("cannot find nodemap '%s': rc = %d\n",
245                         (char *)m->private, rc);
246                 return rc;
247         }
248
249         seq_printf(m, "[\n");
250
251         mutex_lock(&nodemap->nm_member_list_lock);
252         list_for_each_entry(exp, &nodemap->nm_member_list,
253                             exp_target_data.ted_nodemap_member) {
254                 if (exp->exp_connection != NULL)
255                         libcfs_nid2str_r(exp->exp_connection->c_peer.nid,
256                                          nidstr, sizeof(nidstr));
257
258                 seq_printf(m, " { nid: %s, uuid: %s },",
259                            nidstr, exp->exp_client_uuid.uuid);
260         }
261         mutex_unlock(&nodemap->nm_member_list_lock);
262
263         seq_printf(m, "\n");
264         seq_printf(m, "]\n");
265
266         nodemap_putref(nodemap);
267         return 0;
268 }
269
270 /**
271  * Attaches nodemap_idmap_show to proc file.
272  *
273  * \param       inode           inode of seq file in proc fs
274  * \param       file            seq file
275  * \retval      0               success
276  */
277 static int nodemap_exports_open(struct inode *inode, struct file *file)
278 {
279         return single_open(file, nodemap_exports_show, PDE_DATA(inode));
280 }
281
282 /**
283  * Reads and prints the active flag for the given nodemap.
284  *
285  * \param       m               seq file in proc fs
286  * \param       data            unused
287  * \retval      0               success
288  */
289 static int nodemap_active_seq_show(struct seq_file *m, void *data)
290 {
291         seq_printf(m, "%u\n", (unsigned int)nodemap_active);
292         return 0;
293 }
294
295 /**
296  * Activate/deactivate nodemap.
297  *
298  * \param[in] file      proc file
299  * \param[in] buffer    string, "1" or "0" to activate/deactivate nodemap
300  * \param[in] count     \a buffer length
301  * \param[in] off       unused
302  * \retval              \a count on success
303  * \retval              negative number on error
304  */
305 static ssize_t
306 nodemap_active_seq_write(struct file *file, const char __user *buffer,
307                          size_t count, loff_t *off)
308 {
309         char                    active_string[NODEMAP_LPROC_FLAG_LEN + 1];
310         long unsigned int       active;
311         int                     rc;
312
313         if (count == 0)
314                 return 0;
315
316         if (count >= sizeof(active_string))
317                 return -EINVAL;
318
319         if (copy_from_user(active_string, buffer, count))
320                 return -EFAULT;
321
322         active_string[count] = '\0';
323         rc = kstrtoul(active_string, 10, &active);
324         if (rc != 0)
325                 return -EINVAL;
326
327         nodemap_activate(active);
328
329         return count;
330 }
331 LPROC_SEQ_FOPS(nodemap_active);
332
333 /**
334  * Reads and prints the nodemap ID for the given nodemap.
335  *
336  * \param       m               seq file in proc fs
337  * \param       data            unused
338  * \retval      0               success
339  */
340 static int nodemap_id_seq_show(struct seq_file *m, void *data)
341 {
342         struct lu_nodemap *nodemap;
343
344         mutex_lock(&active_config_lock);
345         nodemap = nodemap_lookup(m->private);
346         mutex_unlock(&active_config_lock);
347         if (IS_ERR(nodemap)) {
348                 int rc = PTR_ERR(nodemap);
349                 CERROR("cannot find nodemap '%s': rc = %d\n",
350                         (char *)m->private, rc);
351                 return rc;
352         }
353
354         seq_printf(m, "%u\n", nodemap->nm_id);
355         nodemap_putref(nodemap);
356         return 0;
357 }
358 LPROC_SEQ_FOPS_RO(nodemap_id);
359
360 /**
361  * Reads and prints the root squash UID for the given nodemap.
362  *
363  * \param       m               seq file in proc fs
364  * \param       data            unused
365  * \retval      0               success
366  */
367 static int nodemap_squash_uid_seq_show(struct seq_file *m, void *data)
368 {
369         struct lu_nodemap *nodemap;
370
371         mutex_lock(&active_config_lock);
372         nodemap = nodemap_lookup(m->private);
373         mutex_unlock(&active_config_lock);
374         if (IS_ERR(nodemap)) {
375                 int rc = PTR_ERR(nodemap);
376                 CERROR("cannot find nodemap '%s': rc = %d\n",
377                         (char *)m->private, rc);
378                 return rc;
379         }
380
381         seq_printf(m, "%u\n", nodemap->nm_squash_uid);
382         nodemap_putref(nodemap);
383         return 0;
384 }
385
386 /**
387  * Reads and prints the root squash GID for the given nodemap.
388  *
389  * \param       m               seq file in proc fs
390  * \param       data            unused
391  * \retval      0               success
392  */
393 static int nodemap_squash_gid_seq_show(struct seq_file *m, void *data)
394 {
395         struct lu_nodemap *nodemap;
396
397         mutex_lock(&active_config_lock);
398         nodemap = nodemap_lookup(m->private);
399         mutex_unlock(&active_config_lock);
400         if (IS_ERR(nodemap)) {
401                 int rc = PTR_ERR(nodemap);
402                 CERROR("cannot find nodemap '%s': rc = %d\n",
403                         (char *)m->private, rc);
404                 return rc;
405         }
406
407         seq_printf(m, "%u\n", nodemap->nm_squash_gid);
408         nodemap_putref(nodemap);
409         return 0;
410 }
411
412 /**
413  * Reads and prints the trusted flag for the given nodemap.
414  *
415  * \param       m               seq file in proc fs
416  * \param       data            unused
417  * \retval      0               success
418  */
419 static int nodemap_trusted_seq_show(struct seq_file *m, void *data)
420 {
421         struct lu_nodemap *nodemap;
422
423         mutex_lock(&active_config_lock);
424         nodemap = nodemap_lookup(m->private);
425         mutex_unlock(&active_config_lock);
426         if (IS_ERR(nodemap)) {
427                 int rc = PTR_ERR(nodemap);
428
429                 CERROR("cannot find nodemap '%s': rc = %d\n",
430                         (char *)m->private, rc);
431                 return rc;
432         }
433
434         seq_printf(m, "%d\n", (int)nodemap->nmf_trust_client_ids);
435         nodemap_putref(nodemap);
436         return 0;
437 }
438
439 /**
440  * Reads and prints the admin flag for the given nodemap.
441  *
442  * \param       m               seq file in proc fs
443  * \param       data            unused
444  * \retval      0               success
445  */
446 static int nodemap_admin_seq_show(struct seq_file *m, void *data)
447 {
448         struct lu_nodemap *nodemap;
449         int rc;
450
451         mutex_lock(&active_config_lock);
452         nodemap = nodemap_lookup(m->private);
453         mutex_unlock(&active_config_lock);
454         if (IS_ERR(nodemap)) {
455                 rc = PTR_ERR(nodemap);
456                 CERROR("cannot find nodemap '%s': rc = %d\n",
457                         (char *)m->private, rc);
458                 return rc;
459         }
460
461         seq_printf(m, "%d\n", (int)nodemap->nmf_allow_root_access);
462         nodemap_putref(nodemap);
463         return 0;
464 }
465
466 #ifdef NODEMAP_PROC_DEBUG
467 /**
468  * Helper functions to set nodemap flags.
469  *
470  * \param[in] buffer    string, which is "1" or "0" to set/unset flag
471  * \param[in] count     \a buffer length
472  * \param[out] flag_p   where to store flag value
473  * \retval              \a count on success
474  * \retval              negative number on error
475  */
476 static int nodemap_proc_read_flag(const char __user *buffer,
477                                   unsigned long count, unsigned int *flag_p)
478 {
479         char                    scratch[NODEMAP_LPROC_FLAG_LEN + 1];
480         long unsigned int       flag_buf;
481         int                     rc;
482
483         if (count == 0)
484                 return 0;
485
486         if (count >= sizeof(scratch))
487                 return -EINVAL;
488
489         if (copy_from_user(scratch, buffer, count))
490                 return -EFAULT;
491
492         scratch[count] = '\0';
493         rc = kstrtoul(scratch, 10, &flag_buf);
494         if (rc != 0)
495                 return -EINVAL;
496
497         *flag_p = flag_buf;
498
499         return count;
500 }
501
502 /**
503  * Set the squash UID.
504  *
505  * \param[in] file      proc file
506  * \param[in] buffer    string representing squash UID to set
507  * \param[in] count     \a buffer length
508  * \param[in] off       unused
509  * \retval              \a count on success
510  * \retval              negative number on error
511  */
512 static ssize_t
513 nodemap_squash_uid_seq_write(struct file *file, const char __user *buffer,
514                              size_t count, loff_t *off)
515 {
516         char                     squash[NODEMAP_LPROC_ID_LEN + 1];
517         struct seq_file         *m = file->private_data;
518         long unsigned int        squash_uid;
519         int                      rc;
520
521         if (count == 0)
522                 return 0;
523
524         if (count >= sizeof(squash))
525                 return -EINVAL;
526
527         if (copy_from_user(squash, buffer, count))
528                 return -EFAULT;
529
530         squash[count] = '\0';
531         rc = kstrtoul(squash, 10, &squash_uid);
532         if (rc != 0)
533                 return -EINVAL;
534
535         rc = nodemap_set_squash_uid(m->private, squash_uid);
536         if (rc != 0)
537                 return rc;
538
539         return count;
540 }
541
542 /**
543  * Set the squash GID.
544  *
545  * \param[in] file      proc file
546  * \param[in] buffer    string representing squash GID to set
547  * \param[in] count     \a buffer length
548  * \param[in] off       unused
549  * \retval              \a count on success
550  * \retval              negative number on error
551  */
552 static ssize_t
553 nodemap_squash_gid_seq_write(struct file *file, const char __user *buffer,
554                              size_t count, loff_t *off)
555 {
556         char                     squash[NODEMAP_LPROC_ID_LEN + 1];
557         struct seq_file         *m = file->private_data;
558         long unsigned int        squash_gid;
559         int                      rc;
560
561         if (count == 0)
562                 return 0;
563
564         if (count >= sizeof(squash))
565                 return -EINVAL;
566
567         if (copy_from_user(squash, buffer, count))
568                 return -EFAULT;
569
570         squash[count] = '\0';
571         rc = kstrtoul(squash, 10, &squash_gid);
572         if (rc != 0)
573                 return -EINVAL;
574
575         rc = nodemap_set_squash_gid(m->private, squash_gid);
576         if (rc != 0)
577                 return rc;
578
579         return count;
580 }
581
582 /**
583  * Set/unset the trusted flag.
584  *
585  * \param[in] file      proc file
586  * \param[in] buffer    string, "1" or "0"
587  * \param[in] count     \a buffer length
588  * \param[in] off       unused
589  * \retval              \a count on success
590  * \retval              negative number on error
591  */
592 static ssize_t
593 nodemap_trusted_seq_write(struct file *file, const char __user *buffer,
594                           size_t count, loff_t *off)
595 {
596         struct seq_file         *m = file->private_data;
597         int                     flags;
598         int                     rc;
599
600         rc = nodemap_proc_read_flag(buffer, count, &flags);
601         if (rc < 0)
602                 return rc;
603
604         rc = nodemap_set_trust_client_ids(m->private, flags);
605         if (rc != 0)
606                 return rc;
607
608         return count;
609 }
610
611 /**
612  * Set/unset the admin flag.
613  *
614  * \param[in] file      proc file
615  * \param[in] buffer    string, "1" or "0"
616  * \param[in] count     \a buffer length
617  * \param[in] off       unused
618  * \retval              \a count on success
619  * \retval              negative number on error
620  */
621 static ssize_t
622 nodemap_admin_seq_write(struct file *file, const char __user *buffer,
623                         size_t count, loff_t *off)
624 {
625         struct seq_file         *m = file->private_data;
626         int                     flags;
627         int                     rc;
628
629         rc = nodemap_proc_read_flag(buffer, count, &flags);
630         if (rc < 0)
631                 return rc;
632
633         rc = nodemap_set_allow_root(m->private, flags);
634         if (rc != 0)
635                 return rc;
636
637         return count;
638 }
639
640 /**
641  * Add a nodemap.
642  *
643  * \param[in] file      proc file
644  * \param[in] buffer    string, name of the nodemap to add
645  * \param[in] count     \a buffer length
646  * \param[in] off       unused
647  * \retval              \a count on success
648  * \retval              negative number on error
649  */
650 static ssize_t
651 lprocfs_add_nodemap_seq_write(struct file *file, const char __user *buffer,
652                               size_t count, loff_t *off)
653 {
654         char    nodemap_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
655         char    *cpybuf = NULL;
656         char    *pos;
657         int     rc;
658
659         if (count == 0)
660                 return 0;
661
662         if (count >= sizeof(nodemap_name))
663                 return -EINVAL;
664
665         if (copy_from_user(nodemap_name, buffer, count))
666                 return -EFAULT;
667
668         nodemap_name[count] = '\0';
669
670         cpybuf = nodemap_name;
671         pos = strsep(&cpybuf, " \n");
672         if (pos == NULL)
673                 return -EINVAL;
674
675         rc = nodemap_add(nodemap_name);
676         if (rc == 0)
677                 rc = count;
678
679         return rc;
680 }
681 LPROC_SEQ_FOPS_WO_TYPE(nodemap, add_nodemap);
682
683 /**
684  * Delete a nodemap.
685  *
686  * \param[in] file      proc file
687  * \param[in] buffer    string, name of the nodemap to delete
688  * \param[in] count     \a buffer length
689  * \param[in] off       unused
690  * \retval              \a count on success
691  * \retval              negative number on error
692  */
693 static ssize_t
694 lprocfs_del_nodemap_seq_write(struct file *file, const char __user *buffer,
695                               size_t count, loff_t *off)
696 {
697         char    nodemap_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
698         char    *cpybuf = NULL;
699         char    *pos;
700         int     rc = count;
701
702         if (count == 0)
703                 return 0;
704
705         if (count >= sizeof(nodemap_name))
706                 return -EINVAL;
707
708         if (copy_from_user(nodemap_name, buffer, count))
709                 return -EFAULT;
710
711         nodemap_name[count] = '\0';
712
713         cpybuf = nodemap_name;
714         pos = strsep(&cpybuf, " \n");
715         if (pos == NULL)
716                 return -EINVAL;
717
718         rc = nodemap_del(nodemap_name);
719         if (rc == 0)
720                 rc = count;
721
722         return rc;
723
724 }
725 LPROC_SEQ_FOPS_WO_TYPE(nodemap, del_nodemap);
726
727 /**
728  * Helper function to parse a NID string.
729  *
730  * \param[in] rangestr  string representation of NIDs, see libcfs_str2nid()
731  * \param[out] nids     array of two nids
732  * \retval              0 on success
733  * \retval              negative number on error
734  */
735 static int parse_nids(char *rangestr, lnet_nid_t nids[2])
736 {
737         struct list_head        nidlist;
738         char                    nidstr[2][LNET_NIDSTR_SIZE];
739         char                    nidrange_str[2 * LNET_NIDSTR_SIZE + 2];
740         int                     rc = 0;
741
742         INIT_LIST_HEAD(&nidlist);
743
744         if (cfs_parse_nidlist(rangestr, strlen(rangestr),
745             &nidlist) <= 0)
746                 return -EINVAL;
747
748         if (!cfs_nidrange_is_contiguous(&nidlist))
749                 return -EINVAL;
750
751         cfs_nidrange_find_min_max(&nidlist, nidstr[0], nidstr[1],
752                                   LNET_NIDSTR_SIZE);
753         snprintf(nidrange_str, sizeof(nidrange_str), "%s:%s",
754                 nidstr[0], nidstr[1]);
755
756         rc = nodemap_parse_range(nidrange_str, nids);
757         if (rc != 0)
758                 return -EINVAL;
759
760         cfs_free_nidlist(&nidlist);
761
762         return 0;
763 }
764
765 /**
766  * Add a NID range to nodemap.
767  *
768  * \param[in] file      proc file
769  * \param[in] buffer    string, "<nodemap name> <nid range>"
770  * \param[in] count     \a buffer length
771  * \param[in] off       unused
772  * \retval              \a count on success
773  * \retval              negative number on error
774  */
775 static ssize_t
776 lprocfs_add_nodemap_range_seq_write(struct file *file,
777                                     const char __user *buffer,
778                                     size_t count, loff_t *off)
779 {
780         char                    name_range[LUSTRE_NODEMAP_NAME_LENGTH +
781                                            LNET_NIDSTR_SIZE * 2 + 2];
782         char                    *cpybuf = NULL;
783         char                    *name;
784         char                    *rangestr = NULL;
785         lnet_nid_t              nids[2];
786         int                     rc;
787
788         if (count == 0)
789                 return 0;
790
791         if (count >= sizeof(name_range))
792                 GOTO(out, rc = -EINVAL);
793
794         if (copy_from_user(name_range, buffer, count))
795                 GOTO(out, rc = -EFAULT);
796
797         name_range[count] = '\0';
798
799         cpybuf = name_range;
800         name = strsep(&cpybuf, " ");
801         if (name == NULL)
802                 GOTO(out, rc = -EINVAL);
803
804         rangestr = strsep(&cpybuf, " \n");
805         if (rangestr == NULL)
806                 GOTO(out, rc = -EINVAL);
807
808         rc = parse_nids(rangestr, nids);
809         if (rc != 0)
810                 GOTO(out, rc = rc);
811
812         rc = nodemap_add_range(name, nids);
813         if (rc != 0)
814                 GOTO(out, rc = -EINVAL);
815
816         if (rc == 0)
817                 rc = count;
818
819 out:
820         return rc;
821 }
822 LPROC_SEQ_FOPS_WO_TYPE(nodemap, add_nodemap_range);
823
824 /**
825  * Delete a NID range from nodemap.
826  *
827  * \param[in] file      proc file
828  * \param[in] buffer    string, "<nodemap name> <nid range>"
829  * \param[in] count     \a buffer length
830  * \param[in] off       unused
831  * \retval              \a count on success
832  * \retval              negative number on error
833  */
834 static ssize_t
835 lprocfs_del_nodemap_range_seq_write(struct file *file,
836                                     const char __user *buffer,
837                                     size_t count, loff_t *off)
838 {
839         char                    name_range[LUSTRE_NODEMAP_NAME_LENGTH +
840                                            LNET_NIDSTR_SIZE * 2 + 2];
841         char                    *cpybuf = NULL;
842         char                    *name;
843         char                    *rangestr = NULL;
844         lnet_nid_t              nids[2];
845         int                     rc;
846
847         if (count == 0)
848                 return 0;
849
850         if (count >= sizeof(name_range))
851                 GOTO(out, rc = -EINVAL);
852
853         if (copy_from_user(name_range, buffer, count))
854                 GOTO(out, rc = -EFAULT);
855
856         name_range[count] = '\0';
857
858         cpybuf = name_range;
859         name = strsep(&cpybuf, " ");
860         if (name == NULL)
861                 GOTO(out, rc = -EINVAL);
862
863         rangestr = strsep(&cpybuf, " \n");
864         if (rangestr == NULL)
865                 GOTO(out, rc = -EINVAL);
866
867         rc = parse_nids(rangestr, nids);
868         if (rc != 0)
869                 GOTO(out, rc = rc);
870
871         rc = nodemap_del_range(name, nids);
872         if (rc != 0)
873                 GOTO(out, rc = -EINVAL);
874
875         if (rc == 0)
876                 rc = count;
877
878 out:
879         return rc;
880 }
881 LPROC_SEQ_FOPS_WO_TYPE(nodemap, del_nodemap_range);
882
883 /**
884  * Add an idmap to nodemap.
885  *
886  * \param[in] file      proc file
887  * \param[in] buffer    string, "<nodemap name> <uid|gid> <idmap>"
888  * \param[in] count     \a buffer length
889  * \param[in] off       unused
890  * \retval              \a count on success
891  * \retval              negative number on error
892  */
893 static ssize_t
894 lprocfs_add_nodemap_idmap_seq_write(struct file *file,
895                                     const char __user *buffer,
896                                     size_t count, loff_t *off)
897 {
898         char                    name_idmapstr[LUSTRE_NODEMAP_NAME_LENGTH + 16];
899         char                    *cpybuf = NULL;
900         char                    *name;
901         char                    *idtypestr = NULL;
902         char                    *idmapstr = NULL;
903         __u32                   idmap[2];
904         int                     rc = count;
905
906         if (count == 0)
907                 return 0;
908
909         if (count >= sizeof(name_idmapstr))
910                 GOTO(out, rc = -EINVAL);
911
912         if (copy_from_user(name_idmapstr, buffer, count))
913                 GOTO(out, rc = -EFAULT);
914
915         name_idmapstr[count] = '\0';
916
917         cpybuf = name_idmapstr;
918         name = strsep(&cpybuf, " ");
919         if (name == NULL)
920                 GOTO(out, rc = -EINVAL);
921
922         idtypestr = strsep(&cpybuf, " ");
923         if (idtypestr == NULL)
924                 GOTO(out, rc = -EINVAL);
925
926         idmapstr = strsep(&cpybuf, " \n");
927         if (idmapstr == NULL)
928                 GOTO(out, rc = -EINVAL);
929
930         rc = nodemap_parse_idmap(idmapstr, idmap);
931         if (rc != 0)
932                 GOTO(out, rc = -EINVAL);
933
934         if (strcmp(idtypestr, "uid") == 0)
935                 rc = nodemap_add_idmap(name, NODEMAP_UID, idmap);
936         else if (strcmp(idtypestr, "gid") == 0)
937                 rc = nodemap_add_idmap(name, NODEMAP_GID, idmap);
938         else
939                 GOTO(out, rc = -EINVAL);
940
941         if (rc != 0)
942                 GOTO(out, rc = -EINVAL);
943
944         if (rc == 0)
945                 rc = count;
946
947 out:
948         return rc;
949 }
950 LPROC_SEQ_FOPS_WO_TYPE(nodemap, add_nodemap_idmap);
951
952 /**
953  * Delete an idmap from nodemap.
954  *
955  * \param[in] file      proc file
956  * \param[in] buffer    string, "<nodemap name> <uid|gid> <idmap>"
957  * \param[in] count     \a buffer length
958  * \param[in] off       unused
959  * \retval              \a count on success
960  * \retval              negative number on error
961  */
962 static ssize_t
963 lprocfs_del_nodemap_idmap_seq_write(struct file *file,
964                                     const char __user *buffer,
965                                     size_t count, loff_t *off)
966 {
967         char                    name_idmapstr[LUSTRE_NODEMAP_NAME_LENGTH + 16];
968         char                    *cpybuf = NULL;
969         char                    *name;
970         char                    *idtypestr = NULL;
971         char                    *idmapstr = NULL;
972         __u32                   idmap[2];
973         int                     rc = count;
974
975         if (count == 0)
976                 return 0;
977
978         if (count >= sizeof(name_idmapstr))
979                 GOTO(out, rc = -EINVAL);
980
981         if (copy_from_user(name_idmapstr, buffer, count))
982                 GOTO(out, rc = -EFAULT);
983
984         name_idmapstr[count] = '\0';
985
986         cpybuf = name_idmapstr;
987         name = strsep(&cpybuf, " ");
988         if (name == NULL)
989                 GOTO(out, rc = -EINVAL);
990
991         idtypestr = strsep(&cpybuf, " ");
992         if (idtypestr == NULL)
993                 GOTO(out, rc = -EINVAL);
994
995         idmapstr = strsep(&cpybuf, " \n");
996         if (idmapstr == NULL)
997                 GOTO(out, rc = -EINVAL);
998
999         rc = nodemap_parse_idmap(idmapstr, idmap);
1000         if (rc != 0)
1001                 GOTO(out, rc = -EINVAL);
1002
1003         if (strcmp(idtypestr, "uid") == 0)
1004                 rc = nodemap_del_idmap(name, NODEMAP_UID, idmap);
1005         else if (strcmp(idtypestr, "gid") == 0)
1006                 rc = nodemap_del_idmap(name, NODEMAP_GID, idmap);
1007         else
1008                 GOTO(out, rc = -EINVAL);
1009
1010         if (rc != 0)
1011                 GOTO(out, rc = -EINVAL);
1012
1013         if (rc == 0)
1014                 rc = count;
1015
1016 out:
1017         return rc;
1018 }
1019 LPROC_SEQ_FOPS_WO_TYPE(nodemap, del_nodemap_idmap);
1020 #endif /* NODEMAP_PROC_DEBUG */
1021
1022 static struct lprocfs_vars lprocfs_nm_module_vars[] = {
1023         {
1024                 .name           = "active",
1025                 .fops           = &nodemap_active_fops,
1026         },
1027 #ifdef NODEMAP_PROC_DEBUG
1028         {
1029                 .name           = "add_nodemap",
1030                 .fops           = &nodemap_add_nodemap_fops,
1031         },
1032         {
1033                 .name           = "remove_nodemap",
1034                 .fops           = &nodemap_del_nodemap_fops,
1035         },
1036         {
1037                 .name           = "add_nodemap_range",
1038                 .fops           = &nodemap_add_nodemap_range_fops,
1039         },
1040         {
1041                 .name           = "del_nodemap_range",
1042                 .fops           = &nodemap_del_nodemap_range_fops,
1043         },
1044         {
1045                 .name           = "add_nodemap_idmap",
1046                 .fops           = &nodemap_add_nodemap_idmap_fops,
1047         },
1048         {
1049                 .name           = "del_nodemap_idmap",
1050                 .fops           = &nodemap_del_nodemap_idmap_fops,
1051         },
1052 #endif /* NODEMAP_PROC_DEBUG */
1053         {
1054                 NULL
1055         }
1056 };
1057
1058 #ifdef NODEMAP_PROC_DEBUG
1059 LPROC_SEQ_FOPS(nodemap_trusted);
1060 LPROC_SEQ_FOPS(nodemap_admin);
1061 LPROC_SEQ_FOPS(nodemap_squash_uid);
1062 LPROC_SEQ_FOPS(nodemap_squash_gid);
1063 #else
1064 LPROC_SEQ_FOPS_RO(nodemap_trusted);
1065 LPROC_SEQ_FOPS_RO(nodemap_admin);
1066 LPROC_SEQ_FOPS_RO(nodemap_squash_uid);
1067 LPROC_SEQ_FOPS_RO(nodemap_squash_gid);
1068 #endif
1069
1070 const struct file_operations nodemap_ranges_fops = {
1071         .open                   = nodemap_ranges_open,
1072         .read                   = seq_read,
1073         .llseek                 = seq_lseek,
1074         .release                = single_release
1075 };
1076
1077 const struct file_operations nodemap_idmap_fops = {
1078         .open                   = nodemap_idmap_open,
1079         .read                   = seq_read,
1080         .llseek                 = seq_lseek,
1081         .release                = single_release
1082 };
1083
1084 const struct file_operations nodemap_exports_fops = {
1085         .open                   = nodemap_exports_open,
1086         .read                   = seq_read,
1087         .llseek                 = seq_lseek,
1088         .release                = single_release
1089 };
1090
1091 static struct lprocfs_vars lprocfs_nodemap_vars[] = {
1092         {
1093                 .name           = "id",
1094                 .fops           = &nodemap_id_fops,
1095         },
1096         {
1097                 .name           = "trusted_nodemap",
1098                 .fops           = &nodemap_trusted_fops,
1099         },
1100         {
1101                 .name           = "admin_nodemap",
1102                 .fops           = &nodemap_admin_fops,
1103         },
1104         {
1105                 .name           = "squash_uid",
1106                 .fops           = &nodemap_squash_uid_fops,
1107         },
1108         {
1109                 .name           = "squash_gid",
1110                 .fops           = &nodemap_squash_gid_fops,
1111         },
1112         {
1113                 .name           = "ranges",
1114                 .fops           = &nodemap_ranges_fops,
1115         },
1116         {
1117                 .name           = "fileset",
1118                 .fops           = &nodemap_fileset_fops,
1119         },
1120         {
1121                 .name           = "exports",
1122                 .fops           = &nodemap_exports_fops,
1123         },
1124         {
1125                 .name           = "idmap",
1126                 .fops           = &nodemap_idmap_fops,
1127         },
1128         {
1129                 NULL
1130         }
1131 };
1132
1133 static struct lprocfs_vars lprocfs_default_nodemap_vars[] = {
1134         {
1135                 .name           = "id",
1136                 .fops           = &nodemap_id_fops,
1137         },
1138         {
1139                 .name           = "trusted_nodemap",
1140                 .fops           = &nodemap_trusted_fops,
1141         },
1142         {
1143                 .name           = "admin_nodemap",
1144                 .fops           = &nodemap_admin_fops,
1145         },
1146         {
1147                 .name           = "squash_uid",
1148                 .fops           = &nodemap_squash_uid_fops,
1149         },
1150         {
1151                 .name           = "squash_gid",
1152                 .fops           = &nodemap_squash_gid_fops,
1153         },
1154         {
1155                 .name           = "exports",
1156                 .fops           = &nodemap_exports_fops,
1157         },
1158         {
1159                 NULL
1160         }
1161 };
1162
1163 /**
1164  * Initialize the nodemap procfs directory.
1165  *
1166  * \retval      0               success
1167  */
1168 int nodemap_procfs_init(void)
1169 {
1170         int rc = 0;
1171
1172         proc_lustre_nodemap_root = lprocfs_register(LUSTRE_NODEMAP_NAME,
1173                                                     proc_lustre_root,
1174                                                     lprocfs_nm_module_vars,
1175                                                     NULL);
1176         if (IS_ERR(proc_lustre_nodemap_root)) {
1177                 rc = PTR_ERR(proc_lustre_nodemap_root);
1178                 CERROR("cannot create 'nodemap' directory: rc = %d\n",
1179                        rc);
1180                 proc_lustre_nodemap_root = NULL;
1181         }
1182         return rc;
1183 }
1184
1185 /**
1186  * Cleanup nodemap proc entry data structures.
1187  */
1188 void nodemap_procfs_exit(void)
1189 {
1190         struct nodemap_pde *nm_pde;
1191         struct nodemap_pde *tmp;
1192
1193         lprocfs_remove(&proc_lustre_nodemap_root);
1194         list_for_each_entry_safe(nm_pde, tmp, &nodemap_pde_list,
1195                                  npe_list_member) {
1196                 list_del(&nm_pde->npe_list_member);
1197                 OBD_FREE_PTR(nm_pde);
1198         }
1199 }
1200
1201 /**
1202  * Remove a nodemap's procfs entry and related data.
1203  */
1204 void lprocfs_nodemap_remove(struct nodemap_pde *nm_pde)
1205 {
1206         lprocfs_remove(&nm_pde->npe_proc_entry);
1207         list_del(&nm_pde->npe_list_member);
1208         OBD_FREE_PTR(nm_pde);
1209 }
1210
1211 /**
1212  * Register the proc directory for a nodemap
1213  *
1214  * \param       nodemap         nodemap to make the proc dir for
1215  * \param       is_default:     1 if default nodemap
1216  * \retval      0               success
1217  */
1218 int lprocfs_nodemap_register(struct lu_nodemap *nodemap, bool is_default)
1219 {
1220         struct nodemap_pde      *nm_entry;
1221         int                      rc = 0;
1222
1223         OBD_ALLOC_PTR(nm_entry);
1224         if (nm_entry == NULL)
1225                 GOTO(out, rc = -ENOMEM);
1226
1227         nm_entry->npe_proc_entry = proc_mkdir(nodemap->nm_name,
1228                                               proc_lustre_nodemap_root);
1229         if (IS_ERR(nm_entry->npe_proc_entry))
1230                 GOTO(out, rc = PTR_ERR(nm_entry->npe_proc_entry));
1231
1232         snprintf(nm_entry->npe_name, sizeof(nm_entry->npe_name), "%s",
1233                  nodemap->nm_name);
1234
1235         /* Use the nodemap name as stored on the PDE as the private data. This
1236          * is so a nodemap struct can be replaced without updating the proc
1237          * entries.
1238          */
1239         rc = lprocfs_add_vars(nm_entry->npe_proc_entry,
1240                               (is_default ? lprocfs_default_nodemap_vars :
1241                                             lprocfs_nodemap_vars),
1242                               nm_entry->npe_name);
1243         if (rc != 0)
1244                 lprocfs_remove(&nm_entry->npe_proc_entry);
1245         else
1246                 list_add(&nm_entry->npe_list_member, &nodemap_pde_list);
1247
1248 out:
1249         if (rc != 0) {
1250                 CERROR("cannot create 'nodemap/%s': rc = %d\n",
1251                        nodemap->nm_name, rc);
1252                 if (nm_entry != NULL) {
1253                         OBD_FREE_PTR(nm_entry);
1254                         nm_entry = NULL;
1255                 }
1256         }
1257
1258         nodemap->nm_pde_data = nm_entry;
1259
1260         return rc;
1261 }