at v2.6.16-rc2 94 lines 2.2 kB view raw
1/* 2 * linux/mm/filemap.h 3 * 4 * Copyright (C) 1994-1999 Linus Torvalds 5 */ 6 7#ifndef __FILEMAP_H 8#define __FILEMAP_H 9 10#include <linux/types.h> 11#include <linux/fs.h> 12#include <linux/mm.h> 13#include <linux/highmem.h> 14#include <linux/uio.h> 15#include <linux/config.h> 16#include <asm/uaccess.h> 17 18size_t 19__filemap_copy_from_user_iovec(char *vaddr, 20 const struct iovec *iov, 21 size_t base, 22 size_t bytes); 23 24/* 25 * Copy as much as we can into the page and return the number of bytes which 26 * were sucessfully copied. If a fault is encountered then clear the page 27 * out to (offset+bytes) and return the number of bytes which were copied. 28 */ 29static inline size_t 30filemap_copy_from_user(struct page *page, unsigned long offset, 31 const char __user *buf, unsigned bytes) 32{ 33 char *kaddr; 34 int left; 35 36 kaddr = kmap_atomic(page, KM_USER0); 37 left = __copy_from_user_inatomic(kaddr + offset, buf, bytes); 38 kunmap_atomic(kaddr, KM_USER0); 39 40 if (left != 0) { 41 /* Do it the slow way */ 42 kaddr = kmap(page); 43 left = __copy_from_user(kaddr + offset, buf, bytes); 44 kunmap(page); 45 } 46 return bytes - left; 47} 48 49/* 50 * This has the same sideeffects and return value as filemap_copy_from_user(). 51 * The difference is that on a fault we need to memset the remainder of the 52 * page (out to offset+bytes), to emulate filemap_copy_from_user()'s 53 * single-segment behaviour. 54 */ 55static inline size_t 56filemap_copy_from_user_iovec(struct page *page, unsigned long offset, 57 const struct iovec *iov, size_t base, size_t bytes) 58{ 59 char *kaddr; 60 size_t copied; 61 62 kaddr = kmap_atomic(page, KM_USER0); 63 copied = __filemap_copy_from_user_iovec(kaddr + offset, iov, 64 base, bytes); 65 kunmap_atomic(kaddr, KM_USER0); 66 if (copied != bytes) { 67 kaddr = kmap(page); 68 copied = __filemap_copy_from_user_iovec(kaddr + offset, iov, 69 base, bytes); 70 kunmap(page); 71 } 72 return copied; 73} 74 75static inline void 76filemap_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes) 77{ 78 const struct iovec *iov = *iovp; 79 size_t base = *basep; 80 81 while (bytes) { 82 int copy = min(bytes, iov->iov_len - base); 83 84 bytes -= copy; 85 base += copy; 86 if (iov->iov_len == base) { 87 iov++; 88 base = 0; 89 } 90 } 91 *iovp = iov; 92 *basep = base; 93} 94#endif