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