diff options
-rw-r--r-- | fs/namei.c | 100 | ||||
-rw-r--r-- | fs/open.c | 19 | ||||
-rw-r--r-- | include/linux/fs.h | 3 |
3 files changed, 59 insertions, 63 deletions
diff --git a/fs/namei.c b/fs/namei.c index c70dbf720109..a1f8bbbd58e5 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1725,17 +1725,13 @@ static inline int open_to_namei_flags(int flag) | |||
1725 | } | 1725 | } |
1726 | 1726 | ||
1727 | /* | 1727 | /* |
1728 | * open_namei() | ||
1729 | * | ||
1730 | * namei for open - this is in fact almost the whole open-routine. | ||
1731 | * | ||
1732 | * Note that the low bits of "flag" aren't the same as in the open | 1728 | * Note that the low bits of "flag" aren't the same as in the open |
1733 | * system call. See open_to_namei_flags(). | 1729 | * system call. See open_to_namei_flags(). |
1734 | * SMP-safe | ||
1735 | */ | 1730 | */ |
1736 | int open_namei(int dfd, const char *pathname, int open_flag, | 1731 | struct file *do_filp_open(int dfd, const char *pathname, |
1737 | int mode, struct nameidata *nd) | 1732 | int open_flag, int mode) |
1738 | { | 1733 | { |
1734 | struct nameidata nd; | ||
1739 | int acc_mode, error; | 1735 | int acc_mode, error; |
1740 | struct path path; | 1736 | struct path path; |
1741 | struct dentry *dir; | 1737 | struct dentry *dir; |
@@ -1758,18 +1754,19 @@ int open_namei(int dfd, const char *pathname, int open_flag, | |||
1758 | */ | 1754 | */ |
1759 | if (!(flag & O_CREAT)) { | 1755 | if (!(flag & O_CREAT)) { |
1760 | error = path_lookup_open(dfd, pathname, lookup_flags(flag), | 1756 | error = path_lookup_open(dfd, pathname, lookup_flags(flag), |
1761 | nd, flag); | 1757 | &nd, flag); |
1762 | if (error) | 1758 | if (error) |
1763 | return error; | 1759 | return ERR_PTR(error); |
1764 | goto ok; | 1760 | goto ok; |
1765 | } | 1761 | } |
1766 | 1762 | ||
1767 | /* | 1763 | /* |
1768 | * Create - we need to know the parent. | 1764 | * Create - we need to know the parent. |
1769 | */ | 1765 | */ |
1770 | error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode); | 1766 | error = path_lookup_create(dfd, pathname, LOOKUP_PARENT, |
1767 | &nd, flag, mode); | ||
1771 | if (error) | 1768 | if (error) |
1772 | return error; | 1769 | return ERR_PTR(error); |
1773 | 1770 | ||
1774 | /* | 1771 | /* |
1775 | * We have the parent and last component. First of all, check | 1772 | * We have the parent and last component. First of all, check |
@@ -1777,14 +1774,14 @@ int open_namei(int dfd, const char *pathname, int open_flag, | |||
1777 | * will not do. | 1774 | * will not do. |
1778 | */ | 1775 | */ |
1779 | error = -EISDIR; | 1776 | error = -EISDIR; |
1780 | if (nd->last_type != LAST_NORM || nd->last.name[nd->last.len]) | 1777 | if (nd.last_type != LAST_NORM || nd.last.name[nd.last.len]) |
1781 | goto exit; | 1778 | goto exit; |
1782 | 1779 | ||
1783 | dir = nd->path.dentry; | 1780 | dir = nd.path.dentry; |
1784 | nd->flags &= ~LOOKUP_PARENT; | 1781 | nd.flags &= ~LOOKUP_PARENT; |
1785 | mutex_lock(&dir->d_inode->i_mutex); | 1782 | mutex_lock(&dir->d_inode->i_mutex); |
1786 | path.dentry = lookup_hash(nd); | 1783 | path.dentry = lookup_hash(&nd); |
1787 | path.mnt = nd->path.mnt; | 1784 | path.mnt = nd.path.mnt; |
1788 | 1785 | ||
1789 | do_last: | 1786 | do_last: |
1790 | error = PTR_ERR(path.dentry); | 1787 | error = PTR_ERR(path.dentry); |
@@ -1793,18 +1790,18 @@ do_last: | |||
1793 | goto exit; | 1790 | goto exit; |
1794 | } | 1791 | } |
1795 | 1792 | ||
1796 | if (IS_ERR(nd->intent.open.file)) { | 1793 | if (IS_ERR(nd.intent.open.file)) { |
1797 | mutex_unlock(&dir->d_inode->i_mutex); | 1794 | mutex_unlock(&dir->d_inode->i_mutex); |
1798 | error = PTR_ERR(nd->intent.open.file); | 1795 | error = PTR_ERR(nd.intent.open.file); |
1799 | goto exit_dput; | 1796 | goto exit_dput; |
1800 | } | 1797 | } |
1801 | 1798 | ||
1802 | /* Negative dentry, just create the file */ | 1799 | /* Negative dentry, just create the file */ |
1803 | if (!path.dentry->d_inode) { | 1800 | if (!path.dentry->d_inode) { |
1804 | error = __open_namei_create(nd, &path, flag, mode); | 1801 | error = __open_namei_create(&nd, &path, flag, mode); |
1805 | if (error) | 1802 | if (error) |
1806 | goto exit; | 1803 | goto exit; |
1807 | return 0; | 1804 | return nameidata_to_filp(&nd, open_flag); |
1808 | } | 1805 | } |
1809 | 1806 | ||
1810 | /* | 1807 | /* |
@@ -1829,23 +1826,23 @@ do_last: | |||
1829 | if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link) | 1826 | if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link) |
1830 | goto do_link; | 1827 | goto do_link; |
1831 | 1828 | ||
1832 | path_to_nameidata(&path, nd); | 1829 | path_to_nameidata(&path, &nd); |
1833 | error = -EISDIR; | 1830 | error = -EISDIR; |
1834 | if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode)) | 1831 | if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode)) |
1835 | goto exit; | 1832 | goto exit; |
1836 | ok: | 1833 | ok: |
1837 | error = may_open(nd, acc_mode, flag); | 1834 | error = may_open(&nd, acc_mode, flag); |
1838 | if (error) | 1835 | if (error) |
1839 | goto exit; | 1836 | goto exit; |
1840 | return 0; | 1837 | return nameidata_to_filp(&nd, open_flag); |
1841 | 1838 | ||
1842 | exit_dput: | 1839 | exit_dput: |
1843 | path_put_conditional(&path, nd); | 1840 | path_put_conditional(&path, &nd); |
1844 | exit: | 1841 | exit: |
1845 | if (!IS_ERR(nd->intent.open.file)) | 1842 | if (!IS_ERR(nd.intent.open.file)) |
1846 | release_open_intent(nd); | 1843 | release_open_intent(&nd); |
1847 | path_put(&nd->path); | 1844 | path_put(&nd.path); |
1848 | return error; | 1845 | return ERR_PTR(error); |
1849 | 1846 | ||
1850 | do_link: | 1847 | do_link: |
1851 | error = -ELOOP; | 1848 | error = -ELOOP; |
@@ -1861,43 +1858,60 @@ do_link: | |||
1861 | * stored in nd->last.name and we will have to putname() it when we | 1858 | * stored in nd->last.name and we will have to putname() it when we |
1862 | * are done. Procfs-like symlinks just set LAST_BIND. | 1859 | * are done. Procfs-like symlinks just set LAST_BIND. |
1863 | */ | 1860 | */ |
1864 | nd->flags |= LOOKUP_PARENT; | 1861 | nd.flags |= LOOKUP_PARENT; |
1865 | error = security_inode_follow_link(path.dentry, nd); | 1862 | error = security_inode_follow_link(path.dentry, &nd); |
1866 | if (error) | 1863 | if (error) |
1867 | goto exit_dput; | 1864 | goto exit_dput; |
1868 | error = __do_follow_link(&path, nd); | 1865 | error = __do_follow_link(&path, &nd); |
1869 | if (error) { | 1866 | if (error) { |
1870 | /* Does someone understand code flow here? Or it is only | 1867 | /* Does someone understand code flow here? Or it is only |
1871 | * me so stupid? Anathema to whoever designed this non-sense | 1868 | * me so stupid? Anathema to whoever designed this non-sense |
1872 | * with "intent.open". | 1869 | * with "intent.open". |
1873 | */ | 1870 | */ |
1874 | release_open_intent(nd); | 1871 | release_open_intent(&nd); |
1875 | return error; | 1872 | return ERR_PTR(error); |
1876 | } | 1873 | } |
1877 | nd->flags &= ~LOOKUP_PARENT; | 1874 | nd.flags &= ~LOOKUP_PARENT; |
1878 | if (nd->last_type == LAST_BIND) | 1875 | if (nd.last_type == LAST_BIND) |
1879 | goto ok; | 1876 | goto ok; |
1880 | error = -EISDIR; | 1877 | error = -EISDIR; |
1881 | if (nd->last_type != LAST_NORM) | 1878 | if (nd.last_type != LAST_NORM) |
1882 | goto exit; | 1879 | goto exit; |
1883 | if (nd->last.name[nd->last.len]) { | 1880 | if (nd.last.name[nd.last.len]) { |
1884 | __putname(nd->last.name); | 1881 | __putname(nd.last.name); |
1885 | goto exit; | 1882 | goto exit; |
1886 | } | 1883 | } |
1887 | error = -ELOOP; | 1884 | error = -ELOOP; |
1888 | if (count++==32) { | 1885 | if (count++==32) { |
1889 | __putname(nd->last.name); | 1886 | __putname(nd.last.name); |
1890 | goto exit; | 1887 | goto exit; |
1891 | } | 1888 | } |
1892 | dir = nd->path.dentry; | 1889 | dir = nd.path.dentry; |
1893 | mutex_lock(&dir->d_inode->i_mutex); | 1890 | mutex_lock(&dir->d_inode->i_mutex); |
1894 | path.dentry = lookup_hash(nd); | 1891 | path.dentry = lookup_hash(&nd); |
1895 | path.mnt = nd->path.mnt; | 1892 | path.mnt = nd.path.mnt; |
1896 | __putname(nd->last.name); | 1893 | __putname(nd.last.name); |
1897 | goto do_last; | 1894 | goto do_last; |
1898 | } | 1895 | } |
1899 | 1896 | ||
1900 | /** | 1897 | /** |
1898 | * filp_open - open file and return file pointer | ||
1899 | * | ||
1900 | * @filename: path to open | ||
1901 | * @flags: open flags as per the open(2) second argument | ||
1902 | * @mode: mode for the new file if O_CREAT is set, else ignored | ||
1903 | * | ||
1904 | * This is the helper to open a file from kernelspace if you really | ||
1905 | * have to. But in generally you should not do this, so please move | ||
1906 | * along, nothing to see here.. | ||
1907 | */ | ||
1908 | struct file *filp_open(const char *filename, int flags, int mode) | ||
1909 | { | ||
1910 | return do_filp_open(AT_FDCWD, filename, flags, mode); | ||
1911 | } | ||
1912 | EXPORT_SYMBOL(filp_open); | ||
1913 | |||
1914 | /** | ||
1901 | * lookup_create - lookup a dentry, creating it if it doesn't exist | 1915 | * lookup_create - lookup a dentry, creating it if it doesn't exist |
1902 | * @nd: nameidata info | 1916 | * @nd: nameidata info |
1903 | * @is_dir: directory flag | 1917 | * @is_dir: directory flag |
@@ -796,25 +796,6 @@ cleanup_file: | |||
796 | return ERR_PTR(error); | 796 | return ERR_PTR(error); |
797 | } | 797 | } |
798 | 798 | ||
799 | static struct file *do_filp_open(int dfd, const char *filename, int flags, | ||
800 | int mode) | ||
801 | { | ||
802 | int error; | ||
803 | struct nameidata nd; | ||
804 | |||
805 | error = open_namei(dfd, filename, flags, mode, &nd); | ||
806 | if (!error) | ||
807 | return nameidata_to_filp(&nd, flags); | ||
808 | |||
809 | return ERR_PTR(error); | ||
810 | } | ||
811 | |||
812 | struct file *filp_open(const char *filename, int flags, int mode) | ||
813 | { | ||
814 | return do_filp_open(AT_FDCWD, filename, flags, mode); | ||
815 | } | ||
816 | EXPORT_SYMBOL(filp_open); | ||
817 | |||
818 | /** | 799 | /** |
819 | * lookup_instantiate_filp - instantiates the open intent filp | 800 | * lookup_instantiate_filp - instantiates the open intent filp |
820 | * @nd: pointer to nameidata | 801 | * @nd: pointer to nameidata |
diff --git a/include/linux/fs.h b/include/linux/fs.h index b84b848431f2..013b9c2b88e6 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1735,7 +1735,8 @@ extern struct file *create_read_pipe(struct file *f); | |||
1735 | extern struct file *create_write_pipe(void); | 1735 | extern struct file *create_write_pipe(void); |
1736 | extern void free_write_pipe(struct file *); | 1736 | extern void free_write_pipe(struct file *); |
1737 | 1737 | ||
1738 | extern int open_namei(int dfd, const char *, int, int, struct nameidata *); | 1738 | extern struct file *do_filp_open(int dfd, const char *pathname, |
1739 | int open_flag, int mode); | ||
1739 | extern int may_open(struct nameidata *, int, int); | 1740 | extern int may_open(struct nameidata *, int, int); |
1740 | 1741 | ||
1741 | extern int kernel_read(struct file *, unsigned long, char *, unsigned long); | 1742 | extern int kernel_read(struct file *, unsigned long, char *, unsigned long); |