Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
[cascardo/linux.git] / fs / reiserfs / inode.c
index 29db722..ae35413 100644 (file)
@@ -25,7 +25,7 @@ int reiserfs_commit_write(struct file *f, struct page *page,
 int reiserfs_prepare_write(struct file *f, struct page *page,
                           unsigned from, unsigned to);
 
-void reiserfs_delete_inode(struct inode *inode)
+void reiserfs_evict_inode(struct inode *inode)
 {
        /* We need blocks for transaction + (user+group) quota update (possibly delete) */
        int jbegin_count =
@@ -35,10 +35,12 @@ void reiserfs_delete_inode(struct inode *inode)
        int depth;
        int err;
 
-       if (!is_bad_inode(inode))
+       if (!inode->i_nlink && !is_bad_inode(inode))
                dquot_initialize(inode);
 
        truncate_inode_pages(&inode->i_data, 0);
+       if (inode->i_nlink)
+               goto no_delete;
 
        depth = reiserfs_write_lock_once(inode->i_sb);
 
@@ -77,9 +79,14 @@ void reiserfs_delete_inode(struct inode *inode)
                ;
        }
       out:
-       clear_inode(inode);     /* note this must go after the journal_end to prevent deadlock */
+       end_writeback(inode);   /* note this must go after the journal_end to prevent deadlock */
+       dquot_drop(inode);
        inode->i_blocks = 0;
        reiserfs_write_unlock_once(inode->i_sb, depth);
+
+no_delete:
+       end_writeback(inode);
+       dquot_drop(inode);
 }
 
 static void _make_cpu_key(struct cpu_key *key, int version, __u32 dirid,
@@ -1138,7 +1145,6 @@ static void init_inode(struct inode *inode, struct treepath *path)
        REISERFS_I(inode)->i_prealloc_count = 0;
        REISERFS_I(inode)->i_trans_id = 0;
        REISERFS_I(inode)->i_jl = NULL;
-       mutex_init(&(REISERFS_I(inode)->i_mmap));
        reiserfs_init_xattr_rwsem(inode);
 
        if (stat_data_v1(ih)) {
@@ -1841,7 +1847,6 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
        REISERFS_I(inode)->i_attrs =
            REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK;
        sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode);
-       mutex_init(&(REISERFS_I(inode)->i_mmap));
        reiserfs_init_xattr_rwsem(inode);
 
        /* key to search for correct place for new stat data */
@@ -2587,8 +2592,7 @@ static int reiserfs_write_begin(struct file *file,
                old_ref = th->t_refcount;
                th->t_refcount++;
        }
-       ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
-                               reiserfs_get_block);
+       ret = __block_write_begin(page, pos, len, reiserfs_get_block);
        if (ret && reiserfs_transaction_running(inode->i_sb)) {
                struct reiserfs_transaction_handle *th = current->journal_info;
                /* this gets a little ugly.  If reiserfs_get_block returned an
@@ -3059,10 +3063,25 @@ static ssize_t reiserfs_direct_IO(int rw, struct kiocb *iocb,
 {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
+       ssize_t ret;
 
-       return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
+       ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
                                  offset, nr_segs,
                                  reiserfs_get_blocks_direct_io, NULL);
+
+       /*
+        * In case of error extending write may have instantiated a few
+        * blocks outside i_size. Trim these off again.
+        */
+       if (unlikely((rw & WRITE) && ret < 0)) {
+               loff_t isize = i_size_read(inode);
+               loff_t end = offset + iov_length(iov, nr_segs);
+
+               if (end > isize)
+                       vmtruncate(inode, isize);
+       }
+
+       return ret;
 }
 
 int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
@@ -3072,6 +3091,10 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
        int depth;
        int error;
 
+       error = inode_change_ok(inode, attr);
+       if (error)
+               return error;
+
        /* must be turned off for recursive notify_change calls */
        ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
 
@@ -3121,55 +3144,58 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
                goto out;
        }
 
-       error = inode_change_ok(inode, attr);
-       if (!error) {
-               if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
-                   (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
-                       error = reiserfs_chown_xattrs(inode, attr);
+       if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
+           (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
+               struct reiserfs_transaction_handle th;
+               int jbegin_count =
+                   2 *
+                   (REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb) +
+                    REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb)) +
+                   2;
 
-                       if (!error) {
-                               struct reiserfs_transaction_handle th;
-                               int jbegin_count =
-                                   2 *
-                                   (REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb) +
-                                    REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb)) +
-                                   2;
-
-                               /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */
-                               error =
-                                   journal_begin(&th, inode->i_sb,
-                                                 jbegin_count);
-                               if (error)
-                                       goto out;
-                               error = dquot_transfer(inode, attr);
-                               if (error) {
-                                       journal_end(&th, inode->i_sb,
-                                                   jbegin_count);
-                                       goto out;
-                               }
-                               /* Update corresponding info in inode so that everything is in
-                                * one transaction */
-                               if (attr->ia_valid & ATTR_UID)
-                                       inode->i_uid = attr->ia_uid;
-                               if (attr->ia_valid & ATTR_GID)
-                                       inode->i_gid = attr->ia_gid;
-                               mark_inode_dirty(inode);
-                               error =
-                                   journal_end(&th, inode->i_sb, jbegin_count);
-                       }
-               }
-               if (!error) {
-                       /*
-                        * Relax the lock here, as it might truncate the
-                        * inode pages and wait for inode pages locks.
-                        * To release such page lock, the owner needs the
-                        * reiserfs lock
-                        */
-                       reiserfs_write_unlock_once(inode->i_sb, depth);
-                       error = inode_setattr(inode, attr);
-                       depth = reiserfs_write_lock_once(inode->i_sb);
+               error = reiserfs_chown_xattrs(inode, attr);
+
+               if (error)
+                       return error;
+
+               /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */
+               error = journal_begin(&th, inode->i_sb, jbegin_count);
+               if (error)
+                       goto out;
+               error = dquot_transfer(inode, attr);
+               if (error) {
+                       journal_end(&th, inode->i_sb, jbegin_count);
+                       goto out;
                }
+
+               /* Update corresponding info in inode so that everything is in
+                * one transaction */
+               if (attr->ia_valid & ATTR_UID)
+                       inode->i_uid = attr->ia_uid;
+               if (attr->ia_valid & ATTR_GID)
+                       inode->i_gid = attr->ia_gid;
+               mark_inode_dirty(inode);
+               error = journal_end(&th, inode->i_sb, jbegin_count);
+               if (error)
+                       goto out;
+       }
+
+       /*
+        * Relax the lock here, as it might truncate the
+        * inode pages and wait for inode pages locks.
+        * To release such page lock, the owner needs the
+        * reiserfs lock
+        */
+       reiserfs_write_unlock_once(inode->i_sb, depth);
+       if ((attr->ia_valid & ATTR_SIZE) &&
+           attr->ia_size != i_size_read(inode))
+               error = vmtruncate(inode, attr->ia_size);
+
+       if (!error) {
+               setattr_copy(inode, attr);
+               mark_inode_dirty(inode);
        }
+       depth = reiserfs_write_lock_once(inode->i_sb);
 
        if (!error && reiserfs_posixacl(inode->i_sb)) {
                if (attr->ia_valid & ATTR_MODE)