예제 #1
0
파일: inode.c 프로젝트: cilynx/dd-wrt
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name)
{
	struct sysfs_addrm_cxt acxt;
	struct sysfs_dirent **pos, *sd;

	if (!dir_sd)
		return -ENOENT;

	sysfs_addrm_start(&acxt, dir_sd);

	for (pos = &dir_sd->s_children; *pos; pos = &(*pos)->s_sibling) {
		sd = *pos;

		if (!sysfs_type(sd))
			continue;
		if (!strcmp(sd->s_name, name)) {
			*pos = sd->s_sibling;
			sd->s_sibling = NULL;
			sysfs_remove_one(&acxt, sd);
			break;
		}
	}

	if (sysfs_addrm_finish(&acxt))
		return 0;
	return -ENOENT;
}
예제 #2
0
파일: dir.c 프로젝트: cilynx/dd-wrt
static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)
{
	struct sysfs_addrm_cxt acxt;
	struct sysfs_dirent **pos;

	if (!dir_sd)
		return;

	pr_debug("sysfs %s: removing dir\n", dir_sd->s_name);
	sysfs_addrm_start(&acxt, dir_sd);
	pos = &dir_sd->s_children;
	while (*pos) {
		struct sysfs_dirent *sd = *pos;

		if (sysfs_type(sd) && sysfs_type(sd) != SYSFS_DIR) {
			*pos = sd->s_sibling;
			sd->s_sibling = NULL;
			sysfs_remove_one(&acxt, sd);
		} else
			pos = &(*pos)->s_sibling;
	}
	sysfs_addrm_finish(&acxt);

	remove_dir(dir_sd);
}
예제 #3
0
파일: file.c 프로젝트: cilynx/dd-wrt
int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
		   int type)
{
	umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
	struct sysfs_addrm_cxt acxt;
	struct sysfs_dirent *sd;

	sd = sysfs_new_dirent(attr->name, mode, type);
	if (!sd)
		return -ENOMEM;
	sd->s_elem.attr.attr = (void *)attr;

	sysfs_addrm_start(&acxt, dir_sd);

	if (!sysfs_find_dirent(dir_sd, attr->name)) {
		sysfs_add_one(&acxt, sd);
		sysfs_link_sibling(sd);
	}

	if (!sysfs_addrm_finish(&acxt)) {
		sysfs_put(sd);
		return -EEXIST;
	}

	return 0;
}
예제 #4
0
/**
 * sysfs_hash_and_remove - find a sysfs_dirent by name and remove it
 * @dir_sd: parent of the target
 * @name: name of the sysfs_dirent to remove
 * @ns: namespace tag of the sysfs_dirent to remove
 *
 * Look for the sysfs_dirent with @name and @ns under @dir_sd and remove
 * it.  Returns 0 on success, -ENOENT if such entry doesn't exist.
 */
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name,
			  const void *ns)
{
	struct sysfs_addrm_cxt acxt;
	struct sysfs_dirent *sd;

	if (!dir_sd) {
		WARN(1, KERN_WARNING "sysfs: can not remove '%s', no directory\n",
			name);
		return -ENOENT;
	}

	sysfs_addrm_start(&acxt);

	sd = sysfs_find_dirent(dir_sd, name, ns);
	if (sd)
		__sysfs_remove(&acxt, sd);

	sysfs_addrm_finish(&acxt);

	if (sd)
		return 0;
	else
		return -ENOENT;
}
예제 #5
0
파일: dir.c 프로젝트: cilynx/dd-wrt
static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
		      const char *name, struct sysfs_dirent **p_sd)
{
	umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
	struct sysfs_addrm_cxt acxt;
	struct sysfs_dirent *sd;

	/* allocate */
	sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
	if (!sd)
		return -ENOMEM;
	sd->s_elem.dir.kobj = kobj;

	/* link in */
	sysfs_addrm_start(&acxt, parent_sd);

	if (!sysfs_find_dirent(parent_sd, name)) {
		sysfs_add_one(&acxt, sd);
		sysfs_link_sibling(sd);
	}

	if (!sysfs_addrm_finish(&acxt)) {
		sysfs_put(sd);
		return -EEXIST;
	}

	*p_sd = sd;
	return 0;
}
예제 #6
0
static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
		      enum kobj_ns_type type,
		      const char *name, const void *ns,
		      struct sysfs_dirent **p_sd)
{
	umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
	struct sysfs_addrm_cxt acxt;
	struct sysfs_dirent *sd;
	int rc;

	/* allocate */
	sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
	if (!sd)
		return -ENOMEM;

	sd->s_flags |= (type << SYSFS_NS_TYPE_SHIFT);
	sd->s_ns = ns;
	sd->s_dir.kobj = kobj;

	/* link in */
	sysfs_addrm_start(&acxt);
	rc = sysfs_add_one(&acxt, sd, parent_sd);
	sysfs_addrm_finish(&acxt);

	if (rc == 0)
		*p_sd = sd;
	else
		sysfs_put(sd);

	return rc;
}
예제 #7
0
/**
 * sysfs_remove - remove a sysfs_dirent recursively
 * @sd: the sysfs_dirent to remove
 *
 * Remove @sd along with all its subdirectories and files.
 */
void sysfs_remove(struct sysfs_dirent *sd)
{
	struct sysfs_addrm_cxt acxt;

	sysfs_addrm_start(&acxt);
	__sysfs_remove(&acxt, sd);
	sysfs_addrm_finish(&acxt);
}
예제 #8
0
static void remove_dir(struct sysfs_dirent *sd)
{
	struct sysfs_addrm_cxt acxt;

	sysfs_addrm_start(&acxt, sd->s_parent);
	sysfs_remove_one(&acxt, sd);
	sysfs_addrm_finish(&acxt);
}
예제 #9
0
static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
				const char *name, int warn)
{
	struct sysfs_dirent *parent_sd = NULL;
	struct sysfs_dirent *target_sd = NULL;
	struct sysfs_dirent *sd = NULL;
	struct sysfs_addrm_cxt acxt;
	int error;

	BUG_ON(!name);

	if (!kobj)
		parent_sd = &sysfs_root;
	else
		parent_sd = kobj->sd;

	error = -EFAULT;
	if (!parent_sd)
		goto out_put;

	/* target->sd can go away beneath us but is protected with
	 * sysfs_assoc_lock.  Fetch target_sd from it.
	 */
	spin_lock(&sysfs_assoc_lock);
	if (target->sd)
		target_sd = sysfs_get(target->sd);
	spin_unlock(&sysfs_assoc_lock);

	error = -ENOENT;
	if (!target_sd)
		goto out_put;

	error = -ENOMEM;
	sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK);
	if (!sd)
		goto out_put;

	sd->s_symlink.target_sd = target_sd;
	target_sd = NULL;	/* reference is now owned by the symlink */

	sysfs_addrm_start(&acxt, parent_sd);
	if (warn)
		error = sysfs_add_one(&acxt, sd);
	else
		error = __sysfs_add_one(&acxt, sd);
	sysfs_addrm_finish(&acxt);

	if (error)
		goto out_put;

	return 0;

 out_put:
	sysfs_put(target_sd);
	sysfs_put(sd);
	return error;
}
예제 #10
0
파일: dir.c 프로젝트: cilynx/dd-wrt
struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj)
{
	struct sysfs_dirent *parent_sd = kobj->sd->s_parent;
	struct dentry *dir, *parent, *shadow;
	struct inode *inode;
	struct sysfs_dirent *sd;
	struct sysfs_addrm_cxt acxt;

	dir = sysfs_get_dentry(kobj->sd);
	if (IS_ERR(dir)) {
		sd = (void *)dir;
		goto out;
	}
	parent = dir->d_parent;

	inode = dir->d_inode;
	sd = ERR_PTR(-EINVAL);
	if (!sysfs_is_shadowed_inode(inode))
		goto out_dput;

	shadow = d_alloc(parent, &dir->d_name);
	if (!shadow)
		goto nomem;

	sd = sysfs_new_dirent("_SHADOW_", inode->i_mode, SYSFS_DIR);
	if (!sd)
		goto nomem;
	sd->s_elem.dir.kobj = kobj;

	sysfs_addrm_start(&acxt, parent_sd);

	/* add but don't link into children list */
	sysfs_add_one(&acxt, sd);

	/* attach and instantiate dentry */
	sysfs_attach_dentry(sd, shadow);
	d_instantiate(shadow, igrab(inode));
	inc_nlink(inode);	/* tj: synchronization? */

	sysfs_addrm_finish(&acxt);

	dget(shadow);		/* Extra count - pin the dentry in core */

	goto out_dput;

 nomem:
	dput(shadow);
	sd = ERR_PTR(-ENOMEM);
 out_dput:
	dput(dir);
 out:
	return sd;
}
예제 #11
0
int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name)
{
	struct sysfs_addrm_cxt acxt;
	struct sysfs_dirent *sd;

	if (!dir_sd)
		return -ENOENT;

	sysfs_addrm_start(&acxt, dir_sd);

	sd = sysfs_find_dirent(dir_sd, name);
	if (sd)
		sysfs_remove_one(&acxt, sd);

	sysfs_addrm_finish(&acxt);

	if (sd)
		return 0;
	else
		return -ENOENT;
}
예제 #12
0
int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, int type)
{
	umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
	struct sysfs_addrm_cxt acxt;
	struct sysfs_dirent *sd;
	int rc;

	sd = sysfs_new_dirent(attr->name, mode, type);
	if (!sd)
		return -ENOMEM;
	sd->s_attr.attr = (void *)attr;

	sysfs_addrm_start(&acxt, dir_sd);
	rc = sysfs_add_one(&acxt, sd);
	sysfs_addrm_finish(&acxt);

	if (rc)
		sysfs_put(sd);

	return rc;
}