summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--utils/mountd/cache.c54
-rw-r--r--utils/mountd/mountd.c6
2 files changed, 50 insertions, 10 deletions
diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
index 5612a9e..734ddd8 100644
--- a/utils/mountd/cache.c
+++ b/utils/mountd/cache.c
@@ -52,7 +52,7 @@ enum nfsd_fsid {
* Record is terminated with newline.
*
*/
-int cache_export_ent(char *domain, struct exportent *exp);
+int cache_export_ent(char *domain, struct exportent *exp, char *p);
char *lbuf = NULL;
@@ -408,7 +408,7 @@ void nfsd_fh(FILE *f)
}
if (found)
- cache_export_ent(dom, found);
+ cache_export_ent(dom, found, found->e_path);
qword_print(f, dom);
qword_printint(f, fsidtype);
@@ -466,7 +466,7 @@ static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *ex
write_fsloc(f, exp, path);
if (exp->e_uuid == NULL) {
char u[16];
- if (get_uuid(exp->e_path, NULL, 16, u)) {
+ if (get_uuid(path, NULL, 16, u)) {
qword_print(f, "uuid");
qword_printhex(f, u, 16);
}
@@ -598,7 +598,7 @@ int cache_process_req(fd_set *readfds)
* % echo $domain $path $[now+30*60] $options $anonuid $anongid $fsid > /proc/net/rpc/nfsd.export/channel
*/
-int cache_export_ent(char *domain, struct exportent *exp)
+int cache_export_ent(char *domain, struct exportent *exp, char *path)
{
int err;
FILE *f = fopen("/proc/net/rpc/nfsd.export/channel", "w");
@@ -606,12 +606,52 @@ int cache_export_ent(char *domain, struct exportent *exp)
return -1;
err = dump_to_cache(f, domain, exp->e_path, exp);
- fclose(f);
mountlist_add(domain, exp->e_path);
+
+ while ((exp->e_flags & NFSEXP_CROSSMOUNT) && path) {
+ /* really an 'if', but we can break out of
+ * a 'while' more easily */
+ /* Look along 'path' for other filesystems
+ * and export them with the same options
+ */
+ struct stat stb;
+ int l = strlen(exp->e_path);
+ int dev;
+
+ if (strlen(path) <= l || path[l] != '/' ||
+ strncmp(exp->e_path, path, l) != 0)
+ break;
+ if (stat(exp->e_path, &stb) != 0)
+ break;
+ dev = stb.st_dev;
+ while(path[l] == '/') {
+ char c;
+ int err;
+
+ l++;
+ while (path[l] != '/' && path[l])
+ l++;
+ c = path[l];
+ path[l] = 0;
+ err = lstat(path, &stb);
+ path[l] = c;
+ if (err < 0)
+ break;
+ if (stb.st_dev == dev)
+ continue;
+ dev = stb.st_dev;
+ path[l] = 0;
+ dump_to_cache(f, domain, path, exp);
+ path[l] = c;
+ }
+ break;
+ }
+
+ fclose(f);
return err;
}
-int cache_export(nfs_export *exp)
+int cache_export(nfs_export *exp, char *path)
{
int err;
FILE *f;
@@ -628,7 +668,7 @@ int cache_export(nfs_export *exp)
fclose(f);
- err = cache_export_ent(exp->m_client->m_hostname, &exp->m_export)
+ err = cache_export_ent(exp->m_client->m_hostname, &exp->m_export, path)
|| err;
return err;
}
diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c
index fc9a73c..04141d1 100644
--- a/utils/mountd/mountd.c
+++ b/utils/mountd/mountd.c
@@ -29,7 +29,7 @@
extern void cache_open(void);
extern struct nfs_fh_len *cache_get_filehandle(nfs_export *exp, int len, char *p);
-extern int cache_export(nfs_export *exp);
+extern int cache_export(nfs_export *exp, char *path);
extern void my_svc_run(void);
@@ -399,7 +399,7 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, mountstat3 *error, int v3)
p, strerror(errno));
*error = NFSERR_NOENT;
} else if (estb.st_dev != stb.st_dev
- /* && (!new_cache || !(exp->m_export.e_flags & NFSEXP_CROSSMOUNT)) */
+ && (!new_cache || !(exp->m_export.e_flags & NFSEXP_CROSSMOUNT))
) {
xlog(L_WARNING, "request to export directory %s below nearest filesystem %s",
p, exp->m_export.e_path);
@@ -418,7 +418,7 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, mountstat3 *error, int v3)
*/
struct nfs_fh_len *fh;
- if (cache_export(exp)) {
+ if (cache_export(exp, p)) {
*error = NFSERR_ACCES;
return NULL;
}