diff options
| -rw-r--r-- | drivers/base/base.h | 9 | ||||
| -rw-r--r-- | drivers/base/class.c | 11 | ||||
| -rw-r--r-- | fs/sysfs/bin.c | 33 | ||||
| -rw-r--r-- | fs/sysfs/inode.c | 5 | ||||
| -rw-r--r-- | include/linux/device.h | 1 | ||||
| -rw-r--r-- | include/linux/sysfs.h | 3 |
6 files changed, 45 insertions, 17 deletions
diff --git a/drivers/base/base.h b/drivers/base/base.h index 4c035fa27415..cc92a7359569 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -4,3 +4,12 @@ extern void bus_remove_device(struct device * dev); extern int bus_add_driver(struct device_driver *); extern void bus_remove_driver(struct device_driver *); +static inline struct class_device *to_class_dev(struct kobject *obj) +{ + return container_of(obj,struct class_device,kobj); +} +static inline +struct class_device_attribute *to_class_dev_attr(struct attribute *_attr) +{ + return container_of(_attr,struct class_device_attribute,attr); +} diff --git a/drivers/base/class.c b/drivers/base/class.c index bbb9d26a04bb..78899d78b77b 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -148,9 +148,6 @@ static void class_device_driver_unlink(struct class_device * class_dev) } -#define to_class_dev(obj) container_of(obj,struct class_device,kobj) -#define to_class_dev_attr(_attr) container_of(_attr,struct class_device_attribute,attr) - static ssize_t class_device_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) @@ -182,7 +179,15 @@ static struct sysfs_ops class_dev_sysfs_ops = { .store = class_device_attr_store, }; +static void class_dev_release(struct kobject * kobj) +{ + struct class_device *class_dev = to_class_dev(kobj); + if (class_dev->release) + class_dev->release(class_dev); +} + static struct kobj_type ktype_class_device = { + .release = &class_dev_release, .sysfs_ops = &class_dev_sysfs_ops, }; diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index f9981f822206..78884e3dd038 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -30,10 +30,15 @@ read(struct file * file, char * userbuf, size_t count, loff_t * off) loff_t offs = *off; int ret; - if (offs > size) - return 0; - if (offs + count > size) - count = size - offs; + if (count > PAGE_SIZE) + count = PAGE_SIZE; + + if (size) { + if (offs > size) + return 0; + if (offs + count > size) + count = size - offs; + } ret = fill_read(dentry, buffer, offs, count); if (ret < 0) @@ -41,7 +46,7 @@ read(struct file * file, char * userbuf, size_t count, loff_t * off) count = ret; ret = -EFAULT; - if (copy_to_user(userbuf, buffer + offs, count) != 0) + if (copy_to_user(userbuf, buffer, count) != 0) goto Done; *off = offs + count; @@ -69,19 +74,23 @@ static ssize_t write(struct file * file, const char * userbuf, loff_t offs = *off; int ret; - if (offs > size) - return 0; - if (offs + count > size) - count = size - offs; + if (count > PAGE_SIZE) + count = PAGE_SIZE; + if (size) { + if (offs > size) + return 0; + if (offs + count > size) + count = size - offs; + } ret = -EFAULT; - if (copy_from_user(buffer + offs, userbuf, count)) + if (copy_from_user(buffer, userbuf, count)) goto Done; count = flush_write(dentry, buffer, offs, count); if (count > 0) *off = offs + count; - ret = 0; + ret = count; Done: return ret; } @@ -102,7 +111,7 @@ static int open(struct inode * inode, struct file * file) goto Done; error = -ENOMEM; - file->private_data = kmalloc(attr->size, GFP_KERNEL); + file->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!file->private_data) goto Done; diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 0cf2432c4fe1..c22313b1fa7a 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -60,9 +60,10 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *)) Proceed: if (init) error = init(inode); - if (!error) + if (!error) { d_instantiate(dentry, inode); - else + dget(dentry); /* Extra count - pin the dentry in core */ + } else iput(inode); Done: return error; diff --git a/include/linux/device.h b/include/linux/device.h index a43e8a2a2c61..441ab49ffa0b 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -204,6 +204,7 @@ struct class_device { void * class_data; /* class-specific data */ char class_id[BUS_ID_SIZE]; /* unique to this class */ + void (*release)(struct class_device * class_dev); }; static inline void * diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index d639e18caa91..f054416c8145 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -23,6 +23,9 @@ struct bin_attribute { ssize_t (*write)(struct kobject *, char *, loff_t, size_t); }; +int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr); +int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr); + struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *,char *); ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); |
