summaryrefslogtreecommitdiffstats
path: root/utils/mountd/cache.c
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2007-03-19 11:41:21 +1100
committerNeil Brown <neilb@suse.de>2007-03-19 11:41:21 +1100
commit323d1c4d69b65ab36d951aca8473ceb02171ab08 (patch)
tree3de3df486887f235253646e927def626eee822f8 /utils/mountd/cache.c
parent97ccd3d1b61f20cd681a82089e83c58f97438f1a (diff)
downloadnfs-utils-323d1c4d69b65ab36d951aca8473ceb02171ab08.tar.gz
nfs-utils-323d1c4d69b65ab36d951aca8473ceb02171ab08.tar.xz
nfs-utils-323d1c4d69b65ab36d951aca8473ceb02171ab08.zip
Allow exporting of a subfilesystem when 'crossmnt' is set.
If we are asked to export a filesystem which is not explicitly exported, but an ancestor is exported as 'crossmnt', export the filesystems with the same options as the ancestor. This is the first step to making 'crossmnt' effectively export a tree of filesystems.
Diffstat (limited to 'utils/mountd/cache.c')
-rw-r--r--utils/mountd/cache.c54
1 files changed, 47 insertions, 7 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;
}