/* AFS superblock handling * * Copyright (c) 2002, 2007, 2018 Red Hat, Inc. All rights reserved. * * This software may be freely redistributed under the terms of the * GNU General Public License. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Authors: David Howells <dhowells@redhat.com> * David Woodhouse <dwmw2@infradead.org> *
*/
if (atomic_read(&afs_count_active_inodes) != 0) {
printk("kAFS: %d active inode objects still present\n",
atomic_read(&afs_count_active_inodes));
BUG();
}
/* * Make sure all delayed rcu free inodes are flushed before we * destroy cache.
*/
rcu_barrier();
kmem_cache_destroy(afs_inode_cachep);
_leave("");
}
/* * Display the mount options in /proc/mounts.
*/ staticint afs_show_options(struct seq_file *m, struct dentry *root)
{ struct afs_super_info *as = AFS_FS_S(root->d_sb); constchar *p = NULL;
if (as->dyn_root)
seq_puts(m, ",dyn"); switch (as->flock_mode) { case afs_flock_mode_unset: break; case afs_flock_mode_local: p = "local"; break; case afs_flock_mode_openafs: p = "openafs"; break; case afs_flock_mode_strict: p = "strict"; break; case afs_flock_mode_write: p = "write"; break;
} if (p)
seq_printf(m, ",flock=%s", p);
return 0;
}
/* * Parse the source name to get cell name, volume name, volume type and R/W * selector. * * This can be one of the following: * "%[cell:]volume[.]" R/W volume * "#[cell:]volume[.]" R/O or R/W volume (R/O parent), * or R/W (R/W parent) volume * "%[cell:]volume.readonly" R/O volume * "#[cell:]volume.readonly" R/O volume * "%[cell:]volume.backup" Backup volume * "#[cell:]volume.backup" Backup volume
*/ staticint afs_parse_source(struct fs_context *fc, struct fs_parameter *param)
{ struct afs_fs_context *ctx = fc->fs_private; struct afs_cell *cell; constchar *cellname, *suffix, *name = param->string; int cellnamesz;
_enter(",%s", name);
if (fc->source) return invalf(fc, "kAFS: Multiple sources not supported");
if (!name) {
printk(KERN_ERR "kAFS: no volume name specified\n"); return -EINVAL;
}
if ((name[0] != '%' && name[0] != '#') || !name[1]) { /* To use dynroot, we don't want to have to provide a source */ if (strcmp(name, "none") == 0) {
ctx->no_cell = true; return 0;
}
printk(KERN_ERR "kAFS: unparsable volume name\n"); return -EINVAL;
}
/* determine the type of volume we're looking for */ if (name[0] == '%') {
ctx->type = AFSVL_RWVOL;
ctx->force = true;
}
name++;
/* split the cell name out if there is one */
ctx->volname = strchr(name, ':'); if (ctx->volname) {
cellname = name;
cellnamesz = ctx->volname - name;
ctx->volname++;
} else {
ctx->volname = name;
cellname = NULL;
cellnamesz = 0;
}
/* the volume type is further affected by a possible suffix */
suffix = strrchr(ctx->volname, '.'); if (suffix) { if (strcmp(suffix, ".readonly") == 0) {
ctx->type = AFSVL_ROVOL;
ctx->force = true;
} elseif (strcmp(suffix, ".backup") == 0) {
ctx->type = AFSVL_BACKVOL;
ctx->force = true;
} elseif (suffix[1] == 0) {
} else {
suffix = NULL;
}
}
/* * check a superblock to see if it's the one we're looking for
*/ staticint afs_test_super(struct super_block *sb, struct fs_context *fc)
{ struct afs_fs_context *ctx = fc->fs_private; struct afs_super_info *as = AFS_FS_S(sb);
/* Clear the callback interests (which will do ilookup5) before * deactivating the superblock.
*/ if (as->volume)
rcu_assign_pointer(as->volume->sb, NULL);
kill_anon_super(sb); if (as->volume)
afs_deactivate_volume(as->volume);
afs_destroy_sbi(as);
}
/* * Get an AFS superblock and root directory.
*/ staticint afs_get_tree(struct fs_context *fc)
{ struct afs_fs_context *ctx = fc->fs_private; struct super_block *sb; struct afs_super_info *as; int ret;
ret = afs_validate_fc(fc); if (ret) goto error;
_enter("");
/* allocate a superblock info record */
ret = -ENOMEM;
as = afs_alloc_sbi(fc); if (!as) goto error;
fc->s_fs_info = as;
/* allocate a deviceless superblock */
sb = sget_fc(fc,
as->dyn_root ? afs_dynroot_test_super : afs_test_super,
afs_set_super); if (IS_ERR(sb)) {
ret = PTR_ERR(sb); goto error;
}
if (!sb->s_root) { /* initial superblock/root creation */
_debug("create");
ret = afs_fill_super(sb, ctx); if (ret < 0) goto error_sb;
sb->s_flags |= SB_ACTIVE;
} else {
_debug("reuse");
ASSERTCMP(sb->s_flags, &, SB_ACTIVE);
}
/* * Initialise an inode cache slab element prior to any use. Note that * afs_alloc_inode() *must* reset anything that could incorrectly leak from one * inode to another.
*/ staticvoid afs_i_init_once(void *_vnode)
{ struct afs_vnode *vnode = _vnode;
vnode = alloc_inode_sb(sb, afs_inode_cachep, GFP_KERNEL); if (!vnode) return NULL;
atomic_inc(&afs_count_active_inodes);
/* Reset anything that shouldn't leak from one inode to the next. */
memset(&vnode->fid, 0, sizeof(vnode->fid));
memset(&vnode->status, 0, sizeof(vnode->status));
afs_vnode_set_cache(vnode, NULL);
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.28Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.