diff options
-rw-r--r-- | utils/mountd/cache.c | 54 | ||||
-rw-r--r-- | utils/mountd/mountd.c | 6 |
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; } |