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
25 * Copyright (c) 2014, Intel Corporation.
27 * Author: Joshua Walgenbach <jjw@iu.edu>
30 #define NODEMAP_LPROC_ID_LEN 16
31 #define NODEMAP_LPROC_FLAG_LEN 2
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"
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
44 #define NODEMAP_PROC_DEBUG 1
47 * Reads and prints the idmap for the given nodemap.
49 * \param m seq file in proc fs
53 static int nodemap_idmap_show(struct seq_file *m, void *data)
55 struct lu_nodemap *nodemap = m->private;
56 struct lu_idmap *idmap;
61 read_lock(&nodemap->nm_idmap_lock);
62 for (node = rb_first(&nodemap->nm_client_to_fs_uidmap); node;
63 node = rb_next(node)) {
67 idmap = rb_entry(node, struct lu_idmap, id_client_to_fs);
69 seq_printf(m, " { idtype: uid, client_id: %u, "
70 "fs_id: %u }", idmap->id_client,
73 for (node = rb_first(&nodemap->nm_client_to_fs_gidmap);
74 node; node = rb_next(node)) {
77 idmap = rb_entry(node, struct lu_idmap, id_client_to_fs);
79 seq_printf(m, " { idtype: gid, client_id: %u, "
80 "fs_id: %u }", idmap->id_client,
83 read_unlock(&nodemap->nm_idmap_lock);
91 * Attaches nodemap_idmap_show to proc file.
93 * \param inode inode of seq file in proc fs
94 * \param file seq file
97 static int nodemap_idmap_open(struct inode *inode, struct file *file)
99 struct lu_nodemap *nodemap = PDE_DATA(inode);
101 return single_open(file, nodemap_idmap_show, nodemap);
105 * Reads and prints the NID ranges for the given nodemap.
107 * \param m seq file in proc fs
111 static int nodemap_ranges_show(struct seq_file *m, void *data)
113 struct lu_nodemap *nodemap = m->private;
114 struct lu_nid_range *range;
115 struct interval_node_extent ext;
118 seq_printf(m, "[\n");
119 read_lock(&nm_range_tree_lock);
120 list_for_each_entry(range, &nodemap->nm_ranges, rn_list) {
122 seq_printf(m, ",\n");
124 ext = range->rn_node.in_extent;
125 seq_printf(m, " { id: %u, start_nid: %s, "
127 range->rn_id, libcfs_nid2str(ext.start),
128 libcfs_nid2str(ext.end));
130 read_unlock(&nm_range_tree_lock);
132 seq_printf(m, "]\n");
138 * Connects nodemap_idmap_show to proc file.
140 * \param inode inode of seq file in proc fs
141 * \param file seq file
144 static int nodemap_ranges_open(struct inode *inode, struct file *file)
146 struct lu_nodemap *nodemap = PDE_DATA(inode);
148 return single_open(file, nodemap_ranges_show, nodemap);
152 * Hash callback, reads and prints the exports attached to this nodemap.
154 * \param hs nodemap member hash
156 * \param hnode current member in hash
157 * \param data seq_file to print to
160 static int nodemap_exports_show_cb(cfs_hash_t *hs, cfs_hash_bd_t *bd,
161 struct hlist_node *hnode, void *data)
163 struct seq_file *m = data;
164 struct obd_export *exp;
167 exp = hlist_entry(hnode, struct obd_export,
168 exp_target_data.ted_nodemap_member);
169 key = cfs_hash_key(hs, hnode);
170 seq_printf(m, " { nid: %s, uuid: %s },",
171 obd_export_nid2str(exp), exp->exp_client_uuid.uuid);
177 * Reads and prints the exports attached to the given nodemap via hash
180 * \param m seq file in proc fs
184 static int nodemap_exports_show(struct seq_file *m, void *data)
186 struct lu_nodemap *nodemap = m->private;
188 seq_printf(m, "[\n");
190 cfs_hash_for_each(nodemap->nm_member_hash, nodemap_exports_show_cb, m);
193 seq_printf(m, "]\n");
199 * Attaches nodemap_idmap_show to proc file.
201 * \param inode inode of seq file in proc fs
202 * \param file seq file
205 static int nodemap_exports_open(struct inode *inode, struct file *file)
207 struct lu_nodemap *nodemap = PDE_DATA(inode);
209 return single_open(file, nodemap_exports_show, nodemap);
213 * Reads and prints the active flag for the given nodemap.
215 * \param m seq file in proc fs
219 static int nodemap_active_seq_show(struct seq_file *m, void *data)
221 return seq_printf(m, "%u\n", (unsigned int)nodemap_active);
225 * Activate/deactivate nodemap.
227 * \param[in] file proc file
228 * \param[in] buffer string, "1" or "0" to activate/deactivate nodemap
229 * \param[in] count \a buffer length
230 * \param[in] off unused
231 * \retval \a count on success
232 * \retval negative number on error
235 nodemap_active_seq_write(struct file *file, const char __user *buffer,
236 size_t count, loff_t *off)
238 char active_string[NODEMAP_LPROC_FLAG_LEN + 1];
239 long unsigned int active;
245 if (count >= sizeof(active_string))
248 if (copy_from_user(active_string, buffer, count))
251 active_string[count] = '\0';
252 rc = kstrtoul(active_string, 10, &active);
256 nodemap_active = active;
260 LPROC_SEQ_FOPS(nodemap_active);
263 * Reads and prints the nodemap ID for the given nodemap.
265 * \param m seq file in proc fs
269 static int nodemap_id_seq_show(struct seq_file *m, void *data)
271 struct lu_nodemap *nodemap = m->private;
273 return seq_printf(m, "%u\n", nodemap->nm_id);
275 LPROC_SEQ_FOPS_RO(nodemap_id);
278 * Reads and prints the root squash UID for the given nodemap.
280 * \param m seq file in proc fs
284 static int nodemap_squash_uid_seq_show(struct seq_file *m, void *data)
286 struct lu_nodemap *nodemap = m->private;
288 return seq_printf(m, "%u\n", nodemap->nm_squash_uid);
292 * Reads and prints the root squash GID for the given nodemap.
294 * \param m seq file in proc fs
298 static int nodemap_squash_gid_seq_show(struct seq_file *m, void *data)
300 struct lu_nodemap *nodemap = m->private;
302 return seq_printf(m, "%u\n", nodemap->nm_squash_gid);
306 * Reads and prints the trusted flag for the given nodemap.
308 * \param m seq file in proc fs
312 static int nodemap_trusted_seq_show(struct seq_file *m, void *data)
314 struct lu_nodemap *nodemap = m->private;
316 return seq_printf(m, "%d\n", (int)nodemap->nmf_trust_client_ids);
320 * Reads and prints the admin flag for the given nodemap.
322 * \param m seq file in proc fs
326 static int nodemap_admin_seq_show(struct seq_file *m, void *data)
328 struct lu_nodemap *nodemap = m->private;
330 return seq_printf(m, "%d\n", (int)nodemap->nmf_allow_root_access);
333 #ifdef NODEMAP_PROC_DEBUG
335 * Helper functions to set nodemap flags.
337 * \param[in] buffer string, which is "1" or "0" to set/unset flag
338 * \param[in] count \a buffer length
339 * \param[out] flag_p where to store flag value
340 * \retval \a count on success
341 * \retval negative number on error
343 static int nodemap_proc_read_flag(const char __user *buffer,
344 unsigned long count, unsigned int *flag_p)
346 char scratch[NODEMAP_LPROC_FLAG_LEN + 1];
347 long unsigned int flag_buf;
353 if (count >= sizeof(scratch))
356 if (copy_from_user(scratch, buffer, count))
359 scratch[count] = '\0';
360 rc = kstrtoul(scratch, 10, &flag_buf);
370 * Set the squash UID.
372 * \param[in] file proc file
373 * \param[in] buffer string representing squash UID to set
374 * \param[in] count \a buffer length
375 * \param[in] off unused
376 * \retval \a count on success
377 * \retval negative number on error
380 nodemap_squash_uid_seq_write(struct file *file, const char __user *buffer,
381 size_t count, loff_t *off)
383 char squash[NODEMAP_LPROC_ID_LEN + 1];
384 struct seq_file *m = file->private_data;
385 struct lu_nodemap *nodemap = m->private;
386 long unsigned int squash_uid;
392 if (count >= sizeof(squash))
395 if (copy_from_user(squash, buffer, count))
398 squash[count] = '\0';
399 rc = kstrtoul(squash, 10, &squash_uid);
403 nodemap->nm_squash_uid = squash_uid;
409 * Set the squash GID.
411 * \param[in] file proc file
412 * \param[in] buffer string representing squash GID to set
413 * \param[in] count \a buffer length
414 * \param[in] off unused
415 * \retval \a count on success
416 * \retval negative number on error
419 nodemap_squash_gid_seq_write(struct file *file, const char __user *buffer,
420 size_t count, loff_t *off)
422 char squash[NODEMAP_LPROC_ID_LEN + 1];
423 struct seq_file *m = file->private_data;
424 struct lu_nodemap *nodemap = m->private;
425 long unsigned int squash_gid;
431 if (count >= sizeof(squash))
434 if (copy_from_user(squash, buffer, count))
437 squash[count] = '\0';
438 rc = kstrtoul(squash, 10, &squash_gid);
442 nodemap->nm_squash_gid = squash_gid;
448 * Set/unset the trusted flag.
450 * \param[in] file proc file
451 * \param[in] buffer string, "1" or "0"
452 * \param[in] count \a buffer length
453 * \param[in] off unused
454 * \retval \a count on success
455 * \retval negative number on error
458 nodemap_trusted_seq_write(struct file *file, const char __user *buffer,
459 size_t count, loff_t *off)
461 struct seq_file *m = file->private_data;
462 struct lu_nodemap *nodemap = m->private;
466 rc = nodemap_proc_read_flag(buffer, count, &flags);
468 nodemap->nmf_trust_client_ids = !!flags;
469 nm_member_revoke_locks(nodemap);
476 * Set/unset the admin flag.
478 * \param[in] file proc file
479 * \param[in] buffer string, "1" or "0"
480 * \param[in] count \a buffer length
481 * \param[in] off unused
482 * \retval \a count on success
483 * \retval negative number on error
486 nodemap_admin_seq_write(struct file *file, const char __user *buffer,
487 size_t count, loff_t *off)
489 struct seq_file *m = file->private_data;
490 struct lu_nodemap *nodemap = m->private;
494 rc = nodemap_proc_read_flag(buffer, count, &flags);
496 nodemap->nmf_allow_root_access = !!flags;
497 nm_member_revoke_locks(nodemap);
506 * \param[in] file proc file
507 * \param[in] buffer string, name of the nodemap to add
508 * \param[in] count \a buffer length
509 * \param[in] off unused
510 * \retval \a count on success
511 * \retval negative number on error
514 lprocfs_add_nodemap_seq_write(struct file *file, const char __user *buffer,
515 size_t count, loff_t *off)
517 char nodemap_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
525 if (count >= sizeof(nodemap_name))
528 if (copy_from_user(nodemap_name, buffer, count))
531 nodemap_name[count] = '\0';
533 cpybuf = nodemap_name;
534 pos = strsep(&cpybuf, " \n");
538 rc = nodemap_add(nodemap_name);
544 LPROC_SEQ_FOPS_WO_TYPE(nodemap, add_nodemap);
549 * \param[in] file proc file
550 * \param[in] buffer string, name of the nodemap to delete
551 * \param[in] count \a buffer length
552 * \param[in] off unused
553 * \retval \a count on success
554 * \retval negative number on error
557 lprocfs_del_nodemap_seq_write(struct file *file, const char __user *buffer,
558 size_t count, loff_t *off)
560 char nodemap_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
568 if (count >= sizeof(nodemap_name))
571 if (copy_from_user(nodemap_name, buffer, count))
574 nodemap_name[count] = '\0';
576 cpybuf = nodemap_name;
577 pos = strsep(&cpybuf, " \n");
581 rc = nodemap_del(nodemap_name);
588 LPROC_SEQ_FOPS_WO_TYPE(nodemap, del_nodemap);
591 * Helper function to parse a NID string.
593 * \param[in] rangestr string representation of NIDs, see libcfs_str2nid()
594 * \param[out] nids array of two nids
595 * \retval 0 on success
596 * \retval negative number on error
598 static int parse_nids(char *rangestr, lnet_nid_t nids[2])
600 struct list_head nidlist;
601 char nidstr[2][LNET_NIDSTR_SIZE];
602 char nidrange_str[2 * LNET_NIDSTR_SIZE + 2];
605 INIT_LIST_HEAD(&nidlist);
607 if (cfs_parse_nidlist(rangestr, strlen(rangestr),
611 if (!cfs_nidrange_is_contiguous(&nidlist))
614 cfs_nidrange_find_min_max(&nidlist, nidstr[0], nidstr[1],
616 snprintf(nidrange_str, sizeof(nidrange_str), "%s:%s",
617 nidstr[0], nidstr[1]);
619 rc = nodemap_parse_range(nidrange_str, nids);
623 cfs_free_nidlist(&nidlist);
629 * Add a NID range to nodemap.
631 * \param[in] file proc file
632 * \param[in] buffer string, "<nodemap name> <nid range>"
633 * \param[in] count \a buffer length
634 * \param[in] off unused
635 * \retval \a count on success
636 * \retval negative number on error
639 lprocfs_add_nodemap_range_seq_write(struct file *file,
640 const char __user *buffer,
641 size_t count, loff_t *off)
643 char name_range[LUSTRE_NODEMAP_NAME_LENGTH +
644 LNET_NIDSTR_SIZE * 2 + 2];
647 char *rangestr = NULL;
654 if (count >= sizeof(name_range))
655 GOTO(out, rc = -EINVAL);
657 if (copy_from_user(name_range, buffer, count))
658 GOTO(out, rc = -EFAULT);
660 name_range[count] = '\0';
663 name = strsep(&cpybuf, " ");
665 GOTO(out, rc = -EINVAL);
667 rangestr = strsep(&cpybuf, " \n");
668 if (rangestr == NULL)
669 GOTO(out, rc = -EINVAL);
671 rc = parse_nids(rangestr, nids);
675 rc = nodemap_add_range(name, nids);
677 GOTO(out, rc = -EINVAL);
685 LPROC_SEQ_FOPS_WO_TYPE(nodemap, add_nodemap_range);
688 * Delete a NID range from nodemap.
690 * \param[in] file proc file
691 * \param[in] buffer string, "<nodemap name> <nid range>"
692 * \param[in] count \a buffer length
693 * \param[in] off unused
694 * \retval \a count on success
695 * \retval negative number on error
698 lprocfs_del_nodemap_range_seq_write(struct file *file,
699 const char __user *buffer,
700 size_t count, loff_t *off)
702 char name_range[LUSTRE_NODEMAP_NAME_LENGTH +
703 LNET_NIDSTR_SIZE * 2 + 2];
706 char *rangestr = NULL;
713 if (count >= sizeof(name_range))
714 GOTO(out, rc = -EINVAL);
716 if (copy_from_user(name_range, buffer, count))
717 GOTO(out, rc = -EFAULT);
719 name_range[count] = '\0';
722 name = strsep(&cpybuf, " ");
724 GOTO(out, rc = -EINVAL);
726 rangestr = strsep(&cpybuf, " \n");
727 if (rangestr == NULL)
728 GOTO(out, rc = -EINVAL);
730 rc = parse_nids(rangestr, nids);
734 rc = nodemap_del_range(name, nids);
736 GOTO(out, rc = -EINVAL);
744 LPROC_SEQ_FOPS_WO_TYPE(nodemap, del_nodemap_range);
747 * Add an idmap to nodemap.
749 * \param[in] file proc file
750 * \param[in] buffer string, "<nodemap name> <uid|gid> <idmap>"
751 * \param[in] count \a buffer length
752 * \param[in] off unused
753 * \retval \a count on success
754 * \retval negative number on error
757 lprocfs_add_nodemap_idmap_seq_write(struct file *file,
758 const char __user *buffer,
759 size_t count, loff_t *off)
761 char name_idmapstr[LUSTRE_NODEMAP_NAME_LENGTH + 16];
764 char *idtypestr = NULL;
765 char *idmapstr = NULL;
772 if (count >= sizeof(name_idmapstr))
773 GOTO(out, rc = -EINVAL);
775 if (copy_from_user(name_idmapstr, buffer, count))
776 GOTO(out, rc = -EFAULT);
778 name_idmapstr[count] = '\0';
780 cpybuf = name_idmapstr;
781 name = strsep(&cpybuf, " ");
783 GOTO(out, rc = -EINVAL);
785 idtypestr = strsep(&cpybuf, " ");
786 if (idtypestr == NULL)
787 GOTO(out, rc = -EINVAL);
789 idmapstr = strsep(&cpybuf, " \n");
790 if (idmapstr == NULL)
791 GOTO(out, rc = -EINVAL);
793 rc = nodemap_parse_idmap(idmapstr, idmap);
795 GOTO(out, rc = -EINVAL);
797 if (strcmp(idtypestr, "uid") == 0)
798 rc = nodemap_add_idmap(name, NODEMAP_UID, idmap);
799 else if (strcmp(idtypestr, "gid") == 0)
800 rc = nodemap_add_idmap(name, NODEMAP_GID, idmap);
802 GOTO(out, rc = -EINVAL);
805 GOTO(out, rc = -EINVAL);
813 LPROC_SEQ_FOPS_WO_TYPE(nodemap, add_nodemap_idmap);
816 * Delete an idmap from nodemap.
818 * \param[in] file proc file
819 * \param[in] buffer string, "<nodemap name> <uid|gid> <idmap>"
820 * \param[in] count \a buffer length
821 * \param[in] off unused
822 * \retval \a count on success
823 * \retval negative number on error
826 lprocfs_del_nodemap_idmap_seq_write(struct file *file,
827 const char __user *buffer,
828 size_t count, loff_t *off)
830 char name_idmapstr[LUSTRE_NODEMAP_NAME_LENGTH + 16];
833 char *idtypestr = NULL;
834 char *idmapstr = NULL;
841 if (count >= sizeof(name_idmapstr))
842 GOTO(out, rc = -EINVAL);
844 if (copy_from_user(name_idmapstr, buffer, count))
845 GOTO(out, rc = -EFAULT);
847 name_idmapstr[count] = '\0';
849 cpybuf = name_idmapstr;
850 name = strsep(&cpybuf, " ");
852 GOTO(out, rc = -EINVAL);
854 idtypestr = strsep(&cpybuf, " ");
855 if (idtypestr == NULL)
856 GOTO(out, rc = -EINVAL);
858 idmapstr = strsep(&cpybuf, " \n");
859 if (idmapstr == NULL)
860 GOTO(out, rc = -EINVAL);
862 rc = nodemap_parse_idmap(idmapstr, idmap);
864 GOTO(out, rc = -EINVAL);
866 if (strcmp(idtypestr, "uid") == 0)
867 rc = nodemap_del_idmap(name, NODEMAP_UID, idmap);
868 else if (strcmp(idtypestr, "gid") == 0)
869 rc = nodemap_del_idmap(name, NODEMAP_GID, idmap);
871 GOTO(out, rc = -EINVAL);
874 GOTO(out, rc = -EINVAL);
882 LPROC_SEQ_FOPS_WO_TYPE(nodemap, del_nodemap_idmap);
883 #endif /* NODEMAP_PROC_DEBUG */
885 static struct lprocfs_vars lprocfs_nm_module_vars[] = {
888 .fops = &nodemap_active_fops,
890 #ifdef NODEMAP_PROC_DEBUG
892 .name = "add_nodemap",
893 .fops = &nodemap_add_nodemap_fops,
896 .name = "remove_nodemap",
897 .fops = &nodemap_del_nodemap_fops,
900 .name = "add_nodemap_range",
901 .fops = &nodemap_add_nodemap_range_fops,
904 .name = "del_nodemap_range",
905 .fops = &nodemap_del_nodemap_range_fops,
908 .name = "add_nodemap_idmap",
909 .fops = &nodemap_add_nodemap_idmap_fops,
912 .name = "del_nodemap_idmap",
913 .fops = &nodemap_del_nodemap_idmap_fops,
915 #endif /* NODEMAP_PROC_DEBUG */
921 #ifdef NODEMAP_PROC_DEBUG
922 LPROC_SEQ_FOPS(nodemap_trusted);
923 LPROC_SEQ_FOPS(nodemap_admin);
924 LPROC_SEQ_FOPS(nodemap_squash_uid);
925 LPROC_SEQ_FOPS(nodemap_squash_gid);
927 LPROC_SEQ_FOPS_RO(nodemap_trusted);
928 LPROC_SEQ_FOPS_RO(nodemap_admin);
929 LPROC_SEQ_FOPS_RO(nodemap_squash_uid);
930 LPROC_SEQ_FOPS_RO(nodemap_squash_gid);
933 const struct file_operations nodemap_ranges_fops = {
934 .open = nodemap_ranges_open,
937 .release = single_release
940 const struct file_operations nodemap_idmap_fops = {
941 .open = nodemap_idmap_open,
944 .release = single_release
947 const struct file_operations nodemap_exports_fops = {
948 .open = nodemap_exports_open,
951 .release = single_release
954 static struct lprocfs_vars lprocfs_nodemap_vars[] = {
957 .fops = &nodemap_id_fops,
960 .name = "trusted_nodemap",
961 .fops = &nodemap_trusted_fops,
964 .name = "admin_nodemap",
965 .fops = &nodemap_admin_fops,
968 .name = "squash_uid",
969 .fops = &nodemap_squash_uid_fops,
972 .name = "squash_gid",
973 .fops = &nodemap_squash_gid_fops,
977 .fops = &nodemap_ranges_fops,
981 .fops = &nodemap_exports_fops,
985 .fops = &nodemap_idmap_fops,
992 static struct lprocfs_vars lprocfs_default_nodemap_vars[] = {
995 .fops = &nodemap_id_fops,
998 .name = "trusted_nodemap",
999 .fops = &nodemap_trusted_fops,
1002 .name = "admin_nodemap",
1003 .fops = &nodemap_admin_fops,
1006 .name = "squash_uid",
1007 .fops = &nodemap_squash_uid_fops,
1010 .name = "squash_gid",
1011 .fops = &nodemap_squash_gid_fops,
1015 .fops = &nodemap_exports_fops,
1023 * Initialize the nodemap procfs directory.
1027 int nodemap_procfs_init(void)
1031 proc_lustre_nodemap_root = lprocfs_register(LUSTRE_NODEMAP_NAME,
1033 lprocfs_nm_module_vars,
1035 if (IS_ERR(proc_lustre_nodemap_root)) {
1036 rc = PTR_ERR(proc_lustre_nodemap_root);
1037 CERROR("cannot create 'nodemap' directory: rc = %d\n",
1039 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_register(name, proc_lustre_nodemap_root,
1061 lprocfs_default_nodemap_vars,
1064 nodemap_proc_entry =
1065 lprocfs_register(name, proc_lustre_nodemap_root,
1066 lprocfs_nodemap_vars,
1069 if (IS_ERR(nodemap_proc_entry)) {
1070 rc = PTR_ERR(nodemap_proc_entry);
1071 CERROR("cannot create 'nodemap/%s': rc = %d\n", name, rc);
1072 nodemap_proc_entry = NULL;
1075 nodemap->nm_proc_entry = nodemap_proc_entry;