diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-27 05:16:07 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-27 05:16:07 +0100 |
commit | d895cb1af15c04c522a25c79cc429076987c089b (patch) | |
tree | 895dc9157e28f603d937a58be664e4e440d5530c /fs/namei.c | |
parent | Merge tag 'xtensa-next-20130225' of git://github.com/czankel/xtensa-linux (diff) | |
parent | saner proc_get_inode() calling conventions (diff) | |
download | linux-d895cb1af15c04c522a25c79cc429076987c089b.tar.xz linux-d895cb1af15c04c522a25c79cc429076987c089b.zip |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs pile (part one) from Al Viro:
"Assorted stuff - cleaning namei.c up a bit, fixing ->d_name/->d_parent
locking violations, etc.
The most visible changes here are death of FS_REVAL_DOT (replaced with
"has ->d_weak_revalidate()") and a new helper getting from struct file
to inode. Some bits of preparation to xattr method interface changes.
Misc patches by various people sent this cycle *and* ocfs2 fixes from
several cycles ago that should've been upstream right then.
PS: the next vfs pile will be xattr stuff."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (46 commits)
saner proc_get_inode() calling conventions
proc: avoid extra pde_put() in proc_fill_super()
fs: change return values from -EACCES to -EPERM
fs/exec.c: make bprm_mm_init() static
ocfs2/dlm: use GFP_ATOMIC inside a spin_lock
ocfs2: fix possible use-after-free with AIO
ocfs2: Fix oops in ocfs2_fast_symlink_readpage() code path
get_empty_filp()/alloc_file() leave both ->f_pos and ->f_version zero
target: writev() on single-element vector is pointless
export kernel_write(), convert open-coded instances
fs: encode_fh: return FILEID_INVALID if invalid fid_type
kill f_vfsmnt
vfs: kill FS_REVAL_DOT by adding a d_weak_revalidate dentry op
nfsd: handle vfs_getattr errors in acl protocol
switch vfs_getattr() to struct path
default SET_PERSONALITY() in linux/elf.h
ceph: prepopulate inodes only when request is aborted
d_hash_and_lookup(): export, switch open-coded instances
9p: switch v9fs_set_create_acl() to inode+fid, do it before d_instantiate()
9p: split dropping the acls from v9fs_set_create_acl()
...
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 67 |
1 files changed, 29 insertions, 38 deletions
diff --git a/fs/namei.c b/fs/namei.c index 43a97ee1d4c8..dc984fee5532 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -600,14 +600,10 @@ static int complete_walk(struct nameidata *nd) if (likely(!(nd->flags & LOOKUP_JUMPED))) return 0; - if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE))) + if (likely(!(dentry->d_flags & DCACHE_OP_WEAK_REVALIDATE))) return 0; - if (likely(!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT))) - return 0; - - /* Note: we do not d_invalidate() */ - status = d_revalidate(dentry, nd->flags); + status = dentry->d_op->d_weak_revalidate(dentry, nd->flags); if (status > 0) return 0; @@ -1342,7 +1338,7 @@ static struct dentry *__lookup_hash(struct qstr *name, * small and for now I'd prefer to have fast path as straight as possible. * It _is_ time-critical. */ -static int lookup_fast(struct nameidata *nd, struct qstr *name, +static int lookup_fast(struct nameidata *nd, struct path *path, struct inode **inode) { struct vfsmount *mnt = nd->path.mnt; @@ -1358,7 +1354,7 @@ static int lookup_fast(struct nameidata *nd, struct qstr *name, */ if (nd->flags & LOOKUP_RCU) { unsigned seq; - dentry = __d_lookup_rcu(parent, name, &seq, nd->inode); + dentry = __d_lookup_rcu(parent, &nd->last, &seq, nd->inode); if (!dentry) goto unlazy; @@ -1400,7 +1396,7 @@ unlazy: if (unlazy_walk(nd, dentry)) return -ECHILD; } else { - dentry = __d_lookup(parent, name); + dentry = __d_lookup(parent, &nd->last); } if (unlikely(!dentry)) @@ -1436,8 +1432,7 @@ need_lookup: } /* Fast lookup failed, do it the slow way */ -static int lookup_slow(struct nameidata *nd, struct qstr *name, - struct path *path) +static int lookup_slow(struct nameidata *nd, struct path *path) { struct dentry *dentry, *parent; int err; @@ -1446,7 +1441,7 @@ static int lookup_slow(struct nameidata *nd, struct qstr *name, BUG_ON(nd->inode != parent->d_inode); mutex_lock(&parent->d_inode->i_mutex); - dentry = __lookup_hash(name, parent, nd->flags); + dentry = __lookup_hash(&nd->last, parent, nd->flags); mutex_unlock(&parent->d_inode->i_mutex); if (IS_ERR(dentry)) return PTR_ERR(dentry); @@ -1519,7 +1514,7 @@ static inline int should_follow_link(struct inode *inode, int follow) } static inline int walk_component(struct nameidata *nd, struct path *path, - struct qstr *name, int type, int follow) + int follow) { struct inode *inode; int err; @@ -1528,14 +1523,14 @@ static inline int walk_component(struct nameidata *nd, struct path *path, * to be able to know about the current root directory and * parent relationships. */ - if (unlikely(type != LAST_NORM)) - return handle_dots(nd, type); - err = lookup_fast(nd, name, path, &inode); + if (unlikely(nd->last_type != LAST_NORM)) + return handle_dots(nd, nd->last_type); + err = lookup_fast(nd, path, &inode); if (unlikely(err)) { if (err < 0) goto out_err; - err = lookup_slow(nd, name, path); + err = lookup_slow(nd, path); if (err < 0) goto out_err; @@ -1594,8 +1589,7 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd) res = follow_link(&link, nd, &cookie); if (res) break; - res = walk_component(nd, path, &nd->last, - nd->last_type, LOOKUP_FOLLOW); + res = walk_component(nd, path, LOOKUP_FOLLOW); put_link(nd, &link, cookie); } while (res > 0); @@ -1802,8 +1796,11 @@ static int link_path_walk(const char *name, struct nameidata *nd) } } + nd->last = this; + nd->last_type = type; + if (!name[len]) - goto last_component; + return 0; /* * If it wasn't NUL, we know it was '/'. Skip that * slash, and continue until no more slashes. @@ -1812,10 +1809,11 @@ static int link_path_walk(const char *name, struct nameidata *nd) len++; } while (unlikely(name[len] == '/')); if (!name[len]) - goto last_component; + return 0; + name += len; - err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW); + err = walk_component(nd, &next, LOOKUP_FOLLOW); if (err < 0) return err; @@ -1824,16 +1822,10 @@ static int link_path_walk(const char *name, struct nameidata *nd) if (err) return err; } - if (can_lookup(nd->inode)) - continue; - err = -ENOTDIR; - break; - /* here ends the main loop */ - -last_component: - nd->last = this; - nd->last_type = type; - return 0; + if (!can_lookup(nd->inode)) { + err = -ENOTDIR; + break; + } } terminate_walk(nd); return err; @@ -1932,8 +1924,7 @@ static inline int lookup_last(struct nameidata *nd, struct path *path) nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; nd->flags &= ~LOOKUP_PARENT; - return walk_component(nd, path, &nd->last, nd->last_type, - nd->flags & LOOKUP_FOLLOW); + return walk_component(nd, path, nd->flags & LOOKUP_FOLLOW); } /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ @@ -2732,7 +2723,7 @@ static int do_last(struct nameidata *nd, struct path *path, if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW)) symlink_ok = true; /* we _can_ be in RCU mode here */ - error = lookup_fast(nd, &nd->last, path, &inode); + error = lookup_fast(nd, path, &inode); if (likely(!error)) goto finish_lookup; @@ -2778,7 +2769,7 @@ retry_lookup: goto out; if ((*opened & FILE_CREATED) || - !S_ISREG(file->f_path.dentry->d_inode->i_mode)) + !S_ISREG(file_inode(file)->i_mode)) will_truncate = false; audit_inode(name, file->f_path.dentry, 0); @@ -2941,8 +2932,8 @@ static struct file *path_openat(int dfd, struct filename *pathname, int error; file = get_empty_filp(); - if (!file) - return ERR_PTR(-ENFILE); + if (IS_ERR(file)) + return file; file->f_flags = op->open_flag; |