filemap.h 2.2 KB

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