diff options
Diffstat (limited to 'fs/configfs/file.c')
-rw-r--r-- | fs/configfs/file.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/fs/configfs/file.c b/fs/configfs/file.c index 3527c7c6def8..a3658f9a082c 100644 --- a/fs/configfs/file.c +++ b/fs/configfs/file.c | |||
@@ -27,19 +27,26 @@ | |||
27 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/mutex.h> | ||
30 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
31 | #include <asm/semaphore.h> | ||
32 | 32 | ||
33 | #include <linux/configfs.h> | 33 | #include <linux/configfs.h> |
34 | #include "configfs_internal.h" | 34 | #include "configfs_internal.h" |
35 | 35 | ||
36 | /* | ||
37 | * A simple attribute can only be 4096 characters. Why 4k? Because the | ||
38 | * original code limited it to PAGE_SIZE. That's a bad idea, though, | ||
39 | * because an attribute of 16k on ia64 won't work on x86. So we limit to | ||
40 | * 4k, our minimum common page size. | ||
41 | */ | ||
42 | #define SIMPLE_ATTR_SIZE 4096 | ||
36 | 43 | ||
37 | struct configfs_buffer { | 44 | struct configfs_buffer { |
38 | size_t count; | 45 | size_t count; |
39 | loff_t pos; | 46 | loff_t pos; |
40 | char * page; | 47 | char * page; |
41 | struct configfs_item_operations * ops; | 48 | struct configfs_item_operations * ops; |
42 | struct semaphore sem; | 49 | struct mutex mutex; |
43 | int needs_read_fill; | 50 | int needs_read_fill; |
44 | }; | 51 | }; |
45 | 52 | ||
@@ -69,7 +76,7 @@ static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buf | |||
69 | 76 | ||
70 | count = ops->show_attribute(item,attr,buffer->page); | 77 | count = ops->show_attribute(item,attr,buffer->page); |
71 | buffer->needs_read_fill = 0; | 78 | buffer->needs_read_fill = 0; |
72 | BUG_ON(count > (ssize_t)PAGE_SIZE); | 79 | BUG_ON(count > (ssize_t)SIMPLE_ATTR_SIZE); |
73 | if (count >= 0) | 80 | if (count >= 0) |
74 | buffer->count = count; | 81 | buffer->count = count; |
75 | else | 82 | else |
@@ -102,7 +109,7 @@ configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *pp | |||
102 | struct configfs_buffer * buffer = file->private_data; | 109 | struct configfs_buffer * buffer = file->private_data; |
103 | ssize_t retval = 0; | 110 | ssize_t retval = 0; |
104 | 111 | ||
105 | down(&buffer->sem); | 112 | mutex_lock(&buffer->mutex); |
106 | if (buffer->needs_read_fill) { | 113 | if (buffer->needs_read_fill) { |
107 | if ((retval = fill_read_buffer(file->f_path.dentry,buffer))) | 114 | if ((retval = fill_read_buffer(file->f_path.dentry,buffer))) |
108 | goto out; | 115 | goto out; |
@@ -112,7 +119,7 @@ configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *pp | |||
112 | retval = simple_read_from_buffer(buf, count, ppos, buffer->page, | 119 | retval = simple_read_from_buffer(buf, count, ppos, buffer->page, |
113 | buffer->count); | 120 | buffer->count); |
114 | out: | 121 | out: |
115 | up(&buffer->sem); | 122 | mutex_unlock(&buffer->mutex); |
116 | return retval; | 123 | return retval; |
117 | } | 124 | } |
118 | 125 | ||
@@ -137,8 +144,8 @@ fill_write_buffer(struct configfs_buffer * buffer, const char __user * buf, size | |||
137 | if (!buffer->page) | 144 | if (!buffer->page) |
138 | return -ENOMEM; | 145 | return -ENOMEM; |
139 | 146 | ||
140 | if (count >= PAGE_SIZE) | 147 | if (count >= SIMPLE_ATTR_SIZE) |
141 | count = PAGE_SIZE - 1; | 148 | count = SIMPLE_ATTR_SIZE - 1; |
142 | error = copy_from_user(buffer->page,buf,count); | 149 | error = copy_from_user(buffer->page,buf,count); |
143 | buffer->needs_read_fill = 1; | 150 | buffer->needs_read_fill = 1; |
144 | /* if buf is assumed to contain a string, terminate it by \0, | 151 | /* if buf is assumed to contain a string, terminate it by \0, |
@@ -193,13 +200,13 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof | |||
193 | struct configfs_buffer * buffer = file->private_data; | 200 | struct configfs_buffer * buffer = file->private_data; |
194 | ssize_t len; | 201 | ssize_t len; |
195 | 202 | ||
196 | down(&buffer->sem); | 203 | mutex_lock(&buffer->mutex); |
197 | len = fill_write_buffer(buffer, buf, count); | 204 | len = fill_write_buffer(buffer, buf, count); |
198 | if (len > 0) | 205 | if (len > 0) |
199 | len = flush_write_buffer(file->f_path.dentry, buffer, count); | 206 | len = flush_write_buffer(file->f_path.dentry, buffer, count); |
200 | if (len > 0) | 207 | if (len > 0) |
201 | *ppos += len; | 208 | *ppos += len; |
202 | up(&buffer->sem); | 209 | mutex_unlock(&buffer->mutex); |
203 | return len; | 210 | return len; |
204 | } | 211 | } |
205 | 212 | ||
@@ -253,7 +260,7 @@ static int check_perm(struct inode * inode, struct file * file) | |||
253 | error = -ENOMEM; | 260 | error = -ENOMEM; |
254 | goto Enomem; | 261 | goto Enomem; |
255 | } | 262 | } |
256 | init_MUTEX(&buffer->sem); | 263 | mutex_init(&buffer->mutex); |
257 | buffer->needs_read_fill = 1; | 264 | buffer->needs_read_fill = 1; |
258 | buffer->ops = ops; | 265 | buffer->ops = ops; |
259 | file->private_data = buffer; | 266 | file->private_data = buffer; |
@@ -292,6 +299,7 @@ static int configfs_release(struct inode * inode, struct file * filp) | |||
292 | if (buffer) { | 299 | if (buffer) { |
293 | if (buffer->page) | 300 | if (buffer->page) |
294 | free_page((unsigned long)buffer->page); | 301 | free_page((unsigned long)buffer->page); |
302 | mutex_destroy(&buffer->mutex); | ||
295 | kfree(buffer); | 303 | kfree(buffer); |
296 | } | 304 | } |
297 | return 0; | 305 | return 0; |