diff options
author | Carsten Otte <cotte@de.ibm.com> | 2005-06-23 22:05:25 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-24 00:06:41 -0700 |
commit | ceffc078528befc008c6f2c2c4decda79eabd534 (patch) | |
tree | a289e10162bdef0c0d9f6533f1a647b0fe1ed7a9 /mm/filemap.h | |
parent | 420edbcc09008342c7b2665453f6b370739aadb0 (diff) | |
download | lwn-ceffc078528befc008c6f2c2c4decda79eabd534.tar.gz lwn-ceffc078528befc008c6f2c2c4decda79eabd534.zip |
[PATCH] xip: fs/mm: execute in place
- generic_file* file operations do no longer have a xip/non-xip split
- filemap_xip.c implements a new set of fops that require get_xip_page
aop to work proper. all new fops are exported GPL-only (don't like to
see whatever code use those except GPL modules)
- __xip_unmap now uses page_check_address, which is no longer static
in rmap.c, and defined in linux/rmap.h
- mm/filemap.h is now much more clean, plainly having just Linus'
inline funcs moved here from filemap.c
- fix includes in filemap_xip to make it build cleanly on i386
Signed-off-by: Carsten Otte <cotte@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm/filemap.h')
-rw-r--r-- | mm/filemap.h | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/mm/filemap.h b/mm/filemap.h new file mode 100644 index 000000000000..c2d0546a57eb --- /dev/null +++ b/mm/filemap.h @@ -0,0 +1,94 @@ +/* + * linux/mm/filemap.h + * + * Copyright (C) 1994-1999 Linus Torvalds + */ + +#ifndef __FILEMAP_H +#define __FILEMAP_H + +#include <linux/types.h> +#include <linux/fs.h> +#include <linux/mm.h> +#include <linux/highmem.h> +#include <linux/uio.h> +#include <linux/config.h> +#include <asm/uaccess.h> + +extern size_t +__filemap_copy_from_user_iovec(char *vaddr, + const struct iovec *iov, + size_t base, + size_t bytes); + +/* + * Copy as much as we can into the page and return the number of bytes which + * were sucessfully copied. If a fault is encountered then clear the page + * out to (offset+bytes) and return the number of bytes which were copied. + */ +static inline size_t +filemap_copy_from_user(struct page *page, unsigned long offset, + const char __user *buf, unsigned bytes) +{ + char *kaddr; + int left; + + kaddr = kmap_atomic(page, KM_USER0); + left = __copy_from_user_inatomic(kaddr + offset, buf, bytes); + kunmap_atomic(kaddr, KM_USER0); + + if (left != 0) { + /* Do it the slow way */ + kaddr = kmap(page); + left = __copy_from_user(kaddr + offset, buf, bytes); + kunmap(page); + } + return bytes - left; +} + +/* + * This has the same sideeffects and return value as filemap_copy_from_user(). + * The difference is that on a fault we need to memset the remainder of the + * page (out to offset+bytes), to emulate filemap_copy_from_user()'s + * single-segment behaviour. + */ +static inline size_t +filemap_copy_from_user_iovec(struct page *page, unsigned long offset, + const struct iovec *iov, size_t base, size_t bytes) +{ + char *kaddr; + size_t copied; + + kaddr = kmap_atomic(page, KM_USER0); + copied = __filemap_copy_from_user_iovec(kaddr + offset, iov, + base, bytes); + kunmap_atomic(kaddr, KM_USER0); + if (copied != bytes) { + kaddr = kmap(page); + copied = __filemap_copy_from_user_iovec(kaddr + offset, iov, + base, bytes); + kunmap(page); + } + return copied; +} + +static inline void +filemap_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes) +{ + const struct iovec *iov = *iovp; + size_t base = *basep; + + while (bytes) { + int copy = min(bytes, iov->iov_len - base); + + bytes -= copy; + base += copy; + if (iov->iov_len == base) { + iov++; + base = 0; + } + } + *iovp = iov; + *basep = base; +} +#endif |