diff options
Diffstat (limited to 'fs/file.c')
| -rw-r--r-- | fs/file.c | 58 | 
1 files changed, 44 insertions, 14 deletions
diff --git a/fs/file.c b/fs/file.c index 771578b33fb6..60a45e9f5323 100644 --- a/fs/file.c +++ b/fs/file.c @@ -34,7 +34,7 @@ static void *alloc_fdmem(size_t size)  	 * vmalloc() if the allocation size will be considered "large" by the VM.  	 */  	if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) { -		void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN); +		void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN|__GFP_NORETRY);  		if (data != NULL)  			return data;  	} @@ -683,35 +683,65 @@ EXPORT_SYMBOL(fget_raw);   * The fput_needed flag returned by fget_light should be passed to the   * corresponding fput_light.   */ -struct file *__fget_light(unsigned int fd, fmode_t mask, int *fput_needed) +static unsigned long __fget_light(unsigned int fd, fmode_t mask)  {  	struct files_struct *files = current->files;  	struct file *file; -	*fput_needed = 0;  	if (atomic_read(&files->count) == 1) {  		file = __fcheck_files(files, fd); -		if (file && (file->f_mode & mask)) -			file = NULL; +		if (!file || unlikely(file->f_mode & mask)) +			return 0; +		return (unsigned long)file;  	} else {  		file = __fget(fd, mask); -		if (file) -			*fput_needed = 1; +		if (!file) +			return 0; +		return FDPUT_FPUT | (unsigned long)file;  	} - -	return file;  } -struct file *fget_light(unsigned int fd, int *fput_needed) +unsigned long __fdget(unsigned int fd)  { -	return __fget_light(fd, FMODE_PATH, fput_needed); +	return __fget_light(fd, FMODE_PATH);  } -EXPORT_SYMBOL(fget_light); +EXPORT_SYMBOL(__fdget); -struct file *fget_raw_light(unsigned int fd, int *fput_needed) +unsigned long __fdget_raw(unsigned int fd)  { -	return __fget_light(fd, 0, fput_needed); +	return __fget_light(fd, 0); +} + +unsigned long __fdget_pos(unsigned int fd) +{ +	struct files_struct *files = current->files; +	struct file *file; +	unsigned long v; + +	if (atomic_read(&files->count) == 1) { +		file = __fcheck_files(files, fd); +		v = 0; +	} else { +		file = __fget(fd, 0); +		v = FDPUT_FPUT; +	} +	if (!file) +		return 0; + +	if (file->f_mode & FMODE_ATOMIC_POS) { +		if (file_count(file) > 1) { +			v |= FDPUT_POS_UNLOCK; +			mutex_lock(&file->f_pos_lock); +		} +	} +	return v | (unsigned long)file;  } +/* + * We only lock f_pos if we have threads or if the file might be + * shared with another process. In both cases we'll have an elevated + * file count (done either by fdget() or by fork()). + */ +  void set_close_on_exec(unsigned int fd, int flag)  {  	struct files_struct *files = current->files;  | 
