Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 12bf3142 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "IB/hfi1: convert to debugfs_file_get() and -put()"

parents 3f6817ec a19fc3cd
Loading
Loading
Loading
Loading
+10 −10
Original line number Diff line number Diff line
@@ -71,13 +71,13 @@ static ssize_t hfi1_seq_read(
	loff_t *ppos)
{
	struct dentry *d = file->f_path.dentry;
	int srcu_idx;
	ssize_t r;

	r = debugfs_use_file_start(d, &srcu_idx);
	if (likely(!r))
	r = debugfs_file_get(d);
	if (unlikely(r))
		return r;
	r = seq_read(file, buf, size, ppos);
	debugfs_use_file_finish(srcu_idx);
	debugfs_file_put(d);
	return r;
}

@@ -87,13 +87,13 @@ static loff_t hfi1_seq_lseek(
	int whence)
{
	struct dentry *d = file->f_path.dentry;
	int srcu_idx;
	loff_t r;

	r = debugfs_use_file_start(d, &srcu_idx);
	if (likely(!r))
	r = debugfs_file_get(d);
	if (unlikely(r))
		return r;
	r = seq_lseek(file, offset, whence);
	debugfs_use_file_finish(srcu_idx);
	debugfs_file_put(d);
	return r;
}

+99 −61
Original line number Diff line number Diff line
@@ -98,28 +98,69 @@ EXPORT_SYMBOL_GPL(debugfs_use_file_finish);
#define F_DENTRY(filp) ((filp)->f_path.dentry)

const struct file_operations *debugfs_real_fops(const struct file *filp)
	__must_hold(&debugfs_srcu)
{
	struct debugfs_fsdata *fsd = F_DENTRY(filp)->d_fsdata;
	/*
	 * Neither the pointer to the struct file_operations, nor its
	 * contents ever change -- srcu_dereference() is not needed here.
	 */

	return fsd->real_fops;
}
EXPORT_SYMBOL_GPL(debugfs_real_fops);

/**
 * debugfs_file_get - mark the beginning of file data access
 * @dentry: the dentry object whose data is being accessed.
 *
 * Up to a matching call to debugfs_file_put(), any successive call
 * into the file removing functions debugfs_remove() and
 * debugfs_remove_recursive() will block. Since associated private
 * file data may only get freed after a successful return of any of
 * the removal functions, you may safely access it after a successful
 * call to debugfs_file_get() without worrying about lifetime issues.
 *
 * If -%EIO is returned, the file has already been removed and thus,
 * it is not safe to access any of its data. If, on the other hand,
 * it is allowed to access the file data, zero is returned.
 */
int debugfs_file_get(struct dentry *dentry)
{
	struct debugfs_fsdata *fsd = dentry->d_fsdata;

	/* Avoid starvation of removers. */
	if (d_unlinked(dentry))
		return -EIO;

	if (!refcount_inc_not_zero(&fsd->active_users))
		return -EIO;

	return 0;
}
EXPORT_SYMBOL_GPL(debugfs_file_get);

/**
 * debugfs_file_put - mark the end of file data access
 * @dentry: the dentry object formerly passed to
 *          debugfs_file_get().
 *
 * Allow any ongoing concurrent call into debugfs_remove() or
 * debugfs_remove_recursive() blocked by a former call to
 * debugfs_file_get() to proceed and return to its caller.
 */
void debugfs_file_put(struct dentry *dentry)
{
	struct debugfs_fsdata *fsd = dentry->d_fsdata;

	if (refcount_dec_and_test(&fsd->active_users))
		complete(&fsd->active_users_drained);
}
EXPORT_SYMBOL_GPL(debugfs_file_put);

static int open_proxy_open(struct inode *inode, struct file *filp)
{
	const struct dentry *dentry = F_DENTRY(filp);
	struct dentry *dentry = F_DENTRY(filp);
	const struct file_operations *real_fops = NULL;
	int srcu_idx, r;
	int r = 0;

	r = debugfs_use_file_start(dentry, &srcu_idx);
	if (r) {
		r = -ENOENT;
		goto out;
	}
	if (debugfs_file_get(dentry))
		return -ENOENT;

	real_fops = debugfs_real_fops(filp);
	real_fops = fops_get(real_fops);
@@ -136,7 +177,7 @@ static int open_proxy_open(struct inode *inode, struct file *filp)
		r = real_fops->open(inode, filp);

out:
	debugfs_use_file_finish(srcu_idx);
	debugfs_file_put(dentry);
	return r;
}

@@ -150,16 +191,16 @@ const struct file_operations debugfs_open_proxy_file_operations = {
#define FULL_PROXY_FUNC(name, ret_type, filp, proto, args)		\
static ret_type full_proxy_ ## name(proto)				\
{									\
	const struct dentry *dentry = F_DENTRY(filp);			\
	struct dentry *dentry = F_DENTRY(filp);			\
	const struct file_operations *real_fops =			\
		debugfs_real_fops(filp);				\
	int srcu_idx;							\
	ret_type r;							\
									\
	r = debugfs_use_file_start(dentry, &srcu_idx);			\
	if (likely(!r))						\
	r = debugfs_file_get(dentry);					\
	if (unlikely(r))						\
		return r;						\
	r = real_fops->name(args);					\
	debugfs_use_file_finish(srcu_idx);				\
	debugfs_file_put(dentry);					\
	return r;							\
}

@@ -184,18 +225,15 @@ FULL_PROXY_FUNC(unlocked_ioctl, long, filp,
static unsigned int full_proxy_poll(struct file *filp,
				struct poll_table_struct *wait)
{
	const struct dentry *dentry = F_DENTRY(filp);
	const struct file_operations *real_fops = debugfs_real_fops(filp);
	int srcu_idx;
	struct dentry *dentry = F_DENTRY(filp);
	unsigned int r = 0;

	if (debugfs_use_file_start(dentry, &srcu_idx)) {
		debugfs_use_file_finish(srcu_idx);
	if (debugfs_file_get(dentry))
		return POLLHUP;
	}

	r = real_fops->poll(filp, wait);
	debugfs_use_file_finish(srcu_idx);
	debugfs_file_put(dentry);
	return r;
}

@@ -239,16 +277,13 @@ static void __full_proxy_fops_init(struct file_operations *proxy_fops,

static int full_proxy_open(struct inode *inode, struct file *filp)
{
	const struct dentry *dentry = F_DENTRY(filp);
	struct dentry *dentry = F_DENTRY(filp);
	const struct file_operations *real_fops = NULL;
	struct file_operations *proxy_fops = NULL;
	int srcu_idx, r;
	int r = 0;

	r = debugfs_use_file_start(dentry, &srcu_idx);
	if (r) {
		r = -ENOENT;
		goto out;
	}
	if (debugfs_file_get(dentry))
		return -ENOENT;

	real_fops = debugfs_real_fops(filp);
	real_fops = fops_get(real_fops);
@@ -286,7 +321,7 @@ static int full_proxy_open(struct inode *inode, struct file *filp)
	kfree(proxy_fops);
	fops_put(real_fops);
out:
	debugfs_use_file_finish(srcu_idx);
	debugfs_file_put(dentry);
	return r;
}

@@ -297,13 +332,14 @@ const struct file_operations debugfs_full_proxy_file_operations = {
ssize_t debugfs_attr_read(struct file *file, char __user *buf,
			size_t len, loff_t *ppos)
{
	struct dentry *dentry = F_DENTRY(file);
	ssize_t ret;
	int srcu_idx;

	ret = debugfs_use_file_start(F_DENTRY(file), &srcu_idx);
	if (likely(!ret))
	ret = debugfs_file_get(dentry);
	if (unlikely(ret))
		return ret;
	ret = simple_attr_read(file, buf, len, ppos);
	debugfs_use_file_finish(srcu_idx);
	debugfs_file_put(dentry);
	return ret;
}
EXPORT_SYMBOL_GPL(debugfs_attr_read);
@@ -311,13 +347,14 @@ EXPORT_SYMBOL_GPL(debugfs_attr_read);
ssize_t debugfs_attr_write(struct file *file, const char __user *buf,
			 size_t len, loff_t *ppos)
{
	struct dentry *dentry = F_DENTRY(file);
	ssize_t ret;
	int srcu_idx;

	ret = debugfs_use_file_start(F_DENTRY(file), &srcu_idx);
	if (likely(!ret))
	ret = debugfs_file_get(dentry);
	if (unlikely(ret))
		return ret;
	ret = simple_attr_write(file, buf, len, ppos);
	debugfs_use_file_finish(srcu_idx);
	debugfs_file_put(dentry);
	return ret;
}
EXPORT_SYMBOL_GPL(debugfs_attr_write);
@@ -751,14 +788,14 @@ ssize_t debugfs_read_file_bool(struct file *file, char __user *user_buf,
{
	char buf[3];
	bool val;
	int r, srcu_idx;
	int r;
	struct dentry *dentry = F_DENTRY(file);

	r = debugfs_use_file_start(F_DENTRY(file), &srcu_idx);
	if (likely(!r))
		val = *(bool *)file->private_data;
	debugfs_use_file_finish(srcu_idx);
	if (r)
	r = debugfs_file_get(dentry);
	if (unlikely(r))
		return r;
	val = *(bool *)file->private_data;
	debugfs_file_put(dentry);

	if (val)
		buf[0] = 'Y';
@@ -776,8 +813,9 @@ ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf,
	char buf[32];
	size_t buf_size;
	bool bv;
	int r, srcu_idx;
	int r;
	bool *val = file->private_data;
	struct dentry *dentry = F_DENTRY(file);

	buf_size = min(count, (sizeof(buf)-1));
	if (copy_from_user(buf, user_buf, buf_size))
@@ -785,12 +823,11 @@ ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf,

	buf[buf_size] = '\0';
	if (strtobool(buf, &bv) == 0) {
		r = debugfs_use_file_start(F_DENTRY(file), &srcu_idx);
		if (likely(!r))
			*val = bv;
		debugfs_use_file_finish(srcu_idx);
		if (r)
		r = debugfs_file_get(dentry);
		if (unlikely(r))
			return r;
		*val = bv;
		debugfs_file_put(dentry);
	}

	return count;
@@ -852,14 +889,15 @@ static ssize_t read_file_blob(struct file *file, char __user *user_buf,
			      size_t count, loff_t *ppos)
{
	struct debugfs_blob_wrapper *blob = file->private_data;
	struct dentry *dentry = F_DENTRY(file);
	ssize_t r;
	int srcu_idx;

	r = debugfs_use_file_start(F_DENTRY(file), &srcu_idx);
	if (likely(!r))
	r = debugfs_file_get(dentry);
	if (unlikely(r))
		return r;
	r = simple_read_from_buffer(user_buf, count, ppos, blob->data,
				blob->size);
	debugfs_use_file_finish(srcu_idx);
	debugfs_file_put(dentry);
	return r;
}

+23 −6
Original line number Diff line number Diff line
@@ -374,6 +374,7 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,

	inode->i_fop = proxy_fops;
	fsd->real_fops = real_fops;
	refcount_set(&fsd->active_users, 1);
	dentry->d_fsdata = fsd;

	d_instantiate(dentry, inode);
@@ -631,18 +632,34 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
}
EXPORT_SYMBOL_GPL(debugfs_create_symlink);

static void __debugfs_remove_file(struct dentry *dentry, struct dentry *parent)
{
	struct debugfs_fsdata *fsd;

	simple_unlink(d_inode(parent), dentry);
	d_delete(dentry);
	fsd = dentry->d_fsdata;
	init_completion(&fsd->active_users_drained);
	if (!refcount_dec_and_test(&fsd->active_users))
		wait_for_completion(&fsd->active_users_drained);
}

static int __debugfs_remove(struct dentry *dentry, struct dentry *parent)
{
	int ret = 0;

	if (simple_positive(dentry)) {
		dget(dentry);
		if (!d_is_reg(dentry)) {
			if (d_is_dir(dentry))
				ret = simple_rmdir(d_inode(parent), dentry);
			else
				simple_unlink(d_inode(parent), dentry);
			if (!ret)
				d_delete(dentry);
		} else {
			__debugfs_remove_file(dentry, parent);
		}
		dput(dentry);
	}
	return ret;
+2 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ extern const struct file_operations debugfs_full_proxy_file_operations;

struct debugfs_fsdata {
	const struct file_operations *real_fops;
	refcount_t active_users;
	struct completion active_users_drained;
};

#endif /* _DEBUGFS_INTERNAL_H_ */
+12 −2
Original line number Diff line number Diff line
@@ -95,8 +95,10 @@ int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx)

void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu);

const struct file_operations *debugfs_real_fops(const struct file *filp)
	__must_hold(&debugfs_srcu);
const struct file_operations *debugfs_real_fops(const struct file *filp);

int debugfs_file_get(struct dentry *dentry);
void debugfs_file_put(struct dentry *dentry);

ssize_t debugfs_attr_read(struct file *file, char __user *buf,
			size_t len, loff_t *ppos);
@@ -236,6 +238,14 @@ static inline void debugfs_use_file_finish(int srcu_idx)
	__releases(&debugfs_srcu)
{ }

static inline int debugfs_file_get(struct dentry *dentry)
{
	return 0;
}

static inline void debugfs_file_put(struct dentry *dentry)
{ }

static inline ssize_t debugfs_attr_read(struct file *file, char __user *buf,
					size_t len, loff_t *ppos)
{