linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / fs / namei.c
index 577bf13..cd234db 100644 (file)
  */
 /*
  * [Sep 2001 AV] Single-semaphore locking scheme (kudos to David Holland)
- * implemented.  Let's see if raised priority of ->s_vfs_rename_mutex gives
+ * implemented.  Let's see if raised priority of ->s_vfs_rename_sem gives
  * any extra contention...
  */
 
@@ -231,7 +231,7 @@ int generic_permission(struct inode *inode, int mask,
 
 static inline int vx_barrier(struct inode *inode)
 {
-       if (IS_BARRIER(inode) && !vx_check(0, VX_ADMIN)) {
+       if (IS_BARRIER(inode) && !vx_check(0, VX_ADMIN|VX_IDENT)) {
                vxwprintk(1, "xid=%d did hit the barrier.",
                        vx_current_xid());
                return 1;
@@ -587,22 +587,6 @@ struct path {
        struct dentry *dentry;
 };
 
-static inline void dput_path(struct path *path, struct nameidata *nd)
-{
-       dput(path->dentry);
-       if (path->mnt != nd->mnt)
-               mntput(path->mnt);
-}
-
-static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
-{
-       dput(nd->dentry);
-       if (nd->mnt != path->mnt)
-               mntput(nd->mnt);
-       nd->mnt = path->mnt;
-       nd->dentry = path->dentry;
-}
-
 static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd)
 {
        int error;
@@ -612,11 +596,8 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
        touch_atime(path->mnt, dentry);
        nd_set_link(nd, NULL);
 
-       if (path->mnt != nd->mnt) {
-               path_to_nameidata(path, nd);
-               dget(dentry);
-       }
-       mntget(path->mnt);
+       if (path->mnt == nd->mnt)
+               mntget(path->mnt);
        cookie = dentry->d_inode->i_op->follow_link(dentry, nd);
        error = PTR_ERR(cookie);
        if (!IS_ERR(cookie)) {
@@ -633,6 +614,22 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
        return error;
 }
 
+static inline void dput_path(struct path *path, struct nameidata *nd)
+{
+       dput(path->dentry);
+       if (path->mnt != nd->mnt)
+               mntput(path->mnt);
+}
+
+static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
+{
+       dput(nd->dentry);
+       if (nd->mnt != path->mnt)
+               mntput(nd->mnt);
+       nd->mnt = path->mnt;
+       nd->dentry = path->dentry;
+}
+
 /*
  * This limits recursive symlink follows to 8, while
  * limiting consecutive symlinks to 40.
@@ -780,7 +777,7 @@ static __always_inline void follow_dotdot(struct nameidata *nd)
  *  It _is_ time-critical.
  */
 static int do_lookup(struct nameidata *nd, struct qstr *name,
-                    struct path *path, int atomic)
+                    struct path *path)
 {
        struct vfsmount *mnt = nd->mnt;
        struct dentry *dentry = __d_lookup(nd->dentry, name);
@@ -824,16 +821,12 @@ hidden:
        return -ENOENT;
 
 need_lookup:
-       if (atomic)
-               return -EWOULDBLOCKIO;
        dentry = real_lookup(nd->dentry, name, nd);
        if (IS_ERR(dentry))
                goto fail;
        goto done;
 
 need_revalidate:
-       if (atomic)
-               return -EWOULDBLOCKIO;
        if (dentry->d_op->d_revalidate(dentry, nd))
                goto done;
        if (d_invalidate(dentry))
@@ -857,11 +850,9 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
 {
        struct path next;
        struct inode *inode;
-       int err, atomic;
+       int err;
        unsigned int lookup_flags = nd->flags;
-
-       atomic = (lookup_flags & LOOKUP_ATOMIC);
-
+       
        while (*name=='/')
                name++;
        if (!*name)
@@ -930,7 +921,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
                                break;
                }
                /* This does the actual lookups.. */
-               err = do_lookup(nd, &this, &next, atomic);
+               err = do_lookup(nd, &this, &next);
                if (err)
                        break;
 
@@ -985,7 +976,7 @@ last_component:
                        if (err < 0)
                                break;
                }
-               err = do_lookup(nd, &this, &next, atomic);
+               err = do_lookup(nd, &this, &next);
                if (err)
                        break;
                inode = next.dentry->d_inode;
@@ -1331,7 +1322,7 @@ out:
        return dentry;
 }
 
-static struct dentry *lookup_hash(struct nameidata *nd)
+struct dentry * lookup_hash(struct nameidata *nd)
 {
        return __lookup_hash(&nd->last, nd->dentry, nd);
 }
@@ -1434,7 +1425,6 @@ static int may_delete(struct inode *dir, struct dentry *victim,
                return -ENOENT;
 
        BUG_ON(victim->d_parent->d_inode != dir);
-       audit_inode_child(victim->d_name.name, victim->d_inode, dir->i_ino);
 
        error = permission(dir,MAY_WRITE | MAY_EXEC, nd);
        if (error)
@@ -1488,8 +1478,6 @@ static inline int lookup_flags(unsigned int f)
        
        if (f & O_DIRECTORY)
                retval |= LOOKUP_DIRECTORY;
-       if (f & O_ATOMICLOOKUP)
-               retval |= LOOKUP_ATOMIC;
 
        return retval;
 }
@@ -1506,7 +1494,7 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
                return NULL;
        }
 
-       mutex_lock(&p1->d_inode->i_sb->s_vfs_rename_mutex);
+       down(&p1->d_inode->i_sb->s_vfs_rename_sem);
 
        for (p = p1; p->d_parent != p; p = p->d_parent) {
                if (p->d_parent == p2) {
@@ -1534,7 +1522,7 @@ void unlock_rename(struct dentry *p1, struct dentry *p2)
        mutex_unlock(&p1->d_inode->i_mutex);
        if (p1 != p2) {
                mutex_unlock(&p2->d_inode->i_mutex);
-               mutex_unlock(&p1->d_inode->i_sb->s_vfs_rename_mutex);
+               up(&p1->d_inode->i_sb->s_vfs_rename_sem);
        }
 }
 
@@ -1556,7 +1544,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
        DQUOT_INIT(dir);
        error = dir->i_op->create(dir, dentry, mode, nd);
        if (!error)
-               fsnotify_create(dir, dentry);
+               fsnotify_create(dir, dentry->d_name.name);
        return error;
 }
 
@@ -1891,7 +1879,7 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry,
        DQUOT_INIT(dir);
        error = dir->i_op->mknod(dir, dentry, mode, dev);
        if (!error)
-               fsnotify_create(dir, dentry);
+               fsnotify_create(dir, dentry->d_name.name);
        return error;
 }
 
@@ -1970,7 +1958,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry,
        DQUOT_INIT(dir);
        error = dir->i_op->mkdir(dir, dentry, mode);
        if (!error)
-               fsnotify_mkdir(dir, dentry);
+               fsnotify_mkdir(dir, dentry->d_name.name);
        return error;
 }
 
@@ -2237,7 +2225,7 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry,
        DQUOT_INIT(dir);
        error = dir->i_op->symlink(dir, dentry, oldname);
        if (!error)
-               fsnotify_create(dir, dentry);
+               fsnotify_create(dir, dentry->d_name.name);
        return error;
 }
 
@@ -2316,7 +2304,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir,
        error = dir->i_op->link(old_dentry, dir, new_dentry);
        mutex_unlock(&old_dentry->d_inode->i_mutex);
        if (!error)
-               fsnotify_create(dir, new_dentry);
+               fsnotify_create(dir, new_dentry->d_name.name);
        return error;
 }
 
@@ -2389,17 +2377,17 @@ asmlinkage long sys_link(const char __user *oldname, const char __user *newname)
  *     a) we can get into loop creation. Check is done in is_subdir().
  *     b) race potential - two innocent renames can create a loop together.
  *        That's where 4.4 screws up. Current fix: serialization on
- *        sb->s_vfs_rename_mutex. We might be more accurate, but that's another
+ *        sb->s_vfs_rename_sem. We might be more accurate, but that's another
  *        story.
  *     c) we have to lock _three_ objects - parents and victim (if it exists).
  *        And that - after we got ->i_mutex on parents (until then we don't know
  *        whether the target exists).  Solution: try to be smart with locking
  *        order for inodes.  We rely on the fact that tree topology may change
- *        only under ->s_vfs_rename_mutex _and_ that parent of the object we
+ *        only under ->s_vfs_rename_sem _and_ that parent of the object we
  *        move will be locked.  Thus we can rank directories by the tree
  *        (ancestors first) and rank all non-directories after them.
  *        That works since everybody except rename does "lock parent, lookup,
- *        lock child" and rename is under ->s_vfs_rename_mutex.
+ *        lock child" and rename is under ->s_vfs_rename_sem.
  *        HOWEVER, it relies on the assumption that any object with ->lookup()
  *        has no more than 1 dentry.  If "hybrid" objects will ever appear,
  *        we'd better make sure that there's no link(2) for them.
@@ -2736,27 +2724,16 @@ int __page_symlink(struct inode *inode, const char *symname, int len,
        int err = -ENOMEM;
        char *kaddr;
 
-retry:
        page = find_or_create_page(mapping, 0, gfp_mask);
        if (!page)
                goto fail;
        err = mapping->a_ops->prepare_write(NULL, page, 0, len-1);
-       if (err == AOP_TRUNCATED_PAGE) {
-               page_cache_release(page);
-               goto retry;
-       }
        if (err)
                goto fail_map;
        kaddr = kmap_atomic(page, KM_USER0);
        memcpy(kaddr, symname, len-1);
        kunmap_atomic(kaddr, KM_USER0);
-       err = mapping->a_ops->commit_write(NULL, page, 0, len-1);
-       if (err == AOP_TRUNCATED_PAGE) {
-               page_cache_release(page);
-               goto retry;
-       }
-       if (err)
-               goto fail_map;
+       mapping->a_ops->commit_write(NULL, page, 0, len-1);
        /*
         * Notice that we are _not_ going to block here - end of page is
         * unmapped, so this will only try to map the rest of page, see
@@ -2766,8 +2743,7 @@ retry:
         */
        if (!PageUptodate(page)) {
                err = mapping->a_ops->readpage(NULL, page);
-               if (err != AOP_TRUNCATED_PAGE)
-                       wait_on_page_locked(page);
+               wait_on_page_locked(page);
        } else {
                unlock_page(page);
        }
@@ -2802,6 +2778,7 @@ EXPORT_SYMBOL(follow_up);
 EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
 EXPORT_SYMBOL(getname);
 EXPORT_SYMBOL(lock_rename);
+EXPORT_SYMBOL(lookup_hash);
 EXPORT_SYMBOL(lookup_one_len);
 EXPORT_SYMBOL(page_follow_link_light);
 EXPORT_SYMBOL(page_put_link);