Whamcloud - gitweb
LU-7117 osp: set ptlrpc_request::rq_allow_replay properly
[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 = 0;
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         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 /**
467  * Reads and prints the deny_unknown flag for the given nodemap.
468  *
469  * \param       m               seq file in proc fs
470  * \param       data            unused
471  * \retval      0               success
472  */
473 static int nodemap_deny_unknown_seq_show(struct seq_file *m, void *data)
474 {
475         struct lu_nodemap *nodemap;
476         int rc;
477
478         mutex_lock(&active_config_lock);
479         nodemap = nodemap_lookup(m->private);
480         mutex_unlock(&active_config_lock);
481         if (IS_ERR(nodemap)) {
482                 rc = PTR_ERR(nodemap);
483                 CERROR("cannot find nodemap '%s': rc = %d\n",
484                         (char *)m->private, rc);
485                 return rc;
486         }
487
488         seq_printf(m, "%d\n", (int)nodemap->nmf_deny_unknown);
489         nodemap_putref(nodemap);
490         return 0;
491 }
492
493 #ifdef NODEMAP_PROC_DEBUG
494 /**
495  * Helper functions to set nodemap flags.
496  *
497  * \param[in] buffer    string, which is "1" or "0" to set/unset flag
498  * \param[in] count     \a buffer length
499  * \param[out] flag_p   where to store flag value
500  * \retval              \a count on success
501  * \retval              negative number on error
502  */
503 static int nodemap_proc_read_flag(const char __user *buffer,
504                                   unsigned long count, unsigned int *flag_p)
505 {
506         char                    scratch[NODEMAP_LPROC_FLAG_LEN + 1];
507         long unsigned int       flag_buf;
508         int                     rc;
509
510         if (count == 0)
511                 return 0;
512
513         if (count >= sizeof(scratch))
514                 return -EINVAL;
515
516         if (copy_from_user(scratch, buffer, count))
517                 return -EFAULT;
518
519         scratch[count] = '\0';
520         rc = kstrtoul(scratch, 10, &flag_buf);
521         if (rc != 0)
522                 return -EINVAL;
523
524         *flag_p = flag_buf;
525
526         return count;
527 }
528
529 /**
530  * Set the squash UID.
531  *
532  * \param[in] file      proc file
533  * \param[in] buffer    string representing squash UID to set
534  * \param[in] count     \a buffer length
535  * \param[in] off       unused
536  * \retval              \a count on success
537  * \retval              negative number on error
538  */
539 static ssize_t
540 nodemap_squash_uid_seq_write(struct file *file, const char __user *buffer,
541                              size_t count, loff_t *off)
542 {
543         char                     squash[NODEMAP_LPROC_ID_LEN + 1];
544         struct seq_file         *m = file->private_data;
545         long unsigned int        squash_uid;
546         int                      rc;
547
548         if (count == 0)
549                 return 0;
550
551         if (count >= sizeof(squash))
552                 return -EINVAL;
553
554         if (copy_from_user(squash, buffer, count))
555                 return -EFAULT;
556
557         squash[count] = '\0';
558         rc = kstrtoul(squash, 10, &squash_uid);
559         if (rc != 0)
560                 return -EINVAL;
561
562         rc = nodemap_set_squash_uid(m->private, squash_uid);
563         if (rc != 0)
564                 return rc;
565
566         return count;
567 }
568
569 /**
570  * Set the squash GID.
571  *
572  * \param[in] file      proc file
573  * \param[in] buffer    string representing squash GID to set
574  * \param[in] count     \a buffer length
575  * \param[in] off       unused
576  * \retval              \a count on success
577  * \retval              negative number on error
578  */
579 static ssize_t
580 nodemap_squash_gid_seq_write(struct file *file, const char __user *buffer,
581                              size_t count, loff_t *off)
582 {
583         char                     squash[NODEMAP_LPROC_ID_LEN + 1];
584         struct seq_file         *m = file->private_data;
585         long unsigned int        squash_gid;
586         int                      rc;
587
588         if (count == 0)
589                 return 0;
590
591         if (count >= sizeof(squash))
592                 return -EINVAL;
593
594         if (copy_from_user(squash, buffer, count))
595                 return -EFAULT;
596
597         squash[count] = '\0';
598         rc = kstrtoul(squash, 10, &squash_gid);
599         if (rc != 0)
600                 return -EINVAL;
601
602         rc = nodemap_set_squash_gid(m->private, squash_gid);
603         if (rc != 0)
604                 return rc;
605
606         return count;
607 }
608
609 /**
610  * Set/unset the trusted flag.
611  *
612  * \param[in] file      proc file
613  * \param[in] buffer    string, "1" or "0"
614  * \param[in] count     \a buffer length
615  * \param[in] off       unused
616  * \retval              \a count on success
617  * \retval              negative number on error
618  */
619 static ssize_t
620 nodemap_trusted_seq_write(struct file *file, const char __user *buffer,
621                           size_t count, loff_t *off)
622 {
623         struct seq_file         *m = file->private_data;
624         int                     flags;
625         int                     rc;
626
627         rc = nodemap_proc_read_flag(buffer, count, &flags);
628         if (rc < 0)
629                 return rc;
630
631         rc = nodemap_set_trust_client_ids(m->private, flags);
632         if (rc != 0)
633                 return rc;
634
635         return count;
636 }
637
638 /**
639  * Set/unset the admin flag.
640  *
641  * \param[in] file      proc file
642  * \param[in] buffer    string, "1" or "0"
643  * \param[in] count     \a buffer length
644  * \param[in] off       unused
645  * \retval              \a count on success
646  * \retval              negative number on error
647  */
648 static ssize_t
649 nodemap_admin_seq_write(struct file *file, const char __user *buffer,
650                         size_t count, loff_t *off)
651 {
652         struct seq_file         *m = file->private_data;
653         int                     flags;
654         int                     rc;
655
656         rc = nodemap_proc_read_flag(buffer, count, &flags);
657         if (rc < 0)
658                 return rc;
659
660         rc = nodemap_set_allow_root(m->private, flags);
661         if (rc != 0)
662                 return rc;
663
664         return count;
665 }
666
667 /**
668  * Add a nodemap.
669  *
670  * \param[in] file      proc file
671  * \param[in] buffer    string, name of the nodemap to add
672  * \param[in] count     \a buffer length
673  * \param[in] off       unused
674  * \retval              \a count on success
675  * \retval              negative number on error
676  */
677 static ssize_t
678 lprocfs_add_nodemap_seq_write(struct file *file, const char __user *buffer,
679                               size_t count, loff_t *off)
680 {
681         char    nodemap_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
682         char    *cpybuf = NULL;
683         char    *pos;
684         int     rc;
685
686         if (count == 0)
687                 return 0;
688
689         if (count >= sizeof(nodemap_name))
690                 return -EINVAL;
691
692         if (copy_from_user(nodemap_name, buffer, count))
693                 return -EFAULT;
694
695         nodemap_name[count] = '\0';
696
697         cpybuf = nodemap_name;
698         pos = strsep(&cpybuf, " \n");
699         if (pos == NULL)
700                 return -EINVAL;
701
702         rc = nodemap_add(nodemap_name);
703         if (rc == 0)
704                 rc = count;
705
706         return rc;
707 }
708 LPROC_SEQ_FOPS_WO_TYPE(nodemap, add_nodemap);
709
710 /**
711  * Delete a nodemap.
712  *
713  * \param[in] file      proc file
714  * \param[in] buffer    string, name of the nodemap to delete
715  * \param[in] count     \a buffer length
716  * \param[in] off       unused
717  * \retval              \a count on success
718  * \retval              negative number on error
719  */
720 static ssize_t
721 lprocfs_del_nodemap_seq_write(struct file *file, const char __user *buffer,
722                               size_t count, loff_t *off)
723 {
724         char    nodemap_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
725         char    *cpybuf = NULL;
726         char    *pos;
727         int     rc = count;
728
729         if (count == 0)
730                 return 0;
731
732         if (count >= sizeof(nodemap_name))
733                 return -EINVAL;
734
735         if (copy_from_user(nodemap_name, buffer, count))
736                 return -EFAULT;
737
738         nodemap_name[count] = '\0';
739
740         cpybuf = nodemap_name;
741         pos = strsep(&cpybuf, " \n");
742         if (pos == NULL)
743                 return -EINVAL;
744
745         rc = nodemap_del(nodemap_name);
746         if (rc == 0)
747                 rc = count;
748
749         return rc;
750
751 }
752 LPROC_SEQ_FOPS_WO_TYPE(nodemap, del_nodemap);
753
754 /**
755  * Helper function to parse a NID string.
756  *
757  * \param[in] rangestr  string representation of NIDs, see libcfs_str2nid()
758  * \param[out] nids     array of two nids
759  * \retval              0 on success
760  * \retval              negative number on error
761  */
762 static int parse_nids(char *rangestr, lnet_nid_t nids[2])
763 {
764         struct list_head        nidlist;
765         char                    nidstr[2][LNET_NIDSTR_SIZE];
766         char                    nidrange_str[2 * LNET_NIDSTR_SIZE + 2];
767         int                     rc = 0;
768
769         INIT_LIST_HEAD(&nidlist);
770
771         if (cfs_parse_nidlist(rangestr, strlen(rangestr),
772             &nidlist) <= 0)
773                 return -EINVAL;
774
775         if (!cfs_nidrange_is_contiguous(&nidlist))
776                 return -EINVAL;
777
778         cfs_nidrange_find_min_max(&nidlist, nidstr[0], nidstr[1],
779                                   LNET_NIDSTR_SIZE);
780         snprintf(nidrange_str, sizeof(nidrange_str), "%s:%s",
781                 nidstr[0], nidstr[1]);
782
783         rc = nodemap_parse_range(nidrange_str, nids);
784         if (rc != 0)
785                 return -EINVAL;
786
787         cfs_free_nidlist(&nidlist);
788
789         return 0;
790 }
791
792 /**
793  * Add a NID range to nodemap.
794  *
795  * \param[in] file      proc file
796  * \param[in] buffer    string, "<nodemap name> <nid range>"
797  * \param[in] count     \a buffer length
798  * \param[in] off       unused
799  * \retval              \a count on success
800  * \retval              negative number on error
801  */
802 static ssize_t
803 lprocfs_add_nodemap_range_seq_write(struct file *file,
804                                     const char __user *buffer,
805                                     size_t count, loff_t *off)
806 {
807         char                    name_range[LUSTRE_NODEMAP_NAME_LENGTH +
808                                            LNET_NIDSTR_SIZE * 2 + 2];
809         char                    *cpybuf = NULL;
810         char                    *name;
811         char                    *rangestr = NULL;
812         lnet_nid_t              nids[2];
813         int                     rc;
814
815         if (count == 0)
816                 return 0;
817
818         if (count >= sizeof(name_range))
819                 GOTO(out, rc = -EINVAL);
820
821         if (copy_from_user(name_range, buffer, count))
822                 GOTO(out, rc = -EFAULT);
823
824         name_range[count] = '\0';
825
826         cpybuf = name_range;
827         name = strsep(&cpybuf, " ");
828         if (name == NULL)
829                 GOTO(out, rc = -EINVAL);
830
831         rangestr = strsep(&cpybuf, " \n");
832         if (rangestr == NULL)
833                 GOTO(out, rc = -EINVAL);
834
835         rc = parse_nids(rangestr, nids);
836         if (rc != 0)
837                 GOTO(out, rc = rc);
838
839         rc = nodemap_add_range(name, nids);
840         if (rc != 0)
841                 GOTO(out, rc = -EINVAL);
842
843         if (rc == 0)
844                 rc = count;
845
846 out:
847         return rc;
848 }
849 LPROC_SEQ_FOPS_WO_TYPE(nodemap, add_nodemap_range);
850
851 /**
852  * Delete a NID range from nodemap.
853  *
854  * \param[in] file      proc file
855  * \param[in] buffer    string, "<nodemap name> <nid range>"
856  * \param[in] count     \a buffer length
857  * \param[in] off       unused
858  * \retval              \a count on success
859  * \retval              negative number on error
860  */
861 static ssize_t
862 lprocfs_del_nodemap_range_seq_write(struct file *file,
863                                     const char __user *buffer,
864                                     size_t count, loff_t *off)
865 {
866         char                    name_range[LUSTRE_NODEMAP_NAME_LENGTH +
867                                            LNET_NIDSTR_SIZE * 2 + 2];
868         char                    *cpybuf = NULL;
869         char                    *name;
870         char                    *rangestr = NULL;
871         lnet_nid_t              nids[2];
872         int                     rc;
873
874         if (count == 0)
875                 return 0;
876
877         if (count >= sizeof(name_range))
878                 GOTO(out, rc = -EINVAL);
879
880         if (copy_from_user(name_range, buffer, count))
881                 GOTO(out, rc = -EFAULT);
882
883         name_range[count] = '\0';
884
885         cpybuf = name_range;
886         name = strsep(&cpybuf, " ");
887         if (name == NULL)
888                 GOTO(out, rc = -EINVAL);
889
890         rangestr = strsep(&cpybuf, " \n");
891         if (rangestr == NULL)
892                 GOTO(out, rc = -EINVAL);
893
894         rc = parse_nids(rangestr, nids);
895         if (rc != 0)
896                 GOTO(out, rc = rc);
897
898         rc = nodemap_del_range(name, nids);
899         if (rc != 0)
900                 GOTO(out, rc = -EINVAL);
901
902         if (rc == 0)
903                 rc = count;
904
905 out:
906         return rc;
907 }
908 LPROC_SEQ_FOPS_WO_TYPE(nodemap, del_nodemap_range);
909
910 /**
911  * Add an idmap to nodemap.
912  *
913  * \param[in] file      proc file
914  * \param[in] buffer    string, "<nodemap name> <uid|gid> <idmap>"
915  * \param[in] count     \a buffer length
916  * \param[in] off       unused
917  * \retval              \a count on success
918  * \retval              negative number on error
919  */
920 static ssize_t
921 lprocfs_add_nodemap_idmap_seq_write(struct file *file,
922                                     const char __user *buffer,
923                                     size_t count, loff_t *off)
924 {
925         char                    name_idmapstr[LUSTRE_NODEMAP_NAME_LENGTH + 16];
926         char                    *cpybuf = NULL;
927         char                    *name;
928         char                    *idtypestr = NULL;
929         char                    *idmapstr = NULL;
930         __u32                   idmap[2];
931         int                     rc = count;
932
933         if (count == 0)
934                 return 0;
935
936         if (count >= sizeof(name_idmapstr))
937                 GOTO(out, rc = -EINVAL);
938
939         if (copy_from_user(name_idmapstr, buffer, count))
940                 GOTO(out, rc = -EFAULT);
941
942         name_idmapstr[count] = '\0';
943
944         cpybuf = name_idmapstr;
945         name = strsep(&cpybuf, " ");
946         if (name == NULL)
947                 GOTO(out, rc = -EINVAL);
948
949         idtypestr = strsep(&cpybuf, " ");
950         if (idtypestr == NULL)
951                 GOTO(out, rc = -EINVAL);
952
953         idmapstr = strsep(&cpybuf, " \n");
954         if (idmapstr == NULL)
955                 GOTO(out, rc = -EINVAL);
956
957         rc = nodemap_parse_idmap(idmapstr, idmap);
958         if (rc != 0)
959                 GOTO(out, rc = -EINVAL);
960
961         if (strcmp(idtypestr, "uid") == 0)
962                 rc = nodemap_add_idmap(name, NODEMAP_UID, idmap);
963         else if (strcmp(idtypestr, "gid") == 0)
964                 rc = nodemap_add_idmap(name, NODEMAP_GID, idmap);
965         else
966                 GOTO(out, rc = -EINVAL);
967
968         if (rc != 0)
969                 GOTO(out, rc = -EINVAL);
970
971         if (rc == 0)
972                 rc = count;
973
974 out:
975         return rc;
976 }
977 LPROC_SEQ_FOPS_WO_TYPE(nodemap, add_nodemap_idmap);
978
979 /**
980  * Delete an idmap from nodemap.
981  *
982  * \param[in] file      proc file
983  * \param[in] buffer    string, "<nodemap name> <uid|gid> <idmap>"
984  * \param[in] count     \a buffer length
985  * \param[in] off       unused
986  * \retval              \a count on success
987  * \retval              negative number on error
988  */
989 static ssize_t
990 lprocfs_del_nodemap_idmap_seq_write(struct file *file,
991                                     const char __user *buffer,
992                                     size_t count, loff_t *off)
993 {
994         char                    name_idmapstr[LUSTRE_NODEMAP_NAME_LENGTH + 16];
995         char                    *cpybuf = NULL;
996         char                    *name;
997         char                    *idtypestr = NULL;
998         char                    *idmapstr = NULL;
999         __u32                   idmap[2];
1000         int                     rc = count;
1001
1002         if (count == 0)
1003                 return 0;
1004
1005         if (count >= sizeof(name_idmapstr))
1006                 GOTO(out, rc = -EINVAL);
1007
1008         if (copy_from_user(name_idmapstr, buffer, count))
1009                 GOTO(out, rc = -EFAULT);
1010
1011         name_idmapstr[count] = '\0';
1012
1013         cpybuf = name_idmapstr;
1014         name = strsep(&cpybuf, " ");
1015         if (name == NULL)
1016                 GOTO(out, rc = -EINVAL);
1017
1018         idtypestr = strsep(&cpybuf, " ");
1019         if (idtypestr == NULL)
1020                 GOTO(out, rc = -EINVAL);
1021
1022         idmapstr = strsep(&cpybuf, " \n");
1023         if (idmapstr == NULL)
1024                 GOTO(out, rc = -EINVAL);
1025
1026         rc = nodemap_parse_idmap(idmapstr, idmap);
1027         if (rc != 0)
1028                 GOTO(out, rc = -EINVAL);
1029
1030         if (strcmp(idtypestr, "uid") == 0)
1031                 rc = nodemap_del_idmap(name, NODEMAP_UID, idmap);
1032         else if (strcmp(idtypestr, "gid") == 0)
1033                 rc = nodemap_del_idmap(name, NODEMAP_GID, idmap);
1034         else
1035                 GOTO(out, rc = -EINVAL);
1036
1037         if (rc != 0)
1038                 GOTO(out, rc = -EINVAL);
1039
1040         if (rc == 0)
1041                 rc = count;
1042
1043 out:
1044         return rc;
1045 }
1046 LPROC_SEQ_FOPS_WO_TYPE(nodemap, del_nodemap_idmap);
1047 #endif /* NODEMAP_PROC_DEBUG */
1048
1049 static struct lprocfs_vars lprocfs_nm_module_vars[] = {
1050         {
1051                 .name           = "active",
1052                 .fops           = &nodemap_active_fops,
1053         },
1054 #ifdef NODEMAP_PROC_DEBUG
1055         {
1056                 .name           = "add_nodemap",
1057                 .fops           = &nodemap_add_nodemap_fops,
1058         },
1059         {
1060                 .name           = "remove_nodemap",
1061                 .fops           = &nodemap_del_nodemap_fops,
1062         },
1063         {
1064                 .name           = "add_nodemap_range",
1065                 .fops           = &nodemap_add_nodemap_range_fops,
1066         },
1067         {
1068                 .name           = "del_nodemap_range",
1069                 .fops           = &nodemap_del_nodemap_range_fops,
1070         },
1071         {
1072                 .name           = "add_nodemap_idmap",
1073                 .fops           = &nodemap_add_nodemap_idmap_fops,
1074         },
1075         {
1076                 .name           = "del_nodemap_idmap",
1077                 .fops           = &nodemap_del_nodemap_idmap_fops,
1078         },
1079 #endif /* NODEMAP_PROC_DEBUG */
1080         {
1081                 NULL
1082         }
1083 };
1084
1085 #ifdef NODEMAP_PROC_DEBUG
1086 LPROC_SEQ_FOPS(nodemap_trusted);
1087 LPROC_SEQ_FOPS(nodemap_admin);
1088 LPROC_SEQ_FOPS(nodemap_squash_uid);
1089 LPROC_SEQ_FOPS(nodemap_squash_gid);
1090 #else
1091 LPROC_SEQ_FOPS_RO(nodemap_trusted);
1092 LPROC_SEQ_FOPS_RO(nodemap_admin);
1093 LPROC_SEQ_FOPS_RO(nodemap_squash_uid);
1094 LPROC_SEQ_FOPS_RO(nodemap_squash_gid);
1095 #endif
1096
1097 LPROC_SEQ_FOPS_RO(nodemap_deny_unknown);
1098
1099 const struct file_operations nodemap_ranges_fops = {
1100         .open                   = nodemap_ranges_open,
1101         .read                   = seq_read,
1102         .llseek                 = seq_lseek,
1103         .release                = single_release
1104 };
1105
1106 const struct file_operations nodemap_idmap_fops = {
1107         .open                   = nodemap_idmap_open,
1108         .read                   = seq_read,
1109         .llseek                 = seq_lseek,
1110         .release                = single_release
1111 };
1112
1113 const struct file_operations nodemap_exports_fops = {
1114         .open                   = nodemap_exports_open,
1115         .read                   = seq_read,
1116         .llseek                 = seq_lseek,
1117         .release                = single_release
1118 };
1119
1120 static struct lprocfs_vars lprocfs_nodemap_vars[] = {
1121         {
1122                 .name           = "id",
1123                 .fops           = &nodemap_id_fops,
1124         },
1125         {
1126                 .name           = "trusted_nodemap",
1127                 .fops           = &nodemap_trusted_fops,
1128         },
1129         {
1130                 .name           = "admin_nodemap",
1131                 .fops           = &nodemap_admin_fops,
1132         },
1133         {
1134                 .name           = "deny_unknown",
1135                 .fops           = &nodemap_deny_unknown_fops,
1136         },
1137         {
1138                 .name           = "squash_uid",
1139                 .fops           = &nodemap_squash_uid_fops,
1140         },
1141         {
1142                 .name           = "squash_gid",
1143                 .fops           = &nodemap_squash_gid_fops,
1144         },
1145         {
1146                 .name           = "ranges",
1147                 .fops           = &nodemap_ranges_fops,
1148         },
1149         {
1150                 .name           = "fileset",
1151                 .fops           = &nodemap_fileset_fops,
1152         },
1153         {
1154                 .name           = "exports",
1155                 .fops           = &nodemap_exports_fops,
1156         },
1157         {
1158                 .name           = "idmap",
1159                 .fops           = &nodemap_idmap_fops,
1160         },
1161         {
1162                 NULL
1163         }
1164 };
1165
1166 static struct lprocfs_vars lprocfs_default_nodemap_vars[] = {
1167         {
1168                 .name           = "id",
1169                 .fops           = &nodemap_id_fops,
1170         },
1171         {
1172                 .name           = "trusted_nodemap",
1173                 .fops           = &nodemap_trusted_fops,
1174         },
1175         {
1176                 .name           = "admin_nodemap",
1177                 .fops           = &nodemap_admin_fops,
1178         },
1179         {
1180                 .name           = "squash_uid",
1181                 .fops           = &nodemap_squash_uid_fops,
1182         },
1183         {
1184                 .name           = "squash_gid",
1185                 .fops           = &nodemap_squash_gid_fops,
1186         },
1187         {
1188                 .name           = "exports",
1189                 .fops           = &nodemap_exports_fops,
1190         },
1191         {
1192                 NULL
1193         }
1194 };
1195
1196 /**
1197  * Initialize the nodemap procfs directory.
1198  *
1199  * \retval      0               success
1200  */
1201 int nodemap_procfs_init(void)
1202 {
1203         int rc = 0;
1204
1205         proc_lustre_nodemap_root = lprocfs_register(LUSTRE_NODEMAP_NAME,
1206                                                     proc_lustre_root,
1207                                                     lprocfs_nm_module_vars,
1208                                                     NULL);
1209         if (IS_ERR(proc_lustre_nodemap_root)) {
1210                 rc = PTR_ERR(proc_lustre_nodemap_root);
1211                 CERROR("cannot create 'nodemap' directory: rc = %d\n",
1212                        rc);
1213                 proc_lustre_nodemap_root = NULL;
1214         }
1215         return rc;
1216 }
1217
1218 /**
1219  * Cleanup nodemap proc entry data structures.
1220  */
1221 void nodemap_procfs_exit(void)
1222 {
1223         struct nodemap_pde *nm_pde;
1224         struct nodemap_pde *tmp;
1225
1226         lprocfs_remove(&proc_lustre_nodemap_root);
1227         list_for_each_entry_safe(nm_pde, tmp, &nodemap_pde_list,
1228                                  npe_list_member) {
1229                 list_del(&nm_pde->npe_list_member);
1230                 OBD_FREE_PTR(nm_pde);
1231         }
1232 }
1233
1234 /**
1235  * Remove a nodemap's procfs entry and related data.
1236  */
1237 void lprocfs_nodemap_remove(struct nodemap_pde *nm_pde)
1238 {
1239         lprocfs_remove(&nm_pde->npe_proc_entry);
1240         list_del(&nm_pde->npe_list_member);
1241         OBD_FREE_PTR(nm_pde);
1242 }
1243
1244 /**
1245  * Register the proc directory for a nodemap
1246  *
1247  * \param       nodemap         nodemap to make the proc dir for
1248  * \param       is_default:     1 if default nodemap
1249  * \retval      0               success
1250  */
1251 int lprocfs_nodemap_register(struct lu_nodemap *nodemap, bool is_default)
1252 {
1253         struct nodemap_pde      *nm_entry;
1254         int                      rc = 0;
1255
1256         OBD_ALLOC_PTR(nm_entry);
1257         if (nm_entry == NULL)
1258                 GOTO(out, rc = -ENOMEM);
1259
1260         nm_entry->npe_proc_entry = proc_mkdir(nodemap->nm_name,
1261                                               proc_lustre_nodemap_root);
1262         if (IS_ERR(nm_entry->npe_proc_entry))
1263                 GOTO(out, rc = PTR_ERR(nm_entry->npe_proc_entry));
1264
1265         snprintf(nm_entry->npe_name, sizeof(nm_entry->npe_name), "%s",
1266                  nodemap->nm_name);
1267
1268         /* Use the nodemap name as stored on the PDE as the private data. This
1269          * is so a nodemap struct can be replaced without updating the proc
1270          * entries.
1271          */
1272         rc = lprocfs_add_vars(nm_entry->npe_proc_entry,
1273                               (is_default ? lprocfs_default_nodemap_vars :
1274                                             lprocfs_nodemap_vars),
1275                               nm_entry->npe_name);
1276         if (rc != 0)
1277                 lprocfs_remove(&nm_entry->npe_proc_entry);
1278         else
1279                 list_add(&nm_entry->npe_list_member, &nodemap_pde_list);
1280
1281 out:
1282         if (rc != 0) {
1283                 CERROR("cannot create 'nodemap/%s': rc = %d\n",
1284                        nodemap->nm_name, rc);
1285                 if (nm_entry != NULL) {
1286                         OBD_FREE_PTR(nm_entry);
1287                         nm_entry = NULL;
1288                 }
1289         }
1290
1291         nodemap->nm_pde_data = nm_entry;
1292
1293         return rc;
1294 }