History

afs: Display manually added cells in dynamic root mount

Alter the dynroot mount so that cells created by manipulation of /proc/fs/afs/cells and /proc/fs/afs/rootcell and by specification of a root cell as a module parameter will cause directories for those cells to be created in the dynamic root superblock for the network namespace[*]. To this end: (1) Only one dynamic root superblock is now created per network namespace and this is shared between all attempts to mount it. This makes it easier to find the superblock to modify. (2) When a dynamic root superblock is created, the list of cells is walked and directories created for each cell already defined. (3) When a new cell is added, if a dynamic root superblock exists, a directory is created for it. (4) When a cell is destroyed, the directory is removed. (5) These directories are created by calling lookup_one_len() on the root dir which automatically creates them if they don't exist. [*] Inasmuch as network namespaces are currently supported here.

David Howells committed 8 years ago

Commit 0da0b7f1 parent c88d5a77 files · +200 −27Browse files

Unified · Split

7 files
  1. fs/afs/cell.c +8 −4
  2. fs/afs/dynroot.c +123 −1
  3. fs/afs/internal.h +6 −1
  4. fs/afs/main.c +1 −1
  5. fs/afs/super.c +32 −20
  6. fs/namei.c +29 −0
  7. include/linux/namei.h +1 −0
fs/afs/cell.c+8−4
@@ -15,6 +15,7 @@ · 14 unmodified lines
1515 #include <linux/dns_resolver.h>
1616 #include <linux/sched.h>
1717 #include <linux/inet.h>
18+#include <linux/namei.h>
1819 #include <keys/rxrpc-type.h>
1920 #include "internal.h"
2021
@@ -531,9 +532,11 @@ static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell) · 510 unmodified lines
531532 ret = afs_proc_cell_setup(cell);
532533 if (ret < 0)
533534 return ret;
534− spin_lock(&net->proc_cells_lock);
535+
536+ mutex_lock(&net->proc_cells_lock);
535537 list_add_tail(&cell->proc_link, &net->proc_cells);
536− spin_unlock(&net->proc_cells_lock);
538+ afs_dynroot_mkdir(net, cell);
539+ mutex_unlock(&net->proc_cells_lock);
537540 return 0;
538541 }
539542
@@ -546,9 +549,10 @@ static void afs_deactivate_cell(struct afs_net *net, struct afs_cell *cell) · 6 unmodified lines
546549
547550 afs_proc_cell_remove(cell);
548551
549− spin_lock(&net->proc_cells_lock);
552+ mutex_lock(&net->proc_cells_lock);
550553 list_del_init(&cell->proc_link);
551− spin_unlock(&net->proc_cells_lock);
554+ afs_dynroot_rmdir(net, cell);
555+ mutex_unlock(&net->proc_cells_lock);
552556
553557 #ifdef CONFIG_AFS_FSCACHE
554558 fscache_relinquish_cookie(cell->cache, NULL, false);
fs/afs/dynroot.c+123−1
@@ -1,4 +1,4 @@
1−/* dir.c: AFS dynamic root handling
1+/* AFS dynamic root handling
22 *
33 * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
44 * Written by David Howells (dhowells@redhat.com)
@@ -207,3 +207,125 @@ const struct dentry_operations afs_dynroot_dentry_operations = { · 202 unmodified lines
207207 .d_release = afs_d_release,
208208 .d_automount = afs_d_automount,
209209 };
210+
211+/*
212+ * Create a manually added cell mount directory.
213+ * - The caller must hold net->proc_cells_lock
214+ */
215+int afs_dynroot_mkdir(struct afs_net *net, struct afs_cell *cell)
216+{
217+ struct super_block *sb = net->dynroot_sb;
218+ struct dentry *root, *subdir;
219+ int ret;
220+
221+ if (!sb || atomic_read(&sb->s_active) == 0)
222+ return 0;
223+
224+ /* Let the ->lookup op do the creation */
225+ root = sb->s_root;
226+ inode_lock(root->d_inode);
227+ subdir = lookup_one_len(cell->name, root, cell->name_len);
228+ if (IS_ERR(subdir)) {
229+ ret = PTR_ERR(subdir);
230+ goto unlock;
231+ }
232+
233+ /* Note that we're retaining an extra ref on the dentry */
234+ subdir->d_fsdata = (void *)1UL;
235+ ret = 0;
236+unlock:
237+ inode_unlock(root->d_inode);
238+ return ret;
239+}
240+
241+/*
242+ * Remove a manually added cell mount directory.
243+ * - The caller must hold net->proc_cells_lock
244+ */
245+void afs_dynroot_rmdir(struct afs_net *net, struct afs_cell *cell)
246+{
247+ struct super_block *sb = net->dynroot_sb;
248+ struct dentry *root, *subdir;
249+
250+ if (!sb || atomic_read(&sb->s_active) == 0)
251+ return;
252+
253+ root = sb->s_root;
254+ inode_lock(root->d_inode);
255+
256+ /* Don't want to trigger a lookup call, which will re-add the cell */
257+ subdir = try_lookup_one_len(cell->name, root, cell->name_len);
258+ if (IS_ERR_OR_NULL(subdir)) {
259+ _debug("lookup %ld", PTR_ERR(subdir));
260+ goto no_dentry;
261+ }
262+
263+ _debug("rmdir %pd %u", subdir, d_count(subdir));
264+
265+ if (subdir->d_fsdata) {
266+ _debug("unpin %u", d_count(subdir));
267+ subdir->d_fsdata = NULL;
268+ dput(subdir);
269+ }
270+ dput(subdir);
271+no_dentry:
272+ inode_unlock(root->d_inode);
273+ _leave("");
274+}
275+
276+/*
277+ * Populate a newly created dynamic root with cell names.
278+ */
279+int afs_dynroot_populate(struct super_block *sb)
280+{
281+ struct afs_cell *cell;
282+ struct afs_net *net = afs_sb2net(sb);
283+ int ret;
284+
285+ if (mutex_lock_interruptible(&net->proc_cells_lock) < 0)
286+ return -ERESTARTSYS;
287+
288+ net->dynroot_sb = sb;
289+ list_for_each_entry(cell, &net->proc_cells, proc_link) {
290+ ret = afs_dynroot_mkdir(net, cell);
291+ if (ret < 0)
292+ goto error;
293+ }
294+
295+ ret = 0;
296+out:
297+ mutex_unlock(&net->proc_cells_lock);
298+ return ret;
299+
300+error:
301+ net->dynroot_sb = NULL;
302+ goto out;
303+}
304+
305+/*
306+ * When a dynamic root that's in the process of being destroyed, depopulate it
307+ * of pinned directories.
308+ */
309+void afs_dynroot_depopulate(struct super_block *sb)
310+{
311+ struct afs_net *net = afs_sb2net(sb);
312+ struct dentry *root = sb->s_root, *subdir, *tmp;
313+
314+ /* Prevent more subdirs from being created */
315+ mutex_lock(&net->proc_cells_lock);
316+ if (net->dynroot_sb == sb)
317+ net->dynroot_sb = NULL;
318+ mutex_unlock(&net->proc_cells_lock);
319+
320+ inode_lock(root->d_inode);
321+
322+ /* Remove all the pins for dirs created for manually added cells */
323+ list_for_each_entry_safe(subdir, tmp, &root->d_subdirs, d_child) {
324+ if (subdir->d_fsdata) {
325+ subdir->d_fsdata = NULL;
326+ dput(subdir);
327+ }
328+ }
329+
330+ inode_unlock(root->d_inode);
331+}
fs/afs/internal.h+6−1
@@ -240,7 +240,7 @@ struct afs_net { · 239 unmodified lines
240240 atomic_t cells_outstanding;
241241 seqlock_t cells_lock;
242242
243− spinlock_t proc_cells_lock;
243+ struct mutex proc_cells_lock;
244244 struct list_head proc_cells;
245245
246246 /* Known servers. Theoretically each fileserver can only be in one
@@ -264,6 +264,7 @@ struct afs_net { · 17 unmodified lines
264264 struct mutex lock_manager_mutex;
265265
266266 /* Misc */
267+ struct super_block *dynroot_sb; /* Dynamic root mount superblock */
267268 struct proc_dir_entry *proc_afs; /* /proc/net/afs directory */
268269 struct afs_sysnames *sysnames;
269270 rwlock_t sysnames_lock;
@@ -722,6 +723,10 @@ extern const struct inode_operations afs_dynroot_inode_operations; · 452 unmodified lines
722723 extern const struct dentry_operations afs_dynroot_dentry_operations;
723724
724725 extern struct inode *afs_try_auto_mntpt(struct dentry *, struct inode *);
726+extern int afs_dynroot_mkdir(struct afs_net *, struct afs_cell *);
727+extern void afs_dynroot_rmdir(struct afs_net *, struct afs_cell *);
728+extern int afs_dynroot_populate(struct super_block *);
729+extern void afs_dynroot_depopulate(struct super_block *);
725730
726731 /*
727732 * file.c
fs/afs/main.c+1−1
@@ -86,7 +86,7 @@ static int __net_init afs_net_init(struct net *net_ns) · 85 unmodified lines
8686 INIT_WORK(&net->cells_manager, afs_manage_cells);
8787 timer_setup(&net->cells_timer, afs_cells_timer, 0);
8888
89− spin_lock_init(&net->proc_cells_lock);
89+ mutex_init(&net->proc_cells_lock);
9090 INIT_LIST_HEAD(&net->proc_cells);
9191
9292 seqlock_init(&net->fs_lock);
fs/afs/super.c+32−20
@@ -355,12 +355,17 @@ static int afs_test_super(struct super_block *sb, void *data) · 354 unmodified lines
355355
356356 return (as->net_ns == as1->net_ns &&
357357 as->volume &&
358− as->volume->vid == as1->volume->vid);
358+ as->volume->vid == as1->volume->vid &&
359+ !as->dyn_root);
359360 }
360361
361362 static int afs_dynroot_test_super(struct super_block *sb, void *data)
362363 {
363− return false;
364+ struct afs_super_info *as1 = data;
365+ struct afs_super_info *as = AFS_FS_S(sb);
366+
367+ return (as->net_ns == as1->net_ns &&
368+ as->dyn_root);
364369 }
365370
366371 static int afs_set_super(struct super_block *sb, void *data)
@@ -420,10 +425,14 @@ static int afs_fill_super(struct super_block *sb, · 53 unmodified lines
420425 if (!sb->s_root)
421426 goto error;
422427
423− if (params->dyn_root)
428+ if (as->dyn_root) {
424429 sb->s_d_op = &afs_dynroot_dentry_operations;
425− else
430+ ret = afs_dynroot_populate(sb);
431+ if (ret < 0)
432+ goto error;
433+ } else {
426434 sb->s_d_op = &afs_fs_dentry_operations;
435+ }
427436
428437 _leave(" = 0");
429438 return 0;
@@ -458,6 +467,25 @@ static void afs_destroy_sbi(struct afs_super_info *as) · 28 unmodified lines
458467 }
459468 }
460469
470+static void afs_kill_super(struct super_block *sb)
471+{
472+ struct afs_super_info *as = AFS_FS_S(sb);
473+ struct afs_net *net = afs_net(as->net_ns);
474+
475+ if (as->dyn_root)
476+ afs_dynroot_depopulate(sb);
477+
478+ /* Clear the callback interests (which will do ilookup5) before
479+ * deactivating the superblock.
480+ */
481+ if (as->volume)
482+ afs_clear_callback_interests(net, as->volume->servers);
483+ kill_anon_super(sb);
484+ if (as->volume)
485+ afs_deactivate_volume(as->volume);
486+ afs_destroy_sbi(as);
487+}
488+
461489 /*
462490 * get an AFS superblock
463491 */
@@ -566,22 +594,6 @@ error: · 102 unmodified lines
566594 return ERR_PTR(ret);
567595 }
568596
569−static void afs_kill_super(struct super_block *sb)
570−{
571− struct afs_super_info *as = AFS_FS_S(sb);
572−
573− /* Clear the callback interests (which will do ilookup5) before
574− * deactivating the superblock.
575− */
576− if (as->volume)
577− afs_clear_callback_interests(afs_net(as->net_ns),
578− as->volume->servers);
579− kill_anon_super(sb);
580− if (as->volume)
581− afs_deactivate_volume(as->volume);
582− afs_destroy_sbi(as);
583−}
584−
585597 /*
586598 * Initialise an inode cache slab element prior to any use. Note that
587599 * afs_alloc_inode() *must* reset anything that could incorrectly leak from one
fs/namei.c+29−0
@@ -2463,6 +2463,35 @@ static int lookup_one_len_common(const char *name, struct dentry *base, · 2462 unmodified lines
24632463 return inode_permission(base->d_inode, MAY_EXEC);
24642464 }
24652465
2466+/**
2467+ * try_lookup_one_len - filesystem helper to lookup single pathname component
2468+ * @name: pathname component to lookup
2469+ * @base: base directory to lookup from
2470+ * @len: maximum length @len should be interpreted to
2471+ *
2472+ * Look up a dentry by name in the dcache, returning NULL if it does not
2473+ * currently exist. The function does not try to create a dentry.
2474+ *
2475+ * Note that this routine is purely a helper for filesystem usage and should
2476+ * not be called by generic code.
2477+ *
2478+ * The caller must hold base->i_mutex.
2479+ */
2480+struct dentry *try_lookup_one_len(const char *name, struct dentry *base, int len)
2481+{
2482+ struct qstr this;
2483+ int err;
2484+
2485+ WARN_ON_ONCE(!inode_is_locked(base->d_inode));
2486+
2487+ err = lookup_one_len_common(name, base, len, &this);
2488+ if (err)
2489+ return ERR_PTR(err);
2490+
2491+ return lookup_dcache(&this, base, 0);
2492+}
2493+EXPORT_SYMBOL(try_lookup_one_len);
2494+
24662495 /**
24672496 * lookup_one_len - filesystem helper to lookup single pathname component
24682497 * @name: pathname component to lookup
include/linux/namei.h+1−0
@@ -81,6 +81,7 @@ extern void done_path_create(struct path *, struct dentry *); · 80 unmodified lines
8181 extern struct dentry *kern_path_locked(const char *, struct path *);
8282 extern int kern_path_mountpoint(int, const char *, struct path *, unsigned int);
8383
84+extern struct dentry *try_lookup_one_len(const char *, struct dentry *, int);
8485 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
8586 extern struct dentry *lookup_one_len_unlocked(const char *, struct dentry *, int);
8687