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 / ufs / truncate.c
index e312bf8..02e8629 100644 (file)
  * Idea from Pierre del Perugia <delperug@gla.ecoledoc.ibp.fr>
  */
 
+/*
+ * Modified to avoid infinite loop on 2006 by
+ * Evgeniy Dushistov <dushistov@mail.ru>
+ */
+
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
 #define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift)
 #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift)
 
-#define DATA_BUFFER_USED(bh) \
-       (atomic_read(&bh->b_count)>1 || buffer_locked(bh))
 
 static int ufs_trunc_direct (struct inode * inode)
 {
        struct ufs_inode_info *ufsi = UFS_I(inode);
        struct super_block * sb;
        struct ufs_sb_private_info * uspi;
-       struct buffer_head * bh;
        __fs32 * p;
        unsigned frag1, frag2, frag3, frag4, block1, block2;
        unsigned frag_to_free, free_count;
-       unsigned i, j, tmp;
+       unsigned i, tmp;
        int retry;
        
        UFSD(("ENTER\n"))
@@ -117,15 +119,7 @@ static int ufs_trunc_direct (struct inode * inode)
                ufs_panic (sb, "ufs_trunc_direct", "internal error");
        frag1 = ufs_fragnum (frag1);
        frag2 = ufs_fragnum (frag2);
-       for (j = frag1; j < frag2; j++) {
-               bh = sb_find_get_block (sb, tmp + j);
-               if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *p)) {
-                       retry = 1;
-                       brelse (bh);
-                       goto next1;
-               }
-               bforget (bh);
-       }
+
        inode->i_blocks -= (frag2-frag1) << uspi->s_nspfshift;
        mark_inode_dirty(inode);
        ufs_free_fragments (inode, tmp + frag1, frag2 - frag1);
@@ -140,15 +134,7 @@ next1:
                tmp = fs32_to_cpu(sb, *p);
                if (!tmp)
                        continue;
-               for (j = 0; j < uspi->s_fpb; j++) {
-                       bh = sb_find_get_block(sb, tmp + j);
-                       if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *p)) {
-                               retry = 1;
-                               brelse (bh);
-                               goto next2;
-                       }
-                       bforget (bh);
-               }
+
                *p = 0;
                inode->i_blocks -= uspi->s_nspb;
                mark_inode_dirty(inode);
@@ -162,7 +148,6 @@ next1:
                        frag_to_free = tmp;
                        free_count = uspi->s_fpb;
                }
-next2:;
        }
        
        if (free_count > 0)
@@ -179,15 +164,7 @@ next2:;
        if (!tmp )
                ufs_panic(sb, "ufs_truncate_direct", "internal error");
        frag4 = ufs_fragnum (frag4);
-       for (j = 0; j < frag4; j++) {
-               bh = sb_find_get_block (sb, tmp + j);
-               if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *p)) {
-                       retry = 1;
-                       brelse (bh);
-                       goto next1;
-               }
-               bforget (bh);
-       }
+
        *p = 0;
        inode->i_blocks -= frag4 << uspi->s_nspfshift;
        mark_inode_dirty(inode);
@@ -204,9 +181,8 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p)
        struct super_block * sb;
        struct ufs_sb_private_info * uspi;
        struct ufs_buffer_head * ind_ubh;
-       struct buffer_head * bh;
        __fs32 * ind;
-       unsigned indirect_block, i, j, tmp;
+       unsigned indirect_block, i, tmp;
        unsigned frag_to_free, free_count;
        int retry;
 
@@ -238,15 +214,7 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p)
                tmp = fs32_to_cpu(sb, *ind);
                if (!tmp)
                        continue;
-               for (j = 0; j < uspi->s_fpb; j++) {
-                       bh = sb_find_get_block(sb, tmp + j);
-                       if ((bh && DATA_BUFFER_USED(bh)) || tmp != fs32_to_cpu(sb, *ind)) {
-                               retry = 1;
-                               brelse (bh);
-                               goto next;
-                       }
-                       bforget (bh);
-               }       
+
                *ind = 0;
                ubh_mark_buffer_dirty(ind_ubh);
                if (free_count == 0) {
@@ -261,7 +229,6 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p)
                }
                inode->i_blocks -= uspi->s_nspb;
                mark_inode_dirty(inode);
-next:;
        }
 
        if (free_count > 0) {
@@ -285,8 +252,7 @@ next:;
                }
        }
        if (IS_SYNC(inode) && ind_ubh && ubh_buffer_dirty(ind_ubh)) {
-               ubh_wait_on_buffer (ind_ubh);
-               ubh_ll_rw_block (WRITE, 1, &ind_ubh);
+               ubh_ll_rw_block (SWRITE, 1, &ind_ubh);
                ubh_wait_on_buffer (ind_ubh);
        }
        ubh_brelse (ind_ubh);
@@ -353,8 +319,7 @@ static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p)
                }
        }
        if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh)) {
-               ubh_wait_on_buffer (dind_bh);
-               ubh_ll_rw_block (WRITE, 1, &dind_bh);
+               ubh_ll_rw_block (SWRITE, 1, &dind_bh);
                ubh_wait_on_buffer (dind_bh);
        }
        ubh_brelse (dind_bh);
@@ -418,8 +383,7 @@ static int ufs_trunc_tindirect (struct inode * inode)
                }
        }
        if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh)) {
-               ubh_wait_on_buffer (tind_bh);
-               ubh_ll_rw_block (WRITE, 1, &tind_bh);
+               ubh_ll_rw_block (SWRITE, 1, &tind_bh);
                ubh_wait_on_buffer (tind_bh);
        }
        ubh_brelse (tind_bh);
@@ -433,9 +397,7 @@ void ufs_truncate (struct inode * inode)
        struct ufs_inode_info *ufsi = UFS_I(inode);
        struct super_block * sb;
        struct ufs_sb_private_info * uspi;
-       struct buffer_head * bh;
-       unsigned offset;
-       int err, retry;
+       int retry;
        
        UFSD(("ENTER\n"))
        sb = inode->i_sb;
@@ -445,6 +407,9 @@ void ufs_truncate (struct inode * inode)
                return;
        if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
                return;
+
+       block_truncate_page(inode->i_mapping,   inode->i_size, ufs_getfrag_block);
+
        lock_kernel();
        while (1) {
                retry = ufs_trunc_direct(inode);
@@ -460,15 +425,7 @@ void ufs_truncate (struct inode * inode)
                blk_run_address_space(inode->i_mapping);
                yield();
        }
-       offset = inode->i_size & uspi->s_fshift;
-       if (offset) {
-               bh = ufs_bread (inode, inode->i_size >> uspi->s_fshift, 0, &err);
-               if (bh) {
-                       memset (bh->b_data + offset, 0, uspi->s_fsize - offset);
-                       mark_buffer_dirty (bh);
-                       brelse (bh);
-               }
-       }
+
        inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
        ufsi->i_lastfrag = DIRECT_FRAGMENT;
        unlock_kernel();