aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-20 19:00:33 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-20 19:00:33 -0400
commit1d345dac1f30af1cd9f3a1faa12f9f18f17f236e (patch)
tree42a7deda7589edf704fe60dc262046755bd3f6a8 /fs
parentfb395884576684ebb54b19b1054f4caed589d5f0 (diff)
parent87c8a4433b608261a9becdb0ce2d2f2ed4b71d05 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
Diffstat (limited to 'fs')
-rw-r--r--fs/coda/psdev.c18
-rw-r--r--fs/debugfs/file.c67
-rw-r--r--fs/libfs.c100
-rw-r--r--fs/sysfs/bin.c4
-rw-r--r--fs/sysfs/dir.c26
-rw-r--r--fs/sysfs/file.c6
-rw-r--r--fs/sysfs/inode.c102
-rw-r--r--fs/sysfs/mount.c4
-rw-r--r--fs/sysfs/symlink.c8
-rw-r--r--fs/sysfs/sysfs.h4
10 files changed, 265 insertions, 74 deletions
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index ef001a9313e6..3d1cce3653b8 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -61,7 +61,7 @@ unsigned long coda_timeout = 30; /* .. secs, then signals will dequeue */
61 61
62 62
63struct venus_comm coda_comms[MAX_CODADEVS]; 63struct venus_comm coda_comms[MAX_CODADEVS];
64static struct class_simple *coda_psdev_class; 64static struct class *coda_psdev_class;
65 65
66/* 66/*
67 * Device operations 67 * Device operations
@@ -363,14 +363,14 @@ static int init_coda_psdev(void)
363 CODA_PSDEV_MAJOR); 363 CODA_PSDEV_MAJOR);
364 return -EIO; 364 return -EIO;
365 } 365 }
366 coda_psdev_class = class_simple_create(THIS_MODULE, "coda"); 366 coda_psdev_class = class_create(THIS_MODULE, "coda");
367 if (IS_ERR(coda_psdev_class)) { 367 if (IS_ERR(coda_psdev_class)) {
368 err = PTR_ERR(coda_psdev_class); 368 err = PTR_ERR(coda_psdev_class);
369 goto out_chrdev; 369 goto out_chrdev;
370 } 370 }
371 devfs_mk_dir ("coda"); 371 devfs_mk_dir ("coda");
372 for (i = 0; i < MAX_CODADEVS; i++) { 372 for (i = 0; i < MAX_CODADEVS; i++) {
373 class_simple_device_add(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR,i), 373 class_device_create(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR,i),
374 NULL, "cfs%d", i); 374 NULL, "cfs%d", i);
375 err = devfs_mk_cdev(MKDEV(CODA_PSDEV_MAJOR, i), 375 err = devfs_mk_cdev(MKDEV(CODA_PSDEV_MAJOR, i),
376 S_IFCHR|S_IRUSR|S_IWUSR, "coda/%d", i); 376 S_IFCHR|S_IRUSR|S_IWUSR, "coda/%d", i);
@@ -382,8 +382,8 @@ static int init_coda_psdev(void)
382 382
383out_class: 383out_class:
384 for (i = 0; i < MAX_CODADEVS; i++) 384 for (i = 0; i < MAX_CODADEVS; i++)
385 class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i)); 385 class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
386 class_simple_destroy(coda_psdev_class); 386 class_destroy(coda_psdev_class);
387out_chrdev: 387out_chrdev:
388 unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); 388 unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
389out: 389out:
@@ -425,10 +425,10 @@ static int __init init_coda(void)
425 return 0; 425 return 0;
426out: 426out:
427 for (i = 0; i < MAX_CODADEVS; i++) { 427 for (i = 0; i < MAX_CODADEVS; i++) {
428 class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i)); 428 class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
429 devfs_remove("coda/%d", i); 429 devfs_remove("coda/%d", i);
430 } 430 }
431 class_simple_destroy(coda_psdev_class); 431 class_destroy(coda_psdev_class);
432 devfs_remove("coda"); 432 devfs_remove("coda");
433 unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); 433 unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
434 coda_sysctl_clean(); 434 coda_sysctl_clean();
@@ -447,10 +447,10 @@ static void __exit exit_coda(void)
447 printk("coda: failed to unregister filesystem\n"); 447 printk("coda: failed to unregister filesystem\n");
448 } 448 }
449 for (i = 0; i < MAX_CODADEVS; i++) { 449 for (i = 0; i < MAX_CODADEVS; i++) {
450 class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i)); 450 class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
451 devfs_remove("coda/%d", i); 451 devfs_remove("coda/%d", i);
452 } 452 }
453 class_simple_destroy(coda_psdev_class); 453 class_destroy(coda_psdev_class);
454 devfs_remove("coda"); 454 devfs_remove("coda");
455 unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); 455 unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
456 coda_sysctl_clean(); 456 coda_sysctl_clean();
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 548556ff2506..efc97d9b7860 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -45,44 +45,15 @@ struct file_operations debugfs_file_operations = {
45 .open = default_open, 45 .open = default_open,
46}; 46};
47 47
48#define simple_type(type, format, temptype, strtolfn) \ 48static void debugfs_u8_set(void *data, u64 val)
49static ssize_t read_file_##type(struct file *file, char __user *user_buf, \ 49{
50 size_t count, loff_t *ppos) \ 50 *(u8 *)data = val;
51{ \ 51}
52 char buf[32]; \ 52static u64 debugfs_u8_get(void *data)
53 type *val = file->private_data; \ 53{
54 \ 54 return *(u8 *)data;
55 snprintf(buf, sizeof(buf), format "\n", *val); \ 55}
56 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));\ 56DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n");
57} \
58static ssize_t write_file_##type(struct file *file, const char __user *user_buf,\
59 size_t count, loff_t *ppos) \
60{ \
61 char *endp; \
62 char buf[32]; \
63 int buf_size; \
64 type *val = file->private_data; \
65 temptype tmp; \
66 \
67 memset(buf, 0x00, sizeof(buf)); \
68 buf_size = min(count, (sizeof(buf)-1)); \
69 if (copy_from_user(buf, user_buf, buf_size)) \
70 return -EFAULT; \
71 \
72 tmp = strtolfn(buf, &endp, 0); \
73 if ((endp == buf) || ((type)tmp != tmp)) \
74 return -EINVAL; \
75 *val = tmp; \
76 return count; \
77} \
78static struct file_operations fops_##type = { \
79 .read = read_file_##type, \
80 .write = write_file_##type, \
81 .open = default_open, \
82};
83simple_type(u8, "%c", unsigned long, simple_strtoul);
84simple_type(u16, "%hi", unsigned long, simple_strtoul);
85simple_type(u32, "%i", unsigned long, simple_strtoul);
86 57
87/** 58/**
88 * debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. 59 * debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
@@ -116,6 +87,16 @@ struct dentry *debugfs_create_u8(const char *name, mode_t mode,
116} 87}
117EXPORT_SYMBOL_GPL(debugfs_create_u8); 88EXPORT_SYMBOL_GPL(debugfs_create_u8);
118 89
90static void debugfs_u16_set(void *data, u64 val)
91{
92 *(u16 *)data = val;
93}
94static u64 debugfs_u16_get(void *data)
95{
96 return *(u16 *)data;
97}
98DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n");
99
119/** 100/**
120 * debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. 101 * debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
121 * 102 *
@@ -148,6 +129,16 @@ struct dentry *debugfs_create_u16(const char *name, mode_t mode,
148} 129}
149EXPORT_SYMBOL_GPL(debugfs_create_u16); 130EXPORT_SYMBOL_GPL(debugfs_create_u16);
150 131
132static void debugfs_u32_set(void *data, u64 val)
133{
134 *(u32 *)data = val;
135}
136static u64 debugfs_u32_get(void *data)
137{
138 return *(u32 *)data;
139}
140DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n");
141
151/** 142/**
152 * debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. 143 * debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
153 * 144 *
diff --git a/fs/libfs.c b/fs/libfs.c
index f90b29595927..5025563e7379 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -519,6 +519,102 @@ int simple_transaction_release(struct inode *inode, struct file *file)
519 return 0; 519 return 0;
520} 520}
521 521
522/* Simple attribute files */
523
524struct simple_attr {
525 u64 (*get)(void *);
526 void (*set)(void *, u64);
527 char get_buf[24]; /* enough to store a u64 and "\n\0" */
528 char set_buf[24];
529 void *data;
530 const char *fmt; /* format for read operation */
531 struct semaphore sem; /* protects access to these buffers */
532};
533
534/* simple_attr_open is called by an actual attribute open file operation
535 * to set the attribute specific access operations. */
536int simple_attr_open(struct inode *inode, struct file *file,
537 u64 (*get)(void *), void (*set)(void *, u64),
538 const char *fmt)
539{
540 struct simple_attr *attr;
541
542 attr = kmalloc(sizeof(*attr), GFP_KERNEL);
543 if (!attr)
544 return -ENOMEM;
545
546 attr->get = get;
547 attr->set = set;
548 attr->data = inode->u.generic_ip;
549 attr->fmt = fmt;
550 init_MUTEX(&attr->sem);
551
552 file->private_data = attr;
553
554 return nonseekable_open(inode, file);
555}
556
557int simple_attr_close(struct inode *inode, struct file *file)
558{
559 kfree(file->private_data);
560 return 0;
561}
562
563/* read from the buffer that is filled with the get function */
564ssize_t simple_attr_read(struct file *file, char __user *buf,
565 size_t len, loff_t *ppos)
566{
567 struct simple_attr *attr;
568 size_t size;
569 ssize_t ret;
570
571 attr = file->private_data;
572
573 if (!attr->get)
574 return -EACCES;
575
576 down(&attr->sem);
577 if (*ppos) /* continued read */
578 size = strlen(attr->get_buf);
579 else /* first read */
580 size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
581 attr->fmt,
582 (unsigned long long)attr->get(attr->data));
583
584 ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
585 up(&attr->sem);
586 return ret;
587}
588
589/* interpret the buffer as a number to call the set function with */
590ssize_t simple_attr_write(struct file *file, const char __user *buf,
591 size_t len, loff_t *ppos)
592{
593 struct simple_attr *attr;
594 u64 val;
595 size_t size;
596 ssize_t ret;
597
598 attr = file->private_data;
599
600 if (!attr->set)
601 return -EACCES;
602
603 down(&attr->sem);
604 ret = -EFAULT;
605 size = min(sizeof(attr->set_buf) - 1, len);
606 if (copy_from_user(attr->set_buf, buf, size))
607 goto out;
608
609 ret = len; /* claim we got the whole input */
610 attr->set_buf[size] = '\0';
611 val = simple_strtol(attr->set_buf, NULL, 0);
612 attr->set(attr->data, val);
613out:
614 up(&attr->sem);
615 return ret;
616}
617
522EXPORT_SYMBOL(dcache_dir_close); 618EXPORT_SYMBOL(dcache_dir_close);
523EXPORT_SYMBOL(dcache_dir_lseek); 619EXPORT_SYMBOL(dcache_dir_lseek);
524EXPORT_SYMBOL(dcache_dir_open); 620EXPORT_SYMBOL(dcache_dir_open);
@@ -547,3 +643,7 @@ EXPORT_SYMBOL(simple_read_from_buffer);
547EXPORT_SYMBOL(simple_transaction_get); 643EXPORT_SYMBOL(simple_transaction_get);
548EXPORT_SYMBOL(simple_transaction_read); 644EXPORT_SYMBOL(simple_transaction_read);
549EXPORT_SYMBOL(simple_transaction_release); 645EXPORT_SYMBOL(simple_transaction_release);
646EXPORT_SYMBOL_GPL(simple_attr_open);
647EXPORT_SYMBOL_GPL(simple_attr_close);
648EXPORT_SYMBOL_GPL(simple_attr_read);
649EXPORT_SYMBOL_GPL(simple_attr_write);
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index d4aaa88d0214..78899eeab974 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -25,7 +25,7 @@ fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
25 struct kobject * kobj = to_kobj(dentry->d_parent); 25 struct kobject * kobj = to_kobj(dentry->d_parent);
26 26
27 if (!attr->read) 27 if (!attr->read)
28 return -EINVAL; 28 return -EIO;
29 29
30 return attr->read(kobj, buffer, off, count); 30 return attr->read(kobj, buffer, off, count);
31} 31}
@@ -71,7 +71,7 @@ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
71 struct kobject *kobj = to_kobj(dentry->d_parent); 71 struct kobject *kobj = to_kobj(dentry->d_parent);
72 72
73 if (!attr->write) 73 if (!attr->write)
74 return -EINVAL; 74 return -EIO;
75 75
76 return attr->write(kobj, buffer, offset, count); 76 return attr->write(kobj, buffer, offset, count);
77} 77}
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index fe198210bc2d..37d7a6875d86 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -101,18 +101,19 @@ static int create_dir(struct kobject * k, struct dentry * p,
101 down(&p->d_inode->i_sem); 101 down(&p->d_inode->i_sem);
102 *d = sysfs_get_dentry(p,n); 102 *d = sysfs_get_dentry(p,n);
103 if (!IS_ERR(*d)) { 103 if (!IS_ERR(*d)) {
104 error = sysfs_create(*d, mode, init_dir); 104 error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, SYSFS_DIR);
105 if (!error) { 105 if (!error) {
106 error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, 106 error = sysfs_create(*d, mode, init_dir);
107 SYSFS_DIR);
108 if (!error) { 107 if (!error) {
109 p->d_inode->i_nlink++; 108 p->d_inode->i_nlink++;
110 (*d)->d_op = &sysfs_dentry_ops; 109 (*d)->d_op = &sysfs_dentry_ops;
111 d_rehash(*d); 110 d_rehash(*d);
112 } 111 }
113 } 112 }
114 if (error && (error != -EEXIST)) 113 if (error && (error != -EEXIST)) {
114 sysfs_put((*d)->d_fsdata);
115 d_drop(*d); 115 d_drop(*d);
116 }
116 dput(*d); 117 dput(*d);
117 } else 118 } else
118 error = PTR_ERR(*d); 119 error = PTR_ERR(*d);
@@ -171,17 +172,19 @@ static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry)
171 init = init_file; 172 init = init_file;
172 } 173 }
173 174
175 dentry->d_fsdata = sysfs_get(sd);
176 sd->s_dentry = dentry;
174 error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init); 177 error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init);
175 if (error) 178 if (error) {
179 sysfs_put(sd);
176 return error; 180 return error;
181 }
177 182
178 if (bin_attr) { 183 if (bin_attr) {
179 dentry->d_inode->i_size = bin_attr->size; 184 dentry->d_inode->i_size = bin_attr->size;
180 dentry->d_inode->i_fop = &bin_fops; 185 dentry->d_inode->i_fop = &bin_fops;
181 } 186 }
182 dentry->d_op = &sysfs_dentry_ops; 187 dentry->d_op = &sysfs_dentry_ops;
183 dentry->d_fsdata = sysfs_get(sd);
184 sd->s_dentry = dentry;
185 d_rehash(dentry); 188 d_rehash(dentry);
186 189
187 return 0; 190 return 0;
@@ -191,13 +194,15 @@ static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry)
191{ 194{
192 int err = 0; 195 int err = 0;
193 196
197 dentry->d_fsdata = sysfs_get(sd);
198 sd->s_dentry = dentry;
194 err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink); 199 err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink);
195 if (!err) { 200 if (!err) {
196 dentry->d_op = &sysfs_dentry_ops; 201 dentry->d_op = &sysfs_dentry_ops;
197 dentry->d_fsdata = sysfs_get(sd);
198 sd->s_dentry = dentry;
199 d_rehash(dentry); 202 d_rehash(dentry);
200 } 203 } else
204 sysfs_put(sd);
205
201 return err; 206 return err;
202} 207}
203 208
@@ -228,6 +233,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
228 233
229struct inode_operations sysfs_dir_inode_operations = { 234struct inode_operations sysfs_dir_inode_operations = {
230 .lookup = sysfs_lookup, 235 .lookup = sysfs_lookup,
236 .setattr = sysfs_setattr,
231}; 237};
232 238
233static void remove_dir(struct dentry * d) 239static void remove_dir(struct dentry * d)
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 364208071e17..849aac115460 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -23,7 +23,7 @@ subsys_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
23{ 23{
24 struct subsystem * s = to_subsys(kobj); 24 struct subsystem * s = to_subsys(kobj);
25 struct subsys_attribute * sattr = to_sattr(attr); 25 struct subsys_attribute * sattr = to_sattr(attr);
26 ssize_t ret = 0; 26 ssize_t ret = -EIO;
27 27
28 if (sattr->show) 28 if (sattr->show)
29 ret = sattr->show(s,page); 29 ret = sattr->show(s,page);
@@ -36,7 +36,7 @@ subsys_attr_store(struct kobject * kobj, struct attribute * attr,
36{ 36{
37 struct subsystem * s = to_subsys(kobj); 37 struct subsystem * s = to_subsys(kobj);
38 struct subsys_attribute * sattr = to_sattr(attr); 38 struct subsys_attribute * sattr = to_sattr(attr);
39 ssize_t ret = 0; 39 ssize_t ret = -EIO;
40 40
41 if (sattr->store) 41 if (sattr->store)
42 ret = sattr->store(s,page,count); 42 ret = sattr->store(s,page,count);
@@ -182,7 +182,7 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
182 return -ENOMEM; 182 return -ENOMEM;
183 183
184 if (count >= PAGE_SIZE) 184 if (count >= PAGE_SIZE)
185 count = PAGE_SIZE - 1; 185 count = PAGE_SIZE;
186 error = copy_from_user(buffer->page,buf,count); 186 error = copy_from_user(buffer->page,buf,count);
187 buffer->needs_read_fill = 1; 187 buffer->needs_read_fill = 1;
188 return error ? -EFAULT : count; 188 return error ? -EFAULT : count;
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index aff7b2dfa8ee..565cac1d4200 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -26,18 +26,107 @@ static struct backing_dev_info sysfs_backing_dev_info = {
26 .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, 26 .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
27}; 27};
28 28
29struct inode * sysfs_new_inode(mode_t mode) 29static struct inode_operations sysfs_inode_operations ={
30 .setattr = sysfs_setattr,
31};
32
33int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
34{
35 struct inode * inode = dentry->d_inode;
36 struct sysfs_dirent * sd = dentry->d_fsdata;
37 struct iattr * sd_iattr;
38 unsigned int ia_valid = iattr->ia_valid;
39 int error;
40
41 if (!sd)
42 return -EINVAL;
43
44 sd_iattr = sd->s_iattr;
45
46 error = inode_change_ok(inode, iattr);
47 if (error)
48 return error;
49
50 error = inode_setattr(inode, iattr);
51 if (error)
52 return error;
53
54 if (!sd_iattr) {
55 /* setting attributes for the first time, allocate now */
56 sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL);
57 if (!sd_iattr)
58 return -ENOMEM;
59 /* assign default attributes */
60 memset(sd_iattr, 0, sizeof(struct iattr));
61 sd_iattr->ia_mode = sd->s_mode;
62 sd_iattr->ia_uid = 0;
63 sd_iattr->ia_gid = 0;
64 sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME;
65 sd->s_iattr = sd_iattr;
66 }
67
68 /* attributes were changed atleast once in past */
69
70 if (ia_valid & ATTR_UID)
71 sd_iattr->ia_uid = iattr->ia_uid;
72 if (ia_valid & ATTR_GID)
73 sd_iattr->ia_gid = iattr->ia_gid;
74 if (ia_valid & ATTR_ATIME)
75 sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
76 inode->i_sb->s_time_gran);
77 if (ia_valid & ATTR_MTIME)
78 sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
79 inode->i_sb->s_time_gran);
80 if (ia_valid & ATTR_CTIME)
81 sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
82 inode->i_sb->s_time_gran);
83 if (ia_valid & ATTR_MODE) {
84 umode_t mode = iattr->ia_mode;
85
86 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
87 mode &= ~S_ISGID;
88 sd_iattr->ia_mode = mode;
89 }
90
91 return error;
92}
93
94static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
95{
96 inode->i_mode = mode;
97 inode->i_uid = 0;
98 inode->i_gid = 0;
99 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
100}
101
102static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
103{
104 inode->i_mode = iattr->ia_mode;
105 inode->i_uid = iattr->ia_uid;
106 inode->i_gid = iattr->ia_gid;
107 inode->i_atime = iattr->ia_atime;
108 inode->i_mtime = iattr->ia_mtime;
109 inode->i_ctime = iattr->ia_ctime;
110}
111
112struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
30{ 113{
31 struct inode * inode = new_inode(sysfs_sb); 114 struct inode * inode = new_inode(sysfs_sb);
32 if (inode) { 115 if (inode) {
33 inode->i_mode = mode;
34 inode->i_uid = 0;
35 inode->i_gid = 0;
36 inode->i_blksize = PAGE_CACHE_SIZE; 116 inode->i_blksize = PAGE_CACHE_SIZE;
37 inode->i_blocks = 0; 117 inode->i_blocks = 0;
38 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
39 inode->i_mapping->a_ops = &sysfs_aops; 118 inode->i_mapping->a_ops = &sysfs_aops;
40 inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; 119 inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
120 inode->i_op = &sysfs_inode_operations;
121
122 if (sd->s_iattr) {
123 /* sysfs_dirent has non-default attributes
124 * get them for the new inode from persistent copy
125 * in sysfs_dirent
126 */
127 set_inode_attr(inode, sd->s_iattr);
128 } else
129 set_default_inode_attr(inode, mode);
41 } 130 }
42 return inode; 131 return inode;
43} 132}
@@ -48,7 +137,8 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
48 struct inode * inode = NULL; 137 struct inode * inode = NULL;
49 if (dentry) { 138 if (dentry) {
50 if (!dentry->d_inode) { 139 if (!dentry->d_inode) {
51 if ((inode = sysfs_new_inode(mode))) { 140 struct sysfs_dirent * sd = dentry->d_fsdata;
141 if ((inode = sysfs_new_inode(mode, sd))) {
52 if (dentry->d_parent && dentry->d_parent->d_inode) { 142 if (dentry->d_parent && dentry->d_parent->d_inode) {
53 struct inode *p_inode = dentry->d_parent->d_inode; 143 struct inode *p_inode = dentry->d_parent->d_inode;
54 p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; 144 p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 5c805bb1a4b7..f1117e885bd6 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -28,6 +28,7 @@ static struct sysfs_dirent sysfs_root = {
28 .s_children = LIST_HEAD_INIT(sysfs_root.s_children), 28 .s_children = LIST_HEAD_INIT(sysfs_root.s_children),
29 .s_element = NULL, 29 .s_element = NULL,
30 .s_type = SYSFS_ROOT, 30 .s_type = SYSFS_ROOT,
31 .s_iattr = NULL,
31}; 32};
32 33
33static int sysfs_fill_super(struct super_block *sb, void *data, int silent) 34static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
@@ -42,7 +43,8 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
42 sb->s_time_gran = 1; 43 sb->s_time_gran = 1;
43 sysfs_sb = sb; 44 sysfs_sb = sb;
44 45
45 inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO); 46 inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
47 &sysfs_root);
46 if (inode) { 48 if (inode) {
47 inode->i_op = &sysfs_dir_inode_operations; 49 inode->i_op = &sysfs_dir_inode_operations;
48 inode->i_fop = &sysfs_dir_operations; 50 inode->i_fop = &sysfs_dir_operations;
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index dfdf70174354..fae57c83a722 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -43,7 +43,7 @@ static void fill_object_path(struct kobject * kobj, char * buffer, int length)
43 } 43 }
44} 44}
45 45
46static int sysfs_add_link(struct dentry * parent, char * name, struct kobject * target) 46static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target)
47{ 47{
48 struct sysfs_dirent * parent_sd = parent->d_fsdata; 48 struct sysfs_dirent * parent_sd = parent->d_fsdata;
49 struct sysfs_symlink * sl; 49 struct sysfs_symlink * sl;
@@ -79,7 +79,7 @@ exit1:
79 * @target: object we're pointing to. 79 * @target: object we're pointing to.
80 * @name: name of the symlink. 80 * @name: name of the symlink.
81 */ 81 */
82int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name) 82int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
83{ 83{
84 struct dentry * dentry = kobj->dentry; 84 struct dentry * dentry = kobj->dentry;
85 int error = 0; 85 int error = 0;
@@ -99,13 +99,13 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * nam
99 * @name: name of the symlink to remove. 99 * @name: name of the symlink to remove.
100 */ 100 */
101 101
102void sysfs_remove_link(struct kobject * kobj, char * name) 102void sysfs_remove_link(struct kobject * kobj, const char * name)
103{ 103{
104 sysfs_hash_and_remove(kobj->dentry,name); 104 sysfs_hash_and_remove(kobj->dentry,name);
105} 105}
106 106
107static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target, 107static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
108 char *path) 108 char *path)
109{ 109{
110 char * s; 110 char * s;
111 int depth, size; 111 int depth, size;
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index a8a24a0c0b3b..29da6f5f07c8 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -2,7 +2,7 @@
2extern struct vfsmount * sysfs_mount; 2extern struct vfsmount * sysfs_mount;
3extern kmem_cache_t *sysfs_dir_cachep; 3extern kmem_cache_t *sysfs_dir_cachep;
4 4
5extern struct inode * sysfs_new_inode(mode_t mode); 5extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
6extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); 6extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
7 7
8extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, 8extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
@@ -17,6 +17,7 @@ extern void sysfs_remove_subdir(struct dentry *);
17 17
18extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd); 18extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
19extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent); 19extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
20extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
20 21
21extern struct rw_semaphore sysfs_rename_sem; 22extern struct rw_semaphore sysfs_rename_sem;
22extern struct super_block * sysfs_sb; 23extern struct super_block * sysfs_sb;
@@ -75,6 +76,7 @@ static inline void release_sysfs_dirent(struct sysfs_dirent * sd)
75 kobject_put(sl->target_kobj); 76 kobject_put(sl->target_kobj);
76 kfree(sl); 77 kfree(sl);
77 } 78 }
79 kfree(sd->s_iattr);
78 kmem_cache_free(sysfs_dir_cachep, sd); 80 kmem_cache_free(sysfs_dir_cachep, sd);
79} 81}
80 82