diff options
| author | Takashi Iwai <tiwai@suse.de> | 2006-04-28 09:13:40 -0400 |
|---|---|---|
| committer | Jaroslav Kysela <perex@suse.cz> | 2006-06-22 15:33:07 -0400 |
| commit | 7e4eeec8a30fa9e00cac67a37ca9ddf6cbdb79c4 (patch) | |
| tree | 73e296c11c87e399b32aa9b7714575180bf8b39a /sound/core/info.c | |
| parent | 2f4ca8e5c7cf6a6f7935483d8ee4aa8b039bdd7d (diff) | |
[ALSA] Make buffer size of proc text interface variable
Make the read/write buffer size of proc text interface variable.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core/info.c')
| -rw-r--r-- | sound/core/info.c | 149 |
1 files changed, 79 insertions, 70 deletions
diff --git a/sound/core/info.c b/sound/core/info.c index 9c288539e99d..86366839c4bb 100644 --- a/sound/core/info.c +++ b/sound/core/info.c | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | 21 | ||
| 22 | #include <sound/driver.h> | 22 | #include <sound/driver.h> |
| 23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| 24 | #include <linux/vmalloc.h> | ||
| 25 | #include <linux/time.h> | 24 | #include <linux/time.h> |
| 26 | #include <linux/smp_lock.h> | 25 | #include <linux/smp_lock.h> |
| 27 | #include <linux/string.h> | 26 | #include <linux/string.h> |
| @@ -82,6 +81,24 @@ static int snd_info_version_init(void); | |||
| 82 | static int snd_info_version_done(void); | 81 | static int snd_info_version_done(void); |
| 83 | 82 | ||
| 84 | 83 | ||
| 84 | /* resize the proc r/w buffer */ | ||
| 85 | static int resize_info_buffer(struct snd_info_buffer *buffer, | ||
| 86 | unsigned int nsize) | ||
| 87 | { | ||
| 88 | char *nbuf; | ||
| 89 | |||
| 90 | nsize = PAGE_ALIGN(nsize); | ||
| 91 | nbuf = kmalloc(nsize, GFP_KERNEL); | ||
| 92 | if (! nbuf) | ||
| 93 | return -ENOMEM; | ||
| 94 | |||
| 95 | memcpy(nbuf, buffer->buffer, buffer->len); | ||
| 96 | kfree(buffer->buffer); | ||
| 97 | buffer->buffer = nbuf; | ||
| 98 | buffer->len = nsize; | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 85 | /** | 102 | /** |
| 86 | * snd_iprintf - printf on the procfs buffer | 103 | * snd_iprintf - printf on the procfs buffer |
| 87 | * @buffer: the procfs buffer | 104 | * @buffer: the procfs buffer |
| @@ -95,17 +112,25 @@ int snd_iprintf(struct snd_info_buffer *buffer, char *fmt,...) | |||
| 95 | { | 112 | { |
| 96 | va_list args; | 113 | va_list args; |
| 97 | int len, res; | 114 | int len, res; |
| 115 | int err = 0; | ||
| 98 | 116 | ||
| 99 | if (buffer->stop || buffer->error) | 117 | if (buffer->stop || buffer->error) |
| 100 | return 0; | 118 | return 0; |
| 101 | len = buffer->len - buffer->size; | 119 | len = buffer->len - buffer->size; |
| 102 | va_start(args, fmt); | 120 | va_start(args, fmt); |
| 103 | res = vsnprintf(buffer->curr, len, fmt, args); | 121 | for (;;) { |
| 104 | va_end(args); | 122 | res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, args); |
| 105 | if (res >= len) { | 123 | if (res < len) |
| 106 | buffer->stop = 1; | 124 | break; |
| 107 | return 0; | 125 | err = resize_info_buffer(buffer, buffer->len + PAGE_SIZE); |
| 126 | if (err < 0) | ||
| 127 | break; | ||
| 128 | len = buffer->len - buffer->size; | ||
| 108 | } | 129 | } |
| 130 | va_end(args); | ||
| 131 | |||
| 132 | if (err < 0) | ||
| 133 | return err; | ||
| 109 | buffer->curr += res; | 134 | buffer->curr += res; |
| 110 | buffer->size += res; | 135 | buffer->size += res; |
| 111 | return res; | 136 | return res; |
| @@ -225,7 +250,7 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer | |||
| 225 | struct snd_info_private_data *data; | 250 | struct snd_info_private_data *data; |
| 226 | struct snd_info_entry *entry; | 251 | struct snd_info_entry *entry; |
| 227 | struct snd_info_buffer *buf; | 252 | struct snd_info_buffer *buf; |
| 228 | size_t size = 0; | 253 | ssize_t size = 0; |
| 229 | loff_t pos; | 254 | loff_t pos; |
| 230 | 255 | ||
| 231 | data = file->private_data; | 256 | data = file->private_data; |
| @@ -241,14 +266,20 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer | |||
| 241 | buf = data->wbuffer; | 266 | buf = data->wbuffer; |
| 242 | if (buf == NULL) | 267 | if (buf == NULL) |
| 243 | return -EIO; | 268 | return -EIO; |
| 244 | if (pos >= buf->len) | 269 | mutex_unlock(&entry->access); |
| 245 | return -ENOMEM; | 270 | if (pos + count >= buf->len) { |
| 246 | size = buf->len - pos; | 271 | if (resize_info_buffer(buf, pos + count)) { |
| 247 | size = min(count, size); | 272 | mutex_unlock(&entry->access); |
| 248 | if (copy_from_user(buf->buffer + pos, buffer, size)) | 273 | return -ENOMEM; |
| 274 | } | ||
| 275 | } | ||
| 276 | if (copy_from_user(buf->buffer + pos, buffer, count)) { | ||
| 277 | mutex_unlock(&entry->access); | ||
| 249 | return -EFAULT; | 278 | return -EFAULT; |
| 250 | if ((long)buf->size < pos + size) | 279 | } |
| 251 | buf->size = pos + size; | 280 | buf->size = pos + count; |
| 281 | mutex_unlock(&entry->access); | ||
| 282 | size = count; | ||
| 252 | break; | 283 | break; |
| 253 | case SNDRV_INFO_CONTENT_DATA: | 284 | case SNDRV_INFO_CONTENT_DATA: |
| 254 | if (entry->c.ops->write) | 285 | if (entry->c.ops->write) |
| @@ -283,18 +314,14 @@ static int snd_info_entry_open(struct inode *inode, struct file *file) | |||
| 283 | } | 314 | } |
| 284 | mode = file->f_flags & O_ACCMODE; | 315 | mode = file->f_flags & O_ACCMODE; |
| 285 | if (mode == O_RDONLY || mode == O_RDWR) { | 316 | if (mode == O_RDONLY || mode == O_RDWR) { |
| 286 | if ((entry->content == SNDRV_INFO_CONTENT_TEXT && | 317 | if ((entry->content == SNDRV_INFO_CONTENT_DATA && |
| 287 | !entry->c.text.read_size) || | ||
| 288 | (entry->content == SNDRV_INFO_CONTENT_DATA && | ||
| 289 | entry->c.ops->read == NULL)) { | 318 | entry->c.ops->read == NULL)) { |
| 290 | err = -ENODEV; | 319 | err = -ENODEV; |
| 291 | goto __error; | 320 | goto __error; |
| 292 | } | 321 | } |
| 293 | } | 322 | } |
| 294 | if (mode == O_WRONLY || mode == O_RDWR) { | 323 | if (mode == O_WRONLY || mode == O_RDWR) { |
| 295 | if ((entry->content == SNDRV_INFO_CONTENT_TEXT && | 324 | if ((entry->content == SNDRV_INFO_CONTENT_DATA && |
| 296 | !entry->c.text.write_size) || | ||
| 297 | (entry->content == SNDRV_INFO_CONTENT_DATA && | ||
| 298 | entry->c.ops->write == NULL)) { | 325 | entry->c.ops->write == NULL)) { |
| 299 | err = -ENODEV; | 326 | err = -ENODEV; |
| 300 | goto __error; | 327 | goto __error; |
| @@ -310,49 +337,23 @@ static int snd_info_entry_open(struct inode *inode, struct file *file) | |||
| 310 | case SNDRV_INFO_CONTENT_TEXT: | 337 | case SNDRV_INFO_CONTENT_TEXT: |
| 311 | if (mode == O_RDONLY || mode == O_RDWR) { | 338 | if (mode == O_RDONLY || mode == O_RDWR) { |
| 312 | buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); | 339 | buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); |
| 313 | if (buffer == NULL) { | 340 | if (buffer == NULL) |
| 314 | kfree(data); | 341 | goto __nomem; |
| 315 | err = -ENOMEM; | ||
| 316 | goto __error; | ||
| 317 | } | ||
| 318 | buffer->len = (entry->c.text.read_size + | ||
| 319 | (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); | ||
| 320 | buffer->buffer = vmalloc(buffer->len); | ||
| 321 | if (buffer->buffer == NULL) { | ||
| 322 | kfree(buffer); | ||
| 323 | kfree(data); | ||
| 324 | err = -ENOMEM; | ||
| 325 | goto __error; | ||
| 326 | } | ||
| 327 | buffer->curr = buffer->buffer; | ||
| 328 | data->rbuffer = buffer; | 342 | data->rbuffer = buffer; |
| 343 | buffer->len = PAGE_SIZE; | ||
| 344 | buffer->buffer = kmalloc(buffer->len, GFP_KERNEL); | ||
| 345 | if (buffer->buffer == NULL) | ||
| 346 | goto __nomem; | ||
| 329 | } | 347 | } |
| 330 | if (mode == O_WRONLY || mode == O_RDWR) { | 348 | if (mode == O_WRONLY || mode == O_RDWR) { |
| 331 | buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); | 349 | buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); |
| 332 | if (buffer == NULL) { | 350 | if (buffer == NULL) |
| 333 | if (mode == O_RDWR) { | 351 | goto __nomem; |
| 334 | vfree(data->rbuffer->buffer); | ||
| 335 | kfree(data->rbuffer); | ||
| 336 | } | ||
| 337 | kfree(data); | ||
| 338 | err = -ENOMEM; | ||
| 339 | goto __error; | ||
| 340 | } | ||
| 341 | buffer->len = (entry->c.text.write_size + | ||
| 342 | (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); | ||
| 343 | buffer->buffer = vmalloc(buffer->len); | ||
| 344 | if (buffer->buffer == NULL) { | ||
| 345 | if (mode == O_RDWR) { | ||
| 346 | vfree(data->rbuffer->buffer); | ||
| 347 | kfree(data->rbuffer); | ||
| 348 | } | ||
| 349 | kfree(buffer); | ||
| 350 | kfree(data); | ||
| 351 | err = -ENOMEM; | ||
| 352 | goto __error; | ||
| 353 | } | ||
| 354 | buffer->curr = buffer->buffer; | ||
| 355 | data->wbuffer = buffer; | 352 | data->wbuffer = buffer; |
| 353 | buffer->len = PAGE_SIZE; | ||
| 354 | buffer->buffer = kmalloc(buffer->len, GFP_KERNEL); | ||
| 355 | if (buffer->buffer == NULL) | ||
| 356 | goto __nomem; | ||
| 356 | } | 357 | } |
| 357 | break; | 358 | break; |
| 358 | case SNDRV_INFO_CONTENT_DATA: /* data */ | 359 | case SNDRV_INFO_CONTENT_DATA: /* data */ |
| @@ -377,6 +378,17 @@ static int snd_info_entry_open(struct inode *inode, struct file *file) | |||
| 377 | } | 378 | } |
| 378 | return 0; | 379 | return 0; |
| 379 | 380 | ||
| 381 | __nomem: | ||
| 382 | if (data->rbuffer) { | ||
| 383 | kfree(data->rbuffer->buffer); | ||
| 384 | kfree(data->rbuffer); | ||
| 385 | } | ||
| 386 | if (data->wbuffer) { | ||
| 387 | kfree(data->wbuffer->buffer); | ||
| 388 | kfree(data->wbuffer); | ||
| 389 | } | ||
| 390 | kfree(data); | ||
| 391 | err = -ENOMEM; | ||
| 380 | __error: | 392 | __error: |
| 381 | module_put(entry->module); | 393 | module_put(entry->module); |
| 382 | __error1: | 394 | __error1: |
| @@ -395,11 +407,11 @@ static int snd_info_entry_release(struct inode *inode, struct file *file) | |||
| 395 | entry = data->entry; | 407 | entry = data->entry; |
| 396 | switch (entry->content) { | 408 | switch (entry->content) { |
| 397 | case SNDRV_INFO_CONTENT_TEXT: | 409 | case SNDRV_INFO_CONTENT_TEXT: |
| 398 | if (mode == O_RDONLY || mode == O_RDWR) { | 410 | if (data->rbuffer) { |
| 399 | vfree(data->rbuffer->buffer); | 411 | kfree(data->rbuffer->buffer); |
| 400 | kfree(data->rbuffer); | 412 | kfree(data->rbuffer); |
| 401 | } | 413 | } |
| 402 | if (mode == O_WRONLY || mode == O_RDWR) { | 414 | if (data->wbuffer) { |
| 403 | if (entry->c.text.write) { | 415 | if (entry->c.text.write) { |
| 404 | entry->c.text.write(entry, data->wbuffer); | 416 | entry->c.text.write(entry, data->wbuffer); |
| 405 | if (data->wbuffer->error) { | 417 | if (data->wbuffer->error) { |
| @@ -408,7 +420,7 @@ static int snd_info_entry_release(struct inode *inode, struct file *file) | |||
| 408 | data->wbuffer->error); | 420 | data->wbuffer->error); |
| 409 | } | 421 | } |
| 410 | } | 422 | } |
| 411 | vfree(data->wbuffer->buffer); | 423 | kfree(data->wbuffer->buffer); |
| 412 | kfree(data->wbuffer); | 424 | kfree(data->wbuffer); |
| 413 | } | 425 | } |
| 414 | break; | 426 | break; |
| @@ -668,24 +680,22 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len) | |||
| 668 | if (len <= 0 || buffer->stop || buffer->error) | 680 | if (len <= 0 || buffer->stop || buffer->error) |
| 669 | return 1; | 681 | return 1; |
| 670 | while (--len > 0) { | 682 | while (--len > 0) { |
| 671 | c = *buffer->curr++; | 683 | c = buffer->buffer[buffer->curr++]; |
| 672 | if (c == '\n') { | 684 | if (c == '\n') { |
| 673 | if ((buffer->curr - buffer->buffer) >= (long)buffer->size) { | 685 | if (buffer->curr >= buffer->size) |
| 674 | buffer->stop = 1; | 686 | buffer->stop = 1; |
| 675 | } | ||
| 676 | break; | 687 | break; |
| 677 | } | 688 | } |
| 678 | *line++ = c; | 689 | *line++ = c; |
| 679 | if ((buffer->curr - buffer->buffer) >= (long)buffer->size) { | 690 | if (buffer->curr >= buffer->size) { |
| 680 | buffer->stop = 1; | 691 | buffer->stop = 1; |
| 681 | break; | 692 | break; |
| 682 | } | 693 | } |
| 683 | } | 694 | } |
| 684 | while (c != '\n' && !buffer->stop) { | 695 | while (c != '\n' && !buffer->stop) { |
| 685 | c = *buffer->curr++; | 696 | c = buffer->buffer[buffer->curr++]; |
| 686 | if ((buffer->curr - buffer->buffer) >= (long)buffer->size) { | 697 | if (buffer->curr >= buffer->size) |
| 687 | buffer->stop = 1; | 698 | buffer->stop = 1; |
| 688 | } | ||
| 689 | } | 699 | } |
| 690 | *line = '\0'; | 700 | *line = '\0'; |
| 691 | return 0; | 701 | return 0; |
| @@ -978,7 +988,6 @@ static int __init snd_info_version_init(void) | |||
| 978 | entry = snd_info_create_module_entry(THIS_MODULE, "version", NULL); | 988 | entry = snd_info_create_module_entry(THIS_MODULE, "version", NULL); |
| 979 | if (entry == NULL) | 989 | if (entry == NULL) |
| 980 | return -ENOMEM; | 990 | return -ENOMEM; |
| 981 | entry->c.text.read_size = 256; | ||
| 982 | entry->c.text.read = snd_info_version_read; | 991 | entry->c.text.read = snd_info_version_read; |
| 983 | if (snd_info_register(entry) < 0) { | 992 | if (snd_info_register(entry) < 0) { |
| 984 | snd_info_free_entry(entry); | 993 | snd_info_free_entry(entry); |
