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