fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / fs / ufs / namei.c
index 2958cde..e84c0ec 100644 (file)
@@ -1,6 +1,9 @@
 /*
  * linux/fs/ufs/namei.c
  *
+ * Migration to usage of "page cache" on May 2006 by
+ * Evgeniy Dushistov <dushistov@mail.ru> based on ext2 code base.
+ *
  * Copyright (C) 1998
  * Daniel Pirkl <daniel.pirkl@email.cz>
  * Charles University, Faculty of Mathematics and Physics
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
 #include <linux/smp_lock.h>
-#include <linux/buffer_head.h>
 #include "swab.h"      /* will go away - see comment in mknod() */
 #include "util.h"
 
-/*
-#undef UFS_NAMEI_DEBUG
-*/
-#define UFS_NAMEI_DEBUG
-
-#ifdef UFS_NAMEI_DEBUG
-#define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
-#else
-#define UFSD(x)
-#endif
-
-static inline void ufs_inc_count(struct inode *inode)
-{
-       inode->i_nlink++;
-       mark_inode_dirty(inode);
-}
-
-static inline void ufs_dec_count(struct inode *inode)
-{
-       inode->i_nlink--;
-       mark_inode_dirty(inode);
-}
-
 static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode)
 {
        int err = ufs_add_link(dentry, inode);
@@ -62,7 +41,7 @@ static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode)
                d_instantiate(dentry, inode);
                return 0;
        }
-       ufs_dec_count(inode);
+       inode_dec_link_count(inode);
        iput(inode);
        return err;
 }
@@ -100,8 +79,13 @@ static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, stru
 static int ufs_create (struct inode * dir, struct dentry * dentry, int mode,
                struct nameidata *nd)
 {
-       struct inode * inode = ufs_new_inode(dir, mode);
-       int err = PTR_ERR(inode);
+       struct inode *inode;
+       int err;
+
+       UFSD("BEGIN\n");
+       inode = ufs_new_inode(dir, mode);
+       err = PTR_ERR(inode);
+
        if (!IS_ERR(inode)) {
                inode->i_op = &ufs_file_inode_operations;
                inode->i_fop = &ufs_file_operations;
@@ -111,6 +95,7 @@ static int ufs_create (struct inode * dir, struct dentry * dentry, int mode,
                err = ufs_add_nondir(dentry, inode);
                unlock_kernel();
        }
+       UFSD("END: err=%d\n", err);
        return err;
 }
 
@@ -144,7 +129,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
        struct inode * inode;
 
        if (l > sb->s_blocksize)
-               goto out;
+               goto out_notlocked;
 
        lock_kernel();
        inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO);
@@ -170,10 +155,11 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
        err = ufs_add_nondir(dentry, inode);
 out:
        unlock_kernel();
+out_notlocked:
        return err;
 
 out_fail:
-       ufs_dec_count(inode);
+       inode_dec_link_count(inode);
        iput(inode);
        goto out;
 }
@@ -191,7 +177,7 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir,
        }
 
        inode->i_ctime = CURRENT_TIME_SEC;
-       ufs_inc_count(inode);
+       inode_inc_link_count(inode);
        atomic_inc(&inode->i_count);
 
        error = ufs_add_nondir(dentry, inode);
@@ -208,7 +194,7 @@ static int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
                goto out;
 
        lock_kernel();
-       ufs_inc_count(dir);
+       inode_inc_link_count(dir);
 
        inode = ufs_new_inode(dir, S_IFDIR|mode);
        err = PTR_ERR(inode);
@@ -217,8 +203,9 @@ static int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 
        inode->i_op = &ufs_dir_inode_operations;
        inode->i_fop = &ufs_dir_operations;
+       inode->i_mapping->a_ops = &ufs_aops;
 
-       ufs_inc_count(inode);
+       inode_inc_link_count(inode);
 
        err = ufs_make_empty(inode, dir);
        if (err)
@@ -234,36 +221,34 @@ out:
        return err;
 
 out_fail:
-       ufs_dec_count(inode);
-       ufs_dec_count(inode);
+       inode_dec_link_count(inode);
+       inode_dec_link_count(inode);
        iput (inode);
 out_dir:
-       ufs_dec_count(dir);
+       inode_dec_link_count(dir);
        unlock_kernel();
        goto out;
 }
 
-static int ufs_unlink(struct inode * dir, struct dentry *dentry)
+static int ufs_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct inode * inode = dentry->d_inode;
-       struct buffer_head * bh;
-       struct ufs_dir_entry * de;
+       struct ufs_dir_entry *de;
+       struct page *page;
        int err = -ENOENT;
 
-       lock_kernel();
-       de = ufs_find_entry (dentry, &bh);
+       de = ufs_find_entry(dir, dentry, &page);
        if (!de)
                goto out;
 
-       err = ufs_delete_entry (dir, de, bh);
+       err = ufs_delete_entry(dir, de, page);
        if (err)
                goto out;
 
        inode->i_ctime = dir->i_ctime;
-       ufs_dec_count(inode);
+       inode_dec_link_count(inode);
        err = 0;
 out:
-       unlock_kernel();
        return err;
 }
 
@@ -277,88 +262,96 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
                err = ufs_unlink(dir, dentry);
                if (!err) {
                        inode->i_size = 0;
-                       ufs_dec_count(inode);
-                       ufs_dec_count(dir);
+                       inode_dec_link_count(inode);
+                       inode_dec_link_count(dir);
                }
        }
        unlock_kernel();
        return err;
 }
 
-static int ufs_rename (struct inode * old_dir, struct dentry * old_dentry,
-       struct inode * new_dir, struct dentry * new_dentry )
+static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
+                     struct inode *new_dir, struct dentry *new_dentry)
 {
        struct inode *old_inode = old_dentry->d_inode;
        struct inode *new_inode = new_dentry->d_inode;
-       struct buffer_head *dir_bh = NULL;
-       struct ufs_dir_entry *dir_de = NULL;
-       struct buffer_head *old_bh;
+       struct page *dir_page = NULL;
+       struct ufs_dir_entry * dir_de = NULL;
+       struct page *old_page;
        struct ufs_dir_entry *old_de;
        int err = -ENOENT;
 
-       lock_kernel();
-       old_de = ufs_find_entry (old_dentry, &old_bh);
+       old_de = ufs_find_entry(old_dir, old_dentry, &old_page);
        if (!old_de)
                goto out;
 
        if (S_ISDIR(old_inode->i_mode)) {
                err = -EIO;
-               dir_de = ufs_dotdot(old_inode, &dir_bh);
+               dir_de = ufs_dotdot(old_inode, &dir_page);
                if (!dir_de)
                        goto out_old;
        }
 
        if (new_inode) {
-               struct buffer_head *new_bh;
+               struct page *new_page;
                struct ufs_dir_entry *new_de;
 
                err = -ENOTEMPTY;
-               if (dir_de && !ufs_empty_dir (new_inode))
+               if (dir_de && !ufs_empty_dir(new_inode))
                        goto out_dir;
+
                err = -ENOENT;
-               new_de = ufs_find_entry (new_dentry, &new_bh);
+               new_de = ufs_find_entry(new_dir, new_dentry, &new_page);
                if (!new_de)
                        goto out_dir;
-               ufs_inc_count(old_inode);
-               ufs_set_link(new_dir, new_de, new_bh, old_inode);
+               inode_inc_link_count(old_inode);
+               ufs_set_link(new_dir, new_de, new_page, old_inode);
                new_inode->i_ctime = CURRENT_TIME_SEC;
                if (dir_de)
-                       new_inode->i_nlink--;
-               ufs_dec_count(new_inode);
+                       drop_nlink(new_inode);
+               inode_dec_link_count(new_inode);
        } else {
                if (dir_de) {
                        err = -EMLINK;
                        if (new_dir->i_nlink >= UFS_LINK_MAX)
                                goto out_dir;
                }
-               ufs_inc_count(old_inode);
+               inode_inc_link_count(old_inode);
                err = ufs_add_link(new_dentry, old_inode);
                if (err) {
-                       ufs_dec_count(old_inode);
+                       inode_dec_link_count(old_inode);
                        goto out_dir;
                }
                if (dir_de)
-                       ufs_inc_count(new_dir);
+                       inode_inc_link_count(new_dir);
        }
 
-       ufs_delete_entry (old_dir, old_de, old_bh);
+       /*
+        * Like most other Unix systems, set the ctime for inodes on a
+        * rename.
+        * inode_dec_link_count() will mark the inode dirty.
+        */
+       old_inode->i_ctime = CURRENT_TIME_SEC;
 
-       ufs_dec_count(old_inode);
+       ufs_delete_entry(old_dir, old_de, old_page);
+       inode_dec_link_count(old_inode);
 
        if (dir_de) {
-               ufs_set_link(old_inode, dir_de, dir_bh, new_dir);
-               ufs_dec_count(old_dir);
+               ufs_set_link(old_inode, dir_de, dir_page, new_dir);
+               inode_dec_link_count(old_dir);
        }
-       unlock_kernel();
        return 0;
 
+
 out_dir:
-       if (dir_de)
-               brelse(dir_bh);
+       if (dir_de) {
+               kunmap(dir_page);
+               page_cache_release(dir_page);
+       }
 out_old:
-       brelse (old_bh);
+       kunmap(old_page);
+       page_cache_release(old_page);
 out:
-       unlock_kernel();
        return err;
 }