aboutsummaryrefslogtreecommitdiffstats
path: root/net/rds/page.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/rds/page.c')
-rw-r--r--net/rds/page.c28
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}
84EXPORT_SYMBOL_GPL(rds_page_copy_user); 72EXPORT_SYMBOL_GPL(rds_page_copy_user);
85 73