4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
23 * Copyright (C) 2013, Trustees of Indiana University
24 * Author: Joshua Walgenbach <jjw@iu.edu>
27 #define NODEMAP_LPROC_ID_LEN 16
28 #define NODEMAP_LPROC_FLAG_LEN 2
30 #include <lprocfs_status.h>
31 #include <lustre_net.h>
32 #include <lustre_export.h>
33 #include <obd_class.h>
34 #include <interval_tree.h>
35 #include "nodemap_internal.h"
37 /* Turn on proc debug interface to allow OSS and
38 * MDS nodes to configure nodemap independently of
39 * MGS (since the nodemap distribution is not written
41 #define NODEMAP_PROC_DEBUG 1
44 * Reads and prints the idmap for the given nodemap.
46 * \param m seq file in proc fs
50 static int nodemap_idmap_show(struct seq_file *m, void *data)
52 struct lu_nodemap *nodemap = m->private;
53 struct lu_idmap *idmap;
58 read_lock(&nodemap->nm_idmap_lock);
59 for (node = rb_first(&nodemap->nm_client_to_fs_uidmap); node;
60 node = rb_next(node)) {
64 idmap = rb_entry(node, struct lu_idmap, id_client_to_fs);
66 seq_printf(m, " { idtype: uid, client_id: %u, "
67 "fs_id: %u }", idmap->id_client,
70 for (node = rb_first(&nodemap->nm_client_to_fs_gidmap);
71 node; node = rb_next(node)) {
74 idmap = rb_entry(node, struct lu_idmap, id_client_to_fs);
76 seq_printf(m, " { idtype: gid, client_id: %u, "
77 "fs_id: %u }", idmap->id_client,
80 read_unlock(&nodemap->nm_idmap_lock);
88 * Attaches nodemap_idmap_show to proc file.
90 * \param inode inode of seq file in proc fs
91 * \param file seq file
94 static int nodemap_idmap_open(struct inode *inode, struct file *file)
96 struct lu_nodemap *nodemap = PDE_DATA(inode);
98 return single_open(file, nodemap_idmap_show, nodemap);
102 * Reads and prints the NID ranges for the given nodemap.
104 * \param m seq file in proc fs
108 static int nodemap_ranges_show(struct seq_file *m, void *data)
110 struct lu_nodemap *nodemap = m->private;
111 struct lu_nid_range *range;
112 struct interval_node_extent ext;
115 seq_printf(m, "[\n");
116 read_lock(&nm_range_tree_lock);
117 list_for_each_entry(range, &nodemap->nm_ranges, rn_list) {
119 seq_printf(m, ",\n");
121 ext = range->rn_node.in_extent;
122 seq_printf(m, " { id: %u, start_nid: %s, "
124 range->rn_id, libcfs_nid2str(ext.start),
125 libcfs_nid2str(ext.end));
127 read_unlock(&nm_range_tree_lock);
129 seq_printf(m, "]\n");
135 * Connects nodemap_idmap_show to proc file.
137 * \param inode inode of seq file in proc fs
138 * \param file seq file
141 static int nodemap_ranges_open(struct inode *inode, struct file *file)
143 struct lu_nodemap *nodemap = PDE_DATA(inode);
145 return single_open(file, nodemap_ranges_show, nodemap);
149 * Hash callback, reads and prints the exports attached to this nodemap.
151 * \param hs nodemap member hash
153 * \param hnode current member in hash
154 * \param data seq_file to print to
157 static int nodemap_exports_show_cb(cfs_hash_t *hs, cfs_hash_bd_t *bd,
158 struct hlist_node *hnode, void *data)
160 struct seq_file *m = data;
161 struct obd_export *exp;
164 exp = hlist_entry(hnode, struct obd_export,
165 exp_target_data.ted_nodemap_member);
166 key = cfs_hash_key(hs, hnode);
167 seq_printf(m, " { nid: %s, uuid: %s },",
168 obd_export_nid2str(exp), exp->exp_client_uuid.uuid);
174 * Reads and prints the exports attached to the given nodemap via hash
177 * \param m seq file in proc fs
181 static int nodemap_exports_show(struct seq_file *m, void *data)
183 struct lu_nodemap *nodemap = m->private;
185 seq_printf(m, "[\n");
187 cfs_hash_for_each(nodemap->nm_member_hash, nodemap_exports_show_cb, m);
190 seq_printf(m, "]\n");
196 * Attaches nodemap_idmap_show to proc file.
198 * \param inode inode of seq file in proc fs
199 * \param file seq file
202 static int nodemap_exports_open(struct inode *inode, struct file *file)
204 struct proc_dir_entry *dir = PDE(inode);
205 struct lu_nodemap *nodemap = dir->data;
207 return single_open(file, nodemap_exports_show, nodemap);
211 * Reads and prints the active flag for the given nodemap.
213 * \param m seq file in proc fs
217 static int nodemap_active_seq_show(struct seq_file *m, void *data)
219 return seq_printf(m, "%u\n", (unsigned int)nodemap_active);
223 * Activate/deactivate nodemap.
225 * \param[in] file proc file
226 * \param[in] buffer string, "1" or "0" to activate/deactivate nodemap
227 * \param[in] count \a buffer length
228 * \param[in] off unused
229 * \retval \a count on success
230 * \retval negative number on error
233 nodemap_active_seq_write(struct file *file, const char __user *buffer,
234 size_t count, loff_t *off)
236 char active_string[NODEMAP_LPROC_FLAG_LEN + 1];
237 long unsigned int active;
243 if (count >= sizeof(active_string))
246 if (copy_from_user(active_string, buffer, count))
249 active_string[count] = '\0';
250 rc = kstrtoul(active_string, 10, &active);
254 nodemap_active = active;
258 LPROC_SEQ_FOPS(nodemap_active);
261 * Reads and prints the nodemap ID for the given nodemap.
263 * \param m seq file in proc fs
267 static int nodemap_id_seq_show(struct seq_file *m, void *data)
269 struct lu_nodemap *nodemap = m->private;
271 return seq_printf(m, "%u\n", nodemap->nm_id);
273 LPROC_SEQ_FOPS_RO(nodemap_id);
276 * Reads and prints the root squash UID for the given nodemap.
278 * \param m seq file in proc fs
282 static int nodemap_squash_uid_seq_show(struct seq_file *m, void *data)
284 struct lu_nodemap *nodemap = m->private;
286 return seq_printf(m, "%u\n", nodemap->nm_squash_uid);
290 * Reads and prints the root squash GID for the given nodemap.
292 * \param m seq file in proc fs
296 static int nodemap_squash_gid_seq_show(struct seq_file *m, void *data)
298 struct lu_nodemap *nodemap = m->private;
300 return seq_printf(m, "%u\n", nodemap->nm_squash_gid);
304 * Reads and prints the trusted flag for the given nodemap.
306 * \param m seq file in proc fs
310 static int nodemap_trusted_seq_show(struct seq_file *m, void *data)
312 struct lu_nodemap *nodemap = m->private;
314 return seq_printf(m, "%d\n", (int)nodemap->nmf_trust_client_ids);
318 * Reads and prints the admin flag for the given nodemap.
320 * \param m seq file in proc fs
324 static int nodemap_admin_seq_show(struct seq_file *m, void *data)
326 struct lu_nodemap *nodemap = m->private;
328 return seq_printf(m, "%d\n", (int)nodemap->nmf_allow_root_access);
331 #ifdef NODEMAP_PROC_DEBUG
333 * Helper functions to set nodemap flags.
335 * \param[in] buffer string, which is "1" or "0" to set/unset flag
336 * \param[in] count \a buffer length
337 * \param[out] flag_p where to store flag value
338 * \retval \a count on success
339 * \retval negative number on error
341 static int nodemap_proc_read_flag(const char __user *buffer,
342 unsigned long count, unsigned int *flag_p)
344 char scratch[NODEMAP_LPROC_FLAG_LEN + 1];
345 long unsigned int flag_buf;
351 if (count >= sizeof(scratch))
354 if (copy_from_user(scratch, buffer, count))
357 scratch[count] = '\0';
358 rc = kstrtoul(scratch, 10, &flag_buf);
368 * Set the squash UID.
370 * \param[in] file proc file
371 * \param[in] buffer string representing squash UID to set
372 * \param[in] count \a buffer length
373 * \param[in] off unused
374 * \retval \a count on success
375 * \retval negative number on error
378 nodemap_squash_uid_seq_write(struct file *file, const char __user *buffer,
379 size_t count, loff_t *off)
381 char squash[NODEMAP_LPROC_ID_LEN + 1];
382 struct seq_file *m = file->private_data;
383 struct lu_nodemap *nodemap = m->private;
384 long unsigned int squash_uid;
390 if (count >= sizeof(squash))
393 if (copy_from_user(squash, buffer, count))
396 squash[count] = '\0';
397 rc = kstrtoul(squash, 10, &squash_uid);
401 nodemap->nm_squash_uid = squash_uid;
407 * Set the squash GID.
409 * \param[in] file proc file
410 * \param[in] buffer string representing squash GID to set
411 * \param[in] count \a buffer length
412 * \param[in] off unused
413 * \retval \a count on success
414 * \retval negative number on error
417 nodemap_squash_gid_seq_write(struct file *file, const char __user *buffer,
418 size_t count, loff_t *off)
420 char squash[NODEMAP_LPROC_ID_LEN + 1];
421 struct seq_file *m = file->private_data;
422 struct lu_nodemap *nodemap = m->private;
423 long unsigned int squash_gid;
429 if (count >= sizeof(squash))
432 if (copy_from_user(squash, buffer, count))
435 squash[count] = '\0';
436 rc = kstrtoul(squash, 10, &squash_gid);
440 nodemap->nm_squash_gid = squash_gid;
446 * Set/unset the trusted flag.
448 * \param[in] file proc file
449 * \param[in] buffer string, "1" or "0"
450 * \param[in] count \a buffer length
451 * \param[in] off unused
452 * \retval \a count on success
453 * \retval negative number on error
456 nodemap_trusted_seq_write(struct file *file, const char __user *buffer,
457 size_t count, loff_t *off)
459 struct seq_file *m = file->private_data;
460 struct lu_nodemap *nodemap = m->private;
464 rc = nodemap_proc_read_flag(buffer, count, &flags);
466 nodemap->nmf_trust_client_ids = !!flags;
467 nm_member_revoke_locks(nodemap);
474 * Set/unset the admin flag.
476 * \param[in] file proc file
477 * \param[in] buffer string, "1" or "0"
478 * \param[in] count \a buffer length
479 * \param[in] off unused
480 * \retval \a count on success
481 * \retval negative number on error
484 nodemap_admin_seq_write(struct file *file, const char __user *buffer,
485 size_t count, loff_t *off)
487 struct seq_file *m = file->private_data;
488 struct lu_nodemap *nodemap = m->private;
492 rc = nodemap_proc_read_flag(buffer, count, &flags);
494 nodemap->nmf_allow_root_access = !!flags;
495 nm_member_revoke_locks(nodemap);
504 * \param[in] file proc file
505 * \param[in] buffer string, name of the nodemap to add
506 * \param[in] count \a buffer length
507 * \param[in] off unused
508 * \retval \a count on success
509 * \retval negative number on error
512 lprocfs_add_nodemap_seq_write(struct file *file, const char __user *buffer,
513 size_t count, loff_t *off)
515 char nodemap_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
523 if (count >= sizeof(nodemap_name))
526 if (copy_from_user(nodemap_name, buffer, count))
529 nodemap_name[count] = '\0';
531 cpybuf = nodemap_name;
532 pos = strsep(&cpybuf, " \n");
536 rc = nodemap_add(nodemap_name);
542 LPROC_SEQ_FOPS_WO_TYPE(nodemap, add_nodemap);
547 * \param[in] file proc file
548 * \param[in] buffer string, name of the nodemap to delete
549 * \param[in] count \a buffer length
550 * \param[in] off unused
551 * \retval \a count on success
552 * \retval negative number on error
555 lprocfs_del_nodemap_seq_write(struct file *file, const char __user *buffer,
556 size_t count, loff_t *off)
558 char nodemap_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
566 if (count >= sizeof(nodemap_name))
569 if (copy_from_user(nodemap_name, buffer, count))
572 nodemap_name[count] = '\0';
574 cpybuf = nodemap_name;
575 pos = strsep(&cpybuf, " \n");
579 rc = nodemap_del(nodemap_name);
586 LPROC_SEQ_FOPS_WO_TYPE(nodemap, del_nodemap);
589 * Helper function to parse a NID string.
591 * \param[in] rangestr string representation of NIDs, see libcfs_str2nid()
592 * \param[out] nids array of two nids
593 * \retval 0 on success
594 * \retval negative number on error
596 static int parse_nids(char *rangestr, lnet_nid_t nids[2])
598 struct list_head nidlist;
599 char nidstr[2][LNET_NIDSTR_SIZE];
600 char nidrange_str[2 * LNET_NIDSTR_SIZE + 2];
603 INIT_LIST_HEAD(&nidlist);
605 if (cfs_parse_nidlist(rangestr, strlen(rangestr),
609 if (!cfs_nidrange_is_contiguous(&nidlist))
612 cfs_nidrange_find_min_max(&nidlist, nidstr[0], nidstr[1],
614 snprintf(nidrange_str, sizeof(nidrange_str), "%s:%s",
615 nidstr[0], nidstr[1]);
617 rc = nodemap_parse_range(nidrange_str, nids);
621 cfs_free_nidlist(&nidlist);
627 * Add a NID range to nodemap.
629 * \param[in] file proc file
630 * \param[in] buffer string, "<nodemap name> <nid range>"
631 * \param[in] count \a buffer length
632 * \param[in] off unused
633 * \retval \a count on success
634 * \retval negative number on error
637 lprocfs_add_nodemap_range_seq_write(struct file *file,
638 const char __user *buffer,
639 size_t count, loff_t *off)
641 char name_range[LUSTRE_NODEMAP_NAME_LENGTH +
642 LNET_NIDSTR_SIZE * 2 + 2];
645 char *rangestr = NULL;
652 if (count >= sizeof(name_range))
653 GOTO(out, rc = -EINVAL);
655 if (copy_from_user(name_range, buffer, count))
656 GOTO(out, rc = -EFAULT);
658 name_range[count] = '\0';
661 name = strsep(&cpybuf, " ");
663 GOTO(out, rc = -EINVAL);
665 rangestr = strsep(&cpybuf, " \n");
666 if (rangestr == NULL)
667 GOTO(out, rc = -EINVAL);
669 rc = parse_nids(rangestr, nids);
673 rc = nodemap_add_range(name, nids);
675 GOTO(out, rc = -EINVAL);
683 LPROC_SEQ_FOPS_WO_TYPE(nodemap, add_nodemap_range);
686 * Delete a NID range from nodemap.
688 * \param[in] file proc file
689 * \param[in] buffer string, "<nodemap name> <nid range>"
690 * \param[in] count \a buffer length
691 * \param[in] off unused
692 * \retval \a count on success
693 * \retval negative number on error
696 lprocfs_del_nodemap_range_seq_write(struct file *file,
697 const char __user *buffer,
698 size_t count, loff_t *off)
700 char name_range[LUSTRE_NODEMAP_NAME_LENGTH +
701 LNET_NIDSTR_SIZE * 2 + 2];
704 char *rangestr = NULL;
711 if (count >= sizeof(name_range))
712 GOTO(out, rc = -EINVAL);
714 if (copy_from_user(name_range, buffer, count))
715 GOTO(out, rc = -EFAULT);
717 name_range[count] = '\0';
720 name = strsep(&cpybuf, " ");
722 GOTO(out, rc = -EINVAL);
724 rangestr = strsep(&cpybuf, " \n");
725 if (rangestr == NULL)
726 GOTO(out, rc = -EINVAL);
728 rc = parse_nids(rangestr, nids);
732 rc = nodemap_del_range(name, nids);
734 GOTO(out, rc = -EINVAL);
742 LPROC_SEQ_FOPS_WO_TYPE(nodemap, del_nodemap_range);
745 * Add an idmap to nodemap.
747 * \param[in] file proc file
748 * \param[in] buffer string, "<nodemap name> <uid|gid> <idmap>"
749 * \param[in] count \a buffer length
750 * \param[in] off unused
751 * \retval \a count on success
752 * \retval negative number on error
755 lprocfs_add_nodemap_idmap_seq_write(struct file *file,
756 const char __user *buffer,
757 size_t count, loff_t *off)
759 char name_idmapstr[LUSTRE_NODEMAP_NAME_LENGTH + 16];
762 char *idtypestr = NULL;
763 char *idmapstr = NULL;
770 if (count >= sizeof(name_idmapstr))
771 GOTO(out, rc = -EINVAL);
773 if (copy_from_user(name_idmapstr, buffer, count))
774 GOTO(out, rc = -EFAULT);
776 name_idmapstr[count] = '\0';
778 cpybuf = name_idmapstr;
779 name = strsep(&cpybuf, " ");
781 GOTO(out, rc = -EINVAL);
783 idtypestr = strsep(&cpybuf, " ");
784 if (idtypestr == NULL)
785 GOTO(out, rc = -EINVAL);
787 idmapstr = strsep(&cpybuf, " \n");
788 if (idmapstr == NULL)
789 GOTO(out, rc = -EINVAL);
791 rc = nodemap_parse_idmap(idmapstr, idmap);
793 GOTO(out, rc = -EINVAL);
795 if (strcmp(idtypestr, "uid") == 0)
796 rc = nodemap_add_idmap(name, NODEMAP_UID, idmap);
797 else if (strcmp(idtypestr, "gid") == 0)
798 rc = nodemap_add_idmap(name, NODEMAP_GID, idmap);
800 GOTO(out, rc = -EINVAL);
803 GOTO(out, rc = -EINVAL);
811 LPROC_SEQ_FOPS_WO_TYPE(nodemap, add_nodemap_idmap);
814 * Delete an idmap from nodemap.
816 * \param[in] file proc file
817 * \param[in] buffer string, "<nodemap name> <uid|gid> <idmap>"
818 * \param[in] count \a buffer length
819 * \param[in] off unused
820 * \retval \a count on success
821 * \retval negative number on error
824 lprocfs_del_nodemap_idmap_seq_write(struct file *file,
825 const char __user *buffer,
826 size_t count, loff_t *off)
828 char name_idmapstr[LUSTRE_NODEMAP_NAME_LENGTH + 16];
831 char *idtypestr = NULL;
832 char *idmapstr = NULL;
839 if (count >= sizeof(name_idmapstr))
840 GOTO(out, rc = -EINVAL);
842 if (copy_from_user(name_idmapstr, buffer, count))
843 GOTO(out, rc = -EFAULT);
845 name_idmapstr[count] = '\0';
847 cpybuf = name_idmapstr;
848 name = strsep(&cpybuf, " ");
850 GOTO(out, rc = -EINVAL);
852 idtypestr = strsep(&cpybuf, " ");
853 if (idtypestr == NULL)
854 GOTO(out, rc = -EINVAL);
856 idmapstr = strsep(&cpybuf, " \n");
857 if (idmapstr == NULL)
858 GOTO(out, rc = -EINVAL);
860 rc = nodemap_parse_idmap(idmapstr, idmap);
862 GOTO(out, rc = -EINVAL);
864 if (strcmp(idtypestr, "uid") == 0)
865 rc = nodemap_del_idmap(name, NODEMAP_UID, idmap);
866 else if (strcmp(idtypestr, "gid") == 0)
867 rc = nodemap_del_idmap(name, NODEMAP_GID, idmap);
869 GOTO(out, rc = -EINVAL);
872 GOTO(out, rc = -EINVAL);
880 LPROC_SEQ_FOPS_WO_TYPE(nodemap, del_nodemap_idmap);
881 #endif /* NODEMAP_PROC_DEBUG */
883 static struct lprocfs_seq_vars lprocfs_nm_module_vars[] = {
886 .fops = &nodemap_active_fops,
888 #ifdef NODEMAP_PROC_DEBUG
890 .name = "add_nodemap",
891 .fops = &nodemap_add_nodemap_fops,
894 .name = "remove_nodemap",
895 .fops = &nodemap_del_nodemap_fops,
898 .name = "add_nodemap_range",
899 .fops = &nodemap_add_nodemap_range_fops,
902 .name = "del_nodemap_range",
903 .fops = &nodemap_del_nodemap_range_fops,
906 .name = "add_nodemap_idmap",
907 .fops = &nodemap_add_nodemap_idmap_fops,
910 .name = "del_nodemap_idmap",
911 .fops = &nodemap_del_nodemap_idmap_fops,
913 #endif /* NODEMAP_PROC_DEBUG */
919 #ifdef NODEMAP_PROC_DEBUG
920 LPROC_SEQ_FOPS(nodemap_trusted);
921 LPROC_SEQ_FOPS(nodemap_admin);
922 LPROC_SEQ_FOPS(nodemap_squash_uid);
923 LPROC_SEQ_FOPS(nodemap_squash_gid);
925 LPROC_SEQ_FOPS_RO(nodemap_trusted);
926 LPROC_SEQ_FOPS_RO(nodemap_admin);
927 LPROC_SEQ_FOPS_RO(nodemap_squash_uid);
928 LPROC_SEQ_FOPS_RO(nodemap_squash_gid);
931 const struct file_operations nodemap_ranges_fops = {
932 .open = nodemap_ranges_open,
935 .release = single_release
938 const struct file_operations nodemap_idmap_fops = {
939 .open = nodemap_idmap_open,
942 .release = single_release
945 const struct file_operations nodemap_exports_fops = {
946 .open = nodemap_exports_open,
949 .release = single_release
952 static struct lprocfs_seq_vars lprocfs_nodemap_vars[] = {
955 .fops = &nodemap_id_fops,
958 .name = "trusted_nodemap",
959 .fops = &nodemap_trusted_fops,
962 .name = "admin_nodemap",
963 .fops = &nodemap_admin_fops,
966 .name = "squash_uid",
967 .fops = &nodemap_squash_uid_fops,
970 .name = "squash_gid",
971 .fops = &nodemap_squash_gid_fops,
975 .fops = &nodemap_ranges_fops,
979 .fops = &nodemap_exports_fops,
983 .fops = &nodemap_idmap_fops,
990 static struct lprocfs_seq_vars lprocfs_default_nodemap_vars[] = {
993 .fops = &nodemap_id_fops,
996 .name = "trusted_nodemap",
997 .fops = &nodemap_trusted_fops,
1000 .name = "admin_nodemap",
1001 .fops = &nodemap_admin_fops,
1004 .name = "squash_uid",
1005 .fops = &nodemap_squash_uid_fops,
1008 .name = "squash_gid",
1009 .fops = &nodemap_squash_gid_fops,
1013 .fops = &nodemap_exports_fops,
1021 * Initialize the nodemap procfs directory.
1025 int nodemap_procfs_init(void)
1029 proc_lustre_nodemap_root = lprocfs_seq_register(LUSTRE_NODEMAP_NAME,
1031 lprocfs_nm_module_vars,
1034 if (IS_ERR(proc_lustre_nodemap_root)) {
1035 rc = PTR_ERR(proc_lustre_nodemap_root);
1036 CERROR("cannot create 'nodemap' directory: rc = %d\n",
1038 proc_lustre_nodemap_root = NULL;
1045 * Register the proc directory for a nodemap
1047 * \param name name of nodemap
1048 * \param is_default: 1 if default nodemap
1051 int lprocfs_nodemap_register(const char *name,
1053 struct lu_nodemap *nodemap)
1055 struct proc_dir_entry *nodemap_proc_entry;
1059 nodemap_proc_entry =
1060 lprocfs_seq_register(name,
1061 proc_lustre_nodemap_root,
1062 lprocfs_default_nodemap_vars,
1065 nodemap_proc_entry =
1066 lprocfs_seq_register(name,
1067 proc_lustre_nodemap_root,
1068 lprocfs_nodemap_vars,
1071 if (IS_ERR(nodemap_proc_entry)) {
1072 rc = PTR_ERR(nodemap_proc_entry);
1073 CERROR("cannot create 'nodemap/%s': rc = %d\n", name, rc);
1074 nodemap_proc_entry = NULL;
1077 nodemap->nm_proc_entry = nodemap_proc_entry;