mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 11:37:47 +00:00
Merge branch 'driver-core-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
This commit is contained in:
commit
51f36d61e6
@ -27,9 +27,17 @@ static ssize_t name##_read(struct file *file, struct kobject *kobj, \
|
||||
loff_t off, size_t count) \
|
||||
{ \
|
||||
struct device *dev = kobj_to_dev(kobj); \
|
||||
cpumask_var_t mask; \
|
||||
ssize_t n; \
|
||||
\
|
||||
return cpumap_print_bitmask_to_buf(buf, topology_##mask(dev->id), \
|
||||
off, count); \
|
||||
if (!alloc_cpumask_var(&mask, GFP_KERNEL)) \
|
||||
return -ENOMEM; \
|
||||
\
|
||||
cpumask_copy(mask, topology_##mask(dev->id)); \
|
||||
n = cpumap_print_bitmask_to_buf(buf, mask, off, count); \
|
||||
free_cpumask_var(mask); \
|
||||
\
|
||||
return n; \
|
||||
} \
|
||||
\
|
||||
static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \
|
||||
@ -37,9 +45,17 @@ static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \
|
||||
loff_t off, size_t count) \
|
||||
{ \
|
||||
struct device *dev = kobj_to_dev(kobj); \
|
||||
cpumask_var_t mask; \
|
||||
ssize_t n; \
|
||||
\
|
||||
return cpumap_print_list_to_buf(buf, topology_##mask(dev->id), \
|
||||
off, count); \
|
||||
if (!alloc_cpumask_var(&mask, GFP_KERNEL)) \
|
||||
return -ENOMEM; \
|
||||
\
|
||||
cpumask_copy(mask, topology_##mask(dev->id)); \
|
||||
n = cpumap_print_list_to_buf(buf, mask, off, count); \
|
||||
free_cpumask_var(mask); \
|
||||
\
|
||||
return n; \
|
||||
}
|
||||
|
||||
define_id_show_func(physical_package_id, "%d");
|
||||
|
@ -64,22 +64,13 @@ const struct file_operations *debugfs_real_fops(const struct file *filp)
|
||||
}
|
||||
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)
|
||||
enum dbgfs_get_mode {
|
||||
DBGFS_GET_ALREADY,
|
||||
DBGFS_GET_REGULAR,
|
||||
DBGFS_GET_SHORT,
|
||||
};
|
||||
|
||||
static int __debugfs_file_get(struct dentry *dentry, enum dbgfs_get_mode mode)
|
||||
{
|
||||
struct debugfs_fsdata *fsd;
|
||||
void *d_fsd;
|
||||
@ -96,15 +87,17 @@ int debugfs_file_get(struct dentry *dentry)
|
||||
if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) {
|
||||
fsd = d_fsd;
|
||||
} else {
|
||||
if (WARN_ON(mode == DBGFS_GET_ALREADY))
|
||||
return -EINVAL;
|
||||
|
||||
fsd = kmalloc(sizeof(*fsd), GFP_KERNEL);
|
||||
if (!fsd)
|
||||
return -ENOMEM;
|
||||
|
||||
if ((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT) {
|
||||
if (mode == DBGFS_GET_SHORT) {
|
||||
fsd->real_fops = NULL;
|
||||
fsd->short_fops = (void *)((unsigned long)d_fsd &
|
||||
~(DEBUGFS_FSDATA_IS_REAL_FOPS_BIT |
|
||||
DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT));
|
||||
~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
|
||||
} else {
|
||||
fsd->real_fops = (void *)((unsigned long)d_fsd &
|
||||
~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
|
||||
@ -138,6 +131,26 @@ int debugfs_file_get(struct dentry *dentry)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
return __debugfs_file_get(dentry, DBGFS_GET_ALREADY);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(debugfs_file_get);
|
||||
|
||||
/**
|
||||
@ -267,7 +280,7 @@ static int open_proxy_open(struct inode *inode, struct file *filp)
|
||||
const struct file_operations *real_fops = NULL;
|
||||
int r;
|
||||
|
||||
r = debugfs_file_get(dentry);
|
||||
r = __debugfs_file_get(dentry, DBGFS_GET_REGULAR);
|
||||
if (r)
|
||||
return r == -EIO ? -ENOENT : r;
|
||||
|
||||
@ -424,7 +437,8 @@ static void __full_proxy_fops_init(struct file_operations *proxy_fops,
|
||||
proxy_fops->unlocked_ioctl = full_proxy_unlocked_ioctl;
|
||||
}
|
||||
|
||||
static int full_proxy_open(struct inode *inode, struct file *filp)
|
||||
static int full_proxy_open(struct inode *inode, struct file *filp,
|
||||
enum dbgfs_get_mode mode)
|
||||
{
|
||||
struct dentry *dentry = F_DENTRY(filp);
|
||||
const struct file_operations *real_fops;
|
||||
@ -432,7 +446,7 @@ static int full_proxy_open(struct inode *inode, struct file *filp)
|
||||
struct debugfs_fsdata *fsd;
|
||||
int r;
|
||||
|
||||
r = debugfs_file_get(dentry);
|
||||
r = __debugfs_file_get(dentry, mode);
|
||||
if (r)
|
||||
return r == -EIO ? -ENOENT : r;
|
||||
|
||||
@ -491,8 +505,22 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int full_proxy_open_regular(struct inode *inode, struct file *filp)
|
||||
{
|
||||
return full_proxy_open(inode, filp, DBGFS_GET_REGULAR);
|
||||
}
|
||||
|
||||
const struct file_operations debugfs_full_proxy_file_operations = {
|
||||
.open = full_proxy_open,
|
||||
.open = full_proxy_open_regular,
|
||||
};
|
||||
|
||||
static int full_proxy_open_short(struct inode *inode, struct file *filp)
|
||||
{
|
||||
return full_proxy_open(inode, filp, DBGFS_GET_SHORT);
|
||||
}
|
||||
|
||||
const struct file_operations debugfs_full_short_proxy_file_operations = {
|
||||
.open = full_proxy_open_short,
|
||||
};
|
||||
|
||||
ssize_t debugfs_attr_read(struct file *file, char __user *buf,
|
||||
|
@ -229,7 +229,7 @@ static void debugfs_release_dentry(struct dentry *dentry)
|
||||
return;
|
||||
|
||||
/* check it wasn't a dir (no fsdata) or automount (no real_fops) */
|
||||
if (fsd && fsd->real_fops) {
|
||||
if (fsd && (fsd->real_fops || fsd->short_fops)) {
|
||||
WARN_ON(!list_empty(&fsd->cancellations));
|
||||
mutex_destroy(&fsd->cancellations_mtx);
|
||||
}
|
||||
@ -455,8 +455,7 @@ struct dentry *debugfs_create_file_full(const char *name, umode_t mode,
|
||||
const struct file_operations *fops)
|
||||
{
|
||||
if (WARN_ON((unsigned long)fops &
|
||||
(DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT |
|
||||
DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)))
|
||||
DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return __debugfs_create_file(name, mode, parent, data,
|
||||
@ -471,15 +470,13 @@ struct dentry *debugfs_create_file_short(const char *name, umode_t mode,
|
||||
const struct debugfs_short_fops *fops)
|
||||
{
|
||||
if (WARN_ON((unsigned long)fops &
|
||||
(DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT |
|
||||
DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)))
|
||||
DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return __debugfs_create_file(name, mode, parent, data,
|
||||
fops ? &debugfs_full_proxy_file_operations :
|
||||
fops ? &debugfs_full_short_proxy_file_operations :
|
||||
&debugfs_noop_file_operations,
|
||||
(const void *)((unsigned long)fops |
|
||||
DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT));
|
||||
fops);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(debugfs_create_file_short);
|
||||
|
||||
|
@ -15,6 +15,7 @@ struct file_operations;
|
||||
extern const struct file_operations debugfs_noop_file_operations;
|
||||
extern const struct file_operations debugfs_open_proxy_file_operations;
|
||||
extern const struct file_operations debugfs_full_proxy_file_operations;
|
||||
extern const struct file_operations debugfs_full_short_proxy_file_operations;
|
||||
|
||||
struct debugfs_fsdata {
|
||||
const struct file_operations *real_fops;
|
||||
@ -40,11 +41,6 @@ struct debugfs_fsdata {
|
||||
* pointer gets its lowest bit set.
|
||||
*/
|
||||
#define DEBUGFS_FSDATA_IS_REAL_FOPS_BIT BIT(0)
|
||||
/*
|
||||
* A dentry's ->d_fsdata, when pointing to real fops, is with
|
||||
* short fops instead of full fops.
|
||||
*/
|
||||
#define DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT BIT(1)
|
||||
|
||||
/* Access BITS */
|
||||
#define DEBUGFS_ALLOW_API BIT(0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user