Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[cascardo/linux.git] / fs / ext4 / super.c
index 5a18e9e..ba191da 100644 (file)
@@ -302,7 +302,7 @@ void ext4_journal_abort_handle(const char *caller, const char *err_fn,
  * write out the superblock safely.
  *
  * We'll just use the jbd2_journal_abort() error code to record an error in
- * the journal instead.  On recovery, the journal will compain about
+ * the journal instead.  On recovery, the journal will complain about
  * that error until we've noted it down and cleared it.
  */
 
@@ -798,6 +798,7 @@ static void destroy_inodecache(void)
 
 static void ext4_clear_inode(struct inode *inode)
 {
+       dquot_drop(inode);
        ext4_discard_preallocations(inode);
        if (EXT4_JOURNAL(inode))
                jbd2_journal_release_jbd_inode(EXT4_SB(inode->i_sb)->s_journal,
@@ -1052,19 +1053,9 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
                                const char *data, size_t len, loff_t off);
 
 static const struct dquot_operations ext4_quota_operations = {
-       .initialize     = dquot_initialize,
-       .drop           = dquot_drop,
-       .alloc_space    = dquot_alloc_space,
-       .reserve_space  = dquot_reserve_space,
-       .claim_space    = dquot_claim_space,
-       .release_rsv    = dquot_release_reserved_space,
 #ifdef CONFIG_QUOTA
        .get_reserved_space = ext4_get_reserved_space,
 #endif
-       .alloc_inode    = dquot_alloc_inode,
-       .free_space     = dquot_free_space,
-       .free_inode     = dquot_free_inode,
-       .transfer       = dquot_transfer,
        .write_dquot    = ext4_write_dquot,
        .acquire_dquot  = ext4_acquire_dquot,
        .release_dquot  = ext4_release_dquot,
@@ -2014,7 +2005,7 @@ static void ext4_orphan_cleanup(struct super_block *sb,
                }
 
                list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan);
-               vfs_dq_init(inode);
+               dquot_initialize(inode);
                if (inode->i_nlink) {
                        ext4_msg(sb, KERN_DEBUG,
                                "%s: truncating inode %lu to %lld bytes",
@@ -2367,7 +2358,7 @@ static void ext4_sb_release(struct kobject *kobj)
 }
 
 
-static struct sysfs_ops ext4_attr_ops = {
+static const struct sysfs_ops ext4_attr_ops = {
        .show   = ext4_attr_show,
        .store  = ext4_attr_store,
 };
@@ -3801,7 +3792,7 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
  * Process 1                         Process 2
  * ext4_create()                     quota_sync()
  *   jbd2_journal_start()                  write_dquot()
- *   vfs_dq_init()                         down(dqio_mutex)
+ *   dquot_initialize()                         down(dqio_mutex)
  *     down(dqio_mutex)                    jbd2_journal_start()
  *
  */
@@ -4010,9 +4001,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
        ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
        int err = 0;
        int offset = off & (sb->s_blocksize - 1);
-       int tocopy;
        int journal_quota = EXT4_SB(sb)->s_qf_names[type] != NULL;
-       size_t towrite = len;
        struct buffer_head *bh;
        handle_t *handle = journal_current_handle();
 
@@ -4022,52 +4011,53 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
                        (unsigned long long)off, (unsigned long long)len);
                return -EIO;
        }
+       /*
+        * Since we account only one data block in transaction credits,
+        * then it is impossible to cross a block boundary.
+        */
+       if (sb->s_blocksize - offset < len) {
+               ext4_msg(sb, KERN_WARNING, "Quota write (off=%llu, len=%llu)"
+                       " cancelled because not block aligned",
+                       (unsigned long long)off, (unsigned long long)len);
+               return -EIO;
+       }
+
        mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
-       while (towrite > 0) {
-               tocopy = sb->s_blocksize - offset < towrite ?
-                               sb->s_blocksize - offset : towrite;
-               bh = ext4_bread(handle, inode, blk, 1, &err);
-               if (!bh)
+       bh = ext4_bread(handle, inode, blk, 1, &err);
+       if (!bh)
+               goto out;
+       if (journal_quota) {
+               err = ext4_journal_get_write_access(handle, bh);
+               if (err) {
+                       brelse(bh);
                        goto out;
-               if (journal_quota) {
-                       err = ext4_journal_get_write_access(handle, bh);
-                       if (err) {
-                               brelse(bh);
-                               goto out;
-                       }
                }
-               lock_buffer(bh);
-               memcpy(bh->b_data+offset, data, tocopy);
-               flush_dcache_page(bh->b_page);
-               unlock_buffer(bh);
-               if (journal_quota)
-                       err = ext4_handle_dirty_metadata(handle, NULL, bh);
-               else {
-                       /* Always do at least ordered writes for quotas */
-                       err = ext4_jbd2_file_inode(handle, inode);
-                       mark_buffer_dirty(bh);
-               }
-               brelse(bh);
-               if (err)
-                       goto out;
-               offset = 0;
-               towrite -= tocopy;
-               data += tocopy;
-               blk++;
        }
+       lock_buffer(bh);
+       memcpy(bh->b_data+offset, data, len);
+       flush_dcache_page(bh->b_page);
+       unlock_buffer(bh);
+       if (journal_quota)
+               err = ext4_handle_dirty_metadata(handle, NULL, bh);
+       else {
+               /* Always do at least ordered writes for quotas */
+               err = ext4_jbd2_file_inode(handle, inode);
+               mark_buffer_dirty(bh);
+       }
+       brelse(bh);
 out:
-       if (len == towrite) {
+       if (err) {
                mutex_unlock(&inode->i_mutex);
                return err;
        }
-       if (inode->i_size < off+len-towrite) {
-               i_size_write(inode, off+len-towrite);
+       if (inode->i_size < off + len) {
+               i_size_write(inode, off + len);
                EXT4_I(inode)->i_disksize = inode->i_size;
        }
        inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        ext4_mark_inode_dirty(handle, inode);
        mutex_unlock(&inode->i_mutex);
-       return len - towrite;
+       return len;
 }
 
 #endif