Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (46 commits) UIO: Fix mapping of logical and virtual memory UIO: add automata sercos3 pci card support UIO: Change driver name of uio_pdrv UIO: Add alignment warnings for uio-mem Driver core: add bus_sort_breadthfirst() function NET: convert the phy_device file to use bus_find_device_by_name kobject: Cleanup kobject_rename and !CONFIG_SYSFS kobject: Fix kobject_rename and !CONFIG_SYSFS sysfs: Make dir and name args to sysfs_notify() const platform: add new device registration helper sysfs: use ilookup5() instead of ilookup5_nowait() PNP: create device attributes via default device attributes Driver core: make bus_find_device_by_name() more robust usb: turn dev_warn+WARN_ON combos into dev_WARN debug: use dev_WARN() rather than WARN_ON() in device_pm_add() debug: Introduce a dev_WARN() function sysfs: fix deadlock device model: Do a quickcheck for driver binding before doing an expensive check Driver core: Fix cleanup in device_create_vargs(). Driver core: Clarify device cleanup. ...
This commit is contained in:
+2
-3
@@ -362,9 +362,8 @@ static int init_coda_psdev(void)
|
||||
goto out_chrdev;
|
||||
}
|
||||
for (i = 0; i < MAX_CODADEVS; i++)
|
||||
device_create_drvdata(coda_psdev_class, NULL,
|
||||
MKDEV(CODA_PSDEV_MAJOR, i),
|
||||
NULL, "cfs%d", i);
|
||||
device_create(coda_psdev_class, NULL,
|
||||
MKDEV(CODA_PSDEV_MAJOR, i), NULL, "cfs%d", i);
|
||||
coda_sysctl_init();
|
||||
goto out;
|
||||
|
||||
|
||||
+31
-11
@@ -61,6 +61,7 @@ read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
|
||||
int size = dentry->d_inode->i_size;
|
||||
loff_t offs = *off;
|
||||
int count = min_t(size_t, bytes, PAGE_SIZE);
|
||||
char *temp;
|
||||
|
||||
if (size) {
|
||||
if (offs > size)
|
||||
@@ -69,23 +70,33 @@ read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
|
||||
count = size - offs;
|
||||
}
|
||||
|
||||
temp = kmalloc(count, GFP_KERNEL);
|
||||
if (!temp)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&bb->mutex);
|
||||
|
||||
count = fill_read(dentry, bb->buffer, offs, count);
|
||||
if (count < 0)
|
||||
goto out_unlock;
|
||||
if (count < 0) {
|
||||
mutex_unlock(&bb->mutex);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (copy_to_user(userbuf, bb->buffer, count)) {
|
||||
memcpy(temp, bb->buffer, count);
|
||||
|
||||
mutex_unlock(&bb->mutex);
|
||||
|
||||
if (copy_to_user(userbuf, temp, count)) {
|
||||
count = -EFAULT;
|
||||
goto out_unlock;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);
|
||||
|
||||
*off = offs + count;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&bb->mutex);
|
||||
out_free:
|
||||
kfree(temp);
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -118,6 +129,7 @@ static ssize_t write(struct file *file, const char __user *userbuf,
|
||||
int size = dentry->d_inode->i_size;
|
||||
loff_t offs = *off;
|
||||
int count = min_t(size_t, bytes, PAGE_SIZE);
|
||||
char *temp;
|
||||
|
||||
if (size) {
|
||||
if (offs > size)
|
||||
@@ -126,19 +138,27 @@ static ssize_t write(struct file *file, const char __user *userbuf,
|
||||
count = size - offs;
|
||||
}
|
||||
|
||||
mutex_lock(&bb->mutex);
|
||||
temp = kmalloc(count, GFP_KERNEL);
|
||||
if (!temp)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(bb->buffer, userbuf, count)) {
|
||||
if (copy_from_user(temp, userbuf, count)) {
|
||||
count = -EFAULT;
|
||||
goto out_unlock;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
mutex_lock(&bb->mutex);
|
||||
|
||||
memcpy(bb->buffer, temp, count);
|
||||
|
||||
count = flush_write(dentry, bb->buffer, offs, count);
|
||||
mutex_unlock(&bb->mutex);
|
||||
|
||||
if (count > 0)
|
||||
*off = offs + count;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&bb->mutex);
|
||||
out_free:
|
||||
kfree(temp);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
+10
-14
@@ -370,17 +370,17 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
|
||||
memset(acxt, 0, sizeof(*acxt));
|
||||
acxt->parent_sd = parent_sd;
|
||||
|
||||
/* Lookup parent inode. inode initialization and I_NEW
|
||||
* clearing are protected by sysfs_mutex. By grabbing it and
|
||||
* looking up with _nowait variant, inode state can be
|
||||
* determined reliably.
|
||||
/* Lookup parent inode. inode initialization is protected by
|
||||
* sysfs_mutex, so inode existence can be determined by
|
||||
* looking up inode while holding sysfs_mutex.
|
||||
*/
|
||||
mutex_lock(&sysfs_mutex);
|
||||
|
||||
inode = ilookup5_nowait(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test,
|
||||
parent_sd);
|
||||
inode = ilookup5(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test,
|
||||
parent_sd);
|
||||
if (inode) {
|
||||
WARN_ON(inode->i_state & I_NEW);
|
||||
|
||||
if (inode && !(inode->i_state & I_NEW)) {
|
||||
/* parent inode available */
|
||||
acxt->parent_inode = inode;
|
||||
|
||||
@@ -393,8 +393,7 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
|
||||
mutex_lock(&inode->i_mutex);
|
||||
mutex_lock(&sysfs_mutex);
|
||||
}
|
||||
} else
|
||||
iput(inode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -636,6 +635,7 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
|
||||
|
||||
return sd;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_get_dirent);
|
||||
|
||||
static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
|
||||
const char *name, struct sysfs_dirent **p_sd)
|
||||
@@ -829,16 +829,12 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
|
||||
if (!new_dentry)
|
||||
goto out_unlock;
|
||||
|
||||
/* rename kobject and sysfs_dirent */
|
||||
/* rename sysfs_dirent */
|
||||
error = -ENOMEM;
|
||||
new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
|
||||
if (!new_name)
|
||||
goto out_unlock;
|
||||
|
||||
error = kobject_set_name(kobj, "%s", new_name);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
|
||||
dup_name = sd->s_name;
|
||||
sd->s_name = new_name;
|
||||
|
||||
|
||||
+32
-14
@@ -19,10 +19,18 @@
|
||||
#include <linux/poll.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/limits.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "sysfs.h"
|
||||
|
||||
/* used in crash dumps to help with debugging */
|
||||
static char last_sysfs_file[PATH_MAX];
|
||||
void sysfs_printk_last_file(void)
|
||||
{
|
||||
printk(KERN_EMERG "last sysfs file: %s\n", last_sysfs_file);
|
||||
}
|
||||
|
||||
/*
|
||||
* There's one sysfs_buffer for each open file and one
|
||||
* sysfs_open_dirent for each sysfs_dirent with one or more open
|
||||
@@ -328,6 +336,11 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
|
||||
struct sysfs_buffer *buffer;
|
||||
struct sysfs_ops *ops;
|
||||
int error = -EACCES;
|
||||
char *p;
|
||||
|
||||
p = d_path(&file->f_path, last_sysfs_file, sizeof(last_sysfs_file));
|
||||
if (p)
|
||||
memmove(last_sysfs_file, p, strlen(p) + 1);
|
||||
|
||||
/* need attr_sd for attr and ops, its parent for kobj */
|
||||
if (!sysfs_get_active_two(attr_sd))
|
||||
@@ -440,7 +453,23 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
|
||||
return POLLERR|POLLPRI;
|
||||
}
|
||||
|
||||
void sysfs_notify(struct kobject *k, char *dir, char *attr)
|
||||
void sysfs_notify_dirent(struct sysfs_dirent *sd)
|
||||
{
|
||||
struct sysfs_open_dirent *od;
|
||||
|
||||
spin_lock(&sysfs_open_dirent_lock);
|
||||
|
||||
od = sd->s_attr.open;
|
||||
if (od) {
|
||||
atomic_inc(&od->event);
|
||||
wake_up_interruptible(&od->poll);
|
||||
}
|
||||
|
||||
spin_unlock(&sysfs_open_dirent_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_notify_dirent);
|
||||
|
||||
void sysfs_notify(struct kobject *k, const char *dir, const char *attr)
|
||||
{
|
||||
struct sysfs_dirent *sd = k->sd;
|
||||
|
||||
@@ -450,19 +479,8 @@ void sysfs_notify(struct kobject *k, char *dir, char *attr)
|
||||
sd = sysfs_find_dirent(sd, dir);
|
||||
if (sd && attr)
|
||||
sd = sysfs_find_dirent(sd, attr);
|
||||
if (sd) {
|
||||
struct sysfs_open_dirent *od;
|
||||
|
||||
spin_lock(&sysfs_open_dirent_lock);
|
||||
|
||||
od = sd->s_attr.open;
|
||||
if (od) {
|
||||
atomic_inc(&od->event);
|
||||
wake_up_interruptible(&od->poll);
|
||||
}
|
||||
|
||||
spin_unlock(&sysfs_open_dirent_lock);
|
||||
}
|
||||
if (sd)
|
||||
sysfs_notify_dirent(sd);
|
||||
|
||||
mutex_unlock(&sysfs_mutex);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/mount.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "sysfs.h"
|
||||
|
||||
@@ -115,3 +116,17 @@ out_err:
|
||||
sysfs_dir_cachep = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#undef sysfs_get
|
||||
struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
|
||||
{
|
||||
return __sysfs_get(sd);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_get);
|
||||
|
||||
#undef sysfs_put
|
||||
void sysfs_put(struct sysfs_dirent *sd)
|
||||
{
|
||||
__sysfs_put(sd);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_put);
|
||||
|
||||
+4
-2
@@ -124,7 +124,7 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name,
|
||||
struct sysfs_dirent **p_sd);
|
||||
void sysfs_remove_subdir(struct sysfs_dirent *sd);
|
||||
|
||||
static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
|
||||
static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd)
|
||||
{
|
||||
if (sd) {
|
||||
WARN_ON(!atomic_read(&sd->s_count));
|
||||
@@ -132,12 +132,14 @@ static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
|
||||
}
|
||||
return sd;
|
||||
}
|
||||
#define sysfs_get(sd) __sysfs_get(sd)
|
||||
|
||||
static inline void sysfs_put(struct sysfs_dirent *sd)
|
||||
static inline void __sysfs_put(struct sysfs_dirent *sd)
|
||||
{
|
||||
if (sd && atomic_dec_and_test(&sd->s_count))
|
||||
release_sysfs_dirent(sd);
|
||||
}
|
||||
#define sysfs_put(sd) __sysfs_put(sd)
|
||||
|
||||
/*
|
||||
* inode.c
|
||||
|
||||
Reference in New Issue
Block a user