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

📄 dir.c

📁 ocfs1.2.7 源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	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);}/* * 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 (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);}static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode){	int ret;	struct config_group *group;	struct config_item *item;	struct config_item *parent_item;	struct configfs_subsystem *subsys;	struct configfs_dirent *sd;	struct config_item_type *type;	struct module *owner;	char *name;	if (dentry->d_parent == configfs_sb->s_root)		return -EPERM;	sd = dentry->d_parent->d_fsdata;	if (!(sd->s_type & CONFIGFS_USET_DIR))		return -EPERM;	parent_item = configfs_get_config_item(dentry->d_parent);	type = parent_item->ci_type;	subsys = to_config_group(parent_item)->cg_subsys;	BUG_ON(!subsys);	if (!type || !type->ct_group_ops ||	    (!type->ct_group_ops->make_group &&	     !type->ct_group_ops->make_item)) {		config_item_put(parent_item);		return -EPERM;  /* What lack-of-mkdir returns */	}	name = kmalloc(dentry->d_name.len + 1, GFP_KERNEL);	if (!name) {		config_item_put(parent_item);		return -ENOMEM;	}	snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);	down(&subsys->su_sem);	group = NULL;	item = NULL;	if (type->ct_group_ops->make_group) {		group = type->ct_group_ops->make_group(to_config_group(parent_item), name);		if (group) {			link_group(to_config_group(parent_item), group);			item = &group->cg_item;		}	} else {		item = type->ct_group_ops->make_item(to_config_group(parent_item), name);		if (item)			link_obj(parent_item, item);	}	up(&subsys->su_sem);	kfree(name);	if (!item) {		config_item_put(parent_item);		return -ENOMEM;	}	ret = -EINVAL;	type = item->ci_type;	if (type) {		owner = type->ct_owner;		if (try_module_get(owner)) {			if (group) {				ret = configfs_attach_group(parent_item,							    item,							    dentry);			} else {				ret = configfs_attach_item(parent_item,							   item,							   dentry);			}			if (ret) {				down(&subsys->su_sem);				if (group)					unlink_group(group);				else					unlink_obj(item);				client_drop_item(parent_item, item);				up(&subsys->su_sem);				config_item_put(parent_item);				module_put(owner);			}		}	}	return ret;}static int configfs_rmdir(struct inode *dir, struct dentry *dentry){	struct config_item *parent_item;	struct config_item *item;	struct configfs_subsystem *subsys;	struct configfs_dirent *sd;	struct module *owner = NULL;	int ret;	if (dentry->d_parent == configfs_sb->s_root)		return -EPERM;	sd = dentry->d_fsdata;	if (sd->s_type & CONFIGFS_USET_DEFAULT)		return -EPERM;	parent_item = configfs_get_config_item(dentry->d_parent);	subsys = to_config_group(parent_item)->cg_subsys;	BUG_ON(!subsys);	if (!parent_item->ci_type) {		config_item_put(parent_item);		return -EINVAL;	}	ret = configfs_detach_prep(dentry);	if (ret) {		configfs_detach_rollback(dentry);		config_item_put(parent_item);		return ret;	}	item = configfs_get_config_item(dentry);	/* Drop reference from above, item already holds one. */	config_item_put(parent_item);	if (item->ci_type)		owner = item->ci_type->ct_owner;	if (sd->s_type & CONFIGFS_USET_DIR) {		configfs_detach_group(item);		down(&subsys->su_sem);		unlink_group(to_config_group(item));	} else {		configfs_detach_item(item);		down(&subsys->su_sem);		unlink_obj(item);	}	client_drop_item(parent_item, item);	up(&subsys->su_sem);	/* Drop our reference from above */	config_item_put(item);	module_put(owner);	return 0;}struct inode_operations configfs_dir_inode_operations = {	.mkdir		= configfs_mkdir,	.rmdir		= configfs_rmdir,	.symlink	= configfs_symlink,	.unlink		= configfs_unlink,	.lookup		= configfs_lookup,};#if 0int configfs_rename_dir(struct config_item * item, const char *new_name){	int error = 0;	struct dentry * new_dentry, * parent;	if (!strcmp(config_item_name(item), new_name))		return -EINVAL;	if (!item->parent)		return -EINVAL;	down_write(&configfs_rename_sem);	parent = item->parent->dentry;	mutex_lock(&parent->d_inode->i_mutex);	new_dentry = lookup_one_len(new_name, parent, strlen(new_name));	if (!IS_ERR(new_dentry)) {  		if (!new_dentry->d_inode) {			error = config_item_set_name(item, "%s", new_name);			if (!error) {				d_add(new_dentry, NULL);				d_move(item->dentry, new_dentry);			}			else				d_delete(new_dentry);		} else			error = -EEXIST;		dput(new_dentry);	}	mutex_unlock(&parent->d_inode->i_mutex);	up_write(&configfs_rename_sem);	return error;}#endifstatic int configfs_dir_open(struct inode *inode, struct file *file){	struct dentry * dentry = file->f_dentry;	struct configfs_dirent * parent_sd = dentry->d_fsdata;	mutex_lock(&dentry->d_inode->i_mutex);	file->private_data = configfs_new_dirent(parent_sd, NULL);	mutex_unlock(&dentry->d_inode->i_mutex);	return file->private_data ? 0 : -ENOMEM;}static int configfs_dir_close(struct inode *inode, struct file *file){	struct dentry * dentry = file->f_dentry;	struct configfs_dirent * cursor = file->private_data;	mutex_lock(&dentry->d_inode->i_mutex);	list_del_init(&cursor->s_sibling);	mutex_unlock(&dentry->d_inode->i_mutex);	release_configfs_dirent(cursor);	return 0;}/* Relationship between s_mode and the DT_xxx types */static inline unsigned char dt_type(struct configfs_dirent *sd){	return (sd->s_mode >> 12) & 15;}static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir){	struct dentry *dentry = filp->f_dentry;	struct configfs_dirent * parent_sd = dentry->d_fsdata;	struct configfs_dirent *cursor = filp->private_data;	struct list_head *p, *q = &cursor->s_sibling;	ino_t ino;	int i = filp->f_pos;	switch (i) {		case 0:			ino = dentry->d_inode->i_ino;			if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)				break;			filp->f_pos++;			i++;			/* fallthrough */		case 1:			ino = parent_ino(dentry);			if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)				break;			filp->f_pos++;			i++;			/* fallthrough */		default:			if (filp->f_pos == 2) {				list_del(q);				list_add(q, &parent_sd->s_children);			}			for (p=q->next; p!= &parent_sd->s_children; p=p->next) {				struct configfs_dirent *next;				const char * name;				int len;				next = list_entry(p, struct configfs_dirent,						   s_sibling);				if (!next->s_element)					continue;				name = configfs_get_name(next);				len = strlen(name);				if (next->s_dentry)					ino = next->s_dentry->d_inode->i_ino;				else					ino = iunique(configfs_sb, 2);				if (filldir(dirent, name, len, filp->f_pos, ino,						 dt_type(next)) < 0)					return 0;				list_del(q);				list_add(q, p);				p = q;				filp->f_pos++;			}	}	return 0;}static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin){	struct dentry * dentry = file->f_dentry;	mutex_lock(&dentry->d_inode->i_mutex);	switch (origin) {		case 1:			offset += file->f_pos;		case 0:			if (offset >= 0)				break;		default:			mutex_unlock(&file->f_dentry->d_inode->i_mutex);			return -EINVAL;	}	if (offset != file->f_pos) {		file->f_pos = offset;		if (file->f_pos >= 2) {			struct configfs_dirent *sd = dentry->d_fsdata;			struct configfs_dirent *cursor = file->private_data;			struct list_head *p;			loff_t n = file->f_pos - 2;			list_del(&cursor->s_sibling);			p = sd->s_children.next;			while (n && p != &sd->s_children) {				struct configfs_dirent *next;				next = list_entry(p, struct configfs_dirent,						   s_sibling);				if (next->s_element)					n--;				p = p->next;			}			list_add_tail(&cursor->s_sibling, p);		}	}	mutex_unlock(&dentry->d_inode->i_mutex);	return offset;}struct file_operations configfs_dir_operations = {	.open		= configfs_dir_open,	.release	= configfs_dir_close,	.llseek		= configfs_dir_lseek,	.read		= generic_read_dir,	.readdir	= configfs_readdir,};int configfs_register_subsystem(struct configfs_subsystem *subsys){	int err;	struct config_group *group = &subsys->su_group;	struct qstr name;	struct dentry *dentry;	struct configfs_dirent *sd;	err = configfs_pin_fs();	if (err)		return err;	if (!group->cg_item.ci_name)		group->cg_item.ci_name = group->cg_item.ci_namebuf;	sd = configfs_sb->s_root->d_fsdata;	link_group(to_config_group(sd->s_element), group);	mutex_lock(&configfs_sb->s_root->d_inode->i_mutex);	name.name = group->cg_item.ci_name;	name.len = strlen(name.name);	name.hash = full_name_hash(name.name, name.len);	err = -ENOMEM;	dentry = d_alloc(configfs_sb->s_root, &name);	if (!dentry)		goto out_release;	d_add(dentry, NULL);	err = configfs_attach_group(sd->s_element, &group->cg_item,				    dentry);	if (!err)		dentry = NULL;	else		d_delete(dentry);	mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex);	if (dentry) {	    dput(dentry);out_release:	    unlink_group(group);	    configfs_release_fs();	}	return err;}void configfs_unregister_subsystem(struct configfs_subsystem *subsys){	struct config_group *group = &subsys->su_group;	struct dentry *dentry = group->cg_item.ci_dentry;	if (dentry->d_parent != configfs_sb->s_root) {		printk(KERN_ERR "configfs: Tried to unregister non-subsystem!\n");		return;	}	mutex_lock(&configfs_sb->s_root->d_inode->i_mutex);	mutex_lock(&dentry->d_inode->i_mutex);	if (configfs_detach_prep(dentry)) {		printk(KERN_ERR "configfs: Tried to unregister non-empty subsystem!\n");	}	configfs_detach_group(&group->cg_item);	dentry->d_inode->i_flags |= S_DEAD;	mutex_unlock(&dentry->d_inode->i_mutex);	d_delete(dentry);	mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex);	dput(dentry);	unlink_group(group);	configfs_release_fs();}EXPORT_SYMBOL(configfs_register_subsystem);EXPORT_SYMBOL(configfs_unregister_subsystem);

⌨️ 快捷键说明

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