aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-12-03 06:05:29 -0500
committerSteve French <smfrench@gmail.com>2012-12-08 23:04:28 -0500
commit41a9f1f6b38664fc08431674d87871a57d763be1 (patch)
tree72c311410a7b5175776385f7a4947d4e77ac5d3c /fs
parentfaa65f07d21e7d37190c91fdcf9f940d733ae3cc (diff)
cifs: avoid extra allocation for small cifs.idmap keys
The cifs.idmap keytype always allocates memory to hold the payload from userspace. In the common case where we're translating a SID to a UID or GID, we're allocating memory to hold something that's less than or equal to the size of a pointer. When the payload is the same size as a pointer or smaller, just store it in the payload.value union member instead. That saves us an extra allocation on the sid_to_id upcall. Note that we have to take extra care to check the datalen when we go to dereference the .data pointer in the union, but the callers now check that as a matter of course anyway. Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifsacl.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index f4508ee4e80d..751d34bd825c 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -49,6 +49,20 @@ cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
49{ 49{
50 char *payload; 50 char *payload;
51 51
52 /*
53 * If the payload is less than or equal to the size of a pointer, then
54 * an allocation here is wasteful. Just copy the data directly to the
55 * payload.value union member instead.
56 *
57 * With this however, you must check the datalen before trying to
58 * dereference payload.data!
59 */
60 if (prep->datalen <= sizeof(void *)) {
61 key->payload.value = 0;
62 memcpy(&key->payload.value, prep->data, prep->datalen);
63 key->datalen = prep->datalen;
64 return 0;
65 }
52 payload = kmalloc(prep->datalen, GFP_KERNEL); 66 payload = kmalloc(prep->datalen, GFP_KERNEL);
53 if (!payload) 67 if (!payload)
54 return -ENOMEM; 68 return -ENOMEM;
@@ -62,7 +76,8 @@ cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
62static inline void 76static inline void
63cifs_idmap_key_destroy(struct key *key) 77cifs_idmap_key_destroy(struct key *key)
64{ 78{
65 kfree(key->payload.data); 79 if (key->datalen > sizeof(void *))
80 kfree(key->payload.data);
66} 81}
67 82
68static struct key_type cifs_idmap_key_type = { 83static struct key_type cifs_idmap_key_type = {
@@ -245,7 +260,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
245 * probably a safe assumption but might be better to check based on 260 * probably a safe assumption but might be better to check based on
246 * sidtype. 261 * sidtype.
247 */ 262 */
248 if (sidkey->datalen < sizeof(uid_t)) { 263 if (sidkey->datalen != sizeof(uid_t)) {
249 rc = -EIO; 264 rc = -EIO;
250 cFYI(1, "%s: Downcall contained malformed key " 265 cFYI(1, "%s: Downcall contained malformed key "
251 "(datalen=%hu)", __func__, sidkey->datalen); 266 "(datalen=%hu)", __func__, sidkey->datalen);
@@ -253,9 +268,9 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
253 } 268 }
254 269
255 if (sidtype == SIDOWNER) 270 if (sidtype == SIDOWNER)
256 fuid = *(uid_t *)sidkey->payload.value; 271 memcpy(&fuid, &sidkey->payload.value, sizeof(uid_t));
257 else 272 else
258 fgid = *(gid_t *)sidkey->payload.value; 273 memcpy(&fgid, &sidkey->payload.value, sizeof(gid_t));
259 274
260out_key_put: 275out_key_put:
261 key_put(sidkey); 276 key_put(sidkey);