| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *  file.c | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  Copyright (C) 1995, 1996 by Volker Lendecke | 
					
						
							|  |  |  |  *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <asm/uaccess.h>
 | 
					
						
							|  |  |  | #include <asm/system.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/time.h>
 | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/errno.h>
 | 
					
						
							|  |  |  | #include <linux/fcntl.h>
 | 
					
						
							|  |  |  | #include <linux/stat.h>
 | 
					
						
							|  |  |  | #include <linux/mm.h>
 | 
					
						
							|  |  |  | #include <linux/vmalloc.h>
 | 
					
						
							| 
									
										
											  
											
												Detach sched.h from mm.h
First thing mm.h does is including sched.h solely for can_do_mlock() inline
function which has "current" dereference inside. By dealing with can_do_mlock()
mm.h can be detached from sched.h which is good. See below, why.
This patch
a) removes unconditional inclusion of sched.h from mm.h
b) makes can_do_mlock() normal function in mm/mlock.c
c) exports can_do_mlock() to not break compilation
d) adds sched.h inclusions back to files that were getting it indirectly.
e) adds less bloated headers to some files (asm/signal.h, jiffies.h) that were
   getting them indirectly
Net result is:
a) mm.h users would get less code to open, read, preprocess, parse, ... if
   they don't need sched.h
b) sched.h stops being dependency for significant number of files:
   on x86_64 allmodconfig touching sched.h results in recompile of 4083 files,
   after patch it's only 3744 (-8.3%).
Cross-compile tested on
	all arm defconfigs, all mips defconfigs, all powerpc defconfigs,
	alpha alpha-up
	arm
	i386 i386-up i386-defconfig i386-allnoconfig
	ia64 ia64-up
	m68k
	mips
	parisc parisc-up
	powerpc powerpc-up
	s390 s390-up
	sparc sparc-up
	sparc64 sparc64-up
	um-x86_64
	x86_64 x86_64-up x86_64-defconfig x86_64-allnoconfig
as well as my two usual configs.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
											
										 
											2007-05-21 01:22:52 +04:00
										 |  |  | #include <linux/sched.h>
 | 
					
						
							| 
									
										
										
										
											2008-06-27 11:05:24 +02:00
										 |  |  | #include <linux/smp_lock.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <linux/ncp_fs.h>
 | 
					
						
							|  |  |  | #include "ncplib_kernel.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int ncp_fsync(struct file *file, struct dentry *dentry, int datasync) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Open a file with the specified read/write mode. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int ncp_make_open(struct inode *inode, int right) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int error; | 
					
						
							|  |  |  | 	int access; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	error = -EINVAL; | 
					
						
							|  |  |  | 	if (!inode) { | 
					
						
							|  |  |  | 		printk(KERN_ERR "ncp_make_open: got NULL inode\n"); | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DPRINTK("ncp_make_open: opened=%d, volume # %u, dir entry # %u\n", | 
					
						
							|  |  |  | 		atomic_read(&NCP_FINFO(inode)->opened),  | 
					
						
							|  |  |  | 		NCP_FINFO(inode)->volNumber,  | 
					
						
							|  |  |  | 		NCP_FINFO(inode)->dirEntNum); | 
					
						
							|  |  |  | 	error = -EACCES; | 
					
						
							| 
									
										
										
										
											2006-03-23 03:00:43 -08:00
										 |  |  | 	mutex_lock(&NCP_FINFO(inode)->open_mutex); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (!atomic_read(&NCP_FINFO(inode)->opened)) { | 
					
						
							|  |  |  | 		struct ncp_entry_info finfo; | 
					
						
							|  |  |  | 		int result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* tries max. rights */ | 
					
						
							|  |  |  | 		finfo.access = O_RDWR; | 
					
						
							|  |  |  | 		result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), | 
					
						
							|  |  |  | 					inode, NULL, OC_MODE_OPEN, | 
					
						
							|  |  |  | 					0, AR_READ | AR_WRITE, &finfo); | 
					
						
							|  |  |  | 		if (!result) | 
					
						
							|  |  |  | 			goto update; | 
					
						
							|  |  |  | 		/* RDWR did not succeeded, try readonly or writeonly as requested */ | 
					
						
							|  |  |  | 		switch (right) { | 
					
						
							|  |  |  | 			case O_RDONLY: | 
					
						
							|  |  |  | 				finfo.access = O_RDONLY; | 
					
						
							|  |  |  | 				result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), | 
					
						
							|  |  |  | 					inode, NULL, OC_MODE_OPEN, | 
					
						
							|  |  |  | 					0, AR_READ, &finfo); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case O_WRONLY: | 
					
						
							|  |  |  | 				finfo.access = O_WRONLY; | 
					
						
							|  |  |  | 				result = ncp_open_create_file_or_subdir(NCP_SERVER(inode), | 
					
						
							|  |  |  | 					inode, NULL, OC_MODE_OPEN, | 
					
						
							|  |  |  | 					0, AR_WRITE, &finfo); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (result) { | 
					
						
							|  |  |  | 			PPRINTK("ncp_make_open: failed, result=%d\n", result); | 
					
						
							|  |  |  | 			goto out_unlock; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * Update the inode information. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 	update: | 
					
						
							|  |  |  | 		ncp_update_inode(inode, &finfo); | 
					
						
							|  |  |  | 		atomic_set(&NCP_FINFO(inode)->opened, 1); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	access = NCP_FINFO(inode)->access; | 
					
						
							|  |  |  | 	PPRINTK("ncp_make_open: file open, access=%x\n", access); | 
					
						
							|  |  |  | 	if (access == right || access == O_RDWR) { | 
					
						
							|  |  |  | 		atomic_inc(&NCP_FINFO(inode)->opened); | 
					
						
							|  |  |  | 		error = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | out_unlock: | 
					
						
							| 
									
										
										
										
											2006-03-23 03:00:43 -08:00
										 |  |  | 	mutex_unlock(&NCP_FINFO(inode)->open_mutex); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | out: | 
					
						
							|  |  |  | 	return error; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t | 
					
						
							|  |  |  | ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-12-08 02:37:22 -08:00
										 |  |  | 	struct dentry *dentry = file->f_path.dentry; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	struct inode *inode = dentry->d_inode; | 
					
						
							|  |  |  | 	size_t already_read = 0; | 
					
						
							|  |  |  | 	off_t pos; | 
					
						
							|  |  |  | 	size_t bufsize; | 
					
						
							|  |  |  | 	int error; | 
					
						
							|  |  |  | 	void* freepage; | 
					
						
							|  |  |  | 	size_t freelen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DPRINTK("ncp_file_read: enter %s/%s\n", | 
					
						
							|  |  |  | 		dentry->d_parent->d_name.name, dentry->d_name.name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!ncp_conn_valid(NCP_SERVER(inode))) | 
					
						
							|  |  |  | 		return -EIO; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pos = *ppos; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((ssize_t) count < 0) { | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (!count) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	if (pos > inode->i_sb->s_maxbytes) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	if (pos + count > inode->i_sb->s_maxbytes) { | 
					
						
							|  |  |  | 		count = inode->i_sb->s_maxbytes - pos; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	error = ncp_make_open(inode, O_RDONLY); | 
					
						
							|  |  |  | 	if (error) { | 
					
						
							|  |  |  | 		DPRINTK(KERN_ERR "ncp_file_read: open failed, error=%d\n", error); | 
					
						
							|  |  |  | 		return error; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bufsize = NCP_SERVER(inode)->buffer_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	error = -EIO; | 
					
						
							|  |  |  | 	freelen = ncp_read_bounce_size(bufsize); | 
					
						
							|  |  |  | 	freepage = vmalloc(freelen); | 
					
						
							|  |  |  | 	if (!freepage) | 
					
						
							|  |  |  | 		goto outrel; | 
					
						
							|  |  |  | 	error = 0; | 
					
						
							|  |  |  | 	/* First read in as much as possible for each bufsize. */ | 
					
						
							|  |  |  | 	while (already_read < count) { | 
					
						
							|  |  |  | 		int read_this_time; | 
					
						
							|  |  |  | 		size_t to_read = min_t(unsigned int, | 
					
						
							|  |  |  | 				     bufsize - (pos % bufsize), | 
					
						
							|  |  |  | 				     count - already_read); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		error = ncp_read_bounce(NCP_SERVER(inode), | 
					
						
							|  |  |  | 			 	NCP_FINFO(inode)->file_handle, | 
					
						
							|  |  |  | 				pos, to_read, buf, &read_this_time,  | 
					
						
							|  |  |  | 				freepage, freelen); | 
					
						
							|  |  |  | 		if (error) { | 
					
						
							|  |  |  | 			error = -EIO;	/* NW errno -> Linux errno */ | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		pos += read_this_time; | 
					
						
							|  |  |  | 		buf += read_this_time; | 
					
						
							|  |  |  | 		already_read += read_this_time; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (read_this_time != to_read) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	vfree(freepage); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*ppos = pos; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	file_accessed(file); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DPRINTK("ncp_file_read: exit %s/%s\n", | 
					
						
							|  |  |  | 		dentry->d_parent->d_name.name, dentry->d_name.name); | 
					
						
							|  |  |  | outrel: | 
					
						
							|  |  |  | 	ncp_inode_close(inode);		 | 
					
						
							|  |  |  | 	return already_read ? already_read : error; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t | 
					
						
							|  |  |  | ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-12-08 02:37:22 -08:00
										 |  |  | 	struct dentry *dentry = file->f_path.dentry; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	struct inode *inode = dentry->d_inode; | 
					
						
							|  |  |  | 	size_t already_written = 0; | 
					
						
							|  |  |  | 	off_t pos; | 
					
						
							|  |  |  | 	size_t bufsize; | 
					
						
							|  |  |  | 	int errno; | 
					
						
							|  |  |  | 	void* bouncebuffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DPRINTK("ncp_file_write: enter %s/%s\n", | 
					
						
							|  |  |  | 		dentry->d_parent->d_name.name, dentry->d_name.name); | 
					
						
							|  |  |  | 	if (!ncp_conn_valid(NCP_SERVER(inode))) | 
					
						
							|  |  |  | 		return -EIO; | 
					
						
							|  |  |  | 	if ((ssize_t) count < 0) | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	pos = *ppos; | 
					
						
							|  |  |  | 	if (file->f_flags & O_APPEND) { | 
					
						
							|  |  |  | 		pos = inode->i_size; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) { | 
					
						
							|  |  |  | 		if (pos >= MAX_NON_LFS) { | 
					
						
							|  |  |  | 			return -EFBIG; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (count > MAX_NON_LFS - (u32)pos) { | 
					
						
							|  |  |  | 			count = MAX_NON_LFS - (u32)pos; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (pos >= inode->i_sb->s_maxbytes) { | 
					
						
							|  |  |  | 		if (count || pos > inode->i_sb->s_maxbytes) { | 
					
						
							|  |  |  | 			return -EFBIG; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (pos + count > inode->i_sb->s_maxbytes) { | 
					
						
							|  |  |  | 		count = inode->i_sb->s_maxbytes - pos; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (!count) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	errno = ncp_make_open(inode, O_WRONLY); | 
					
						
							|  |  |  | 	if (errno) { | 
					
						
							|  |  |  | 		DPRINTK(KERN_ERR "ncp_file_write: open failed, error=%d\n", errno); | 
					
						
							|  |  |  | 		return errno; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	bufsize = NCP_SERVER(inode)->buffer_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	already_written = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bouncebuffer = vmalloc(bufsize); | 
					
						
							|  |  |  | 	if (!bouncebuffer) { | 
					
						
							|  |  |  | 		errno = -EIO;	/* -ENOMEM */ | 
					
						
							|  |  |  | 		goto outrel; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	while (already_written < count) { | 
					
						
							|  |  |  | 		int written_this_time; | 
					
						
							|  |  |  | 		size_t to_write = min_t(unsigned int, | 
					
						
							|  |  |  | 				      bufsize - (pos % bufsize), | 
					
						
							|  |  |  | 				      count - already_written); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (copy_from_user(bouncebuffer, buf, to_write)) { | 
					
						
							|  |  |  | 			errno = -EFAULT; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (ncp_write_kernel(NCP_SERVER(inode),  | 
					
						
							|  |  |  | 		    NCP_FINFO(inode)->file_handle, | 
					
						
							|  |  |  | 		    pos, to_write, bouncebuffer, &written_this_time) != 0) { | 
					
						
							|  |  |  | 			errno = -EIO; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		pos += written_this_time; | 
					
						
							|  |  |  | 		buf += written_this_time; | 
					
						
							|  |  |  | 		already_written += written_this_time; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (written_this_time != to_write) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	vfree(bouncebuffer); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-09 20:52:01 -08:00
										 |  |  | 	file_update_time(file); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	*ppos = pos; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (pos > inode->i_size) { | 
					
						
							|  |  |  | 		inode->i_size = pos; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	DPRINTK("ncp_file_write: exit %s/%s\n", | 
					
						
							|  |  |  | 		dentry->d_parent->d_name.name, dentry->d_name.name); | 
					
						
							|  |  |  | outrel: | 
					
						
							|  |  |  | 	ncp_inode_close(inode);		 | 
					
						
							|  |  |  | 	return already_written ? already_written : errno; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int ncp_release(struct inode *inode, struct file *file) { | 
					
						
							|  |  |  | 	if (ncp_make_closed(inode)) { | 
					
						
							|  |  |  | 		DPRINTK("ncp_release: failed to close\n"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-27 11:05:24 +02:00
										 |  |  | static loff_t ncp_remote_llseek(struct file *file, loff_t offset, int origin) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	loff_t ret; | 
					
						
							|  |  |  | 	lock_kernel(); | 
					
						
							|  |  |  | 	ret = generic_file_llseek_unlocked(file, offset, origin); | 
					
						
							|  |  |  | 	unlock_kernel(); | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-28 01:56:42 -08:00
										 |  |  | const struct file_operations ncp_file_operations = | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-06-27 11:05:24 +02:00
										 |  |  | 	.llseek 	= ncp_remote_llseek, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	.read		= ncp_file_read, | 
					
						
							|  |  |  | 	.write		= ncp_file_write, | 
					
						
							| 
									
										
										
										
											2010-05-05 15:15:37 +02:00
										 |  |  | 	.unlocked_ioctl	= ncp_ioctl, | 
					
						
							| 
									
										
										
										
											2006-09-30 23:27:55 -07:00
										 |  |  | #ifdef CONFIG_COMPAT
 | 
					
						
							|  |  |  | 	.compat_ioctl	= ncp_compat_ioctl, | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	.mmap		= ncp_mmap, | 
					
						
							|  |  |  | 	.release	= ncp_release, | 
					
						
							|  |  |  | 	.fsync		= ncp_fsync, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-12 00:55:39 -08:00
										 |  |  | const struct inode_operations ncp_file_inode_operations = | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	.setattr	= ncp_notify_change, | 
					
						
							|  |  |  | }; |