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