aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2012-12-21 15:23:36 -0500
committerAlasdair G Kergon <agk@redhat.com>2012-12-21 15:23:36 -0500
commit9c5091f2eeeffe5eca2ffe8a1bc28d312c8a5083 (patch)
tree8452b7ece373cf845bd745ff78750ae325a881d3 /drivers
parent5023e5cf58e1dae904e2e8b5b9779c33512b75a1 (diff)
dm ioctl: use kmalloc if possible
If the parameter buffer is small enough, try to allocate it with kmalloc() rather than vmalloc(). vmalloc is noticeably slower than kmalloc because it has to manipulate page tables. In my tests, on PA-RISC this patch speeds up activation 13 times. On Opteron this patch speeds up activation by 5%. This patch introduces a new function free_params() to free the parameters and this uses new flags that record whether or not vmalloc() was used and whether or not the input buffer must be wiped after use. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/dm-ioctl.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index a37aeba7dc1b..0666b5d14b88 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1543,7 +1543,21 @@ static int check_version(unsigned int cmd, struct dm_ioctl __user *user)
1543 return r; 1543 return r;
1544} 1544}
1545 1545
1546static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param) 1546#define DM_PARAMS_VMALLOC 0x0001 /* Params alloced with vmalloc not kmalloc */
1547#define DM_WIPE_BUFFER 0x0010 /* Wipe input buffer before returning from ioctl */
1548
1549static void free_params(struct dm_ioctl *param, size_t param_size, int param_flags)
1550{
1551 if (param_flags & DM_WIPE_BUFFER)
1552 memset(param, 0, param_size);
1553
1554 if (param_flags & DM_PARAMS_VMALLOC)
1555 vfree(param);
1556 else
1557 kfree(param);
1558}
1559
1560static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param, int *param_flags)
1547{ 1561{
1548 struct dm_ioctl tmp, *dmi; 1562 struct dm_ioctl tmp, *dmi;
1549 int secure_data; 1563 int secure_data;
@@ -1556,10 +1570,21 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param)
1556 1570
1557 secure_data = tmp.flags & DM_SECURE_DATA_FLAG; 1571 secure_data = tmp.flags & DM_SECURE_DATA_FLAG;
1558 1572
1573 *param_flags = secure_data ? DM_WIPE_BUFFER : 0;
1574
1559 /* 1575 /*
1560 * Try to avoid low memory issues when a device is suspended. 1576 * Try to avoid low memory issues when a device is suspended.
1577 * Use kmalloc() rather than vmalloc() when we can.
1561 */ 1578 */
1562 dmi = __vmalloc(tmp.data_size, GFP_NOIO | __GFP_REPEAT | __GFP_HIGH, PAGE_KERNEL); 1579 dmi = NULL;
1580 if (tmp.data_size <= KMALLOC_MAX_SIZE)
1581 dmi = kmalloc(tmp.data_size, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
1582
1583 if (!dmi) {
1584 dmi = __vmalloc(tmp.data_size, GFP_NOIO | __GFP_REPEAT | __GFP_HIGH, PAGE_KERNEL);
1585 *param_flags |= DM_PARAMS_VMALLOC;
1586 }
1587
1563 if (!dmi) { 1588 if (!dmi) {
1564 if (secure_data && clear_user(user, tmp.data_size)) 1589 if (secure_data && clear_user(user, tmp.data_size))
1565 return -EFAULT; 1590 return -EFAULT;
@@ -1585,9 +1610,8 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param)
1585 return 0; 1610 return 0;
1586 1611
1587bad: 1612bad:
1588 if (secure_data) 1613 free_params(dmi, tmp.data_size, *param_flags);
1589 memset(dmi, 0, tmp.data_size); 1614
1590 vfree(dmi);
1591 return -EFAULT; 1615 return -EFAULT;
1592} 1616}
1593 1617
@@ -1624,7 +1648,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param)
1624static int ctl_ioctl(uint command, struct dm_ioctl __user *user) 1648static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1625{ 1649{
1626 int r = 0; 1650 int r = 0;
1627 int wipe_buffer; 1651 int param_flags;
1628 unsigned int cmd; 1652 unsigned int cmd;
1629 struct dm_ioctl *uninitialized_var(param); 1653 struct dm_ioctl *uninitialized_var(param);
1630 ioctl_fn fn = NULL; 1654 ioctl_fn fn = NULL;
@@ -1662,14 +1686,12 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1662 /* 1686 /*
1663 * Copy the parameters into kernel space. 1687 * Copy the parameters into kernel space.
1664 */ 1688 */
1665 r = copy_params(user, &param); 1689 r = copy_params(user, &param, &param_flags);
1666 1690
1667 if (r) 1691 if (r)
1668 return r; 1692 return r;
1669 1693
1670 input_param_size = param->data_size; 1694 input_param_size = param->data_size;
1671 wipe_buffer = param->flags & DM_SECURE_DATA_FLAG;
1672
1673 r = validate_params(cmd, param); 1695 r = validate_params(cmd, param);
1674 if (r) 1696 if (r)
1675 goto out; 1697 goto out;
@@ -1684,10 +1706,7 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1684 r = -EFAULT; 1706 r = -EFAULT;
1685 1707
1686out: 1708out:
1687 if (wipe_buffer) 1709 free_params(param, input_param_size, param_flags);
1688 memset(param, 0, input_param_size);
1689
1690 vfree(param);
1691 return r; 1710 return r;
1692} 1711}
1693 1712