ia64/linux-2.6.18-xen.hg

diff mm/filemap.h @ 0:831230e53067

Import 2.6.18 from kernel.org tarball.
author Ian Campbell <ian.campbell@xensource.com>
date Wed Apr 11 14:15:44 2007 +0100 (2007-04-11)
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mm/filemap.h	Wed Apr 11 14:15:44 2007 +0100
     1.3 @@ -0,0 +1,104 @@
     1.4 +/*
     1.5 + *	linux/mm/filemap.h
     1.6 + *
     1.7 + * Copyright (C) 1994-1999  Linus Torvalds
     1.8 + */
     1.9 +
    1.10 +#ifndef __FILEMAP_H
    1.11 +#define __FILEMAP_H
    1.12 +
    1.13 +#include <linux/types.h>
    1.14 +#include <linux/fs.h>
    1.15 +#include <linux/mm.h>
    1.16 +#include <linux/highmem.h>
    1.17 +#include <linux/uio.h>
    1.18 +#include <linux/config.h>
    1.19 +#include <linux/uaccess.h>
    1.20 +
    1.21 +size_t
    1.22 +__filemap_copy_from_user_iovec_inatomic(char *vaddr,
    1.23 +					const struct iovec *iov,
    1.24 +					size_t base,
    1.25 +					size_t bytes);
    1.26 +
    1.27 +/*
    1.28 + * Copy as much as we can into the page and return the number of bytes which
    1.29 + * were sucessfully copied.  If a fault is encountered then clear the page
    1.30 + * out to (offset+bytes) and return the number of bytes which were copied.
    1.31 + *
    1.32 + * NOTE: For this to work reliably we really want copy_from_user_inatomic_nocache
    1.33 + * to *NOT* zero any tail of the buffer that it failed to copy.  If it does,
    1.34 + * and if the following non-atomic copy succeeds, then there is a small window
    1.35 + * where the target page contains neither the data before the write, nor the
    1.36 + * data after the write (it contains zero).  A read at this time will see
    1.37 + * data that is inconsistent with any ordering of the read and the write.
    1.38 + * (This has been detected in practice).
    1.39 + */
    1.40 +static inline size_t
    1.41 +filemap_copy_from_user(struct page *page, unsigned long offset,
    1.42 +			const char __user *buf, unsigned bytes)
    1.43 +{
    1.44 +	char *kaddr;
    1.45 +	int left;
    1.46 +
    1.47 +	kaddr = kmap_atomic(page, KM_USER0);
    1.48 +	left = __copy_from_user_inatomic_nocache(kaddr + offset, buf, bytes);
    1.49 +	kunmap_atomic(kaddr, KM_USER0);
    1.50 +
    1.51 +	if (left != 0) {
    1.52 +		/* Do it the slow way */
    1.53 +		kaddr = kmap(page);
    1.54 +		left = __copy_from_user_nocache(kaddr + offset, buf, bytes);
    1.55 +		kunmap(page);
    1.56 +	}
    1.57 +	return bytes - left;
    1.58 +}
    1.59 +
    1.60 +/*
    1.61 + * This has the same sideeffects and return value as filemap_copy_from_user().
    1.62 + * The difference is that on a fault we need to memset the remainder of the
    1.63 + * page (out to offset+bytes), to emulate filemap_copy_from_user()'s
    1.64 + * single-segment behaviour.
    1.65 + */
    1.66 +static inline size_t
    1.67 +filemap_copy_from_user_iovec(struct page *page, unsigned long offset,
    1.68 +			const struct iovec *iov, size_t base, size_t bytes)
    1.69 +{
    1.70 +	char *kaddr;
    1.71 +	size_t copied;
    1.72 +
    1.73 +	kaddr = kmap_atomic(page, KM_USER0);
    1.74 +	copied = __filemap_copy_from_user_iovec_inatomic(kaddr + offset, iov,
    1.75 +							 base, bytes);
    1.76 +	kunmap_atomic(kaddr, KM_USER0);
    1.77 +	if (copied != bytes) {
    1.78 +		kaddr = kmap(page);
    1.79 +		copied = __filemap_copy_from_user_iovec_inatomic(kaddr + offset, iov,
    1.80 +								 base, bytes);
    1.81 +		if (bytes - copied)
    1.82 +			memset(kaddr + offset + copied, 0, bytes - copied);
    1.83 +		kunmap(page);
    1.84 +	}
    1.85 +	return copied;
    1.86 +}
    1.87 +
    1.88 +static inline void
    1.89 +filemap_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes)
    1.90 +{
    1.91 +	const struct iovec *iov = *iovp;
    1.92 +	size_t base = *basep;
    1.93 +
    1.94 +	do {
    1.95 +		int copy = min(bytes, iov->iov_len - base);
    1.96 +
    1.97 +		bytes -= copy;
    1.98 +		base += copy;
    1.99 +		if (iov->iov_len == base) {
   1.100 +			iov++;
   1.101 +			base = 0;
   1.102 +		}
   1.103 +	} while (bytes);
   1.104 +	*iovp = iov;
   1.105 +	*basep = base;
   1.106 +}
   1.107 +#endif