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 /drivers/cdrom | |
| 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>
Diffstat (limited to 'drivers/cdrom')
| -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 b927aa24424..cceace61ef2 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: |
