The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mm/filemap.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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/uaccess.h>
   16 
   17 size_t
   18 __filemap_copy_from_user_iovec_inatomic(char *vaddr,
   19                                         const struct iovec *iov,
   20                                         size_t base,
   21                                         size_t bytes);
   22 
   23 /*
   24  * Copy as much as we can into the page and return the number of bytes which
   25  * were sucessfully copied.  If a fault is encountered then clear the page
   26  * out to (offset+bytes) and return the number of bytes which were copied.
   27  *
   28  * NOTE: For this to work reliably we really want copy_from_user_inatomic_nocache
   29  * to *NOT* zero any tail of the buffer that it failed to copy.  If it does,
   30  * and if the following non-atomic copy succeeds, then there is a small window
   31  * where the target page contains neither the data before the write, nor the
   32  * data after the write (it contains zero).  A read at this time will see
   33  * data that is inconsistent with any ordering of the read and the write.
   34  * (This has been detected in practice).
   35  */
   36 static inline size_t
   37 filemap_copy_from_user(struct page *page, unsigned long offset,
   38                         const char __user *buf, unsigned bytes)
   39 {
   40         char *kaddr;
   41         int left;
   42 
   43         kaddr = kmap_atomic(page, KM_USER0);
   44         left = __copy_from_user_inatomic_nocache(kaddr + offset, buf, bytes);
   45         kunmap_atomic(kaddr, KM_USER0);
   46 
   47         if (left != 0) {
   48                 /* Do it the slow way */
   49                 kaddr = kmap(page);
   50                 left = __copy_from_user_nocache(kaddr + offset, buf, bytes);
   51                 kunmap(page);
   52         }
   53         return bytes - left;
   54 }
   55 
   56 /*
   57  * This has the same sideeffects and return value as filemap_copy_from_user().
   58  * The difference is that on a fault we need to memset the remainder of the
   59  * page (out to offset+bytes), to emulate filemap_copy_from_user()'s
   60  * single-segment behaviour.
   61  */
   62 static inline size_t
   63 filemap_copy_from_user_iovec(struct page *page, unsigned long offset,
   64                         const struct iovec *iov, size_t base, size_t bytes)
   65 {
   66         char *kaddr;
   67         size_t copied;
   68 
   69         kaddr = kmap_atomic(page, KM_USER0);
   70         copied = __filemap_copy_from_user_iovec_inatomic(kaddr + offset, iov,
   71                                                          base, bytes);
   72         kunmap_atomic(kaddr, KM_USER0);
   73         if (copied != bytes) {
   74                 kaddr = kmap(page);
   75                 copied = __filemap_copy_from_user_iovec_inatomic(kaddr + offset, iov,
   76                                                                  base, bytes);
   77                 if (bytes - copied)
   78                         memset(kaddr + offset + copied, 0, bytes - copied);
   79                 kunmap(page);
   80         }
   81         return copied;
   82 }
   83 
   84 static inline void
   85 filemap_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes)
   86 {
   87         const struct iovec *iov = *iovp;
   88         size_t base = *basep;
   89 
   90         do {
   91                 int copy = min(bytes, iov->iov_len - base);
   92 
   93                 bytes -= copy;
   94                 base += copy;
   95                 if (iov->iov_len == base) {
   96                         iov++;
   97                         base = 0;
   98                 }
   99         } while (bytes);
  100         *iovp = iov;
  101         *basep = base;
  102 }
  103 #endif

Cache object: 5bcf753294fac5eb0428fcff21514b1e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.