Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / fs / jfs / namei.c
index 8413a36..2d7f32a 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/fs.h>
 #include <linux/ctype.h>
 #include <linux/quotaops.h>
+#include <linux/vserver/xid.h>
 #include "jfs_incore.h"
 #include "jfs_superblock.h"
 #include "jfs_inode.h"
 #include "jfs_acl.h"
 #include "jfs_debug.h"
 
-extern struct inode_operations jfs_file_inode_operations;
-extern struct inode_operations jfs_symlink_inode_operations;
-extern struct file_operations jfs_file_operations;
-extern struct address_space_operations jfs_aops;
-
-extern int jfs_fsync(struct file *, struct dentry *, int);
-extern void jfs_truncate_nolock(struct inode *, loff_t);
-extern int jfs_init_acl(struct inode *, struct inode *);
-
 /*
  * forward references
  */
-struct inode_operations jfs_dir_inode_operations;
-struct file_operations jfs_dir_operations;
 struct dentry_operations jfs_ci_dentry_operations;
 
 static s64 commitZeroLink(tid_t, struct inode *);
 
+/*
+ * NAME:       free_ea_wmap(inode)
+ *
+ * FUNCTION:   free uncommitted extended attributes from working map 
+ *
+ */
+static inline void free_ea_wmap(struct inode *inode)
+{
+       dxd_t *ea = &JFS_IP(inode)->ea;
+
+       if (ea->flag & DXD_EXTENT) {
+               /* free EA pages from cache */
+               invalidate_dxd_metapages(inode, *ea);
+               dbFree(inode, addressDXD(ea), lengthDXD(ea));
+       }
+       ea->flag = 0;
+}
+
 /*
  * NAME:       jfs_create(dip, dentry, mode)
  *
@@ -97,11 +105,22 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
 
        tid = txBegin(dip->i_sb, 0);
 
-       down(&JFS_IP(dip)->commit_sem);
-       down(&JFS_IP(ip)->commit_sem);
+       mutex_lock(&JFS_IP(dip)->commit_mutex);
+       mutex_lock(&JFS_IP(ip)->commit_mutex);
+
+       rc = jfs_init_acl(tid, ip, dip);
+       if (rc)
+               goto out3;
+
+       rc = jfs_init_security(tid, ip, dip);
+       if (rc) {
+               txAbort(tid, 0);
+               goto out3;
+       }
 
        if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
                jfs_err("jfs_create: dtSearch returned %d", rc);
+               txAbort(tid, 0);
                goto out3;
        }
 
@@ -147,9 +166,10 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
 
       out3:
        txEnd(tid);
-       up(&JFS_IP(dip)->commit_sem);
-       up(&JFS_IP(ip)->commit_sem);
+       mutex_unlock(&JFS_IP(dip)->commit_mutex);
+       mutex_unlock(&JFS_IP(ip)->commit_mutex);
        if (rc) {
+               free_ea_wmap(ip);
                ip->i_nlink = 0;
                iput(ip);
        } else
@@ -158,11 +178,6 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
       out2:
        free_UCSname(&dname);
 
-#ifdef CONFIG_JFS_POSIX_ACL
-       if (rc == 0)
-               jfs_init_acl(ip, dip);
-#endif
-
       out1:
 
        jfs_info("jfs_create: rc:%d", rc);
@@ -224,11 +239,22 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
 
        tid = txBegin(dip->i_sb, 0);
 
-       down(&JFS_IP(dip)->commit_sem);
-       down(&JFS_IP(ip)->commit_sem);
+       mutex_lock(&JFS_IP(dip)->commit_mutex);
+       mutex_lock(&JFS_IP(ip)->commit_mutex);
+
+       rc = jfs_init_acl(tid, ip, dip);
+       if (rc)
+               goto out3;
+
+       rc = jfs_init_security(tid, ip, dip);
+       if (rc) {
+               txAbort(tid, 0);
+               goto out3;
+       }
 
        if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
                jfs_err("jfs_mkdir: dtSearch returned %d", rc);
+               txAbort(tid, 0);
                goto out3;
        }
 
@@ -275,9 +301,10 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
 
       out3:
        txEnd(tid);
-       up(&JFS_IP(dip)->commit_sem);
-       up(&JFS_IP(ip)->commit_sem);
+       mutex_unlock(&JFS_IP(dip)->commit_mutex);
+       mutex_unlock(&JFS_IP(ip)->commit_mutex);
        if (rc) {
+               free_ea_wmap(ip);
                ip->i_nlink = 0;
                iput(ip);
        } else
@@ -286,10 +313,6 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
       out2:
        free_UCSname(&dname);
 
-#ifdef CONFIG_JFS_POSIX_ACL
-       if (rc == 0)
-               jfs_init_acl(ip, dip);
-#endif
 
       out1:
 
@@ -343,8 +366,8 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
 
        tid = txBegin(dip->i_sb, 0);
 
-       down(&JFS_IP(dip)->commit_sem);
-       down(&JFS_IP(ip)->commit_sem);
+       mutex_lock(&JFS_IP(dip)->commit_mutex);
+       mutex_lock(&JFS_IP(ip)->commit_mutex);
 
        iplist[0] = dip;
        iplist[1] = ip;
@@ -362,8 +385,8 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
                if (rc == -EIO)
                        txAbort(tid, 1);
                txEnd(tid);
-               up(&JFS_IP(dip)->commit_sem);
-               up(&JFS_IP(ip)->commit_sem);
+               mutex_unlock(&JFS_IP(dip)->commit_mutex);
+               mutex_unlock(&JFS_IP(ip)->commit_mutex);
 
                goto out2;
        }
@@ -400,8 +423,8 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
 
        txEnd(tid);
 
-       up(&JFS_IP(dip)->commit_sem);
-       up(&JFS_IP(ip)->commit_sem);
+       mutex_unlock(&JFS_IP(dip)->commit_mutex);
+       mutex_unlock(&JFS_IP(ip)->commit_mutex);
 
        /*
         * Truncating the directory index table is not guaranteed.  It
@@ -466,8 +489,8 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
 
        tid = txBegin(dip->i_sb, 0);
 
-       down(&JFS_IP(dip)->commit_sem);
-       down(&JFS_IP(ip)->commit_sem);
+       mutex_lock(&JFS_IP(dip)->commit_mutex);
+       mutex_lock(&JFS_IP(ip)->commit_mutex);
 
        iplist[0] = dip;
        iplist[1] = ip;
@@ -481,8 +504,8 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
                if (rc == -EIO)
                        txAbort(tid, 1);        /* Marks FS Dirty */
                txEnd(tid);
-               up(&JFS_IP(dip)->commit_sem);
-               up(&JFS_IP(ip)->commit_sem);
+               mutex_unlock(&JFS_IP(dip)->commit_mutex);
+               mutex_unlock(&JFS_IP(ip)->commit_mutex);
                IWRITE_UNLOCK(ip);
                goto out1;
        }
@@ -505,8 +528,8 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
                if ((new_size = commitZeroLink(tid, ip)) < 0) {
                        txAbort(tid, 1);        /* Marks FS Dirty */
                        txEnd(tid);
-                       up(&JFS_IP(dip)->commit_sem);
-                       up(&JFS_IP(ip)->commit_sem);
+                       mutex_unlock(&JFS_IP(dip)->commit_mutex);
+                       mutex_unlock(&JFS_IP(ip)->commit_mutex);
                        IWRITE_UNLOCK(ip);
                        rc = new_size;
                        goto out1;
@@ -534,13 +557,13 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
 
        txEnd(tid);
 
-       up(&JFS_IP(dip)->commit_sem);
-       up(&JFS_IP(ip)->commit_sem);
+       mutex_unlock(&JFS_IP(dip)->commit_mutex);
+       mutex_unlock(&JFS_IP(ip)->commit_mutex);
 
 
        while (new_size && (rc == 0)) {
                tid = txBegin(dip->i_sb, 0);
-               down(&JFS_IP(ip)->commit_sem);
+               mutex_lock(&JFS_IP(ip)->commit_mutex);
                new_size = xtTruncate_pmap(tid, ip, new_size);
                if (new_size < 0) {
                        txAbort(tid, 1);        /* Marks FS Dirty */
@@ -548,7 +571,7 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
                } else
                        rc = txCommit(tid, 2, &iplist[0], COMMIT_SYNC);
                txEnd(tid);
-               up(&JFS_IP(ip)->commit_sem);
+               mutex_unlock(&JFS_IP(ip)->commit_mutex);
        }
 
        if (ip->i_nlink == 0)
@@ -655,7 +678,7 @@ static s64 commitZeroLink(tid_t tid, struct inode *ip)
 
 
 /*
- * NAME:       freeZeroLink()
+ * NAME:       jfs_free_zero_link()
  *
  * FUNCTION:    for non-directory, called by iClose(),
  *             free resources of a file from cache and WORKING map 
@@ -663,15 +686,12 @@ static s64 commitZeroLink(tid_t tid, struct inode *ip)
  *             while associated with a pager object,
  *
  * PARAMETER:  ip      - pointer to inode of file.
- *
- * RETURN:     0 -ok
  */
-int freeZeroLink(struct inode *ip)
+void jfs_free_zero_link(struct inode *ip)
 {
-       int rc = 0;
        int type;
 
-       jfs_info("freeZeroLink: ip = 0x%p", ip);
+       jfs_info("jfs_free_zero_link: ip = 0x%p", ip);
 
        /* return if not reg or symbolic link or if size is
         * already ok.
@@ -684,10 +704,10 @@ int freeZeroLink(struct inode *ip)
        case S_IFLNK:
                /* if its contained in inode nothing to do */
                if (ip->i_size < IDATASIZE)
-                       return 0;
+                       return;
                break;
        default:
-               return 0;
+               return;
        }
 
        /*
@@ -737,9 +757,7 @@ int freeZeroLink(struct inode *ip)
         * free xtree/data blocks from working block map;
         */
        if (ip->i_size)
-               rc = xtTruncate(0, ip, 0, COMMIT_WMAP);
-
-       return rc;
+               xtTruncate(0, ip, 0, COMMIT_WMAP);
 }
 
 /*
@@ -788,8 +806,8 @@ static int jfs_link(struct dentry *old_dentry,
 
        tid = txBegin(ip->i_sb, 0);
 
-       down(&JFS_IP(dir)->commit_sem);
-       down(&JFS_IP(ip)->commit_sem);
+       mutex_lock(&JFS_IP(dir)->commit_mutex);
+       mutex_lock(&JFS_IP(ip)->commit_mutex);
 
        /*
         * scan parent directory for entry/freespace
@@ -810,6 +828,7 @@ static int jfs_link(struct dentry *old_dentry,
        /* update object inode */
        ip->i_nlink++;          /* for new link */
        ip->i_ctime = CURRENT_TIME;
+       dir->i_ctime = dir->i_mtime = CURRENT_TIME;
        mark_inode_dirty(dir);
        atomic_inc(&ip->i_count);
 
@@ -829,8 +848,8 @@ static int jfs_link(struct dentry *old_dentry,
       out:
        txEnd(tid);
 
-       up(&JFS_IP(dir)->commit_sem);
-       up(&JFS_IP(ip)->commit_sem);
+       mutex_unlock(&JFS_IP(dir)->commit_mutex);
+       mutex_unlock(&JFS_IP(ip)->commit_mutex);
 
        jfs_info("jfs_link: rc:%d", rc);
        return rc;
@@ -898,8 +917,12 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
 
        tid = txBegin(dip->i_sb, 0);
 
-       down(&JFS_IP(dip)->commit_sem);
-       down(&JFS_IP(ip)->commit_sem);
+       mutex_lock(&JFS_IP(dip)->commit_mutex);
+       mutex_lock(&JFS_IP(ip)->commit_mutex);
+
+       rc = jfs_init_security(tid, ip, dip);
+       if (rc)
+               goto out3;
 
        tblk = tid_to_tblock(tid);
        tblk->xflag |= COMMIT_CREATE;
@@ -1003,6 +1026,8 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
        insert_inode_hash(ip);
        mark_inode_dirty(ip);
 
+       dip->i_ctime = dip->i_mtime = CURRENT_TIME;
+       mark_inode_dirty(dip);
        /*
         * commit update of parent directory and link object
         */
@@ -1013,9 +1038,10 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
 
       out3:
        txEnd(tid);
-       up(&JFS_IP(dip)->commit_sem);
-       up(&JFS_IP(ip)->commit_sem);
+       mutex_unlock(&JFS_IP(dip)->commit_mutex);
+       mutex_unlock(&JFS_IP(ip)->commit_mutex);
        if (rc) {
+               free_ea_wmap(ip);
                ip->i_nlink = 0;
                iput(ip);
        } else
@@ -1024,11 +1050,6 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
       out2:
        free_UCSname(&dname);
 
-#ifdef CONFIG_JFS_POSIX_ACL
-       if (rc == 0)
-               jfs_init_acl(ip, dip);
-#endif
-
       out1:
        jfs_info("jfs_symlink: rc:%d", rc);
        return rc;
@@ -1121,13 +1142,13 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
         */
        tid = txBegin(new_dir->i_sb, 0);
 
-       down(&JFS_IP(new_dir)->commit_sem);
-       down(&JFS_IP(old_ip)->commit_sem);
+       mutex_lock(&JFS_IP(new_dir)->commit_mutex);
+       mutex_lock(&JFS_IP(old_ip)->commit_mutex);
        if (old_dir != new_dir)
-               down(&JFS_IP(old_dir)->commit_sem);
+               mutex_lock(&JFS_IP(old_dir)->commit_mutex);
 
        if (new_ip) {
-               down(&JFS_IP(new_ip)->commit_sem);
+               mutex_lock(&JFS_IP(new_ip)->commit_mutex);
                /*
                 * Change existing directory entry to new inode number
                 */
@@ -1140,10 +1161,10 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                if (S_ISDIR(new_ip->i_mode)) {
                        new_ip->i_nlink--;
                        if (new_ip->i_nlink) {
-                               up(&JFS_IP(new_dir)->commit_sem);
-                               up(&JFS_IP(old_ip)->commit_sem);
+                               mutex_unlock(&JFS_IP(new_dir)->commit_mutex);
+                               mutex_unlock(&JFS_IP(old_ip)->commit_mutex);
                                if (old_dir != new_dir)
-                                       up(&JFS_IP(old_dir)->commit_sem);
+                                       mutex_unlock(&JFS_IP(old_dir)->commit_mutex);
                                if (!S_ISDIR(old_ip->i_mode) && new_ip)
                                        IWRITE_UNLOCK(new_ip);
                                jfs_error(new_ip->i_sb,
@@ -1262,16 +1283,16 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
       out4:
        txEnd(tid);
 
-       up(&JFS_IP(new_dir)->commit_sem);
-       up(&JFS_IP(old_ip)->commit_sem);
+       mutex_unlock(&JFS_IP(new_dir)->commit_mutex);
+       mutex_unlock(&JFS_IP(old_ip)->commit_mutex);
        if (old_dir != new_dir)
-               up(&JFS_IP(old_dir)->commit_sem);
+               mutex_unlock(&JFS_IP(old_dir)->commit_mutex);
        if (new_ip)
-               up(&JFS_IP(new_ip)->commit_sem);
+               mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
 
        while (new_size && (rc == 0)) {
                tid = txBegin(new_ip->i_sb, 0);
-               down(&JFS_IP(new_ip)->commit_sem);
+               mutex_lock(&JFS_IP(new_ip)->commit_mutex);
                new_size = xtTruncate_pmap(tid, new_ip, new_size);
                if (new_size < 0) {
                        txAbort(tid, 1);
@@ -1279,7 +1300,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                } else
                        rc = txCommit(tid, 1, &new_ip, COMMIT_SYNC);
                txEnd(tid);
-               up(&JFS_IP(new_ip)->commit_sem);
+               mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
        }
        if (new_ip && (new_ip->i_nlink == 0))
                set_cflag(COMMIT_Nolink, new_ip);
@@ -1341,11 +1362,23 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
 
        tid = txBegin(dir->i_sb, 0);
 
-       down(&JFS_IP(dir)->commit_sem);
-       down(&JFS_IP(ip)->commit_sem);
+       mutex_lock(&JFS_IP(dir)->commit_mutex);
+       mutex_lock(&JFS_IP(ip)->commit_mutex);
 
-       if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE)))
+       rc = jfs_init_acl(tid, ip, dir);
+       if (rc)
+               goto out3;
+
+       rc = jfs_init_security(tid, ip, dir);
+       if (rc) {
+               txAbort(tid, 0);
                goto out3;
+       }
+
+       if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) {
+               txAbort(tid, 0);
+               goto out3;
+       }
 
        tblk = tid_to_tblock(tid);
        tblk->xflag |= COMMIT_CREATE;
@@ -1353,8 +1386,10 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
        tblk->u.ixpxd = JFS_IP(ip)->ixpxd;
 
        ino = ip->i_ino;
-       if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack)))
+       if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) {
+               txAbort(tid, 0);
                goto out3;
+       }
 
        ip->i_op = &jfs_file_inode_operations;
        jfs_ip->dev = new_encode_dev(rdev);
@@ -1373,9 +1408,10 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
 
       out3:
        txEnd(tid);
-       up(&JFS_IP(ip)->commit_sem);
-       up(&JFS_IP(dir)->commit_sem);
+       mutex_unlock(&JFS_IP(ip)->commit_mutex);
+       mutex_unlock(&JFS_IP(dir)->commit_mutex);
        if (rc) {
+               free_ea_wmap(ip);
                ip->i_nlink = 0;
                iput(ip);
        } else
@@ -1384,11 +1420,6 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
       out1:
        free_UCSname(&dname);
 
-#ifdef CONFIG_JFS_POSIX_ACL
-       if (rc == 0)
-               jfs_init_acl(ip, dir);
-#endif
-
       out:
        jfs_info("jfs_mknod: returning %d", rc);
        return rc;
@@ -1406,6 +1437,8 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struc
 
        jfs_info("jfs_lookup: name = %s", name);
 
+       if (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2)
+               dentry->d_op = &jfs_ci_dentry_operations;
 
        if ((name[0] == '.') && (len == 1))
                inum = dip->i_ino;
@@ -1433,9 +1466,7 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struc
                return ERR_PTR(-EACCES);
        }
 
-       if (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2)
-               dentry->d_op = &jfs_ci_dentry_operations;
-
+       vx_propagate_xid(nd, ip);
        dentry = d_splice_alias(ip, dentry);
 
        if (dentry && (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2))
@@ -1488,12 +1519,14 @@ struct inode_operations jfs_dir_inode_operations = {
        .setattr        = jfs_setattr,
        .permission     = jfs_permission,
 #endif
+       .sync_flags     = jfs_sync_flags,
 };
 
-struct file_operations jfs_dir_operations = {
+const struct file_operations jfs_dir_operations = {
        .read           = generic_read_dir,
        .readdir        = jfs_readdir,
        .fsync          = jfs_fsync,
+       .ioctl          = jfs_ioctl,
 };
 
 static int jfs_ci_hash(struct dentry *dir, struct qstr *this)