Whamcloud - gitweb
LU-8602 gss: get rid of cfs_crypto_hash_desc
[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, 2017, 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         down_read(&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         up_read(&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         char *nm_fileset;
214         int rc = 0;
215         ENTRY;
216
217         if (count == 0)
218                 RETURN(0);
219
220         if (count > PATH_MAX)
221                 RETURN(-EINVAL);
222
223         OBD_ALLOC(nm_fileset, count + 1);
224         /* OBD_ALLOC zero-fills the buffer */
225         if (nm_fileset == NULL)
226                 RETURN(-ENOMEM);
227
228         if (copy_from_user(nm_fileset, buffer, count))
229                 GOTO(out, rc = -EFAULT);
230
231         rc = nodemap_set_fileset(m->private, nm_fileset);
232         if (rc != 0)
233                 GOTO(out, rc = -EINVAL);
234
235         rc = count;
236 out:
237         OBD_FREE(nm_fileset, count + 1);
238
239         return rc;
240 }
241 LPROC_SEQ_FOPS(nodemap_fileset);
242
243 /**
244  * Reads and prints the exports attached to the given nodemap.
245  *
246  * \param       m               seq file in proc fs, stores nodemap
247  * \param       data            unused
248  * \retval      0               success
249  */
250 static int nodemap_exports_show(struct seq_file *m, void *data)
251 {
252         struct lu_nodemap *nodemap;
253         struct obd_export *exp;
254         char nidstr[LNET_NIDSTR_SIZE] = "<unknown>";
255         int rc;
256
257         mutex_lock(&active_config_lock);
258         nodemap = nodemap_lookup(m->private);
259         mutex_unlock(&active_config_lock);
260         if (IS_ERR(nodemap)) {
261                 rc = PTR_ERR(nodemap);
262                 CERROR("cannot find nodemap '%s': rc = %d\n",
263                         (char *)m->private, rc);
264                 return rc;
265         }
266
267         seq_printf(m, "[\n");
268
269         mutex_lock(&nodemap->nm_member_list_lock);
270         list_for_each_entry(exp, &nodemap->nm_member_list,
271                             exp_target_data.ted_nodemap_member) {
272                 if (exp->exp_connection != NULL)
273                         libcfs_nid2str_r(exp->exp_connection->c_peer.nid,
274                                          nidstr, sizeof(nidstr));
275
276                 seq_printf(m, " { nid: %s, uuid: %s },",
277                            nidstr, exp->exp_client_uuid.uuid);
278         }
279         mutex_unlock(&nodemap->nm_member_list_lock);
280
281         seq_printf(m, "\n");
282         seq_printf(m, "]\n");
283
284         nodemap_putref(nodemap);
285         return 0;
286 }
287
288 /**
289  * Attaches nodemap_idmap_show to proc file.
290  *
291  * \param       inode           inode of seq file in proc fs
292  * \param       file            seq file
293  * \retval      0               success
294  */
295 static int nodemap_exports_open(struct inode *inode, struct file *file)
296 {
297         return single_open(file, nodemap_exports_show, PDE_DATA(inode));
298 }
299
300 /**
301  * Reads and prints the active flag for the given nodemap.
302  *
303  * \param       m               seq file in proc fs
304  * \param       data            unused
305  * \retval      0               success
306  */
307 static int nodemap_active_seq_show(struct seq_file *m, void *data)
308 {
309         seq_printf(m, "%u\n", (unsigned int)nodemap_active);
310         return 0;
311 }
312
313 /**
314  * Activate/deactivate nodemap.
315  *
316  * \param[in] file      proc file
317  * \param[in] buffer    string, "1" or "0" to activate/deactivate nodemap
318  * \param[in] count     \a buffer length
319  * \param[in] off       unused
320  * \retval              \a count on success
321  * \retval              negative number on error
322  */
323 static ssize_t
324 nodemap_active_seq_write(struct file *file, const char __user *buffer,
325                          size_t count, loff_t *off)
326 {
327         char                    active_string[NODEMAP_LPROC_FLAG_LEN + 1];
328         long unsigned int       active;
329         int                     rc;
330
331         if (count == 0)
332                 return 0;
333
334         if (count >= sizeof(active_string))
335                 return -EINVAL;
336
337         if (copy_from_user(active_string, buffer, count))
338                 return -EFAULT;
339
340         active_string[count] = '\0';
341         rc = kstrtoul(active_string, 10, &active);
342         if (rc != 0)
343                 return -EINVAL;
344
345         nodemap_activate(active);
346
347         return count;
348 }
349 LPROC_SEQ_FOPS(nodemap_active);
350
351 /**
352  * Reads and prints the nodemap ID for the given nodemap.
353  *
354  * \param       m               seq file in proc fs
355  * \param       data            unused
356  * \retval      0               success
357  */
358 static int nodemap_id_seq_show(struct seq_file *m, void *data)
359 {
360         struct lu_nodemap *nodemap;
361
362         mutex_lock(&active_config_lock);
363         nodemap = nodemap_lookup(m->private);
364         mutex_unlock(&active_config_lock);
365         if (IS_ERR(nodemap)) {
366                 int rc = PTR_ERR(nodemap);
367                 CERROR("cannot find nodemap '%s': rc = %d\n",
368                         (char *)m->private, rc);
369                 return rc;
370         }
371
372         seq_printf(m, "%u\n", nodemap->nm_id);
373         nodemap_putref(nodemap);
374         return 0;
375 }
376 LPROC_SEQ_FOPS_RO(nodemap_id);
377
378 /**
379  * Reads and prints the root squash UID for the given nodemap.
380  *
381  * \param       m               seq file in proc fs
382  * \param       data            unused
383  * \retval      0               success
384  */
385 static int nodemap_squash_uid_seq_show(struct seq_file *m, void *data)
386 {
387         struct lu_nodemap *nodemap;
388
389         mutex_lock(&active_config_lock);
390         nodemap = nodemap_lookup(m->private);
391         mutex_unlock(&active_config_lock);
392         if (IS_ERR(nodemap)) {
393                 int rc = PTR_ERR(nodemap);
394                 CERROR("cannot find nodemap '%s': rc = %d\n",
395                         (char *)m->private, rc);
396                 return rc;
397         }
398
399         seq_printf(m, "%u\n", nodemap->nm_squash_uid);
400         nodemap_putref(nodemap);
401         return 0;
402 }
403
404 /**
405  * Reads and prints the root squash GID for the given nodemap.
406  *
407  * \param       m               seq file in proc fs
408  * \param       data            unused
409  * \retval      0               success
410  */
411 static int nodemap_squash_gid_seq_show(struct seq_file *m, void *data)
412 {
413         struct lu_nodemap *nodemap;
414
415         mutex_lock(&active_config_lock);
416         nodemap = nodemap_lookup(m->private);
417         mutex_unlock(&active_config_lock);
418         if (IS_ERR(nodemap)) {
419                 int rc = PTR_ERR(nodemap);
420                 CERROR("cannot find nodemap '%s': rc = %d\n",
421                         (char *)m->private, rc);
422                 return rc;
423         }
424
425         seq_printf(m, "%u\n", nodemap->nm_squash_gid);
426         nodemap_putref(nodemap);
427         return 0;
428 }
429
430 /**
431  * Reads and prints the trusted flag for the given nodemap.
432  *
433  * \param       m               seq file in proc fs
434  * \param       data            unused
435  * \retval      0               success
436  */
437 static int nodemap_trusted_seq_show(struct seq_file *m, void *data)
438 {
439         struct lu_nodemap *nodemap;
440
441         mutex_lock(&active_config_lock);
442         nodemap = nodemap_lookup(m->private);
443         mutex_unlock(&active_config_lock);
444         if (IS_ERR(nodemap)) {
445                 int rc = PTR_ERR(nodemap);
446
447                 CERROR("cannot find nodemap '%s': rc = %d\n",
448                         (char *)m->private, rc);
449                 return rc;
450         }
451
452         seq_printf(m, "%d\n", (int)nodemap->nmf_trust_client_ids);
453         nodemap_putref(nodemap);
454         return 0;
455 }
456
457 /**
458  * Reads and prints the admin flag for the given nodemap.
459  *
460  * \param       m               seq file in proc fs
461  * \param       data            unused
462  * \retval      0               success
463  */
464 static int nodemap_admin_seq_show(struct seq_file *m, void *data)
465 {
466         struct lu_nodemap *nodemap;
467         int rc;
468
469         mutex_lock(&active_config_lock);
470         nodemap = nodemap_lookup(m->private);
471         mutex_unlock(&active_config_lock);
472         if (IS_ERR(nodemap)) {
473                 rc = PTR_ERR(nodemap);
474                 CERROR("cannot find nodemap '%s': rc = %d\n",
475                         (char *)m->private, rc);
476                 return rc;
477         }
478
479         seq_printf(m, "%d\n", (int)nodemap->nmf_allow_root_access);
480         nodemap_putref(nodemap);
481         return 0;
482 }
483
484 /**
485  * Reads and prints the mapping mode for the given nodemap.
486  *
487  * \param       m               seq file in proc fs
488  * \param       data            unused
489  * \retval      0               success
490  */
491 static int nodemap_map_mode_seq_show(struct seq_file *m, void *data)
492 {
493         struct lu_nodemap *nodemap;
494         int rc;
495
496         mutex_lock(&active_config_lock);
497         nodemap = nodemap_lookup(m->private);
498         mutex_unlock(&active_config_lock);
499         if (IS_ERR(nodemap)) {
500                 rc = PTR_ERR(nodemap);
501                 CERROR("cannot find nodemap '%s': rc = %d\n",
502                         (char *)m->private, rc);
503                 return rc;
504         }
505
506         if (nodemap->nmf_map_uid_only)
507                 seq_printf(m, "uid_only\n");
508         else if (nodemap->nmf_map_gid_only)
509                 seq_printf(m, "gid_only\n");
510         else
511                 seq_printf(m, "both\n");
512
513         nodemap_putref(nodemap);
514         return 0;
515 }
516
517 /**
518  * Reads and prints the deny_unknown flag for the given nodemap.
519  *
520  * \param       m               seq file in proc fs
521  * \param       data            unused
522  * \retval      0               success
523  */
524 static int nodemap_deny_unknown_seq_show(struct seq_file *m, void *data)
525 {
526         struct lu_nodemap *nodemap;
527         int rc;
528
529         mutex_lock(&active_config_lock);
530         nodemap = nodemap_lookup(m->private);
531         mutex_unlock(&active_config_lock);
532         if (IS_ERR(nodemap)) {
533                 rc = PTR_ERR(nodemap);
534                 CERROR("cannot find nodemap '%s': rc = %d\n",
535                         (char *)m->private, rc);
536                 return rc;
537         }
538
539         seq_printf(m, "%d\n", (int)nodemap->nmf_deny_unknown);
540         nodemap_putref(nodemap);
541         return 0;
542 }
543
544 /**
545  * Reads and prints the audit_mode flag for the given nodemap.
546  *
547  * \param       m               seq file in proc fs
548  * \param       data            unused
549  * \retval      0               success
550  */
551 static int nodemap_audit_mode_seq_show(struct seq_file *m, void *data)
552 {
553         struct lu_nodemap *nodemap;
554         int rc;
555
556         mutex_lock(&active_config_lock);
557         nodemap = nodemap_lookup(m->private);
558         mutex_unlock(&active_config_lock);
559         if (IS_ERR(nodemap)) {
560                 rc = PTR_ERR(nodemap);
561                 CERROR("cannot find nodemap '%s': rc = %d\n",
562                        (char *)m->private, rc);
563                 return rc;
564         }
565
566         seq_printf(m, "%d\n", (int)nodemap->nmf_enable_audit);
567         nodemap_putref(nodemap);
568         return 0;
569 }
570
571 #ifdef NODEMAP_PROC_DEBUG
572 /**
573  * Helper functions to set nodemap flags.
574  *
575  * \param[in] buffer    string, which is "1" or "0" to set/unset flag
576  * \param[in] count     \a buffer length
577  * \param[out] flag_p   where to store flag value
578  * \retval              \a count on success
579  * \retval              negative number on error
580  */
581 static int nodemap_proc_read_flag(const char __user *buffer,
582                                   unsigned long count, unsigned int *flag_p)
583 {
584         char                    scratch[NODEMAP_LPROC_FLAG_LEN + 1];
585         long unsigned int       flag_buf;
586         int                     rc;
587
588         if (count == 0)
589                 return 0;
590
591         if (count >= sizeof(scratch))
592                 return -EINVAL;
593
594         if (copy_from_user(scratch, buffer, count))
595                 return -EFAULT;
596
597         scratch[count] = '\0';
598         rc = kstrtoul(scratch, 10, &flag_buf);
599         if (rc != 0)
600                 return -EINVAL;
601
602         *flag_p = flag_buf;
603
604         return count;
605 }
606
607 /**
608  * Set the squash UID.
609  *
610  * \param[in] file      proc file
611  * \param[in] buffer    string representing squash UID to set
612  * \param[in] count     \a buffer length
613  * \param[in] off       unused
614  * \retval              \a count on success
615  * \retval              negative number on error
616  */
617 static ssize_t
618 nodemap_squash_uid_seq_write(struct file *file, const char __user *buffer,
619                              size_t count, loff_t *off)
620 {
621         char                     squash[NODEMAP_LPROC_ID_LEN + 1];
622         struct seq_file         *m = file->private_data;
623         long unsigned int        squash_uid;
624         int                      rc;
625
626         if (count == 0)
627                 return 0;
628
629         if (count >= sizeof(squash))
630                 return -EINVAL;
631
632         if (copy_from_user(squash, buffer, count))
633                 return -EFAULT;
634
635         squash[count] = '\0';
636         rc = kstrtoul(squash, 10, &squash_uid);
637         if (rc != 0)
638                 return -EINVAL;
639
640         rc = nodemap_set_squash_uid(m->private, squash_uid);
641         if (rc != 0)
642                 return rc;
643
644         return count;
645 }
646
647 /**
648  * Set the squash GID.
649  *
650  * \param[in] file      proc file
651  * \param[in] buffer    string representing squash GID to set
652  * \param[in] count     \a buffer length
653  * \param[in] off       unused
654  * \retval              \a count on success
655  * \retval              negative number on error
656  */
657 static ssize_t
658 nodemap_squash_gid_seq_write(struct file *file, const char __user *buffer,
659                              size_t count, loff_t *off)
660 {
661         char                     squash[NODEMAP_LPROC_ID_LEN + 1];
662         struct seq_file         *m = file->private_data;
663         long unsigned int        squash_gid;
664         int                      rc;
665
666         if (count == 0)
667                 return 0;
668
669         if (count >= sizeof(squash))
670                 return -EINVAL;
671
672         if (copy_from_user(squash, buffer, count))
673                 return -EFAULT;
674
675         squash[count] = '\0';
676         rc = kstrtoul(squash, 10, &squash_gid);
677         if (rc != 0)
678                 return -EINVAL;
679
680         rc = nodemap_set_squash_gid(m->private, squash_gid);
681         if (rc != 0)
682                 return rc;
683
684         return count;
685 }
686
687 /**
688  * Set/unset the trusted flag.
689  *
690  * \param[in] file      proc file
691  * \param[in] buffer    string, "1" or "0"
692  * \param[in] count     \a buffer length
693  * \param[in] off       unused
694  * \retval              \a count on success
695  * \retval              negative number on error
696  */
697 static ssize_t
698 nodemap_trusted_seq_write(struct file *file, const char __user *buffer,
699                           size_t count, loff_t *off)
700 {
701         struct seq_file         *m = file->private_data;
702         int                     flags;
703         int                     rc;
704
705         rc = nodemap_proc_read_flag(buffer, count, &flags);
706         if (rc < 0)
707                 return rc;
708
709         rc = nodemap_set_trust_client_ids(m->private, flags);
710         if (rc != 0)
711                 return rc;
712
713         return count;
714 }
715
716 /**
717  * Set/unset the admin flag.
718  *
719  * \param[in] file      proc file
720  * \param[in] buffer    string, "1" or "0"
721  * \param[in] count     \a buffer length
722  * \param[in] off       unused
723  * \retval              \a count on success
724  * \retval              negative number on error
725  */
726 static ssize_t
727 nodemap_admin_seq_write(struct file *file, const char __user *buffer,
728                         size_t count, loff_t *off)
729 {
730         struct seq_file         *m = file->private_data;
731         int                     flags;
732         int                     rc;
733
734         rc = nodemap_proc_read_flag(buffer, count, &flags);
735         if (rc < 0)
736                 return rc;
737
738         rc = nodemap_set_allow_root(m->private, flags);
739         if (rc != 0)
740                 return rc;
741
742         return count;
743 }
744
745 /**
746  * Add a nodemap.
747  *
748  * \param[in] file      proc file
749  * \param[in] buffer    string, name of the nodemap to add
750  * \param[in] count     \a buffer length
751  * \param[in] off       unused
752  * \retval              \a count on success
753  * \retval              negative number on error
754  */
755 static ssize_t
756 lprocfs_add_nodemap_seq_write(struct file *file, const char __user *buffer,
757                               size_t count, loff_t *off)
758 {
759         char    nodemap_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
760         char    *cpybuf = NULL;
761         char    *pos;
762         int     rc;
763
764         if (count == 0)
765                 return 0;
766
767         if (count >= sizeof(nodemap_name))
768                 return -EINVAL;
769
770         if (copy_from_user(nodemap_name, buffer, count))
771                 return -EFAULT;
772
773         nodemap_name[count] = '\0';
774
775         cpybuf = nodemap_name;
776         pos = strsep(&cpybuf, " \n");
777         if (pos == NULL)
778                 return -EINVAL;
779
780         rc = nodemap_add(nodemap_name);
781         if (rc == 0)
782                 rc = count;
783
784         return rc;
785 }
786 LPROC_SEQ_FOPS_WR_ONLY(nodemap, add_nodemap);
787
788 /**
789  * Delete a nodemap.
790  *
791  * \param[in] file      proc file
792  * \param[in] buffer    string, name of the nodemap to delete
793  * \param[in] count     \a buffer length
794  * \param[in] off       unused
795  * \retval              \a count on success
796  * \retval              negative number on error
797  */
798 static ssize_t
799 lprocfs_del_nodemap_seq_write(struct file *file, const char __user *buffer,
800                               size_t count, loff_t *off)
801 {
802         char    nodemap_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
803         char    *cpybuf = NULL;
804         char    *pos;
805         int     rc = count;
806
807         if (count == 0)
808                 return 0;
809
810         if (count >= sizeof(nodemap_name))
811                 return -EINVAL;
812
813         if (copy_from_user(nodemap_name, buffer, count))
814                 return -EFAULT;
815
816         nodemap_name[count] = '\0';
817
818         cpybuf = nodemap_name;
819         pos = strsep(&cpybuf, " \n");
820         if (pos == NULL)
821                 return -EINVAL;
822
823         rc = nodemap_del(nodemap_name);
824         if (rc == 0)
825                 rc = count;
826
827         return rc;
828
829 }
830 LPROC_SEQ_FOPS_WR_ONLY(nodemap, del_nodemap);
831
832 /**
833  * Helper function to parse a NID string.
834  *
835  * \param[in] rangestr  string representation of NIDs, see libcfs_str2nid()
836  * \param[out] nids     array of two nids
837  * \retval              0 on success
838  * \retval              negative number on error
839  */
840 static int parse_nids(char *rangestr, lnet_nid_t nids[2])
841 {
842         struct list_head        nidlist;
843         char                    nidstr[2][LNET_NIDSTR_SIZE];
844         char                    nidrange_str[2 * LNET_NIDSTR_SIZE + 2];
845         int                     rc = 0;
846
847         INIT_LIST_HEAD(&nidlist);
848
849         if (cfs_parse_nidlist(rangestr, strlen(rangestr),
850             &nidlist) <= 0)
851                 return -EINVAL;
852
853         rc = cfs_nidrange_find_min_max(&nidlist, nidstr[0], nidstr[1],
854                                        LNET_NIDSTR_SIZE);
855         if (rc < 0)
856                 return rc;
857
858         snprintf(nidrange_str, sizeof(nidrange_str), "%s:%s",
859                 nidstr[0], nidstr[1]);
860
861         rc = nodemap_parse_range(nidrange_str, nids);
862         if (rc != 0)
863                 return -EINVAL;
864
865         cfs_free_nidlist(&nidlist);
866
867         return 0;
868 }
869
870 /**
871  * Add a NID range to nodemap.
872  *
873  * \param[in] file      proc file
874  * \param[in] buffer    string, "<nodemap name> <nid range>"
875  * \param[in] count     \a buffer length
876  * \param[in] off       unused
877  * \retval              \a count on success
878  * \retval              negative number on error
879  */
880 static ssize_t
881 lprocfs_add_nodemap_range_seq_write(struct file *file,
882                                     const char __user *buffer,
883                                     size_t count, loff_t *off)
884 {
885         char                    name_range[LUSTRE_NODEMAP_NAME_LENGTH +
886                                            LNET_NIDSTR_SIZE * 2 + 2];
887         char                    *cpybuf = NULL;
888         char                    *name;
889         char                    *rangestr = NULL;
890         lnet_nid_t              nids[2];
891         int                     rc;
892
893         if (count == 0)
894                 return 0;
895
896         if (count >= sizeof(name_range))
897                 GOTO(out, rc = -EINVAL);
898
899         if (copy_from_user(name_range, buffer, count))
900                 GOTO(out, rc = -EFAULT);
901
902         name_range[count] = '\0';
903
904         cpybuf = name_range;
905         name = strsep(&cpybuf, " ");
906         if (name == NULL)
907                 GOTO(out, rc = -EINVAL);
908
909         rangestr = strsep(&cpybuf, " \n");
910         if (rangestr == NULL)
911                 GOTO(out, rc = -EINVAL);
912
913         rc = parse_nids(rangestr, nids);
914         if (rc != 0)
915                 GOTO(out, rc = rc);
916
917         rc = nodemap_add_range(name, nids);
918         if (rc != 0)
919                 GOTO(out, rc = -EINVAL);
920
921         if (rc == 0)
922                 rc = count;
923
924 out:
925         return rc;
926 }
927 LPROC_SEQ_FOPS_WR_ONLY(nodemap, add_nodemap_range);
928
929 /**
930  * Delete a NID range from nodemap.
931  *
932  * \param[in] file      proc file
933  * \param[in] buffer    string, "<nodemap name> <nid range>"
934  * \param[in] count     \a buffer length
935  * \param[in] off       unused
936  * \retval              \a count on success
937  * \retval              negative number on error
938  */
939 static ssize_t
940 lprocfs_del_nodemap_range_seq_write(struct file *file,
941                                     const char __user *buffer,
942                                     size_t count, loff_t *off)
943 {
944         char                    name_range[LUSTRE_NODEMAP_NAME_LENGTH +
945                                            LNET_NIDSTR_SIZE * 2 + 2];
946         char                    *cpybuf = NULL;
947         char                    *name;
948         char                    *rangestr = NULL;
949         lnet_nid_t              nids[2];
950         int                     rc;
951
952         if (count == 0)
953                 return 0;
954
955         if (count >= sizeof(name_range))
956                 GOTO(out, rc = -EINVAL);
957
958         if (copy_from_user(name_range, buffer, count))
959                 GOTO(out, rc = -EFAULT);
960
961         name_range[count] = '\0';
962
963         cpybuf = name_range;
964         name = strsep(&cpybuf, " ");
965         if (name == NULL)
966                 GOTO(out, rc = -EINVAL);
967
968         rangestr = strsep(&cpybuf, " \n");
969         if (rangestr == NULL)
970                 GOTO(out, rc = -EINVAL);
971
972         rc = parse_nids(rangestr, nids);
973         if (rc != 0)
974                 GOTO(out, rc = rc);
975
976         rc = nodemap_del_range(name, nids);
977         if (rc != 0)
978                 GOTO(out, rc = -EINVAL);
979
980         if (rc == 0)
981                 rc = count;
982
983 out:
984         return rc;
985 }
986 LPROC_SEQ_FOPS_WR_ONLY(nodemap, del_nodemap_range);
987
988 /**
989  * Add an idmap to nodemap.
990  *
991  * \param[in] file      proc file
992  * \param[in] buffer    string, "<nodemap name> <uid|gid> <idmap>"
993  * \param[in] count     \a buffer length
994  * \param[in] off       unused
995  * \retval              \a count on success
996  * \retval              negative number on error
997  */
998 static ssize_t
999 lprocfs_add_nodemap_idmap_seq_write(struct file *file,
1000                                     const char __user *buffer,
1001                                     size_t count, loff_t *off)
1002 {
1003         char                    name_idmapstr[LUSTRE_NODEMAP_NAME_LENGTH + 16];
1004         char                    *cpybuf = NULL;
1005         char                    *name;
1006         char                    *idtypestr = NULL;
1007         char                    *idmapstr = NULL;
1008         __u32                   idmap[2];
1009         int                     rc = count;
1010
1011         if (count == 0)
1012                 return 0;
1013
1014         if (count >= sizeof(name_idmapstr))
1015                 GOTO(out, rc = -EINVAL);
1016
1017         if (copy_from_user(name_idmapstr, buffer, count))
1018                 GOTO(out, rc = -EFAULT);
1019
1020         name_idmapstr[count] = '\0';
1021
1022         cpybuf = name_idmapstr;
1023         name = strsep(&cpybuf, " ");
1024         if (name == NULL)
1025                 GOTO(out, rc = -EINVAL);
1026
1027         idtypestr = strsep(&cpybuf, " ");
1028         if (idtypestr == NULL)
1029                 GOTO(out, rc = -EINVAL);
1030
1031         idmapstr = strsep(&cpybuf, " \n");
1032         if (idmapstr == NULL)
1033                 GOTO(out, rc = -EINVAL);
1034
1035         rc = nodemap_parse_idmap(idmapstr, idmap);
1036         if (rc != 0)
1037                 GOTO(out, rc = -EINVAL);
1038
1039         if (strcmp(idtypestr, "uid") == 0)
1040                 rc = nodemap_add_idmap(name, NODEMAP_UID, idmap);
1041         else if (strcmp(idtypestr, "gid") == 0)
1042                 rc = nodemap_add_idmap(name, NODEMAP_GID, idmap);
1043         else
1044                 GOTO(out, rc = -EINVAL);
1045
1046         if (rc != 0)
1047                 GOTO(out, rc = -EINVAL);
1048
1049         if (rc == 0)
1050                 rc = count;
1051
1052 out:
1053         return rc;
1054 }
1055 LPROC_SEQ_FOPS_WR_ONLY(nodemap, add_nodemap_idmap);
1056
1057 /**
1058  * Delete an idmap from nodemap.
1059  *
1060  * \param[in] file      proc file
1061  * \param[in] buffer    string, "<nodemap name> <uid|gid> <idmap>"
1062  * \param[in] count     \a buffer length
1063  * \param[in] off       unused
1064  * \retval              \a count on success
1065  * \retval              negative number on error
1066  */
1067 static ssize_t
1068 lprocfs_del_nodemap_idmap_seq_write(struct file *file,
1069                                     const char __user *buffer,
1070                                     size_t count, loff_t *off)
1071 {
1072         char                    name_idmapstr[LUSTRE_NODEMAP_NAME_LENGTH + 16];
1073         char                    *cpybuf = NULL;
1074         char                    *name;
1075         char                    *idtypestr = NULL;
1076         char                    *idmapstr = NULL;
1077         __u32                   idmap[2];
1078         int                     rc = count;
1079
1080         if (count == 0)
1081                 return 0;
1082
1083         if (count >= sizeof(name_idmapstr))
1084                 GOTO(out, rc = -EINVAL);
1085
1086         if (copy_from_user(name_idmapstr, buffer, count))
1087                 GOTO(out, rc = -EFAULT);
1088
1089         name_idmapstr[count] = '\0';
1090
1091         cpybuf = name_idmapstr;
1092         name = strsep(&cpybuf, " ");
1093         if (name == NULL)
1094                 GOTO(out, rc = -EINVAL);
1095
1096         idtypestr = strsep(&cpybuf, " ");
1097         if (idtypestr == NULL)
1098                 GOTO(out, rc = -EINVAL);
1099
1100         idmapstr = strsep(&cpybuf, " \n");
1101         if (idmapstr == NULL)
1102                 GOTO(out, rc = -EINVAL);
1103
1104         rc = nodemap_parse_idmap(idmapstr, idmap);
1105         if (rc != 0)
1106                 GOTO(out, rc = -EINVAL);
1107
1108         if (strcmp(idtypestr, "uid") == 0)
1109                 rc = nodemap_del_idmap(name, NODEMAP_UID, idmap);
1110         else if (strcmp(idtypestr, "gid") == 0)
1111                 rc = nodemap_del_idmap(name, NODEMAP_GID, idmap);
1112         else
1113                 GOTO(out, rc = -EINVAL);
1114
1115         if (rc != 0)
1116                 GOTO(out, rc = -EINVAL);
1117
1118         if (rc == 0)
1119                 rc = count;
1120
1121 out:
1122         return rc;
1123 }
1124 LPROC_SEQ_FOPS_WR_ONLY(nodemap, del_nodemap_idmap);
1125 #endif /* NODEMAP_PROC_DEBUG */
1126
1127 static struct lprocfs_vars lprocfs_nm_module_vars[] = {
1128         {
1129                 .name           = "active",
1130                 .fops           = &nodemap_active_fops,
1131         },
1132 #ifdef NODEMAP_PROC_DEBUG
1133         {
1134                 .name           = "add_nodemap",
1135                 .fops           = &nodemap_add_nodemap_fops,
1136         },
1137         {
1138                 .name           = "remove_nodemap",
1139                 .fops           = &nodemap_del_nodemap_fops,
1140         },
1141         {
1142                 .name           = "add_nodemap_range",
1143                 .fops           = &nodemap_add_nodemap_range_fops,
1144         },
1145         {
1146                 .name           = "del_nodemap_range",
1147                 .fops           = &nodemap_del_nodemap_range_fops,
1148         },
1149         {
1150                 .name           = "add_nodemap_idmap",
1151                 .fops           = &nodemap_add_nodemap_idmap_fops,
1152         },
1153         {
1154                 .name           = "del_nodemap_idmap",
1155                 .fops           = &nodemap_del_nodemap_idmap_fops,
1156         },
1157 #endif /* NODEMAP_PROC_DEBUG */
1158         {
1159                 NULL
1160         }
1161 };
1162
1163 #ifdef NODEMAP_PROC_DEBUG
1164 LPROC_SEQ_FOPS(nodemap_trusted);
1165 LPROC_SEQ_FOPS(nodemap_admin);
1166 LPROC_SEQ_FOPS(nodemap_squash_uid);
1167 LPROC_SEQ_FOPS(nodemap_squash_gid);
1168 #else
1169 LPROC_SEQ_FOPS_RO(nodemap_trusted);
1170 LPROC_SEQ_FOPS_RO(nodemap_admin);
1171 LPROC_SEQ_FOPS_RO(nodemap_squash_uid);
1172 LPROC_SEQ_FOPS_RO(nodemap_squash_gid);
1173 #endif
1174
1175 LPROC_SEQ_FOPS_RO(nodemap_deny_unknown);
1176 LPROC_SEQ_FOPS_RO(nodemap_map_mode);
1177 LPROC_SEQ_FOPS_RO(nodemap_audit_mode);
1178
1179 const struct file_operations nodemap_ranges_fops = {
1180         .open                   = nodemap_ranges_open,
1181         .read                   = seq_read,
1182         .llseek                 = seq_lseek,
1183         .release                = single_release
1184 };
1185
1186 const struct file_operations nodemap_idmap_fops = {
1187         .open                   = nodemap_idmap_open,
1188         .read                   = seq_read,
1189         .llseek                 = seq_lseek,
1190         .release                = single_release
1191 };
1192
1193 const struct file_operations nodemap_exports_fops = {
1194         .open                   = nodemap_exports_open,
1195         .read                   = seq_read,
1196         .llseek                 = seq_lseek,
1197         .release                = single_release
1198 };
1199
1200 static struct lprocfs_vars lprocfs_nodemap_vars[] = {
1201         {
1202                 .name           = "id",
1203                 .fops           = &nodemap_id_fops,
1204         },
1205         {
1206                 .name           = "trusted_nodemap",
1207                 .fops           = &nodemap_trusted_fops,
1208         },
1209         {
1210                 .name           = "admin_nodemap",
1211                 .fops           = &nodemap_admin_fops,
1212         },
1213         {
1214                 .name           = "deny_unknown",
1215                 .fops           = &nodemap_deny_unknown_fops,
1216         },
1217         {
1218                 .name           = "map_mode",
1219                 .fops           = &nodemap_map_mode_fops,
1220         },
1221         {
1222                 .name           = "audit_mode",
1223                 .fops           = &nodemap_audit_mode_fops,
1224         },
1225         {
1226                 .name           = "squash_uid",
1227                 .fops           = &nodemap_squash_uid_fops,
1228         },
1229         {
1230                 .name           = "squash_gid",
1231                 .fops           = &nodemap_squash_gid_fops,
1232         },
1233         {
1234                 .name           = "ranges",
1235                 .fops           = &nodemap_ranges_fops,
1236         },
1237         {
1238                 .name           = "fileset",
1239                 .fops           = &nodemap_fileset_fops,
1240         },
1241         {
1242                 .name           = "exports",
1243                 .fops           = &nodemap_exports_fops,
1244         },
1245         {
1246                 .name           = "idmap",
1247                 .fops           = &nodemap_idmap_fops,
1248         },
1249         {
1250                 NULL
1251         }
1252 };
1253
1254 static struct lprocfs_vars lprocfs_default_nodemap_vars[] = {
1255         {
1256                 .name           = "id",
1257                 .fops           = &nodemap_id_fops,
1258         },
1259         {
1260                 .name           = "trusted_nodemap",
1261                 .fops           = &nodemap_trusted_fops,
1262         },
1263         {
1264                 .name           = "admin_nodemap",
1265                 .fops           = &nodemap_admin_fops,
1266         },
1267         {
1268                 .name           = "squash_uid",
1269                 .fops           = &nodemap_squash_uid_fops,
1270         },
1271         {
1272                 .name           = "squash_gid",
1273                 .fops           = &nodemap_squash_gid_fops,
1274         },
1275         {
1276                 .name           = "fileset",
1277                 .fops           = &nodemap_fileset_fops,
1278         },
1279         {
1280                 .name           = "exports",
1281                 .fops           = &nodemap_exports_fops,
1282         },
1283         {
1284                 .name           = "audit_mode",
1285                 .fops           = &nodemap_audit_mode_fops,
1286         },
1287         {
1288                 NULL
1289         }
1290 };
1291
1292 /**
1293  * Initialize the nodemap procfs directory.
1294  *
1295  * \retval      0               success
1296  */
1297 int nodemap_procfs_init(void)
1298 {
1299         int rc = 0;
1300
1301         proc_lustre_nodemap_root = lprocfs_register(LUSTRE_NODEMAP_NAME,
1302                                                     proc_lustre_root,
1303                                                     lprocfs_nm_module_vars,
1304                                                     NULL);
1305         if (IS_ERR(proc_lustre_nodemap_root)) {
1306                 rc = PTR_ERR(proc_lustre_nodemap_root);
1307                 CERROR("cannot create 'nodemap' directory: rc = %d\n",
1308                        rc);
1309                 proc_lustre_nodemap_root = NULL;
1310         }
1311         return rc;
1312 }
1313
1314 /**
1315  * Cleanup nodemap proc entry data structures.
1316  */
1317 void nodemap_procfs_exit(void)
1318 {
1319         struct nodemap_pde *nm_pde;
1320         struct nodemap_pde *tmp;
1321
1322         lprocfs_remove(&proc_lustre_nodemap_root);
1323         list_for_each_entry_safe(nm_pde, tmp, &nodemap_pde_list,
1324                                  npe_list_member) {
1325                 list_del(&nm_pde->npe_list_member);
1326                 OBD_FREE_PTR(nm_pde);
1327         }
1328 }
1329
1330 /**
1331  * Remove a nodemap's procfs entry and related data.
1332  */
1333 void lprocfs_nodemap_remove(struct nodemap_pde *nm_pde)
1334 {
1335         lprocfs_remove(&nm_pde->npe_proc_entry);
1336         list_del(&nm_pde->npe_list_member);
1337         OBD_FREE_PTR(nm_pde);
1338 }
1339
1340 /**
1341  * Register the proc directory for a nodemap
1342  *
1343  * \param       nodemap         nodemap to make the proc dir for
1344  * \param       is_default:     1 if default nodemap
1345  * \retval      0               success
1346  */
1347 int lprocfs_nodemap_register(struct lu_nodemap *nodemap, bool is_default)
1348 {
1349         struct nodemap_pde      *nm_entry;
1350         int                      rc = 0;
1351
1352         OBD_ALLOC_PTR(nm_entry);
1353         if (nm_entry == NULL)
1354                 GOTO(out, rc = -ENOMEM);
1355
1356         nm_entry->npe_proc_entry = proc_mkdir(nodemap->nm_name,
1357                                               proc_lustre_nodemap_root);
1358         if (IS_ERR(nm_entry->npe_proc_entry))
1359                 GOTO(out, rc = PTR_ERR(nm_entry->npe_proc_entry));
1360
1361         snprintf(nm_entry->npe_name, sizeof(nm_entry->npe_name), "%s",
1362                  nodemap->nm_name);
1363
1364         /* Use the nodemap name as stored on the PDE as the private data. This
1365          * is so a nodemap struct can be replaced without updating the proc
1366          * entries.
1367          */
1368         rc = lprocfs_add_vars(nm_entry->npe_proc_entry,
1369                               (is_default ? lprocfs_default_nodemap_vars :
1370                                             lprocfs_nodemap_vars),
1371                               nm_entry->npe_name);
1372         if (rc != 0)
1373                 lprocfs_remove(&nm_entry->npe_proc_entry);
1374         else
1375                 list_add(&nm_entry->npe_list_member, &nodemap_pde_list);
1376
1377 out:
1378         if (rc != 0) {
1379                 CERROR("cannot create 'nodemap/%s': rc = %d\n",
1380                        nodemap->nm_name, rc);
1381                 if (nm_entry != NULL) {
1382                         OBD_FREE_PTR(nm_entry);
1383                         nm_entry = NULL;
1384                 }
1385         }
1386
1387         nodemap->nm_pde_data = nm_entry;
1388
1389         return rc;
1390 }