linux/mmnommu/filemap.c
/*
 * Write to a file through the page cache. 
 *
 * We currently put everything into the page cache prior to writing it.
 * This is not a problem when writing full pages. With partial pages,
 * however, we first have to read the data into the cache, then
 * dirty the page, and finally schedule it for writing. Alternatively, we
 * could write-through just the portion of data that would go into that
 * page, but that would kill performance for applications that write data
 * line by line, and it's prone to race conditions.
 *
 * Note that this routine doesn't try to keep track of dirty pages. Each
 * file system has to do this all by itself, unfortunately.
 *							okir@monad.swb.de
 */
Write to a file through the page cache.
We currently put everything into the page cache prior to writing it.
This is not a problem when writing full pages. With partial pages,
however, we first have to read the data into the cache, then
dirty the page, and finally schedule it for writing. Alternatively, we
could write-through just the portion of data that would go into that
page, but that would kill performance for applications that write data
line by line, and it's prone to race conditions.

Note that this routine doesn't try to keep track of dirty pages. Each
file system has to do this all by itself, unfortunately.
Write to a file through the page cache . We currently put everything into the page cache prior to writing it . This is not a problem when writing full pages . With partial pages however we first have to read the data into the cache then dirty the page and finally schedule it for writing . Alternatively we could write - through just the portion of data that would go into that page but that would kill performance for applications that write data line by line and it ' s prone to race conditions . Note that this routine doesn ' t try to keep track of dirty pages . Each file system has to do this all by itself unfortunately .
ssize_t
generic_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
{
	struct inode	*inode = file->f_dentry->d_inode; 
	struct address_space *mapping = inode->i_mapping;
	unsigned long	limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
	loff_t		pos;
	struct page	*page, *cached_page;
	unsigned long	written;
	long		status;
	int		err;
	cached_page = NULL;
	down(&inode->i_sem);
	pos = *ppos;
	err = -EINVAL;
	if (pos < 0)
		goto out;
	err = file->f_error;
	if (err) {
		file->f_error = 0;
		goto out;
	}
	written = 0;
	if (file->f_flags & O_APPEND)
		pos = inode->i_size;
	err = -EFBIG;
	if (limit != RLIM_INFINITY) {
		if (pos >= limit) {
			send_sig(SIGXFSZ, current, 0);
			goto out;
		}
		if (count > limit - pos) {
			send_sig(SIGXFSZ, current, 0);
			count = limit - pos;
		}
	}
	status  = 0;
	if (count) {
		remove_suid(inode);
		inode->i_ctime = inode->i_mtime = CURRENT_TIME;
		mark_inode_dirty_sync(inode);
	}
	while (count) {
		unsigned long bytes, index, offset;
		char *kaddr;
		int deactivate = 1;
		offset = (pos & (PAGE_CACHE_SIZE -1)); 
		index = pos >> PAGE_CACHE_SHIFT;
		bytes = PAGE_CACHE_SIZE - offset;
		if (bytes > count) {
			bytes = count;
			deactivate = 0;
		}
		{ volatile unsigned char dummy;
			__get_user(dummy, buf);
			__get_user(dummy, buf+bytes-1);
		}
		status = -ENOMEM;	
		page = __grab_cache_page(mapping, index, &cached_page);
		if (!page)
			break;
		if (!PageLocked(page)) {
			PAGE_BUG(page);
		}
		status = mapping->a_ops->prepare_write(file, page, offset, offset+bytes);
		if (status)
			goto unlock;
		kaddr = page_address(page);
		status = copy_from_user(kaddr+offset, buf, bytes);
		flush_dcache_page(page);
		if (status)
			goto fail_write;
		status = mapping->a_ops->commit_write(file, page, offset, offset+bytes);
		if (!status)
			status = bytes;
		if (status >= 0) {
			written += status;
			count -= status;
			pos += status;
			buf += status;
		}
unlock:
		UnlockPage(page);
		if (deactivate)
			deactivate_page(page);
		page_cache_release(page);
		if (status < 0)
			break;
	}
	*ppos = pos;
	if (cached_page)
		page_cache_free(cached_page);
	if ((status >= 0) && (file->f_flags & O_SYNC))
		status = generic_osync_inode(inode, 1); 
	err = written ? written : status;
out:
	up(&inode->i_sem);
	return err;
fail_write:
	status = -EFAULT;
	ClearPageUptodate(page);
	kunmap(page);
	goto unlock;
}
ssize_t generic_file_write ( struct file * file , const char * buf , size_t count , loff_t * ppos ) { struct inode * inode = file -> f_dentry -> d_inode ; struct address_space * mapping = inode -> i_mapping ; unsigned long limit = current -> rlim [ RLIMIT_FSIZE ] . rlim_cur ; loff_t pos ; struct page * page , * cached_page ; unsigned long written ; long status ; int err ; cached_page = NULL ; down ( & inode -> i_sem ) ; pos = * ppos ; err = - EINVAL ; if ( pos < 0 ) goto out ; err = file -> f_error ; if ( err ) { file -> f_error = 0 ; goto out ; } written = 0 ; if ( file -> f_flags & O_APPEND ) pos = inode -> i_size ; err = - EFBIG ; if ( limit != RLIM_INFINITY ) { if ( pos >= limit ) { send_sig ( SIGXFSZ , current , 0 ) ; goto out ; } if ( count > limit - pos ) { send_sig ( SIGXFSZ , current , 0 ) ; count = limit - pos ; } } status = 0 ; if ( count ) { remove_suid ( inode ) ; inode -> i_ctime = inode -> i_mtime = CURRENT_TIME ; mark_inode_dirty_sync ( inode ) ; } while ( count ) { unsigned long bytes , index , offset ; char * kaddr ; int deactivate = 1 ; offset = ( pos & ( PAGE_CACHE_SIZE - 1 ) ) ; index = pos >> PAGE_CACHE_SHIFT ; bytes = PAGE_CACHE_SIZE - offset ; if ( bytes > count ) { bytes = count ; deactivate = 0 ; } { volatile unsigned char dummy ; __get_user ( dummy , buf ) ; __get_user ( dummy , buf + bytes - 1 ) ; } status = - ENOMEM ; page = __grab_cache_page ( mapping , index , & cached_page ) ; if ( ! page ) break ; if ( ! PageLocked ( page ) ) { PAGE_BUG ( page ) ; } status = mapping -> a_ops -> prepare_write ( file , page , offset , offset + bytes ) ; if ( status ) goto unlock ; kaddr = page_address ( page ) ; status = copy_from_user ( kaddr + offset , buf , bytes ) ; flush_dcache_page ( page ) ; if ( status ) goto fail_write ; status = mapping -> a_ops -> commit_write ( file , page , offset , offset + bytes ) ; if ( ! status ) status = bytes ; if ( status >= 0 ) { written += status ; count -= status ; pos += status ; buf += status ; } unlock : UnlockPage ( page ) ; if ( deactivate ) deactivate_page ( page ) ; page_cache_release ( page ) ; if ( status < 0 ) break ; } * ppos = pos ; if ( cached_page ) page_cache_free ( cached_page ) ; if ( ( status >= 0 ) && ( file -> f_flags & O_SYNC ) ) status = generic_osync_inode ( inode , 1 ) ; err = written ? written : status ; out : up ( & inode -> i_sem ) ; return err ; fail_write : status = - EFAULT ; ClearPageUptodate ( page ) ; kunmap ( page ) ; goto unlock ; }
Write to a file through the page cache.
Write to a file through the page cache .
/*
	 * Check whether we've reached the file size limit.
	 */ /*
		 * Try to find the page in the cache. If it isn't there,
		 * allocate a free page.
		 */ /* Within page */ /*
		 * Bring in the user page that we will copy from _first_.
		 * Otherwise there's a nasty deadlock on copying from the
		 * same page as we're writing to, without it being marked
		 * up-to-date.
		 */ /* we'll assign it later anyway */ /* We have exclusive IO access to the page.. */ /* Mark it unlocked again and drop the page.. */ /* For now, when the user asks for O_SYNC, we'll actually
	 * provide O_DSYNC. */ /* 1 means datasync */