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