diff options
Diffstat (limited to 'net/rds/page.c')
| -rw-r--r-- | net/rds/page.c | 28 |
1 files changed, 8 insertions, 20 deletions
diff --git a/net/rds/page.c b/net/rds/page.c index 36790122dfd4..1dfbfea12e9b 100644 --- a/net/rds/page.c +++ b/net/rds/page.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | * | 31 | * |
| 32 | */ | 32 | */ |
| 33 | #include <linux/highmem.h> | 33 | #include <linux/highmem.h> |
| 34 | #include <linux/gfp.h> | ||
| 34 | 35 | ||
| 35 | #include "rds.h" | 36 | #include "rds.h" |
| 36 | 37 | ||
| @@ -56,30 +57,17 @@ int rds_page_copy_user(struct page *page, unsigned long offset, | |||
| 56 | unsigned long ret; | 57 | unsigned long ret; |
| 57 | void *addr; | 58 | void *addr; |
| 58 | 59 | ||
| 59 | if (to_user) | 60 | addr = kmap(page); |
| 61 | if (to_user) { | ||
| 60 | rds_stats_add(s_copy_to_user, bytes); | 62 | rds_stats_add(s_copy_to_user, bytes); |
| 61 | else | 63 | ret = copy_to_user(ptr, addr + offset, bytes); |
| 64 | } else { | ||
| 62 | rds_stats_add(s_copy_from_user, bytes); | 65 | rds_stats_add(s_copy_from_user, bytes); |
| 63 | 66 | ret = copy_from_user(addr + offset, ptr, bytes); | |
| 64 | addr = kmap_atomic(page, KM_USER0); | ||
| 65 | if (to_user) | ||
| 66 | ret = __copy_to_user_inatomic(ptr, addr + offset, bytes); | ||
| 67 | else | ||
| 68 | ret = __copy_from_user_inatomic(addr + offset, ptr, bytes); | ||
| 69 | kunmap_atomic(addr, KM_USER0); | ||
| 70 | |||
| 71 | if (ret) { | ||
| 72 | addr = kmap(page); | ||
| 73 | if (to_user) | ||
| 74 | ret = copy_to_user(ptr, addr + offset, bytes); | ||
| 75 | else | ||
| 76 | ret = copy_from_user(addr + offset, ptr, bytes); | ||
| 77 | kunmap(page); | ||
| 78 | if (ret) | ||
| 79 | return -EFAULT; | ||
| 80 | } | 67 | } |
| 68 | kunmap(page); | ||
| 81 | 69 | ||
| 82 | return 0; | 70 | return ret ? -EFAULT : 0; |
| 83 | } | 71 | } |
| 84 | EXPORT_SYMBOL_GPL(rds_page_copy_user); | 72 | EXPORT_SYMBOL_GPL(rds_page_copy_user); |
| 85 | 73 | ||
