Skip to content

Commit

Permalink
Merge tag 'driver-core-3.16-rc1' of git://git.kernel.org/pub/scm/linu…
Browse files Browse the repository at this point in the history
…x/kernel/git/gregkh/driver-core into next

Pull driver core / kernfs changes from Greg KH:
 "Here is the "big" pull request for 3.16-rc1.

  Not a lot of changes here, some kernfs work, a revert of a very old
  driver core change that ended up cauing some memory leaks on driver
  probe error paths, and other minor things.

  As was pointed out earlier today, one commit here, 26fc9cd
  ("kernfs: move the last knowledge of sysfs out from kernfs") is also
  needed in your 3.15-final branch as well.  If you could cherry-pick it
  there, it would be most appreciated by Andy Lutomirski to prevent a
  regression there.

  All of these have been in linux-next for a while"

* tag 'driver-core-3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core:
  crypto/nx/nx-842: dev_set_drvdata can no longer fail
  kernfs: move the last knowledge of sysfs out from kernfs
  sysfs: fix attribute_group bin file path on removal
  sysfs.h: don't return a void-valued expression in sysfs_remove_file
  init.h: Update initcall_sync variants to fix build errors
  driver core: Inline dev_set/get_drvdata
  driver core: dev_get_drvdata: Don't check for NULL dev
  driver core: dev_set_drvdata returns void
  driver core: dev_set_drvdata can no longer fail
  driver core: Move driver_data back to struct device
  lib/devres.c: fix checkpatch warnings
  lib/devres.c: use dev in devm_request_and_ioremap
  kobject: Make support for uevent_helper optional.
  kernfs: make kernfs_notify() trigger inotify events too
  kernfs: implement kernfs_root->supers list
  • Loading branch information
Linus Torvalds committed Jun 3, 2014
2 parents 4046136 + cda4357 commit 5da7776
Show file tree
Hide file tree
Showing 22 changed files with 141 additions and 89 deletions.
17 changes: 11 additions & 6 deletions drivers/base/Kconfig
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
menu "Generic Driver Options"

config UEVENT_HELPER_PATH
string "path to uevent helper"
default ""
config UEVENT_HELPER
bool "Support for uevent helper"
default y
help
Path to uevent helper program forked by the kernel for
The uevent helper program is forked by the kernel for
every uevent.
Before the switch to the netlink-based uevent source, this was
used to hook hotplug scripts into kernel device events. It
Expand All @@ -15,8 +15,13 @@ config UEVENT_HELPER_PATH
that it creates a high system load, or on smaller systems
it is known to create out-of-memory situations during bootup.

To disable user space helper program execution at early boot
time specify an empty string here. This setting can be altered
config UEVENT_HELPER_PATH
string "path to uevent helper"
depends on UEVENT_HELPER
default ""
help
To disable user space helper program execution at by default
specify an empty string here. This setting can still be altered
via /proc/sys/kernel/hotplug or via /sys/kernel/uevent_helper
later at runtime.

Expand Down
3 changes: 0 additions & 3 deletions drivers/base/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ struct driver_private {
* binding of drivers which were unable to get all the resources needed by
* the device; typically because it depends on another driver getting
* probed first.
* @driver_data - private pointer for driver specific info. Will turn into a
* list soon.
* @device - pointer back to the struct class that this structure is
* associated with.
*
Expand All @@ -76,7 +74,6 @@ struct device_private {
struct klist_node knode_driver;
struct klist_node knode_bus;
struct list_head deferred_probe;
void *driver_data;
struct device *device;
};
#define to_device_private_parent(obj) \
Expand Down
26 changes: 0 additions & 26 deletions drivers/base/dd.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,29 +587,3 @@ void driver_detach(struct device_driver *drv)
put_device(dev);
}
}

/*
* These exports can't be _GPL due to .h files using this within them, and it
* might break something that was previously working...
*/
void *dev_get_drvdata(const struct device *dev)
{
if (dev && dev->p)
return dev->p->driver_data;
return NULL;
}
EXPORT_SYMBOL(dev_get_drvdata);

int dev_set_drvdata(struct device *dev, void *data)
{
int error;

if (!dev->p) {
error = device_private_init(dev);
if (error)
return error;
}
dev->p->driver_data = data;
return 0;
}
EXPORT_SYMBOL(dev_set_drvdata);
7 changes: 1 addition & 6 deletions drivers/crypto/nx/nx-842.c
Original file line number Diff line number Diff line change
Expand Up @@ -1197,12 +1197,7 @@ static int __init nx842_probe(struct vio_dev *viodev,
}

rcu_read_lock();
if (dev_set_drvdata(&viodev->dev, rcu_dereference(devdata))) {
rcu_read_unlock();
dev_err(&viodev->dev, "failed to set driver data for device\n");
ret = -1;
goto error;
}
dev_set_drvdata(&viodev->dev, rcu_dereference(devdata));
rcu_read_unlock();

if (sysfs_create_group(&viodev->dev.kobj, &nx842_attribute_group)) {
Expand Down
7 changes: 1 addition & 6 deletions drivers/iommu/exynos-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -542,12 +542,7 @@ static int exynos_sysmmu_probe(struct platform_device *pdev)
goto err_alloc;
}

ret = dev_set_drvdata(dev, data);
if (ret) {
dev_dbg(dev, "Unabled to initialize driver data\n");
goto err_init;
}

dev_set_drvdata(dev, data);
data->nsfrs = pdev->num_resources / 2;
data->sfrbases = kmalloc(sizeof(*data->sfrbases) * data->nsfrs,
GFP_KERNEL);
Expand Down
8 changes: 1 addition & 7 deletions drivers/vfio/vfio.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,6 @@ struct vfio_device *vfio_group_create_device(struct vfio_group *group,
void *device_data)
{
struct vfio_device *device;
int ret;

device = kzalloc(sizeof(*device), GFP_KERNEL);
if (!device)
Expand All @@ -360,12 +359,7 @@ struct vfio_device *vfio_group_create_device(struct vfio_group *group,
device->group = group;
device->ops = ops;
device->device_data = device_data;

ret = dev_set_drvdata(dev, device);
if (ret) {
kfree(device);
return ERR_PTR(ret);
}
dev_set_drvdata(dev, device);

/* No need to get group_lock, caller has group reference */
vfio_group_get(group);
Expand Down
1 change: 1 addition & 0 deletions fs/kernfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,7 @@ struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
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);
Expand Down
41 changes: 35 additions & 6 deletions fs/kernfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/poll.h>
#include <linux/pagemap.h>
#include <linux/sched.h>
#include <linux/fsnotify.h>

#include "kernfs-internal.h"

Expand Down Expand Up @@ -790,20 +791,48 @@ static unsigned int kernfs_fop_poll(struct file *filp, poll_table *wait)
*/
void kernfs_notify(struct kernfs_node *kn)
{
struct kernfs_root *root = kernfs_root(kn);
struct kernfs_open_node *on;
struct kernfs_super_info *info;
unsigned long flags;

if (WARN_ON(kernfs_type(kn) != KERNFS_FILE))
return;

/* kick poll */
spin_lock_irqsave(&kernfs_open_node_lock, flags);

if (!WARN_ON(kernfs_type(kn) != KERNFS_FILE)) {
on = kn->attr.open;
if (on) {
atomic_inc(&on->event);
wake_up_interruptible(&on->poll);
}
on = kn->attr.open;
if (on) {
atomic_inc(&on->event);
wake_up_interruptible(&on->poll);
}

spin_unlock_irqrestore(&kernfs_open_node_lock, flags);

/* kick fsnotify */
mutex_lock(&kernfs_mutex);

list_for_each_entry(info, &root->supers, node) {
struct inode *inode;
struct dentry *dentry;

inode = ilookup(info->sb, kn->ino);
if (!inode)
continue;

dentry = d_find_any_alias(inode);
if (dentry) {
fsnotify_parent(NULL, dentry, FS_MODIFY);
fsnotify(inode, FS_MODIFY, inode, FSNOTIFY_EVENT_INODE,
NULL, 0);
dput(dentry);
}

iput(inode);
}

mutex_unlock(&kernfs_mutex);
}
EXPORT_SYMBOL_GPL(kernfs_notify);

Expand Down
5 changes: 5 additions & 0 deletions fs/kernfs/kernfs-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn)
* mount.c
*/
struct kernfs_super_info {
struct super_block *sb;

/*
* The root associated with this super_block. Each super_block is
* identified by the root and ns it's associated with.
Expand All @@ -62,6 +64,9 @@ struct kernfs_super_info {
* an array and compare kernfs_node tag against every entry.
*/
const void *ns;

/* anchored at kernfs_root->supers, protected by kernfs_mutex */
struct list_head node;
};
#define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info))

Expand Down
22 changes: 17 additions & 5 deletions fs/kernfs/mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,16 @@ struct kernfs_root *kernfs_root_from_sb(struct super_block *sb)
return NULL;
}

static int kernfs_fill_super(struct super_block *sb)
static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
{
struct kernfs_super_info *info = kernfs_info(sb);
struct inode *inode;
struct dentry *root;

info->sb = sb;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = SYSFS_MAGIC;
sb->s_magic = magic;
sb->s_op = &kernfs_sops;
sb->s_time_gran = 1;

Expand Down Expand Up @@ -131,6 +132,7 @@ const void *kernfs_super_ns(struct super_block *sb)
* @fs_type: file_system_type of the fs being mounted
* @flags: mount flags specified for the mount
* @root: kernfs_root of the hierarchy being mounted
* @magic: file system specific magic number
* @new_sb_created: tell the caller if we allocated a new superblock
* @ns: optional namespace tag of the mount
*
Expand All @@ -142,8 +144,8 @@ const void *kernfs_super_ns(struct super_block *sb)
* The return value can be passed to the vfs layer verbatim.
*/
struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
struct kernfs_root *root, bool *new_sb_created,
const void *ns)
struct kernfs_root *root, unsigned long magic,
bool *new_sb_created, const void *ns)
{
struct super_block *sb;
struct kernfs_super_info *info;
Expand All @@ -166,12 +168,18 @@ struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
*new_sb_created = !sb->s_root;

if (!sb->s_root) {
error = kernfs_fill_super(sb);
struct kernfs_super_info *info = kernfs_info(sb);

error = kernfs_fill_super(sb, magic);
if (error) {
deactivate_locked_super(sb);
return ERR_PTR(error);
}
sb->s_flags |= MS_ACTIVE;

mutex_lock(&kernfs_mutex);
list_add(&info->node, &root->supers);
mutex_unlock(&kernfs_mutex);
}

return dget(sb->s_root);
Expand All @@ -190,6 +198,10 @@ void kernfs_kill_sb(struct super_block *sb)
struct kernfs_super_info *info = kernfs_info(sb);
struct kernfs_node *root_kn = sb->s_root->d_fsdata;

mutex_lock(&kernfs_mutex);
list_del(&info->node);
mutex_unlock(&kernfs_mutex);

/*
* Remove the superblock from fs_supers/s_instances
* so we can't find it, before freeing kernfs_super_info.
Expand Down
10 changes: 5 additions & 5 deletions fs/sysfs/group.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include "sysfs.h"


static void remove_files(struct kernfs_node *parent, struct kobject *kobj,
static void remove_files(struct kernfs_node *parent,
const struct attribute_group *grp)
{
struct attribute *const *attr;
Expand All @@ -29,7 +29,7 @@ static void remove_files(struct kernfs_node *parent, struct kobject *kobj,
kernfs_remove_by_name(parent, (*attr)->name);
if (grp->bin_attrs)
for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++)
sysfs_remove_bin_file(kobj, *bin_attr);
kernfs_remove_by_name(parent, (*bin_attr)->attr.name);
}

static int create_files(struct kernfs_node *parent, struct kobject *kobj,
Expand Down Expand Up @@ -62,7 +62,7 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
break;
}
if (error) {
remove_files(parent, kobj, grp);
remove_files(parent, grp);
goto exit;
}
}
Expand All @@ -79,7 +79,7 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
break;
}
if (error)
remove_files(parent, kobj, grp);
remove_files(parent, grp);
}
exit:
return error;
Expand Down Expand Up @@ -224,7 +224,7 @@ void sysfs_remove_group(struct kobject *kobj,
kernfs_get(kn);
}

remove_files(kn, kobj, grp);
remove_files(kn, grp);
if (grp->name)
kernfs_remove(kn);

Expand Down
4 changes: 3 additions & 1 deletion fs/sysfs/mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define DEBUG

#include <linux/fs.h>
#include <linux/magic.h>
#include <linux/mount.h>
#include <linux/init.h>
#include <linux/user_namespace.h>
Expand All @@ -38,7 +39,8 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
}

ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
root = kernfs_mount_ns(fs_type, flags, sysfs_root, &new_sb, ns);
root = kernfs_mount_ns(fs_type, flags, sysfs_root,
SYSFS_MAGIC, &new_sb, ns);
if (IS_ERR(root) || !new_sb)
kobj_ns_drop(KOBJ_NS_TYPE_NET, ns);
return root;
Expand Down
15 changes: 13 additions & 2 deletions include/linux/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,7 @@ struct acpi_dev_node {
* variants, which GPIO pins act in what additional roles, and so
* on. This shrinks the "Board Support Packages" (BSPs) and
* minimizes board-specific #ifdefs in drivers.
* @driver_data: Private pointer for driver specific info.
* @power: For device power management.
* See Documentation/power/devices.txt for details.
* @pm_domain: Provide callbacks that are executed during system suspend,
Expand Down Expand Up @@ -734,6 +735,8 @@ struct device {
device */
void *platform_data; /* Platform specific data, device
core doesn't touch it */
void *driver_data; /* Driver data, set and get with
dev_set/get_drvdata */
struct dev_pm_info power;
struct dev_pm_domain *pm_domain;

Expand Down Expand Up @@ -823,6 +826,16 @@ static inline void set_dev_node(struct device *dev, int node)
}
#endif

static inline void *dev_get_drvdata(const struct device *dev)
{
return dev->driver_data;
}

static inline void dev_set_drvdata(struct device *dev, void *data)
{
dev->driver_data = data;
}

static inline struct pm_subsys_data *dev_to_psd(struct device *dev)
{
return dev ? dev->power.subsys_data : NULL;
Expand Down Expand Up @@ -907,8 +920,6 @@ extern int device_move(struct device *dev, struct device *new_parent,
extern const char *device_get_devnode(struct device *dev,
umode_t *mode, kuid_t *uid, kgid_t *gid,
const char **tmp);
extern void *dev_get_drvdata(const struct device *dev);
extern int dev_set_drvdata(struct device *dev, void *data);

static inline bool device_supports_offline(struct device *dev)
{
Expand Down
Loading

0 comments on commit 5da7776

Please sign in to comment.