ocfs2-devel: remove redundant OCFS2_MOUNT_POSIX_ACL check in ocfs2_get_acl_nolock()
[safe/jmp/linux-2.6] / fs / ocfs2 / quota_local.c
index b5ddb22..1a2c50a 100644 (file)
@@ -20,6 +20,7 @@
 #include "sysfile.h"
 #include "dlmglue.h"
 #include "quota.h"
+#include "uptodate.h"
 
 /* Number of local quota structures per block */
 static inline unsigned int ol_quota_entries_per_block(struct super_block *sb)
@@ -100,14 +101,15 @@ static int ocfs2_modify_bh(struct inode *inode, struct buffer_head *bh,
        handle_t *handle;
        int status;
 
-       handle = ocfs2_start_trans(OCFS2_SB(sb), 1);
+       handle = ocfs2_start_trans(OCFS2_SB(sb),
+                                  OCFS2_QUOTA_BLOCK_UPDATE_CREDITS);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                mlog_errno(status);
                return status;
        }
-       status = ocfs2_journal_access(handle, inode, bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_dq(handle, INODE_CACHE(inode), bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                ocfs2_commit_trans(OCFS2_SB(sb), handle);
@@ -444,10 +446,6 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
 
        mlog_entry("ino=%lu type=%u", (unsigned long)lqinode->i_ino, type);
 
-       status = ocfs2_lock_global_qf(oinfo, 1);
-       if (status < 0)
-               goto out;
-
        list_for_each_entry_safe(rchunk, next, &(rec->r_list[type]), rc_list) {
                chunk = rchunk->rc_chunk;
                hbh = NULL;
@@ -480,12 +478,18 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
                                     type);
                                goto out_put_bh;
                        }
+                       status = ocfs2_lock_global_qf(oinfo, 1);
+                       if (status < 0) {
+                               mlog_errno(status);
+                               goto out_put_dquot;
+                       }
+
                        handle = ocfs2_start_trans(OCFS2_SB(sb),
                                                   OCFS2_QSYNC_CREDITS);
                        if (IS_ERR(handle)) {
                                status = PTR_ERR(handle);
                                mlog_errno(status);
-                               goto out_put_dquot;
+                               goto out_drop_lock;
                        }
                        mutex_lock(&sb_dqopt(sb)->dqio_mutex);
                        spin_lock(&dq_data_lock);
@@ -506,7 +510,8 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
                                goto out_commit;
                        }
                        /* Release local quota file entry */
-                       status = ocfs2_journal_access(handle, lqinode,
+                       status = ocfs2_journal_access_dq(handle,
+                                       INODE_CACHE(lqinode),
                                        qbh, OCFS2_JOURNAL_ACCESS_WRITE);
                        if (status < 0) {
                                mlog_errno(status);
@@ -523,6 +528,8 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
 out_commit:
                        mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
                        ocfs2_commit_trans(OCFS2_SB(sb), handle);
+out_drop_lock:
+                       ocfs2_unlock_global_qf(oinfo, 1);
 out_put_dquot:
                        dqput(dquot);
 out_put_bh:
@@ -537,8 +544,6 @@ out_put_bh:
                if (status < 0)
                        break;
        }
-       ocfs2_unlock_global_qf(oinfo, 1);
-out:
        if (status < 0)
                free_recovery_list(&(rec->r_list[type]));
        mlog_exit(status);
@@ -608,14 +613,16 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb,
                        goto out_bh;
                /* Mark quota file as clean if we are recovering quota file of
                 * some other node. */
-               handle = ocfs2_start_trans(osb, 1);
+               handle = ocfs2_start_trans(osb,
+                                          OCFS2_LOCAL_QINFO_WRITE_CREDITS);
                if (IS_ERR(handle)) {
                        status = PTR_ERR(handle);
                        mlog_errno(status);
                        goto out_bh;
                }
-               status = ocfs2_journal_access(handle, lqinode, bh,
-                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               status = ocfs2_journal_access_dq(handle, INODE_CACHE(lqinode),
+                                                bh,
+                                                OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
                        goto out_trans;
@@ -655,6 +662,9 @@ static int ocfs2_local_read_info(struct super_block *sb, int type)
        struct ocfs2_quota_recovery *rec;
        int locked = 0;
 
+       /* We don't need the lock and we have to acquire quota file locks
+        * which will later depend on this lock */
+       mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
        info->dqi_maxblimit = 0x7fffffffffffffffLL;
        info->dqi_maxilimit = 0x7fffffffffffffffLL;
        oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS);
@@ -733,6 +743,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type)
                goto out_err;
        }
 
+       mutex_lock(&sb_dqopt(sb)->dqio_mutex);
        return 0;
 out_err:
        if (oinfo) {
@@ -746,6 +757,7 @@ out_err:
                kfree(oinfo);
        }
        brelse(bh);
+       mutex_lock(&sb_dqopt(sb)->dqio_mutex);
        return -1;
 }
 
@@ -933,7 +945,7 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
        struct ocfs2_local_disk_chunk *dchunk;
        int status;
        handle_t *handle;
-       struct buffer_head *bh = NULL;
+       struct buffer_head *bh = NULL, *dbh = NULL;
        u64 p_blkno;
 
        /* We are protected by dqio_sem so no locking needed */
@@ -957,42 +969,44 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
                mlog_errno(status);
                goto out;
        }
+       /* Local quota info and two new blocks we initialize */
+       handle = ocfs2_start_trans(OCFS2_SB(sb),
+                       OCFS2_LOCAL_QINFO_WRITE_CREDITS +
+                       2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS);
+       if (IS_ERR(handle)) {
+               status = PTR_ERR(handle);
+               mlog_errno(status);
+               goto out;
+       }
 
+       /* Initialize chunk header */
        down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
        status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks,
                                             &p_blkno, NULL, NULL);
        up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
        if (status < 0) {
                mlog_errno(status);
-               goto out;
+               goto out_trans;
        }
        bh = sb_getblk(sb, p_blkno);
        if (!bh) {
                status = -ENOMEM;
                mlog_errno(status);
-               goto out;
+               goto out_trans;
        }
        dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data;
-
-       handle = ocfs2_start_trans(OCFS2_SB(sb), 2);
-       if (IS_ERR(handle)) {
-               status = PTR_ERR(handle);
-               mlog_errno(status);
-               goto out;
-       }
-
-       status = ocfs2_journal_access(handle, lqinode, bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       ocfs2_set_new_buffer_uptodate(INODE_CACHE(lqinode), bh);
+       status = ocfs2_journal_access_dq(handle, INODE_CACHE(lqinode), bh,
+                                        OCFS2_JOURNAL_ACCESS_CREATE);
        if (status < 0) {
                mlog_errno(status);
                goto out_trans;
        }
        lock_buffer(bh);
-       dchunk->dqc_free = ol_quota_entries_per_block(sb);
+       dchunk->dqc_free = cpu_to_le32(ol_quota_entries_per_block(sb));
        memset(dchunk->dqc_bitmap, 0,
               sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) -
               OCFS2_QBLK_RESERVED_SPACE);
-       set_buffer_uptodate(bh);
        unlock_buffer(bh);
        status = ocfs2_journal_dirty(handle, bh);
        if (status < 0) {
@@ -1000,6 +1014,38 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
                goto out_trans;
        }
 
+       /* Initialize new block with structures */
+       down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
+       status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks + 1,
+                                            &p_blkno, NULL, NULL);
+       up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+       dbh = sb_getblk(sb, p_blkno);
+       if (!dbh) {
+               status = -ENOMEM;
+               mlog_errno(status);
+               goto out_trans;
+       }
+       ocfs2_set_new_buffer_uptodate(INODE_CACHE(lqinode), dbh);
+       status = ocfs2_journal_access_dq(handle, INODE_CACHE(lqinode), dbh,
+                                        OCFS2_JOURNAL_ACCESS_CREATE);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+       lock_buffer(dbh);
+       memset(dbh->b_data, 0, sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE);
+       unlock_buffer(dbh);
+       status = ocfs2_journal_dirty(handle, dbh);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+
+       /* Update local quotafile info */
        oinfo->dqi_blocks += 2;
        oinfo->dqi_chunks++;
        status = ocfs2_local_write_info(sb, type);
@@ -1024,6 +1070,7 @@ out_trans:
        ocfs2_commit_trans(OCFS2_SB(sb), handle);
 out:
        brelse(bh);
+       brelse(dbh);
        kmem_cache_free(ocfs2_qf_chunk_cachep, chunk);
        return ERR_PTR(status);
 }
@@ -1041,6 +1088,8 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
        struct ocfs2_local_disk_chunk *dchunk;
        int epb = ol_quota_entries_per_block(sb);
        unsigned int chunk_blocks;
+       struct buffer_head *bh;
+       u64 p_blkno;
        int status;
        handle_t *handle;
 
@@ -1068,13 +1117,51 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
                mlog_errno(status);
                goto out;
        }
-       handle = ocfs2_start_trans(OCFS2_SB(sb), 2);
+
+       /* Get buffer from the just added block */
+       down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
+       status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks,
+                                            &p_blkno, NULL, NULL);
+       up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+       bh = sb_getblk(sb, p_blkno);
+       if (!bh) {
+               status = -ENOMEM;
+               mlog_errno(status);
+               goto out;
+       }
+       ocfs2_set_new_buffer_uptodate(INODE_CACHE(lqinode), bh);
+
+       /* Local quota info, chunk header and the new block we initialize */
+       handle = ocfs2_start_trans(OCFS2_SB(sb),
+                       OCFS2_LOCAL_QINFO_WRITE_CREDITS +
+                       2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                mlog_errno(status);
                goto out;
        }
-       status = ocfs2_journal_access(handle, lqinode, chunk->qc_headerbh,
+       /* Zero created block */
+       status = ocfs2_journal_access_dq(handle, INODE_CACHE(lqinode), bh,
+                                OCFS2_JOURNAL_ACCESS_CREATE);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+       lock_buffer(bh);
+       memset(bh->b_data, 0, sb->s_blocksize);
+       unlock_buffer(bh);
+       status = ocfs2_journal_dirty(handle, bh);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+       /* Update chunk header */
+       status = ocfs2_journal_access_dq(handle, INODE_CACHE(lqinode),
+                                        chunk->qc_headerbh,
                                 OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
@@ -1090,6 +1177,7 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
                mlog_errno(status);
                goto out_trans;
        }
+       /* Update file header */
        oinfo->dqi_blocks++;
        status = ocfs2_local_write_info(sb, type);
        if (status < 0) {
@@ -1110,7 +1198,7 @@ out:
        return ERR_PTR(status);
 }
 
-void olq_alloc_dquot(struct buffer_head *bh, void *private)
+static void olq_alloc_dquot(struct buffer_head *bh, void *private)
 {
        int *offset = private;
        struct ocfs2_local_disk_chunk *dchunk;
@@ -1207,7 +1295,8 @@ static int ocfs2_local_release_dquot(struct dquot *dquot)
                goto out;
        }
 
-       status = ocfs2_journal_access(handle, sb_dqopt(sb)->files[type],
+       status = ocfs2_journal_access_dq(handle,
+                       INODE_CACHE(sb_dqopt(sb)->files[type]),
                        od->dq_chunk->qc_headerbh, OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);