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