patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / fs / jfs / namei.c
index abfe33f..998410c 100644 (file)
@@ -135,7 +135,6 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
 
        insert_inode_hash(ip);
        mark_inode_dirty(ip);
-       d_instantiate(dentry, ip);
 
        dip->i_ctime = dip->i_mtime = CURRENT_TIME;
 
@@ -150,7 +149,8 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
        if (rc) {
                ip->i_nlink = 0;
                iput(ip);
-       }
+       } else
+               d_instantiate(dentry, ip);
 
       out2:
        free_UCSname(&dname);
@@ -265,7 +265,6 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
 
        insert_inode_hash(ip);
        mark_inode_dirty(ip);
-       d_instantiate(dentry, ip);
 
        /* update parent directory inode */
        dip->i_nlink++;         /* for '..' from child directory */
@@ -281,7 +280,8 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
        if (rc) {
                ip->i_nlink = 0;
                iput(ip);
-       }
+       } else
+               d_instantiate(dentry, ip);
 
       out2:
        free_UCSname(&dname);
@@ -806,12 +806,14 @@ static int jfs_link(struct dentry *old_dentry,
        ip->i_ctime = CURRENT_TIME;
        mark_inode_dirty(dir);
        atomic_inc(&ip->i_count);
-       d_instantiate(dentry, ip);
 
        iplist[0] = ip;
        iplist[1] = dir;
        rc = txCommit(tid, 2, &iplist[0], 0);
 
+       if (!rc)
+               d_instantiate(dentry, ip);
+
       free_dname:
        free_UCSname(&dname);
 
@@ -856,7 +858,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
        unchar *i_fastsymlink;
        s64 xlen = 0;
        int bmask = 0, xsize;
-       s64 xaddr;
+       s64 extent = 0, xaddr;
        struct metapage *mp;
        struct super_block *sb;
        struct tblock *tblk;
@@ -890,29 +892,11 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
        down(&JFS_IP(dip)->commit_sem);
        down(&JFS_IP(ip)->commit_sem);
 
-       if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE)))
-               goto out3;
-
        tblk = tid_to_tblock(tid);
        tblk->xflag |= COMMIT_CREATE;
        tblk->ino = ip->i_ino;
        tblk->u.ixpxd = JFS_IP(ip)->ixpxd;
 
-       /*
-        * create entry for symbolic link in parent directory
-        */
-
-       ino = ip->i_ino;
-
-
-
-       if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
-               jfs_err("jfs_symlink: dtInsert returned %d", rc);
-               /* discard ne inode */
-               goto out3;
-
-       }
-
        /* fix symlink access permission
         * (dir_create() ANDs in the u.u_cmask, 
         * but symlinks really need to be 777 access)
@@ -920,7 +904,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
        ip->i_mode |= 0777;
 
        /*
-          *       write symbolic link target path name
+        * write symbolic link target path name
         */
        xtInitRoot(tid, ip);
 
@@ -964,62 +948,60 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
                xsize = (ssize + bmask) & ~bmask;
                xaddr = 0;
                xlen = xsize >> JFS_SBI(sb)->l2bsize;
-               if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0)) == 0) {
-                       ip->i_size = ssize - 1;
-                       while (ssize) {
-                               int copy_size = min(ssize, PSIZE);
-
-                               mp = get_metapage(ip, xaddr, PSIZE, 1);
-
-                               if (mp == NULL) {
-                                       dtDelete(tid, dip, &dname, &ino,
-                                                JFS_REMOVE);
-                                       rc = -EIO;
-                                       goto out3;
-                               }
-                               memcpy(mp->data, name, copy_size);
-                               flush_metapage(mp);
-#if 0
-                               set_buffer_uptodate(bp);
-                               mark_buffer_dirty(bp, 1);
-                               if (IS_SYNC(dip))
-                                       sync_dirty_buffer(bp);
-                               brelse(bp);
-#endif                         /* 0 */
-                               ssize -= copy_size;
-                               xaddr += JFS_SBI(sb)->nbperpage;
-                       }
-                       ip->i_blocks = LBLK2PBLK(sb, xlen);
-               } else {
-                       dtDelete(tid, dip, &dname, &ino, JFS_REMOVE);
+               if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0))) {
+                       txAbort(tid, 0);
                        rc = -ENOSPC;
                        goto out3;
                }
+               extent = xaddr;
+               ip->i_size = ssize - 1;
+               while (ssize) {
+                       /* This is kind of silly since PATH_MAX == 4K */
+                       int copy_size = min(ssize, PSIZE);
+
+                       mp = get_metapage(ip, xaddr, PSIZE, 1);
+
+                       if (mp == NULL) {
+                               dbFree(ip, extent, xlen);
+                               rc = -EIO;
+                               txAbort(tid, 0);
+                               goto out3;
+                       }
+                       memcpy(mp->data, name, copy_size);
+                       flush_metapage(mp);
+                       ssize -= copy_size;
+                       name += copy_size;
+                       xaddr += JFS_SBI(sb)->nbperpage;
+               }
+               ip->i_blocks = LBLK2PBLK(sb, xlen);
+       }
+
+       /*
+        * create entry for symbolic link in parent directory
+        */
+       rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE);
+       if (rc == 0) {
+               ino = ip->i_ino;
+               rc = dtInsert(tid, dip, &dname, &ino, &btstack);
+       }
+       if (rc) {
+               if (xlen)
+                       dbFree(ip, extent, xlen);
+               txAbort(tid, 0);
+               /* discard new inode */
+               goto out3;
        }
 
        insert_inode_hash(ip);
        mark_inode_dirty(ip);
-       d_instantiate(dentry, ip);
 
        /*
         * commit update of parent directory and link object
-        *
-        * if extent allocation failed (ENOSPC),
-        * the parent inode is committed regardless to avoid
-        * backing out parent directory update (by dtInsert())
-        * and subsequent dtDelete() which is harmless wrt 
-        * integrity concern.  
-        * the symlink inode will be freed by iput() at exit
-        * as it has a zero link count (by dtDelete()) and 
-        * no permanant resources. 
         */
 
        iplist[0] = dip;
-       if (rc == 0) {
-               iplist[1] = ip;
-               rc = txCommit(tid, 2, &iplist[0], 0);
-       } else
-               rc = txCommit(tid, 1, &iplist[0], 0);
+       iplist[1] = ip;
+       rc = txCommit(tid, 2, &iplist[0], 0);
 
       out3:
        txEnd(tid);
@@ -1028,7 +1010,8 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
        if (rc) {
                ip->i_nlink = 0;
                iput(ip);
-       }
+       } else
+               d_instantiate(dentry, ip);
 
       out2:
        free_UCSname(&dname);
@@ -1221,7 +1204,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        /* Linelock header of dtree */
                        tlck = txLock(tid, old_ip,
                                    (struct metapage *) &JFS_IP(old_ip)->bxflag,
-                                     tlckDTREE | tlckBTROOT);
+                                     tlckDTREE | tlckBTROOT | tlckRELINK);
                        dtlck = (struct dt_lock *) & tlck->lock;
                        ASSERT(dtlck->index == 0);
                        lv = & dtlck->lv[0];
@@ -1368,7 +1351,6 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
 
        insert_inode_hash(ip);
        mark_inode_dirty(ip);
-       d_instantiate(dentry, ip);
 
        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 
@@ -1385,7 +1367,8 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
        if (rc) {
                ip->i_nlink = 0;
                iput(ip);
-       }
+       } else
+               d_instantiate(dentry, ip);
 
       out1:
        free_UCSname(&dname);