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