⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dir.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 * This fakes mkdir(2) on a default_groups[] entry.  It * creates a dentry, attachs it, and then does fixup * on the sd->s_type. * * We could, perhaps, tweak our parent's ->mkdir for a minute and * try using vfs_mkdir.  Just a thought. */static int create_default_group(struct config_group *parent_group,				struct config_group *group){	int ret;	struct qstr name;	struct configfs_dirent *sd;	/* We trust the caller holds a reference to parent */	struct dentry *child, *parent = parent_group->cg_item.ci_dentry;	if (!group->cg_item.ci_name)		group->cg_item.ci_name = group->cg_item.ci_namebuf;	name.name = group->cg_item.ci_name;	name.len = strlen(name.name);	name.hash = full_name_hash(name.name, name.len);	ret = -ENOMEM;	child = d_alloc(parent, &name);	if (child) {		d_add(child, NULL);		ret = configfs_attach_group(&parent_group->cg_item,					    &group->cg_item, child);		if (!ret) {			sd = child->d_fsdata;			sd->s_type |= CONFIGFS_USET_DEFAULT;		} else {			d_delete(child);			dput(child);		}	}	return ret;}static int populate_groups(struct config_group *group){	struct config_group *new_group;	struct dentry *dentry = group->cg_item.ci_dentry;	int ret = 0;	int i;	if (group->default_groups) {		/*		 * FYI, we're faking mkdir here		 * I'm not sure we need this semaphore, as we're called		 * from our parent's mkdir.  That holds our parent's		 * i_mutex, so afaik lookup cannot continue through our		 * parent to find us, let alone mess with our tree.		 * That said, taking our i_mutex is closer to mkdir		 * emulation, and shouldn't hurt.		 */		mutex_lock(&dentry->d_inode->i_mutex);		for (i = 0; group->default_groups[i]; i++) {			new_group = group->default_groups[i];			ret = create_default_group(group, new_group);			if (ret)				break;		}		mutex_unlock(&dentry->d_inode->i_mutex);	}	if (ret)		detach_groups(group);	return ret;}/* * All of link_obj/unlink_obj/link_group/unlink_group require that * subsys->su_mutex is held. */static void unlink_obj(struct config_item *item){	struct config_group *group;	group = item->ci_group;	if (group) {		list_del_init(&item->ci_entry);		item->ci_group = NULL;		item->ci_parent = NULL;		/* Drop the reference for ci_entry */		config_item_put(item);		/* Drop the reference for ci_parent */		config_group_put(group);	}}static void link_obj(struct config_item *parent_item, struct config_item *item){	/*	 * Parent seems redundant with group, but it makes certain	 * traversals much nicer.	 */	item->ci_parent = parent_item;	/*	 * We hold a reference on the parent for the child's ci_parent	 * link.	 */	item->ci_group = config_group_get(to_config_group(parent_item));	list_add_tail(&item->ci_entry, &item->ci_group->cg_children);	/*	 * We hold a reference on the child for ci_entry on the parent's	 * cg_children	 */	config_item_get(item);}static void unlink_group(struct config_group *group){	int i;	struct config_group *new_group;	if (group->default_groups) {		for (i = 0; group->default_groups[i]; i++) {			new_group = group->default_groups[i];			unlink_group(new_group);		}	}	group->cg_subsys = NULL;	unlink_obj(&group->cg_item);}static void link_group(struct config_group *parent_group, struct config_group *group){	int i;	struct config_group *new_group;	struct configfs_subsystem *subsys = NULL; /* gcc is a turd */	link_obj(&parent_group->cg_item, &group->cg_item);	if (parent_group->cg_subsys)		subsys = parent_group->cg_subsys;	else if (configfs_is_root(&parent_group->cg_item))		subsys = to_configfs_subsystem(group);	else		BUG();	group->cg_subsys = subsys;	if (group->default_groups) {		for (i = 0; group->default_groups[i]; i++) {			new_group = group->default_groups[i];			link_group(group, new_group);		}	}}/* * The goal is that configfs_attach_item() (and * configfs_attach_group()) can be called from either the VFS or this * module.  That is, they assume that the items have been created, * the dentry allocated, and the dcache is all ready to go. * * If they fail, they must clean up after themselves as if they * had never been called.  The caller (VFS or local function) will * handle cleaning up the dcache bits. * * configfs_detach_group() and configfs_detach_item() behave similarly on * the way out.  They assume that the proper semaphores are held, they * clean up the configfs items, and they expect their callers will * handle the dcache bits. */static int configfs_attach_item(struct config_item *parent_item,				struct config_item *item,				struct dentry *dentry){	int ret;	ret = configfs_create_dir(item, dentry);	if (!ret) {		ret = populate_attrs(item);		if (ret) {			configfs_remove_dir(item);			d_delete(dentry);		}	}	return ret;}static void configfs_detach_item(struct config_item *item){	detach_attrs(item);	configfs_remove_dir(item);}static int configfs_attach_group(struct config_item *parent_item,				 struct config_item *item,				 struct dentry *dentry){	int ret;	struct configfs_dirent *sd;	ret = configfs_attach_item(parent_item, item, dentry);	if (!ret) {		sd = dentry->d_fsdata;		sd->s_type |= CONFIGFS_USET_DIR;		ret = populate_groups(to_config_group(item));		if (ret) {			configfs_detach_item(item);			d_delete(dentry);		}	}	return ret;}static void configfs_detach_group(struct config_item *item){	detach_groups(to_config_group(item));	configfs_detach_item(item);}/* * After the item has been detached from the filesystem view, we are * ready to tear it out of the hierarchy.  Notify the client before * we do that so they can perform any cleanup that requires * navigating the hierarchy.  A client does not need to provide this * callback.  The subsystem semaphore MUST be held by the caller, and * references must be valid for both items.  It also assumes the * caller has validated ci_type. */static void client_disconnect_notify(struct config_item *parent_item,				     struct config_item *item){	struct config_item_type *type;	type = parent_item->ci_type;	BUG_ON(!type);	if (type->ct_group_ops && type->ct_group_ops->disconnect_notify)		type->ct_group_ops->disconnect_notify(to_config_group(parent_item),						      item);}/* * Drop the initial reference from make_item()/make_group() * This function assumes that reference is held on item * and that item holds a valid reference to the parent.  Also, it * assumes the caller has validated ci_type. */static void client_drop_item(struct config_item *parent_item,			     struct config_item *item){	struct config_item_type *type;	type = parent_item->ci_type;	BUG_ON(!type);	/*	 * If ->drop_item() exists, it is responsible for the	 * config_item_put().	 */	if (type->ct_group_ops && type->ct_group_ops->drop_item)		type->ct_group_ops->drop_item(to_config_group(parent_item),					      item);	else		config_item_put(item);}#ifdef DEBUGstatic void configfs_dump_one(struct configfs_dirent *sd, int level){	printk(KERN_INFO "%*s\"%s\":\n", level, " ", configfs_get_name(sd));#define type_print(_type) if (sd->s_type & _type) printk(KERN_INFO "%*s %s\n", level, " ", #_type);	type_print(CONFIGFS_ROOT);	type_print(CONFIGFS_DIR);	type_print(CONFIGFS_ITEM_ATTR);	type_print(CONFIGFS_ITEM_LINK);	type_print(CONFIGFS_USET_DIR);	type_print(CONFIGFS_USET_DEFAULT);	type_print(CONFIGFS_USET_DROPPING);#undef type_print}static int configfs_dump(struct configfs_dirent *sd, int level){	struct configfs_dirent *child_sd;	int ret = 0;	configfs_dump_one(sd, level);	if (!(sd->s_type & (CONFIGFS_DIR|CONFIGFS_ROOT)))		return 0;	list_for_each_entry(child_sd, &sd->s_children, s_sibling) {		ret = configfs_dump(child_sd, level + 2);		if (ret)			break;	}	return ret;}#endif/* * configfs_depend_item() and configfs_undepend_item() * * WARNING: Do not call these from a configfs callback! * * This describes these functions and their helpers. * * Allow another kernel system to depend on a config_item.  If this * happens, the item cannot go away until the dependant can live without * it.  The idea is to give client modules as simple an interface as * possible.  When a system asks them to depend on an item, they just * call configfs_depend_item().  If the item is live and the client * driver is in good shape, we'll happily do the work for them. * * Why is the locking complex?  Because configfs uses the VFS to handle * all locking, but this function is called outside the normal * VFS->configfs path.  So it must take VFS locks to prevent the * VFS->configfs stuff (configfs_mkdir(), configfs_rmdir(), etc).  This is * why you can't call these functions underneath configfs callbacks. * * Note, btw, that this can be called at *any* time, even when a configfs * subsystem isn't registered, or when configfs is loading or unloading. * Just like configfs_register_subsystem().  So we take the same * precautions.  We pin the filesystem.  We lock each i_mutex _in_order_ * on our way down the tree.  If we can find the target item in the * configfs tree, it must be part of the subsystem tree as well, so we * do not need the subsystem semaphore.  Holding the i_mutex chain locks * out mkdir() and rmdir(), who might be racing us. *//* * configfs_depend_prep() * * Only subdirectories count here.  Files (CONFIGFS_NOT_PINNED) are * attributes.  This is similar but not the same to configfs_detach_prep(). * Note that configfs_detach_prep() expects the parent to be locked when it * is called, but we lock the parent *inside* configfs_depend_prep().  We * do that so we can unlock it if we find nothing. * * Here we do a depth-first search of the dentry hierarchy looking for * our object.  We take i_mutex on each step of the way down.  IT IS * ESSENTIAL THAT i_mutex LOCKING IS ORDERED.  If we come back up a branch, * we'll drop the i_mutex. * * If the target is not found, -ENOENT is bubbled up and we have released * all locks.  If the target was found, the locks will be cleared by * configfs_depend_rollback(). * * This adds a requirement that all config_items be unique! * * This is recursive because the locking traversal is tricky.  There isn't * much on the stack, though, so folks that need this function - be careful * about your stack!  Patches will be accepted to make it iterative. */static int configfs_depend_prep(struct dentry *origin,				struct config_item *target){	struct configfs_dirent *child_sd, *sd = origin->d_fsdata;	int ret = 0;	BUG_ON(!origin || !sd);	/* Lock this guy on the way down */	mutex_lock(&sd->s_dentry->d_inode->i_mutex);	if (sd->s_element == target)  /* Boo-yah */		goto out;	list_for_each_entry(child_sd, &sd->s_children, s_sibling) {		if (child_sd->s_type & CONFIGFS_DIR) {			ret = configfs_depend_prep(child_sd->s_dentry,						   target);			if (!ret)				goto out;  /* Child path boo-yah */		}	}	/* We looped all our children and didn't find target */	mutex_unlock(&sd->s_dentry->d_inode->i_mutex);	ret = -ENOENT;out:	return ret;}/* * This is ONLY called if configfs_depend_prep() did its job.  So we can * trust the entire path from item back up to origin. * * We walk backwards from item, unlocking each i_mutex.  We finish by * unlocking origin. */static void configfs_depend_rollback(struct dentry *origin,				     struct config_item *item){	struct dentry *dentry = item->ci_dentry;	while (dentry != origin) {		mutex_unlock(&dentry->d_inode->i_mutex);		dentry = dentry->d_parent;	}	mutex_unlock(&origin->d_inode->i_mutex);}int configfs_depend_item(struct configfs_subsystem *subsys,			 struct config_item *target){	int ret;	struct configfs_dirent *p, *root_sd, *subsys_sd = NULL;	struct config_item *s_item = &subsys->su_group.cg_item;	/*	 * Pin the configfs filesystem.  This means we can safely access	 * the root of the configfs filesystem.	 */	ret = configfs_pin_fs();	if (ret)		return ret;	/*	 * Next, lock the root directory.  We're going to check that the	 * subsystem is really registered, and so we need to lock out	 * configfs_[un]register_subsystem().	 */	mutex_lock(&configfs_sb->s_root->d_inode->i_mutex);	root_sd = configfs_sb->s_root->d_fsdata;	list_for_each_entry(p, &root_sd->s_children, s_sibling) {		if (p->s_type & CONFIGFS_DIR) {			if (p->s_element == s_item) {				subsys_sd = p;				break;			}		}	}	if (!subsys_sd) {		ret = -ENOENT;		goto out_unlock_fs;	}	/* Ok, now we can trust subsys/s_item */	/* Scan the tree, locking i_mutex recursively, return 0 if found */	ret = configfs_depend_prep(subsys_sd->s_dentry, target);	if (ret)		goto out_unlock_fs;	/* We hold all i_mutexes from the subsystem down to the target */	p = target->ci_dentry->d_fsdata;	p->s_dependent_count += 1;	configfs_depend_rollback(subsys_sd->s_dentry, target);out_unlock_fs:	mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex);	/*	 * If we succeeded, the fs is pinned via other methods.  If not,	 * we're done with it anyway.  So release_fs() is always right.	 */	configfs_release_fs();	return ret;}EXPORT_SYMBOL(configfs_depend_item);/* * Release the dependent linkage.  This is much simpler than * configfs_depend_item() because we know that that the client driver is * pinned, thus the subsystem is pinned, and therefore configfs is pinned. */void configfs_undepend_item(struct configfs_subsystem *subsys,			    struct config_item *target){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -