diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2013-04-30 22:14:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-01 11:12:57 -0400 |
commit | be5f4b335f6e05df1b5c24b7e7d79ff52d7b8dbc (patch) | |
tree | 5076680c91f139ba8908d7ecd51dd02206e57496 /ipc | |
parent | 3d8fa456d5ed22ce8db085a89a037b87568b2b64 (diff) |
ipc: separate msg allocation from userspace copy
Separating msg allocation enables single-block vmalloc
allocation instead.
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Acked-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/msgutil.c | 52 |
1 files changed, 38 insertions, 14 deletions
diff --git a/ipc/msgutil.c b/ipc/msgutil.c index 98b1c2b476cc..0a5c8a95c257 100644 --- a/ipc/msgutil.c +++ b/ipc/msgutil.c | |||
@@ -44,21 +44,54 @@ struct msg_msgseg { | |||
44 | #define DATALEN_MSG (int)(PAGE_SIZE-sizeof(struct msg_msg)) | 44 | #define DATALEN_MSG (int)(PAGE_SIZE-sizeof(struct msg_msg)) |
45 | #define DATALEN_SEG (int)(PAGE_SIZE-sizeof(struct msg_msgseg)) | 45 | #define DATALEN_SEG (int)(PAGE_SIZE-sizeof(struct msg_msgseg)) |
46 | 46 | ||
47 | struct msg_msg *load_msg(const void __user *src, int len) | 47 | |
48 | static struct msg_msg *alloc_msg(int len) | ||
48 | { | 49 | { |
49 | struct msg_msg *msg; | 50 | struct msg_msg *msg; |
50 | struct msg_msgseg **pseg; | 51 | struct msg_msgseg **pseg; |
51 | int err; | ||
52 | int alen; | 52 | int alen; |
53 | 53 | ||
54 | alen = min(len, DATALEN_MSG); | 54 | alen = min(len, DATALEN_MSG); |
55 | msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL); | 55 | msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL); |
56 | if (msg == NULL) | 56 | if (msg == NULL) |
57 | return ERR_PTR(-ENOMEM); | 57 | return NULL; |
58 | 58 | ||
59 | msg->next = NULL; | 59 | msg->next = NULL; |
60 | msg->security = NULL; | 60 | msg->security = NULL; |
61 | 61 | ||
62 | len -= alen; | ||
63 | pseg = &msg->next; | ||
64 | while (len > 0) { | ||
65 | struct msg_msgseg *seg; | ||
66 | alen = min(len, DATALEN_SEG); | ||
67 | seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL); | ||
68 | if (seg == NULL) | ||
69 | goto out_err; | ||
70 | *pseg = seg; | ||
71 | seg->next = NULL; | ||
72 | pseg = &seg->next; | ||
73 | len -= alen; | ||
74 | } | ||
75 | |||
76 | return msg; | ||
77 | |||
78 | out_err: | ||
79 | free_msg(msg); | ||
80 | return NULL; | ||
81 | } | ||
82 | |||
83 | struct msg_msg *load_msg(const void __user *src, int len) | ||
84 | { | ||
85 | struct msg_msg *msg; | ||
86 | struct msg_msgseg *seg; | ||
87 | int err; | ||
88 | int alen; | ||
89 | |||
90 | msg = alloc_msg(len); | ||
91 | if (msg == NULL) | ||
92 | return ERR_PTR(-ENOMEM); | ||
93 | |||
94 | alen = min(len, DATALEN_MSG); | ||
62 | if (copy_from_user(msg + 1, src, alen)) { | 95 | if (copy_from_user(msg + 1, src, alen)) { |
63 | err = -EFAULT; | 96 | err = -EFAULT; |
64 | goto out_err; | 97 | goto out_err; |
@@ -66,23 +99,14 @@ struct msg_msg *load_msg(const void __user *src, int len) | |||
66 | 99 | ||
67 | len -= alen; | 100 | len -= alen; |
68 | src = ((char __user *)src) + alen; | 101 | src = ((char __user *)src) + alen; |
69 | pseg = &msg->next; | 102 | seg = msg->next; |
70 | while (len > 0) { | 103 | while (len > 0) { |
71 | struct msg_msgseg *seg; | ||
72 | alen = min(len, DATALEN_SEG); | 104 | alen = min(len, DATALEN_SEG); |
73 | seg = kmalloc(sizeof(*seg) + alen, | ||
74 | GFP_KERNEL); | ||
75 | if (seg == NULL) { | ||
76 | err = -ENOMEM; | ||
77 | goto out_err; | ||
78 | } | ||
79 | *pseg = seg; | ||
80 | seg->next = NULL; | ||
81 | if (copy_from_user(seg + 1, src, alen)) { | 105 | if (copy_from_user(seg + 1, src, alen)) { |
82 | err = -EFAULT; | 106 | err = -EFAULT; |
83 | goto out_err; | 107 | goto out_err; |
84 | } | 108 | } |
85 | pseg = &seg->next; | 109 | seg = seg->next; |
86 | len -= alen; | 110 | len -= alen; |
87 | src = ((char __user *)src) + alen; | 111 | src = ((char __user *)src) + alen; |
88 | } | 112 | } |