2 * Copyright (C) 2009 Red Hat <nfs@redhat.com>
4 * support/export/v4root.c
6 * Routines used to support NFSv4 pseudo roots
14 #include <sys/types.h>
16 #include <sys/queue.h>
32 static nfs_export pseudo_root = {
38 .e_flags = NFSEXP_READONLY | NFSEXP_ROOTSQUASH
39 | NFSEXP_NOSUBTREECHECK | NFSEXP_FSID
58 void set_pseudofs_security(struct exportent *pseudo, struct exportent *source)
63 if (source->e_flags & NFSEXP_INSECURE_PORT)
64 pseudo->e_flags |= NFSEXP_INSECURE_PORT;
65 if ((source->e_flags & NFSEXP_ROOTSQUASH) == 0)
66 pseudo->e_flags &= ~NFSEXP_ROOTSQUASH;
67 for (se = source->e_secinfo; se->flav; se++) {
68 struct sec_entry *new;
70 i = secinfo_addflavor(se->flav, pseudo);
71 new = &pseudo->e_secinfo[i];
73 if (se->flags & NFSEXP_INSECURE_PORT)
74 new->flags |= NFSEXP_INSECURE_PORT;
79 * Create a pseudo export
81 static struct exportent *
82 v4root_create(char *path, nfs_export *export)
86 struct exportent *curexp = &export->m_export;
88 dupexportent(&eep, &pseudo_root.m_export);
89 eep.e_hostname = curexp->e_hostname;
90 strncpy(eep.e_path, path, sizeof(eep.e_path));
91 if (strcmp(path, "/") != 0)
92 eep.e_flags &= ~NFSEXP_FSID;
93 set_pseudofs_security(&eep, curexp);
94 exp = export_create(&eep, 0);
97 xlog(D_CALL, "v4root_create: path '%s' flags 0x%x",
98 exp->m_export.e_path, exp->m_export.e_flags);
99 return &exp->m_export;
103 * Make sure the kernel has pseudo root support.
108 struct export_features *ef;
109 static int warned = 0;
111 ef = get_export_features();
113 if (ef->flags & NFSEXP_V4ROOT)
116 xlog(L_WARNING, "Kernel does not have pseudo root support.");
117 xlog(L_WARNING, "NFS v4 mounts will be disabled unless fsid=0");
118 xlog(L_WARNING, "is specfied in /etc/exports file.");
124 int pseudofs_update(char *hostname, char *path, nfs_export *source)
128 exp = export_lookup(hostname, path, 0);
129 if (exp && !(exp->m_export.e_flags & NFSEXP_V4ROOT))
132 if (v4root_create(path, source) == NULL) {
133 xlog(L_WARNING, "v4root_set: Unable to create "
134 "pseudo export for '%s'", path);
139 /* Update an existing V4ROOT export: */
140 set_pseudofs_security(&exp->m_export, &source->m_export);
144 static int v4root_add_parents(nfs_export *exp)
146 char *hostname = exp->m_export.e_hostname;
150 path = strdup(exp->m_export.e_path);
152 xlog(L_WARNING, "v4root_add_parents: Unable to create "
153 "pseudo export for '%s'", exp->m_export.e_path);
156 for (ptr = path; ptr; ptr = strchr(ptr, '/')) {
162 ret = pseudofs_update(hostname, *path ? path : "/", exp);
173 * Create pseudo exports by running through the real export
174 * looking at the components of the path that make up the export.
175 * Those path components, if not exported, will become pseudo
176 * exports allowing them to be found when the kernel does an upcall
177 * looking for components of the v4 mount.
187 if (!v4root_support())
190 for (i = 0; i < MCL_MAXTYPES; i++) {
191 for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
192 if (exp->m_export.e_flags & NFSEXP_V4ROOT)
194 * We just added this one, so its
195 * parents are already dealt with!
199 if (strcmp(exp->m_export.e_path, "/") == 0 &&
200 !(exp->m_export.e_flags & NFSEXP_FSID)) {
201 /* Force '/' to be exported as fsid == 0*/
202 exp->m_export.e_flags |= NFSEXP_FSID;
203 exp->m_export.e_fsid = 0;
206 v4root_add_parents(exp);
207 /* XXX: error handling! */