file.c (83f1bfd6f57c422da70d1e296df1becc35c868be) | file.c (5955102c9984fa081b2d570cfac75c97eecf8f3b) |
---|---|
1/* -*- mode: c; c-basic-offset: 8; -*- 2 * vim: noexpandtab sw=8 ts=8 sts=0: 3 * 4 * file.c - operations for regular (text) files. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public 8 * License as published by the Free Software Foundation; either --- 14 unchanged lines hidden (view full) --- 23 * 24 * configfs Copyright (C) 2005 Oracle. All rights reserved. 25 */ 26 27#include <linux/fs.h> 28#include <linux/module.h> 29#include <linux/slab.h> 30#include <linux/mutex.h> | 1/* -*- mode: c; c-basic-offset: 8; -*- 2 * vim: noexpandtab sw=8 ts=8 sts=0: 3 * 4 * file.c - operations for regular (text) files. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public 8 * License as published by the Free Software Foundation; either --- 14 unchanged lines hidden (view full) --- 23 * 24 * configfs Copyright (C) 2005 Oracle. All rights reserved. 25 */ 26 27#include <linux/fs.h> 28#include <linux/module.h> 29#include <linux/slab.h> 30#include <linux/mutex.h> |
31#include <linux/vmalloc.h> |
|
31#include <asm/uaccess.h> 32 33#include <linux/configfs.h> 34#include "configfs_internal.h" 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, --- 4 unchanged lines hidden (view full) --- 43 44struct configfs_buffer { 45 size_t count; 46 loff_t pos; 47 char * page; 48 struct configfs_item_operations * ops; 49 struct mutex mutex; 50 int needs_read_fill; | 32#include <asm/uaccess.h> 33 34#include <linux/configfs.h> 35#include "configfs_internal.h" 36 37/* 38 * A simple attribute can only be 4096 characters. Why 4k? Because the 39 * original code limited it to PAGE_SIZE. That's a bad idea, though, --- 4 unchanged lines hidden (view full) --- 44 45struct configfs_buffer { 46 size_t count; 47 loff_t pos; 48 char * page; 49 struct configfs_item_operations * ops; 50 struct mutex mutex; 51 int needs_read_fill; |
52 bool read_in_progress; 53 bool write_in_progress; 54 char *bin_buffer; 55 int bin_buffer_size; |
|
51}; 52 53 54/** 55 * fill_read_buffer - allocate and fill buffer from item. 56 * @dentry: dentry pointer. 57 * @buffer: data buffer for file. 58 * --- 59 unchanged lines hidden (view full) --- 118 __func__, count, *ppos, buffer->page); 119 retval = simple_read_from_buffer(buf, count, ppos, buffer->page, 120 buffer->count); 121out: 122 mutex_unlock(&buffer->mutex); 123 return retval; 124} 125 | 56}; 57 58 59/** 60 * fill_read_buffer - allocate and fill buffer from item. 61 * @dentry: dentry pointer. 62 * @buffer: data buffer for file. 63 * --- 59 unchanged lines hidden (view full) --- 123 __func__, count, *ppos, buffer->page); 124 retval = simple_read_from_buffer(buf, count, ppos, buffer->page, 125 buffer->count); 126out: 127 mutex_unlock(&buffer->mutex); 128 return retval; 129} 130 |
131/** 132 * configfs_read_bin_file - read a binary attribute. 133 * @file: file pointer. 134 * @buf: buffer to fill. 135 * @count: number of bytes to read. 136 * @ppos: starting offset in file. 137 * 138 * Userspace wants to read a binary attribute file. The attribute 139 * descriptor is in the file's ->d_fsdata. The target item is in the 140 * directory's ->d_fsdata. 141 * 142 * We check whether we need to refill the buffer. If so we will 143 * call the attributes' attr->read() twice. The first time we 144 * will pass a NULL as a buffer pointer, which the attributes' method 145 * will use to return the size of the buffer required. If no error 146 * occurs we will allocate the buffer using vmalloc and call 147 * attr->read() again passing that buffer as an argument. 148 * Then we just copy to user-space using simple_read_from_buffer. 149 */ |
|
126 | 150 |
151static ssize_t 152configfs_read_bin_file(struct file *file, char __user *buf, 153 size_t count, loff_t *ppos) 154{ 155 struct configfs_buffer *buffer = file->private_data; 156 struct dentry *dentry = file->f_path.dentry; 157 struct config_item *item = to_item(dentry->d_parent); 158 struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry); 159 ssize_t retval = 0; 160 ssize_t len = min_t(size_t, count, PAGE_SIZE); 161 162 mutex_lock(&buffer->mutex); 163 164 /* we don't support switching read/write modes */ 165 if (buffer->write_in_progress) { 166 retval = -ETXTBSY; 167 goto out; 168 } 169 buffer->read_in_progress = 1; 170 171 if (buffer->needs_read_fill) { 172 /* perform first read with buf == NULL to get extent */ 173 len = bin_attr->read(item, NULL, 0); 174 if (len <= 0) { 175 retval = len; 176 goto out; 177 } 178 179 /* do not exceed the maximum value */ 180 if (bin_attr->cb_max_size && len > bin_attr->cb_max_size) { 181 retval = -EFBIG; 182 goto out; 183 } 184 185 buffer->bin_buffer = vmalloc(len); 186 if (buffer->bin_buffer == NULL) { 187 retval = -ENOMEM; 188 goto out; 189 } 190 buffer->bin_buffer_size = len; 191 192 /* perform second read to fill buffer */ 193 len = bin_attr->read(item, buffer->bin_buffer, len); 194 if (len < 0) { 195 retval = len; 196 vfree(buffer->bin_buffer); 197 buffer->bin_buffer_size = 0; 198 buffer->bin_buffer = NULL; 199 goto out; 200 } 201 202 buffer->needs_read_fill = 0; 203 } 204 205 retval = simple_read_from_buffer(buf, count, ppos, buffer->bin_buffer, 206 buffer->bin_buffer_size); 207out: 208 mutex_unlock(&buffer->mutex); 209 return retval; 210} 211 212 |
|
127/** 128 * fill_write_buffer - copy buffer from userspace. 129 * @buffer: data buffer for file. 130 * @buf: data from user. 131 * @count: number of bytes in @userbuf. 132 * 133 * Allocate @buffer->page if it hasn't been already, then 134 * copy the user-supplied buffer into it. --- 69 unchanged lines hidden (view full) --- 204 if (len > 0) 205 len = flush_write_buffer(file->f_path.dentry, buffer, len); 206 if (len > 0) 207 *ppos += len; 208 mutex_unlock(&buffer->mutex); 209 return len; 210} 211 | 213/** 214 * fill_write_buffer - copy buffer from userspace. 215 * @buffer: data buffer for file. 216 * @buf: data from user. 217 * @count: number of bytes in @userbuf. 218 * 219 * Allocate @buffer->page if it hasn't been already, then 220 * copy the user-supplied buffer into it. --- 69 unchanged lines hidden (view full) --- 290 if (len > 0) 291 len = flush_write_buffer(file->f_path.dentry, buffer, len); 292 if (len > 0) 293 *ppos += len; 294 mutex_unlock(&buffer->mutex); 295 return len; 296} 297 |
212static int check_perm(struct inode * inode, struct file * file) | 298/** 299 * configfs_write_bin_file - write a binary attribute. 300 * @file: file pointer 301 * @buf: data to write 302 * @count: number of bytes 303 * @ppos: starting offset 304 * 305 * Writing to a binary attribute file is similar to a normal read. 306 * We buffer the consecutive writes (binary attribute files do not 307 * support lseek) in a continuously growing buffer, but we don't 308 * commit until the close of the file. 309 */ 310 311static ssize_t 312configfs_write_bin_file(struct file *file, const char __user *buf, 313 size_t count, loff_t *ppos) |
213{ | 314{ |
315 struct configfs_buffer *buffer = file->private_data; 316 struct dentry *dentry = file->f_path.dentry; 317 struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry); 318 void *tbuf = NULL; 319 ssize_t len; 320 321 mutex_lock(&buffer->mutex); 322 323 /* we don't support switching read/write modes */ 324 if (buffer->read_in_progress) { 325 len = -ETXTBSY; 326 goto out; 327 } 328 buffer->write_in_progress = 1; 329 330 /* buffer grows? */ 331 if (*ppos + count > buffer->bin_buffer_size) { 332 333 if (bin_attr->cb_max_size && 334 *ppos + count > bin_attr->cb_max_size) { 335 len = -EFBIG; 336 } 337 338 tbuf = vmalloc(*ppos + count); 339 if (tbuf == NULL) { 340 len = -ENOMEM; 341 goto out; 342 } 343 344 /* copy old contents */ 345 if (buffer->bin_buffer) { 346 memcpy(tbuf, buffer->bin_buffer, 347 buffer->bin_buffer_size); 348 vfree(buffer->bin_buffer); 349 } 350 351 /* clear the new area */ 352 memset(tbuf + buffer->bin_buffer_size, 0, 353 *ppos + count - buffer->bin_buffer_size); 354 buffer->bin_buffer = tbuf; 355 buffer->bin_buffer_size = *ppos + count; 356 } 357 358 len = simple_write_to_buffer(buffer->bin_buffer, 359 buffer->bin_buffer_size, ppos, buf, count); 360 if (len > 0) 361 *ppos += len; 362out: 363 mutex_unlock(&buffer->mutex); 364 return len; 365} 366 367static int check_perm(struct inode * inode, struct file * file, int type) 368{ |
|
214 struct config_item *item = configfs_get_config_item(file->f_path.dentry->d_parent); 215 struct configfs_attribute * attr = to_attr(file->f_path.dentry); | 369 struct config_item *item = configfs_get_config_item(file->f_path.dentry->d_parent); 370 struct configfs_attribute * attr = to_attr(file->f_path.dentry); |
371 struct configfs_bin_attribute *bin_attr = NULL; |
|
216 struct configfs_buffer * buffer; 217 struct configfs_item_operations * ops = NULL; 218 int error = 0; 219 220 if (!item || !attr) 221 goto Einval; 222 | 372 struct configfs_buffer * buffer; 373 struct configfs_item_operations * ops = NULL; 374 int error = 0; 375 376 if (!item || !attr) 377 goto Einval; 378 |
379 if (type & CONFIGFS_ITEM_BIN_ATTR) 380 bin_attr = to_bin_attr(file->f_path.dentry); 381 |
|
223 /* Grab the module reference for this attribute if we have one */ 224 if (!try_module_get(attr->ca_owner)) { 225 error = -ENODEV; 226 goto Done; 227 } 228 229 if (item->ci_type) 230 ops = item->ci_type->ct_item_ops; 231 else 232 goto Eaccess; 233 234 /* File needs write support. 235 * The inode's perms must say it's ok, 236 * and we must have a store method. 237 */ 238 if (file->f_mode & FMODE_WRITE) { | 382 /* Grab the module reference for this attribute if we have one */ 383 if (!try_module_get(attr->ca_owner)) { 384 error = -ENODEV; 385 goto Done; 386 } 387 388 if (item->ci_type) 389 ops = item->ci_type->ct_item_ops; 390 else 391 goto Eaccess; 392 393 /* File needs write support. 394 * The inode's perms must say it's ok, 395 * and we must have a store method. 396 */ 397 if (file->f_mode & FMODE_WRITE) { |
239 if (!(inode->i_mode & S_IWUGO) || !attr->store) | 398 if (!(inode->i_mode & S_IWUGO)) |
240 goto Eaccess; 241 | 399 goto Eaccess; 400 |
401 if ((type & CONFIGFS_ITEM_ATTR) && !attr->store) 402 goto Eaccess; 403 404 if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->write) 405 goto Eaccess; |
|
242 } 243 244 /* File needs read support. 245 * The inode's perms must say it's ok, and we there 246 * must be a show method for it. 247 */ 248 if (file->f_mode & FMODE_READ) { | 406 } 407 408 /* File needs read support. 409 * The inode's perms must say it's ok, and we there 410 * must be a show method for it. 411 */ 412 if (file->f_mode & FMODE_READ) { |
249 if (!(inode->i_mode & S_IRUGO) || !attr->show) | 413 if (!(inode->i_mode & S_IRUGO)) |
250 goto Eaccess; | 414 goto Eaccess; |
415 416 if ((type & CONFIGFS_ITEM_ATTR) && !attr->show) 417 goto Eaccess; 418 419 if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->read) 420 goto Eaccess; |
|
251 } 252 253 /* No error? Great, allocate a buffer for the file, and store it 254 * it in file->private_data for easy access. 255 */ 256 buffer = kzalloc(sizeof(struct configfs_buffer),GFP_KERNEL); 257 if (!buffer) { 258 error = -ENOMEM; 259 goto Enomem; 260 } 261 mutex_init(&buffer->mutex); 262 buffer->needs_read_fill = 1; | 421 } 422 423 /* No error? Great, allocate a buffer for the file, and store it 424 * it in file->private_data for easy access. 425 */ 426 buffer = kzalloc(sizeof(struct configfs_buffer),GFP_KERNEL); 427 if (!buffer) { 428 error = -ENOMEM; 429 goto Enomem; 430 } 431 mutex_init(&buffer->mutex); 432 buffer->needs_read_fill = 1; |
433 buffer->read_in_progress = 0; 434 buffer->write_in_progress = 0; |
|
263 buffer->ops = ops; 264 file->private_data = buffer; 265 goto Done; 266 267 Einval: 268 error = -EINVAL; 269 goto Done; 270 Eaccess: 271 error = -EACCES; 272 Enomem: 273 module_put(attr->ca_owner); 274 Done: 275 if (error && item) 276 config_item_put(item); 277 return error; 278} 279 | 435 buffer->ops = ops; 436 file->private_data = buffer; 437 goto Done; 438 439 Einval: 440 error = -EINVAL; 441 goto Done; 442 Eaccess: 443 error = -EACCES; 444 Enomem: 445 module_put(attr->ca_owner); 446 Done: 447 if (error && item) 448 config_item_put(item); 449 return error; 450} 451 |
280static int configfs_open_file(struct inode * inode, struct file * filp) | 452static int configfs_release(struct inode *inode, struct file *filp) |
281{ | 453{ |
282 return check_perm(inode,filp); 283} 284 285static int configfs_release(struct inode * inode, struct file * filp) 286{ | |
287 struct config_item * item = to_item(filp->f_path.dentry->d_parent); 288 struct configfs_attribute * attr = to_attr(filp->f_path.dentry); 289 struct module * owner = attr->ca_owner; 290 struct configfs_buffer * buffer = filp->private_data; 291 292 if (item) 293 config_item_put(item); 294 /* After this point, attr should not be accessed. */ 295 module_put(owner); 296 297 if (buffer) { 298 if (buffer->page) 299 free_page((unsigned long)buffer->page); 300 mutex_destroy(&buffer->mutex); 301 kfree(buffer); 302 } 303 return 0; 304} 305 | 454 struct config_item * item = to_item(filp->f_path.dentry->d_parent); 455 struct configfs_attribute * attr = to_attr(filp->f_path.dentry); 456 struct module * owner = attr->ca_owner; 457 struct configfs_buffer * buffer = filp->private_data; 458 459 if (item) 460 config_item_put(item); 461 /* After this point, attr should not be accessed. */ 462 module_put(owner); 463 464 if (buffer) { 465 if (buffer->page) 466 free_page((unsigned long)buffer->page); 467 mutex_destroy(&buffer->mutex); 468 kfree(buffer); 469 } 470 return 0; 471} 472 |
473static int configfs_open_file(struct inode *inode, struct file *filp) 474{ 475 return check_perm(inode, filp, CONFIGFS_ITEM_ATTR); 476} 477 478static int configfs_open_bin_file(struct inode *inode, struct file *filp) 479{ 480 return check_perm(inode, filp, CONFIGFS_ITEM_BIN_ATTR); 481} 482 483static int configfs_release_bin_file(struct inode *inode, struct file *filp) 484{ 485 struct configfs_buffer *buffer = filp->private_data; 486 struct dentry *dentry = filp->f_path.dentry; 487 struct config_item *item = to_item(dentry->d_parent); 488 struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry); 489 ssize_t len = 0; 490 int ret; 491 492 buffer->read_in_progress = 0; 493 494 if (buffer->write_in_progress) { 495 buffer->write_in_progress = 0; 496 497 len = bin_attr->write(item, buffer->bin_buffer, 498 buffer->bin_buffer_size); 499 500 /* vfree on NULL is safe */ 501 vfree(buffer->bin_buffer); 502 buffer->bin_buffer = NULL; 503 buffer->bin_buffer_size = 0; 504 buffer->needs_read_fill = 1; 505 } 506 507 ret = configfs_release(inode, filp); 508 if (len < 0) 509 return len; 510 return ret; 511} 512 513 |
|
306const struct file_operations configfs_file_operations = { 307 .read = configfs_read_file, 308 .write = configfs_write_file, 309 .llseek = generic_file_llseek, 310 .open = configfs_open_file, 311 .release = configfs_release, 312}; 313 | 514const struct file_operations configfs_file_operations = { 515 .read = configfs_read_file, 516 .write = configfs_write_file, 517 .llseek = generic_file_llseek, 518 .open = configfs_open_file, 519 .release = configfs_release, 520}; 521 |
522const struct file_operations configfs_bin_file_operations = { 523 .read = configfs_read_bin_file, 524 .write = configfs_write_bin_file, 525 .llseek = NULL, /* bin file is not seekable */ 526 .open = configfs_open_bin_file, 527 .release = configfs_release_bin_file, 528}; 529 |
|
314/** 315 * configfs_create_file - create an attribute file for an item. 316 * @item: item we're creating for. 317 * @attr: atrribute descriptor. 318 */ 319 320int configfs_create_file(struct config_item * item, const struct configfs_attribute * attr) 321{ 322 struct dentry *dir = item->ci_dentry; 323 struct configfs_dirent *parent_sd = dir->d_fsdata; 324 umode_t mode = (attr->ca_mode & S_IALLUGO) | S_IFREG; 325 int error = 0; 326 | 530/** 531 * configfs_create_file - create an attribute file for an item. 532 * @item: item we're creating for. 533 * @attr: atrribute descriptor. 534 */ 535 536int configfs_create_file(struct config_item * item, const struct configfs_attribute * attr) 537{ 538 struct dentry *dir = item->ci_dentry; 539 struct configfs_dirent *parent_sd = dir->d_fsdata; 540 umode_t mode = (attr->ca_mode & S_IALLUGO) | S_IFREG; 541 int error = 0; 542 |
327 mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_NORMAL); | 543 inode_lock_nested(d_inode(dir), I_MUTEX_NORMAL); |
328 error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode, 329 CONFIGFS_ITEM_ATTR); | 544 error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode, 545 CONFIGFS_ITEM_ATTR); |
330 mutex_unlock(&d_inode(dir)->i_mutex); | 546 inode_unlock(d_inode(dir)); |
331 332 return error; 333} 334 | 547 548 return error; 549} 550 |
551/** 552 * configfs_create_bin_file - create a binary attribute file for an item. 553 * @item: item we're creating for. 554 * @attr: atrribute descriptor. 555 */ 556 557int configfs_create_bin_file(struct config_item *item, 558 const struct configfs_bin_attribute *bin_attr) 559{ 560 struct dentry *dir = item->ci_dentry; 561 struct configfs_dirent *parent_sd = dir->d_fsdata; 562 umode_t mode = (bin_attr->cb_attr.ca_mode & S_IALLUGO) | S_IFREG; 563 int error = 0; 564 565 inode_lock_nested(dir->d_inode, I_MUTEX_NORMAL); 566 error = configfs_make_dirent(parent_sd, NULL, (void *) bin_attr, mode, 567 CONFIGFS_ITEM_BIN_ATTR); 568 inode_unlock(dir->d_inode); 569 570 return error; 571} |
|