dma-buf: minor documentation fixes.
[linux-2.6.git] / fs / ufs / truncate.c
index 749581f..f04f89f 100644 (file)
 
 #include <linux/errno.h>
 #include <linux/fs.h>
-#include <linux/ufs_fs.h>
 #include <linux/fcntl.h>
 #include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/blkdev.h>
 #include <linux/sched.h>
 
+#include "ufs_fs.h"
+#include "ufs.h"
 #include "swab.h"
 #include "util.h"
 
@@ -74,7 +74,7 @@ static int ufs_trunc_direct(struct inode *inode)
        unsigned i, tmp;
        int retry;
        
-       UFSD("ENTER\n");
+       UFSD("ENTER: ino %lu\n", inode->i_ino);
 
        sb = inode->i_sb;
        uspi = UFS_SB(sb)->s_uspi;
@@ -84,7 +84,7 @@ static int ufs_trunc_direct(struct inode *inode)
        retry = 0;
        
        frag1 = DIRECT_FRAGMENT;
-       frag4 = min_t(u32, UFS_NDIR_FRAGMENT, ufsi->i_lastfrag);
+       frag4 = min_t(u64, UFS_NDIR_FRAGMENT, ufsi->i_lastfrag);
        frag2 = ((frag1 & uspi->s_fpbmask) ? ((frag1 | uspi->s_fpbmask) + 1) : frag1);
        frag3 = frag4 & ~uspi->s_fpbmask;
        block1 = block2 = 0;
@@ -96,8 +96,8 @@ static int ufs_trunc_direct(struct inode *inode)
                block2 = ufs_fragstoblks (frag3);
        }
 
-       UFSD("frag1 %llu, frag2 %llu, block1 %llu, block2 %llu, frag3 %llu,"
-            " frag4 %llu\n",
+       UFSD("ino %lu, frag1 %llu, frag2 %llu, block1 %llu, block2 %llu,"
+            " frag3 %llu, frag4 %llu\n", inode->i_ino,
             (unsigned long long)frag1, (unsigned long long)frag2,
             (unsigned long long)block1, (unsigned long long)block2,
             (unsigned long long)frag3, (unsigned long long)frag4);
@@ -163,7 +163,7 @@ next1:
        mark_inode_dirty(inode);
  next3:
 
-       UFSD("EXIT\n");
+       UFSD("EXIT: ino %lu\n", inode->i_ino);
        return retry;
 }
 
@@ -242,13 +242,11 @@ static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p)
                ubh_bforget(ind_ubh);
                ind_ubh = NULL;
        }
-       if (IS_SYNC(inode) && ind_ubh && ubh_buffer_dirty(ind_ubh)) {
-               ubh_ll_rw_block(SWRITE, ind_ubh);
-               ubh_wait_on_buffer (ind_ubh);
-       }
+       if (IS_SYNC(inode) && ind_ubh && ubh_buffer_dirty(ind_ubh))
+               ubh_sync_block(ind_ubh);
        ubh_brelse (ind_ubh);
        
-       UFSD("EXIT\n");
+       UFSD("EXIT: ino %lu\n", inode->i_ino);
        
        return retry;
 }
@@ -262,7 +260,7 @@ static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p)
        void *dind;
        int retry = 0;
        
-       UFSD("ENTER\n");
+       UFSD("ENTER: ino %lu\n", inode->i_ino);
        
        sb = inode->i_sb;
        uspi = UFS_SB(sb)->s_uspi;
@@ -306,13 +304,11 @@ static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p)
                ubh_bforget(dind_bh);
                dind_bh = NULL;
        }
-       if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh)) {
-               ubh_ll_rw_block(SWRITE, dind_bh);
-               ubh_wait_on_buffer (dind_bh);
-       }
+       if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh))
+               ubh_sync_block(dind_bh);
        ubh_brelse (dind_bh);
        
-       UFSD("EXIT\n");
+       UFSD("EXIT: ino %lu\n", inode->i_ino);
        
        return retry;
 }
@@ -327,7 +323,7 @@ static int ufs_trunc_tindirect(struct inode *inode)
        void *tind, *p;
        int retry;
        
-       UFSD("ENTER\n");
+       UFSD("ENTER: ino %lu\n", inode->i_ino);
 
        retry = 0;
        
@@ -348,7 +344,7 @@ static int ufs_trunc_tindirect(struct inode *inode)
        }
 
        for (i = tindirect_block ; i < uspi->s_apb ; i++) {
-               tind = ubh_get_addr32 (tind_bh, i);
+               tind = ubh_get_data_ptr(uspi, tind_bh, i);
                retry |= ufs_trunc_dindirect(inode, UFS_NDADDR + 
                        uspi->s_apb + ((i + 1) << uspi->s_2apbshift), tind);
                ubh_mark_buffer_dirty(tind_bh);
@@ -366,25 +362,25 @@ static int ufs_trunc_tindirect(struct inode *inode)
                ubh_bforget(tind_bh);
                tind_bh = NULL;
        }
-       if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh)) {
-               ubh_ll_rw_block(SWRITE, tind_bh);
-               ubh_wait_on_buffer (tind_bh);
-       }
+       if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh))
+               ubh_sync_block(tind_bh);
        ubh_brelse (tind_bh);
        
-       UFSD("EXIT\n");
+       UFSD("EXIT: ino %lu\n", inode->i_ino);
        return retry;
 }
 
 static int ufs_alloc_lastblock(struct inode *inode)
 {
        int err = 0;
+       struct super_block *sb = inode->i_sb;
        struct address_space *mapping = inode->i_mapping;
-       struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi;
+       struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
        unsigned i, end;
        sector_t lastfrag;
        struct page *lastpage;
        struct buffer_head *bh;
+       u64 phys64;
 
        lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift;
 
@@ -424,6 +420,20 @@ static int ufs_alloc_lastblock(struct inode *inode)
               set_page_dirty(lastpage);
        }
 
+       if (lastfrag >= UFS_IND_FRAGMENT) {
+              end = uspi->s_fpb - ufs_fragnum(lastfrag) - 1;
+              phys64 = bh->b_blocknr + 1;
+              for (i = 0; i < end; ++i) {
+                      bh = sb_getblk(sb, i + phys64);
+                      lock_buffer(bh);
+                      memset(bh->b_data, 0, sb->s_blocksize);
+                      set_buffer_uptodate(bh);
+                      mark_buffer_dirty(bh);
+                      unlock_buffer(bh);
+                      sync_dirty_buffer(bh);
+                      brelse(bh);
+              }
+       }
 out_unlock:
        ufs_put_locked_page(lastpage);
 out:
@@ -456,7 +466,6 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size)
 
        block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block);
 
-       lock_kernel();
        while (1) {
                retry = ufs_trunc_direct(inode);
                retry |= ufs_trunc_indirect(inode, UFS_IND_BLOCK,
@@ -470,27 +479,18 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size)
                        break;
                if (IS_SYNC(inode) && (inode->i_state & I_DIRTY))
                        ufs_sync_inode (inode);
-               blk_run_address_space(inode->i_mapping);
                yield();
        }
 
        inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
        ufsi->i_lastfrag = DIRECT_FRAGMENT;
-       unlock_kernel();
        mark_inode_dirty(inode);
 out:
        UFSD("EXIT: err %d\n", err);
        return err;
 }
 
-
-/*
- * We don't define our `inode->i_op->truncate', and call it here,
- * because of:
- * - there is no way to know old size
- * - there is no way inform user about error, if it happens in `truncate'
- */
-static int ufs_setattr(struct dentry *dentry, struct iattr *attr)
+int ufs_setattr(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = dentry->d_inode;
        unsigned int ia_valid = attr->ia_valid;
@@ -500,17 +500,22 @@ static int ufs_setattr(struct dentry *dentry, struct iattr *attr)
        if (error)
                return error;
 
-       if (ia_valid & ATTR_SIZE &&
-           attr->ia_size != i_size_read(inode)) {
+       if (ia_valid & ATTR_SIZE && attr->ia_size != inode->i_size) {
                loff_t old_i_size = inode->i_size;
-               error = vmtruncate(inode, attr->ia_size);
-               if (error)
-                       return error;
+
+               /* XXX(truncate): truncate_setsize should be called last */
+               truncate_setsize(inode, attr->ia_size);
+
+               lock_ufs(inode->i_sb);
                error = ufs_truncate(inode, old_i_size);
+               unlock_ufs(inode->i_sb);
                if (error)
                        return error;
        }
-       return inode_setattr(inode, attr);
+
+       setattr_copy(inode, attr);
+       mark_inode_dirty(inode);
+       return 0;
 }
 
 const struct inode_operations ufs_file_inode_operations = {