Exemplo n.º 1
0
/**
 * kernfs_create_root - create a new kernfs hierarchy
 * @scops: optional syscall operations for the hierarchy
 * @flags: KERNFS_ROOT_* flags
 * @priv: opaque data associated with the new directory
 *
 * Returns the root of the new hierarchy on success, ERR_PTR() value on
 * failure.
 */
struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
				       unsigned int flags, void *priv)
{
	struct kernfs_root *root;
	struct kernfs_node *kn;

	root = kzalloc(sizeof(*root), GFP_KERNEL);
	if (!root)
		return ERR_PTR(-ENOMEM);

	ida_init(&root->ino_ida);
	INIT_LIST_HEAD(&root->supers);

	kn = __kernfs_new_node(root, "", S_IFDIR | S_IRUGO | S_IXUGO,
			       KERNFS_DIR);
	if (!kn) {
		ida_destroy(&root->ino_ida);
		kfree(root);
		return ERR_PTR(-ENOMEM);
	}

	kn->priv = priv;
	kn->dir.root = root;

	root->syscall_ops = scops;
	root->flags = flags;
	root->kn = kn;
	init_waitqueue_head(&root->deactivate_waitq);

	if (!(root->flags & KERNFS_ROOT_CREATE_DEACTIVATED))
		kernfs_activate(kn);

	return root;
}
Exemplo n.º 2
0
Arquivo: dir.c Projeto: AK101111/linux
/**
 *	kernfs_add_one - add kernfs_node to parent without warning
 *	@kn: kernfs_node to be added
 *
 *	The caller must already have initialized @kn->parent.  This
 *	function increments nlink of the parent's inode if @kn is a
 *	directory and link into the children list of the parent.
 *
 *	RETURNS:
 *	0 on success, -EEXIST if entry with the given name already
 *	exists.
 */
int kernfs_add_one(struct kernfs_node *kn)
{
	struct kernfs_node *parent = kn->parent;
	struct kernfs_iattrs *ps_iattr;
	bool has_ns;
	int ret;

	mutex_lock(&kernfs_mutex);

	ret = -EINVAL;
	has_ns = kernfs_ns_enabled(parent);
	if (WARN(has_ns != (bool)kn->ns, KERN_WARNING "kernfs: ns %s in '%s' for '%s'\n",
		 has_ns ? "required" : "invalid", parent->name, kn->name))
		goto out_unlock;

	if (kernfs_type(parent) != KERNFS_DIR)
		goto out_unlock;

	ret = -ENOENT;
	if (parent->flags & KERNFS_EMPTY_DIR)
		goto out_unlock;

	if ((parent->flags & KERNFS_ACTIVATED) && !kernfs_active(parent))
		goto out_unlock;

	kn->hash = kernfs_name_hash(kn->name, kn->ns);

	ret = kernfs_link_sibling(kn);
	if (ret)
		goto out_unlock;

	/* Update timestamps on the parent */
	ps_iattr = parent->iattr;
	if (ps_iattr) {
		struct iattr *ps_iattrs = &ps_iattr->ia_iattr;
		ktime_get_real_ts(&ps_iattrs->ia_ctime);
		ps_iattrs->ia_mtime = ps_iattrs->ia_ctime;
	}

	mutex_unlock(&kernfs_mutex);

	/*
	 * Activate the new node unless CREATE_DEACTIVATED is requested.
	 * If not activated here, the kernfs user is responsible for
	 * activating the node with kernfs_activate().  A node which hasn't
	 * been activated is not visible to userland and its removal won't
	 * trigger deactivation.
	 */
	if (!(kernfs_root(kn)->flags & KERNFS_ROOT_CREATE_DEACTIVATED))
		kernfs_activate(kn);
	return 0;

out_unlock:
	mutex_unlock(&kernfs_mutex);
	return ret;
}
Exemplo n.º 3
0
static int dslab_mkdir(struct kernfs_node *parent_kn, 
						const char *name, umode_t mode)
{
	struct kernfs_node *kn;
	int ret = 0;

	kn = kernfs_create_dir(parent_kn, name, mode, NULL);
	if (IS_ERR(kn)) {
		ret = PTR_ERR(kn);
		return ret;
	}

	kernfs_activate(kn);
	
	return ret;
}
Exemplo n.º 4
0
static struct dentry *dslab_mount(struct file_system_type *fs_type, 
				int flags, const char *unused_dev_name, 
				void *data)
{
	struct dentry *dentry = NULL;
	struct kernfs_root *kf_root;
	struct kernfs_node *kn;
	bool new_sb;

	kf_root = kernfs_create_root(&dslab_kf_syscall_ops,
							KERNFS_ROOT_CREATE_DEACTIVATED,
							NULL);	

	if (IS_ERR(kf_root))
		goto out;

	kn = __kernfs_create_file(kf_root->kn, "dslab", FS_MODE,
							0, &dslab_kernfs_ops, NULL, NULL,
							NULL);

	if (IS_ERR(kn))
		goto destroy_root;

	dentry = kernfs_mount(fs_type, flags, kf_root,
						FS_MAGIC, &new_sb);

	if (IS_ERR(dentry) || !new_sb)
		goto destroy_kn;

	kernfs_activate(kf_root->kn);	

	goto out;

destroy_kn:
	kernfs_remove_by_name(kf_root->kn, "dslab");

destroy_root:
	kernfs_destroy_root(kf_root);
	kf_root = NULL;

out:
	return dentry;
}