diff options
author | Marcin Slusarz <marcin.slusarz@gmail.com> | 2008-11-16 13:06:37 -0500 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-12-29 02:28:43 -0500 |
commit | d194139c18edb7dae45e159a24f2aa72091033b8 (patch) | |
tree | 98dab9ca446fceca1f519924fd392fbeb5e2eb14 | |
parent | 3147c531b6b53fbbf8942689c4aa113c519f5e4e (diff) |
cdrom: reduce stack usage of mmc_ioctl_dvd_read_struct
1. kmalloc 192 bytes in dvd_read_bca (which is inlined into dvd_read_struct)
2. Pass struct packet_command to all dvd_read_* functions.
Checkstack output:
Before: mmc_ioctl_dvd_read_struct: 280
After: mmc_ioctl_dvd_read_struct: 56
Signed-off-by: Marcin Slusarz <marcin.slusarz@gmail.com>
Cc: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | drivers/cdrom/cdrom.c | 139 |
1 files changed, 77 insertions, 62 deletions
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index b927aa244247..cceace61ef28 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c | |||
@@ -1712,29 +1712,30 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) | |||
1712 | return 0; | 1712 | return 0; |
1713 | } | 1713 | } |
1714 | 1714 | ||
1715 | static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s) | 1715 | static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s, |
1716 | struct packet_command *cgc) | ||
1716 | { | 1717 | { |
1717 | unsigned char buf[21], *base; | 1718 | unsigned char buf[21], *base; |
1718 | struct dvd_layer *layer; | 1719 | struct dvd_layer *layer; |
1719 | struct packet_command cgc; | ||
1720 | struct cdrom_device_ops *cdo = cdi->ops; | 1720 | struct cdrom_device_ops *cdo = cdi->ops; |
1721 | int ret, layer_num = s->physical.layer_num; | 1721 | int ret, layer_num = s->physical.layer_num; |
1722 | 1722 | ||
1723 | if (layer_num >= DVD_LAYERS) | 1723 | if (layer_num >= DVD_LAYERS) |
1724 | return -EINVAL; | 1724 | return -EINVAL; |
1725 | 1725 | ||
1726 | init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); | 1726 | init_cdrom_command(cgc, buf, sizeof(buf), CGC_DATA_READ); |
1727 | cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; | 1727 | cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE; |
1728 | cgc.cmd[6] = layer_num; | 1728 | cgc->cmd[6] = layer_num; |
1729 | cgc.cmd[7] = s->type; | 1729 | cgc->cmd[7] = s->type; |
1730 | cgc.cmd[9] = cgc.buflen & 0xff; | 1730 | cgc->cmd[9] = cgc->buflen & 0xff; |
1731 | 1731 | ||
1732 | /* | 1732 | /* |
1733 | * refrain from reporting errors on non-existing layers (mainly) | 1733 | * refrain from reporting errors on non-existing layers (mainly) |
1734 | */ | 1734 | */ |
1735 | cgc.quiet = 1; | 1735 | cgc->quiet = 1; |
1736 | 1736 | ||
1737 | if ((ret = cdo->generic_packet(cdi, &cgc))) | 1737 | ret = cdo->generic_packet(cdi, cgc); |
1738 | if (ret) | ||
1738 | return ret; | 1739 | return ret; |
1739 | 1740 | ||
1740 | base = &buf[4]; | 1741 | base = &buf[4]; |
@@ -1762,21 +1763,22 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s) | |||
1762 | return 0; | 1763 | return 0; |
1763 | } | 1764 | } |
1764 | 1765 | ||
1765 | static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s) | 1766 | static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s, |
1767 | struct packet_command *cgc) | ||
1766 | { | 1768 | { |
1767 | int ret; | 1769 | int ret; |
1768 | u_char buf[8]; | 1770 | u_char buf[8]; |
1769 | struct packet_command cgc; | ||
1770 | struct cdrom_device_ops *cdo = cdi->ops; | 1771 | struct cdrom_device_ops *cdo = cdi->ops; |
1771 | 1772 | ||
1772 | init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); | 1773 | init_cdrom_command(cgc, buf, sizeof(buf), CGC_DATA_READ); |
1773 | cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; | 1774 | cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE; |
1774 | cgc.cmd[6] = s->copyright.layer_num; | 1775 | cgc->cmd[6] = s->copyright.layer_num; |
1775 | cgc.cmd[7] = s->type; | 1776 | cgc->cmd[7] = s->type; |
1776 | cgc.cmd[8] = cgc.buflen >> 8; | 1777 | cgc->cmd[8] = cgc->buflen >> 8; |
1777 | cgc.cmd[9] = cgc.buflen & 0xff; | 1778 | cgc->cmd[9] = cgc->buflen & 0xff; |
1778 | 1779 | ||
1779 | if ((ret = cdo->generic_packet(cdi, &cgc))) | 1780 | ret = cdo->generic_packet(cdi, cgc); |
1781 | if (ret) | ||
1780 | return ret; | 1782 | return ret; |
1781 | 1783 | ||
1782 | s->copyright.cpst = buf[4]; | 1784 | s->copyright.cpst = buf[4]; |
@@ -1785,79 +1787,89 @@ static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s) | |||
1785 | return 0; | 1787 | return 0; |
1786 | } | 1788 | } |
1787 | 1789 | ||
1788 | static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s) | 1790 | static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s, |
1791 | struct packet_command *cgc) | ||
1789 | { | 1792 | { |
1790 | int ret, size; | 1793 | int ret, size; |
1791 | u_char *buf; | 1794 | u_char *buf; |
1792 | struct packet_command cgc; | ||
1793 | struct cdrom_device_ops *cdo = cdi->ops; | 1795 | struct cdrom_device_ops *cdo = cdi->ops; |
1794 | 1796 | ||
1795 | size = sizeof(s->disckey.value) + 4; | 1797 | size = sizeof(s->disckey.value) + 4; |
1796 | 1798 | ||
1797 | if ((buf = kmalloc(size, GFP_KERNEL)) == NULL) | 1799 | buf = kmalloc(size, GFP_KERNEL); |
1800 | if (!buf) | ||
1798 | return -ENOMEM; | 1801 | return -ENOMEM; |
1799 | 1802 | ||
1800 | init_cdrom_command(&cgc, buf, size, CGC_DATA_READ); | 1803 | init_cdrom_command(cgc, buf, size, CGC_DATA_READ); |
1801 | cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; | 1804 | cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE; |
1802 | cgc.cmd[7] = s->type; | 1805 | cgc->cmd[7] = s->type; |
1803 | cgc.cmd[8] = size >> 8; | 1806 | cgc->cmd[8] = size >> 8; |
1804 | cgc.cmd[9] = size & 0xff; | 1807 | cgc->cmd[9] = size & 0xff; |
1805 | cgc.cmd[10] = s->disckey.agid << 6; | 1808 | cgc->cmd[10] = s->disckey.agid << 6; |
1806 | 1809 | ||
1807 | if (!(ret = cdo->generic_packet(cdi, &cgc))) | 1810 | ret = cdo->generic_packet(cdi, cgc); |
1811 | if (!ret) | ||
1808 | memcpy(s->disckey.value, &buf[4], sizeof(s->disckey.value)); | 1812 | memcpy(s->disckey.value, &buf[4], sizeof(s->disckey.value)); |
1809 | 1813 | ||
1810 | kfree(buf); | 1814 | kfree(buf); |
1811 | return ret; | 1815 | return ret; |
1812 | } | 1816 | } |
1813 | 1817 | ||
1814 | static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s) | 1818 | static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s, |
1819 | struct packet_command *cgc) | ||
1815 | { | 1820 | { |
1816 | int ret; | 1821 | int ret, size = 4 + 188; |
1817 | u_char buf[4 + 188]; | 1822 | u_char *buf; |
1818 | struct packet_command cgc; | ||
1819 | struct cdrom_device_ops *cdo = cdi->ops; | 1823 | struct cdrom_device_ops *cdo = cdi->ops; |
1820 | 1824 | ||
1821 | init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ); | 1825 | buf = kmalloc(size, GFP_KERNEL); |
1822 | cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; | 1826 | if (!buf) |
1823 | cgc.cmd[7] = s->type; | 1827 | return -ENOMEM; |
1824 | cgc.cmd[9] = cgc.buflen & 0xff; | ||
1825 | 1828 | ||
1826 | if ((ret = cdo->generic_packet(cdi, &cgc))) | 1829 | init_cdrom_command(cgc, buf, size, CGC_DATA_READ); |
1827 | return ret; | 1830 | cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE; |
1831 | cgc->cmd[7] = s->type; | ||
1832 | cgc->cmd[9] = cgc->buflen & 0xff; | ||
1833 | |||
1834 | ret = cdo->generic_packet(cdi, cgc); | ||
1835 | if (ret) | ||
1836 | goto out; | ||
1828 | 1837 | ||
1829 | s->bca.len = buf[0] << 8 | buf[1]; | 1838 | s->bca.len = buf[0] << 8 | buf[1]; |
1830 | if (s->bca.len < 12 || s->bca.len > 188) { | 1839 | if (s->bca.len < 12 || s->bca.len > 188) { |
1831 | cdinfo(CD_WARNING, "Received invalid BCA length (%d)\n", s->bca.len); | 1840 | cdinfo(CD_WARNING, "Received invalid BCA length (%d)\n", s->bca.len); |
1832 | return -EIO; | 1841 | ret = -EIO; |
1842 | goto out; | ||
1833 | } | 1843 | } |
1834 | memcpy(s->bca.value, &buf[4], s->bca.len); | 1844 | memcpy(s->bca.value, &buf[4], s->bca.len); |
1835 | 1845 | ret = 0; | |
1836 | return 0; | 1846 | out: |
1847 | kfree(buf); | ||
1848 | return ret; | ||
1837 | } | 1849 | } |
1838 | 1850 | ||
1839 | static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s) | 1851 | static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s, |
1852 | struct packet_command *cgc) | ||
1840 | { | 1853 | { |
1841 | int ret = 0, size; | 1854 | int ret = 0, size; |
1842 | u_char *buf; | 1855 | u_char *buf; |
1843 | struct packet_command cgc; | ||
1844 | struct cdrom_device_ops *cdo = cdi->ops; | 1856 | struct cdrom_device_ops *cdo = cdi->ops; |
1845 | 1857 | ||
1846 | size = sizeof(s->manufact.value) + 4; | 1858 | size = sizeof(s->manufact.value) + 4; |
1847 | 1859 | ||
1848 | if ((buf = kmalloc(size, GFP_KERNEL)) == NULL) | 1860 | buf = kmalloc(size, GFP_KERNEL); |
1861 | if (!buf) | ||
1849 | return -ENOMEM; | 1862 | return -ENOMEM; |
1850 | 1863 | ||
1851 | init_cdrom_command(&cgc, buf, size, CGC_DATA_READ); | 1864 | init_cdrom_command(cgc, buf, size, CGC_DATA_READ); |
1852 | cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE; | 1865 | cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE; |
1853 | cgc.cmd[7] = s->type; | 1866 | cgc->cmd[7] = s->type; |
1854 | cgc.cmd[8] = size >> 8; | 1867 | cgc->cmd[8] = size >> 8; |
1855 | cgc.cmd[9] = size & 0xff; | 1868 | cgc->cmd[9] = size & 0xff; |
1856 | 1869 | ||
1857 | if ((ret = cdo->generic_packet(cdi, &cgc))) { | 1870 | ret = cdo->generic_packet(cdi, cgc); |
1858 | kfree(buf); | 1871 | if (ret) |
1859 | return ret; | 1872 | goto out; |
1860 | } | ||
1861 | 1873 | ||
1862 | s->manufact.len = buf[0] << 8 | buf[1]; | 1874 | s->manufact.len = buf[0] << 8 | buf[1]; |
1863 | if (s->manufact.len < 0 || s->manufact.len > 2048) { | 1875 | if (s->manufact.len < 0 || s->manufact.len > 2048) { |
@@ -1868,27 +1880,29 @@ static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s) | |||
1868 | memcpy(s->manufact.value, &buf[4], s->manufact.len); | 1880 | memcpy(s->manufact.value, &buf[4], s->manufact.len); |
1869 | } | 1881 | } |
1870 | 1882 | ||
1883 | out: | ||
1871 | kfree(buf); | 1884 | kfree(buf); |
1872 | return ret; | 1885 | return ret; |
1873 | } | 1886 | } |
1874 | 1887 | ||
1875 | static int dvd_read_struct(struct cdrom_device_info *cdi, dvd_struct *s) | 1888 | static int dvd_read_struct(struct cdrom_device_info *cdi, dvd_struct *s, |
1889 | struct packet_command *cgc) | ||
1876 | { | 1890 | { |
1877 | switch (s->type) { | 1891 | switch (s->type) { |
1878 | case DVD_STRUCT_PHYSICAL: | 1892 | case DVD_STRUCT_PHYSICAL: |
1879 | return dvd_read_physical(cdi, s); | 1893 | return dvd_read_physical(cdi, s, cgc); |
1880 | 1894 | ||
1881 | case DVD_STRUCT_COPYRIGHT: | 1895 | case DVD_STRUCT_COPYRIGHT: |
1882 | return dvd_read_copyright(cdi, s); | 1896 | return dvd_read_copyright(cdi, s, cgc); |
1883 | 1897 | ||
1884 | case DVD_STRUCT_DISCKEY: | 1898 | case DVD_STRUCT_DISCKEY: |
1885 | return dvd_read_disckey(cdi, s); | 1899 | return dvd_read_disckey(cdi, s, cgc); |
1886 | 1900 | ||
1887 | case DVD_STRUCT_BCA: | 1901 | case DVD_STRUCT_BCA: |
1888 | return dvd_read_bca(cdi, s); | 1902 | return dvd_read_bca(cdi, s, cgc); |
1889 | 1903 | ||
1890 | case DVD_STRUCT_MANUFACT: | 1904 | case DVD_STRUCT_MANUFACT: |
1891 | return dvd_read_manufact(cdi, s); | 1905 | return dvd_read_manufact(cdi, s, cgc); |
1892 | 1906 | ||
1893 | default: | 1907 | default: |
1894 | cdinfo(CD_WARNING, ": Invalid DVD structure read requested (%d)\n", | 1908 | cdinfo(CD_WARNING, ": Invalid DVD structure read requested (%d)\n", |
@@ -3027,7 +3041,8 @@ static noinline int mmc_ioctl_cdrom_pause_resume(struct cdrom_device_info *cdi, | |||
3027 | } | 3041 | } |
3028 | 3042 | ||
3029 | static noinline int mmc_ioctl_dvd_read_struct(struct cdrom_device_info *cdi, | 3043 | static noinline int mmc_ioctl_dvd_read_struct(struct cdrom_device_info *cdi, |
3030 | void __user *arg) | 3044 | void __user *arg, |
3045 | struct packet_command *cgc) | ||
3031 | { | 3046 | { |
3032 | int ret; | 3047 | int ret; |
3033 | dvd_struct *s; | 3048 | dvd_struct *s; |
@@ -3046,7 +3061,7 @@ static noinline int mmc_ioctl_dvd_read_struct(struct cdrom_device_info *cdi, | |||
3046 | return -EFAULT; | 3061 | return -EFAULT; |
3047 | } | 3062 | } |
3048 | 3063 | ||
3049 | ret = dvd_read_struct(cdi, s); | 3064 | ret = dvd_read_struct(cdi, s, cgc); |
3050 | if (ret) | 3065 | if (ret) |
3051 | goto out; | 3066 | goto out; |
3052 | 3067 | ||
@@ -3132,7 +3147,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, | |||
3132 | case CDROMRESUME: | 3147 | case CDROMRESUME: |
3133 | return mmc_ioctl_cdrom_pause_resume(cdi, &cgc, cmd); | 3148 | return mmc_ioctl_cdrom_pause_resume(cdi, &cgc, cmd); |
3134 | case DVD_READ_STRUCT: | 3149 | case DVD_READ_STRUCT: |
3135 | return mmc_ioctl_dvd_read_struct(cdi, userptr); | 3150 | return mmc_ioctl_dvd_read_struct(cdi, userptr, &cgc); |
3136 | case DVD_AUTH: | 3151 | case DVD_AUTH: |
3137 | return mmc_ioctl_dvd_auth(cdi, userptr); | 3152 | return mmc_ioctl_dvd_auth(cdi, userptr); |
3138 | case CDROM_NEXT_WRITABLE: | 3153 | case CDROM_NEXT_WRITABLE: |