diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 41 |
1 files changed, 18 insertions, 23 deletions
diff --git a/fs/namei.c b/fs/namei.c index a856e7f7b6e3..aa30d19e9edd 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1797,8 +1797,6 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
1797 | struct nameidata *nd, struct file **fp) | 1797 | struct nameidata *nd, struct file **fp) |
1798 | { | 1798 | { |
1799 | int retval = 0; | 1799 | int retval = 0; |
1800 | int fput_needed; | ||
1801 | struct file *file; | ||
1802 | 1800 | ||
1803 | nd->last_type = LAST_ROOT; /* if there are only slashes... */ | 1801 | nd->last_type = LAST_ROOT; /* if there are only slashes... */ |
1804 | nd->flags = flags | LOOKUP_JUMPED; | 1802 | nd->flags = flags | LOOKUP_JUMPED; |
@@ -1850,44 +1848,41 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
1850 | get_fs_pwd(current->fs, &nd->path); | 1848 | get_fs_pwd(current->fs, &nd->path); |
1851 | } | 1849 | } |
1852 | } else { | 1850 | } else { |
1851 | struct fd f = fdget_raw(dfd); | ||
1853 | struct dentry *dentry; | 1852 | struct dentry *dentry; |
1854 | 1853 | ||
1855 | file = fget_raw_light(dfd, &fput_needed); | 1854 | if (!f.file) |
1856 | retval = -EBADF; | 1855 | return -EBADF; |
1857 | if (!file) | ||
1858 | goto out_fail; | ||
1859 | 1856 | ||
1860 | dentry = file->f_path.dentry; | 1857 | dentry = f.file->f_path.dentry; |
1861 | 1858 | ||
1862 | if (*name) { | 1859 | if (*name) { |
1863 | retval = -ENOTDIR; | 1860 | if (!S_ISDIR(dentry->d_inode->i_mode)) { |
1864 | if (!S_ISDIR(dentry->d_inode->i_mode)) | 1861 | fdput(f); |
1865 | goto fput_fail; | 1862 | return -ENOTDIR; |
1863 | } | ||
1866 | 1864 | ||
1867 | retval = inode_permission(dentry->d_inode, MAY_EXEC); | 1865 | retval = inode_permission(dentry->d_inode, MAY_EXEC); |
1868 | if (retval) | 1866 | if (retval) { |
1869 | goto fput_fail; | 1867 | fdput(f); |
1868 | return retval; | ||
1869 | } | ||
1870 | } | 1870 | } |
1871 | 1871 | ||
1872 | nd->path = file->f_path; | 1872 | nd->path = f.file->f_path; |
1873 | if (flags & LOOKUP_RCU) { | 1873 | if (flags & LOOKUP_RCU) { |
1874 | if (fput_needed) | 1874 | if (f.need_put) |
1875 | *fp = file; | 1875 | *fp = f.file; |
1876 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); | 1876 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); |
1877 | lock_rcu_walk(); | 1877 | lock_rcu_walk(); |
1878 | } else { | 1878 | } else { |
1879 | path_get(&file->f_path); | 1879 | path_get(&nd->path); |
1880 | fput_light(file, fput_needed); | 1880 | fdput(f); |
1881 | } | 1881 | } |
1882 | } | 1882 | } |
1883 | 1883 | ||
1884 | nd->inode = nd->path.dentry->d_inode; | 1884 | nd->inode = nd->path.dentry->d_inode; |
1885 | return 0; | 1885 | return 0; |
1886 | |||
1887 | fput_fail: | ||
1888 | fput_light(file, fput_needed); | ||
1889 | out_fail: | ||
1890 | return retval; | ||
1891 | } | 1886 | } |
1892 | 1887 | ||
1893 | static inline int lookup_last(struct nameidata *nd, struct path *path) | 1888 | static inline int lookup_last(struct nameidata *nd, struct path *path) |
@@ -3971,7 +3966,7 @@ EXPORT_SYMBOL(user_path_at); | |||
3971 | EXPORT_SYMBOL(follow_down_one); | 3966 | EXPORT_SYMBOL(follow_down_one); |
3972 | EXPORT_SYMBOL(follow_down); | 3967 | EXPORT_SYMBOL(follow_down); |
3973 | EXPORT_SYMBOL(follow_up); | 3968 | EXPORT_SYMBOL(follow_up); |
3974 | EXPORT_SYMBOL(get_write_access); /* binfmt_aout */ | 3969 | EXPORT_SYMBOL(get_write_access); /* nfsd */ |
3975 | EXPORT_SYMBOL(getname); | 3970 | EXPORT_SYMBOL(getname); |
3976 | EXPORT_SYMBOL(lock_rename); | 3971 | EXPORT_SYMBOL(lock_rename); |
3977 | EXPORT_SYMBOL(lookup_one_len); | 3972 | EXPORT_SYMBOL(lookup_one_len); |