diff options
| author | Takashi Iwai <tiwai@suse.de> | 2006-04-28 15:13:40 +0200 | 
|---|---|---|
| committer | Jaroslav Kysela <perex@suse.cz> | 2006-06-22 21:33:07 +0200 | 
| commit | 7e4eeec8a30fa9e00cac67a37ca9ddf6cbdb79c4 (patch) | |
| tree | 73e296c11c87e399b32aa9b7714575180bf8b39a | |
| parent | 2f4ca8e5c7cf6a6f7935483d8ee4aa8b039bdd7d (diff) | |
| download | olio-linux-3.10-7e4eeec8a30fa9e00cac67a37ca9ddf6cbdb79c4.tar.xz olio-linux-3.10-7e4eeec8a30fa9e00cac67a37ca9ddf6cbdb79c4.zip  | |
[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>
| -rw-r--r-- | include/sound/info.h | 6 | ||||
| -rw-r--r-- | sound/core/info.c | 149 | 
2 files changed, 82 insertions, 73 deletions
diff --git a/include/sound/info.h b/include/sound/info.h index f23d8381c21..48128438985 100644 --- a/include/sound/info.h +++ b/include/sound/info.h @@ -27,9 +27,9 @@  /* buffer for information */  struct snd_info_buffer {  	char *buffer;		/* pointer to begin of buffer */ -	char *curr;		/* current position in buffer */ -	unsigned long size;	/* current size */ -	unsigned long len;	/* total length of buffer */ +	unsigned int curr;	/* current position in buffer */ +	unsigned int size;	/* current size */ +	unsigned int len;	/* total length of buffer */  	int stop;		/* stop flag */  	int error;		/* error code */  }; diff --git a/sound/core/info.c b/sound/core/info.c index 9c288539e99..86366839c4b 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -21,7 +21,6 @@  #include <sound/driver.h>  #include <linux/init.h> -#include <linux/vmalloc.h>  #include <linux/time.h>  #include <linux/smp_lock.h>  #include <linux/string.h> @@ -82,6 +81,24 @@ static int snd_info_version_init(void);  static int snd_info_version_done(void); +/* resize the proc r/w buffer */ +static int resize_info_buffer(struct snd_info_buffer *buffer, +			      unsigned int nsize) +{ +	char *nbuf; + +	nsize = PAGE_ALIGN(nsize); +	nbuf = kmalloc(nsize, GFP_KERNEL); +	if (! nbuf) +		return -ENOMEM; + +	memcpy(nbuf, buffer->buffer, buffer->len); +	kfree(buffer->buffer); +	buffer->buffer = nbuf; +	buffer->len = nsize; +	return 0; +} +  /**   * snd_iprintf - printf on the procfs buffer   * @buffer: the procfs buffer @@ -95,17 +112,25 @@ int snd_iprintf(struct snd_info_buffer *buffer, char *fmt,...)  {  	va_list args;  	int len, res; +	int err = 0;  	if (buffer->stop || buffer->error)  		return 0;  	len = buffer->len - buffer->size;  	va_start(args, fmt); -	res = vsnprintf(buffer->curr, len, fmt, args); -	va_end(args); -	if (res >= len) { -		buffer->stop = 1; -		return 0; +	for (;;) { +		res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, args); +		if (res < len) +			break; +		err = resize_info_buffer(buffer, buffer->len + PAGE_SIZE); +		if (err < 0) +			break; +		len = buffer->len - buffer->size;  	} +	va_end(args); + +	if (err < 0) +		return err;  	buffer->curr += res;  	buffer->size += res;  	return res; @@ -225,7 +250,7 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer  	struct snd_info_private_data *data;  	struct snd_info_entry *entry;  	struct snd_info_buffer *buf; -	size_t size = 0; +	ssize_t size = 0;  	loff_t pos;  	data = file->private_data; @@ -241,14 +266,20 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer  		buf = data->wbuffer;  		if (buf == NULL)  			return -EIO; -		if (pos >= buf->len) -			return -ENOMEM; -		size = buf->len - pos; -		size = min(count, size); -		if (copy_from_user(buf->buffer + pos, buffer, size)) +		mutex_unlock(&entry->access); +		if (pos + count >= buf->len) { +			if (resize_info_buffer(buf, pos + count)) { +				mutex_unlock(&entry->access); +				return -ENOMEM; +			} +		} +		if (copy_from_user(buf->buffer + pos, buffer, count)) { +			mutex_unlock(&entry->access);  			return -EFAULT; -		if ((long)buf->size < pos + size) -			buf->size = pos + size; +		} +		buf->size = pos + count; +		mutex_unlock(&entry->access); +		size = count;  		break;  	case SNDRV_INFO_CONTENT_DATA:  		if (entry->c.ops->write) @@ -283,18 +314,14 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)  	}  	mode = file->f_flags & O_ACCMODE;  	if (mode == O_RDONLY || mode == O_RDWR) { -		if ((entry->content == SNDRV_INFO_CONTENT_TEXT && -		     !entry->c.text.read_size) || -		    (entry->content == SNDRV_INFO_CONTENT_DATA && +		if ((entry->content == SNDRV_INFO_CONTENT_DATA &&  		     entry->c.ops->read == NULL)) {  		    	err = -ENODEV;  		    	goto __error;  		}  	}  	if (mode == O_WRONLY || mode == O_RDWR) { -		if ((entry->content == SNDRV_INFO_CONTENT_TEXT && -		     !entry->c.text.write_size) || -		    (entry->content == SNDRV_INFO_CONTENT_DATA && +		if ((entry->content == SNDRV_INFO_CONTENT_DATA &&  		     entry->c.ops->write == NULL)) {  		    	err = -ENODEV;  		    	goto __error; @@ -310,49 +337,23 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)  	case SNDRV_INFO_CONTENT_TEXT:  		if (mode == O_RDONLY || mode == O_RDWR) {  			buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); -			if (buffer == NULL) { -				kfree(data); -				err = -ENOMEM; -				goto __error; -			} -			buffer->len = (entry->c.text.read_size + -				      (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); -			buffer->buffer = vmalloc(buffer->len); -			if (buffer->buffer == NULL) { -				kfree(buffer); -				kfree(data); -				err = -ENOMEM; -				goto __error; -			} -			buffer->curr = buffer->buffer; +			if (buffer == NULL) +				goto __nomem;  			data->rbuffer = buffer; +			buffer->len = PAGE_SIZE; +			buffer->buffer = kmalloc(buffer->len, GFP_KERNEL); +			if (buffer->buffer == NULL) +				goto __nomem;  		}  		if (mode == O_WRONLY || mode == O_RDWR) {  			buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); -			if (buffer == NULL) { -				if (mode == O_RDWR) { -					vfree(data->rbuffer->buffer); -					kfree(data->rbuffer); -				} -				kfree(data); -				err = -ENOMEM; -				goto __error; -			} -			buffer->len = (entry->c.text.write_size + -				      (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); -			buffer->buffer = vmalloc(buffer->len); -			if (buffer->buffer == NULL) { -				if (mode == O_RDWR) { -					vfree(data->rbuffer->buffer); -					kfree(data->rbuffer); -				} -				kfree(buffer); -				kfree(data); -				err = -ENOMEM; -				goto __error; -			} -			buffer->curr = buffer->buffer; +			if (buffer == NULL) +				goto __nomem;  			data->wbuffer = buffer; +			buffer->len = PAGE_SIZE; +			buffer->buffer = kmalloc(buffer->len, GFP_KERNEL); +			if (buffer->buffer == NULL) +				goto __nomem;  		}  		break;  	case SNDRV_INFO_CONTENT_DATA:	/* data */ @@ -377,6 +378,17 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)  	}  	return 0; + __nomem: +	if (data->rbuffer) { +		kfree(data->rbuffer->buffer); +		kfree(data->rbuffer); +	} +	if (data->wbuffer) { +		kfree(data->wbuffer->buffer); +		kfree(data->wbuffer); +	} +	kfree(data); +	err = -ENOMEM;        __error:  	module_put(entry->module);        __error1: @@ -395,11 +407,11 @@ static int snd_info_entry_release(struct inode *inode, struct file *file)  	entry = data->entry;  	switch (entry->content) {  	case SNDRV_INFO_CONTENT_TEXT: -		if (mode == O_RDONLY || mode == O_RDWR) { -			vfree(data->rbuffer->buffer); +		if (data->rbuffer) { +			kfree(data->rbuffer->buffer);  			kfree(data->rbuffer);  		} -		if (mode == O_WRONLY || mode == O_RDWR) { +		if (data->wbuffer) {  			if (entry->c.text.write) {  				entry->c.text.write(entry, data->wbuffer);  				if (data->wbuffer->error) { @@ -408,7 +420,7 @@ static int snd_info_entry_release(struct inode *inode, struct file *file)  						data->wbuffer->error);  				}  			} -			vfree(data->wbuffer->buffer); +			kfree(data->wbuffer->buffer);  			kfree(data->wbuffer);  		}  		break; @@ -668,24 +680,22 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len)  	if (len <= 0 || buffer->stop || buffer->error)  		return 1;  	while (--len > 0) { -		c = *buffer->curr++; +		c = buffer->buffer[buffer->curr++];  		if (c == '\n') { -			if ((buffer->curr - buffer->buffer) >= (long)buffer->size) { +			if (buffer->curr >= buffer->size)  				buffer->stop = 1; -			}  			break;  		}  		*line++ = c; -		if ((buffer->curr - buffer->buffer) >= (long)buffer->size) { +		if (buffer->curr >= buffer->size) {  			buffer->stop = 1;  			break;  		}  	}  	while (c != '\n' && !buffer->stop) { -		c = *buffer->curr++; -		if ((buffer->curr - buffer->buffer) >= (long)buffer->size) { +		c = buffer->buffer[buffer->curr++]; +		if (buffer->curr >= buffer->size)  			buffer->stop = 1; -		}  	}  	*line = '\0';  	return 0; @@ -978,7 +988,6 @@ static int __init snd_info_version_init(void)  	entry = snd_info_create_module_entry(THIS_MODULE, "version", NULL);  	if (entry == NULL)  		return -ENOMEM; -	entry->c.text.read_size = 256;  	entry->c.text.read = snd_info_version_read;  	if (snd_info_register(entry) < 0) {  		snd_info_free_entry(entry);  |