#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)
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);
unsigned int gversions[MAXQUOTAS] = OCFS2_GLOBAL_QVERSIONS;
unsigned int ino[MAXQUOTAS] = { USER_QUOTA_SYSTEM_INODE,
GROUP_QUOTA_SYSTEM_INODE };
- struct buffer_head *bh;
+ struct buffer_head *bh = NULL;
struct inode *linode = sb_dqopt(sb)->files[type];
struct inode *ginode = NULL;
struct ocfs2_disk_dqheader *dqhead;
int status, ret = 0;
/* First check whether we understand local quota file */
- bh = ocfs2_read_quota_block(linode, 0, &status);
- if (!bh) {
+ status = ocfs2_read_quota_block(linode, 0, &bh);
+ if (status) {
mlog_errno(status);
mlog(ML_ERROR, "failed to read quota file header (type=%d)\n",
type);
goto out_err;
}
/* Since the header is read only, we don't care about locking */
- bh = ocfs2_read_quota_block(ginode, 0, &status);
- if (!bh) {
+ status = ocfs2_read_quota_block(ginode, 0, &bh);
+ if (status) {
mlog_errno(status);
mlog(ML_ERROR, "failed to read global quota file header "
"(type=%d)\n", type);
return -ENOMEM;
}
newchunk->qc_num = i;
- newchunk->qc_headerbh = ocfs2_read_quota_block(inode,
+ newchunk->qc_headerbh = NULL;
+ status = ocfs2_read_quota_block(inode,
ol_quota_chunk_block(inode->i_sb, i),
- &status);
- if (!newchunk->qc_headerbh) {
+ &newchunk->qc_headerbh);
+ if (status) {
mlog_errno(status);
kmem_cache_free(ocfs2_qf_chunk_cachep, newchunk);
ocfs2_release_local_quota_bitmaps(head);
int status = 0;
for (i = 0; i < chunks; i++) {
- hbh = ocfs2_read_quota_block(lqinode,
- ol_quota_chunk_block(sb, i),
- &status);
- if (!hbh) {
+ hbh = NULL;
+ status = ocfs2_read_quota_block(lqinode,
+ ol_quota_chunk_block(sb, i),
+ &hbh);
+ if (status) {
mlog_errno(status);
break;
}
goto out_put;
}
/* Now read local header */
- bh = ocfs2_read_quota_block(lqinode, 0, &status);
- if (!bh) {
+ bh = NULL;
+ status = ocfs2_read_quota_block(lqinode, 0, &bh);
+ if (status) {
mlog_errno(status);
mlog(ML_ERROR, "failed to read quota file info header "
"(slot=%d type=%d)\n", slot_num, type);
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 = ocfs2_read_quota_block(lqinode,
- ol_quota_chunk_block(sb, chunk),
- &status);
- if (!hbh) {
+ hbh = NULL;
+ status = ocfs2_read_quota_block(lqinode,
+ ol_quota_chunk_block(sb, chunk),
+ &hbh);
+ if (status) {
mlog_errno(status);
break;
}
dchunk = (struct ocfs2_local_disk_chunk *)hbh->b_data;
for_each_bit(bit, rchunk->rc_bitmap, ol_chunk_entries(sb)) {
- qbh = ocfs2_read_quota_block(lqinode,
+ qbh = NULL;
+ status = ocfs2_read_quota_block(lqinode,
ol_dqblk_block(sb, chunk, bit),
- &status);
- if (!qbh) {
+ &qbh);
+ if (status) {
mlog_errno(status);
break;
}
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);
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);
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:
if (status < 0)
break;
}
- ocfs2_unlock_global_qf(oinfo, 1);
-out:
if (status < 0)
free_recovery_list(&(rec->r_list[type]));
mlog_exit(status);
goto out_put;
}
/* Now read local header */
- bh = ocfs2_read_quota_block(lqinode, 0, &status);
- if (!bh) {
+ bh = NULL;
+ status = ocfs2_read_quota_block(lqinode, 0, &bh);
+ if (status) {
mlog_errno(status);
mlog(ML_ERROR, "failed to read quota file info header "
"(slot=%d type=%d)\n", slot_num, type);
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;
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);
locked = 1;
/* Now read local header */
- bh = ocfs2_read_quota_block(lqinode, 0, &status);
- if (!bh) {
+ status = ocfs2_read_quota_block(lqinode, 0, &bh);
+ if (status) {
mlog_errno(status);
mlog(ML_ERROR, "failed to read quota file info header "
"(type=%d)\n", type);
goto out_err;
}
+ mutex_lock(&sb_dqopt(sb)->dqio_mutex);
return 0;
out_err:
if (oinfo) {
kfree(oinfo);
}
brelse(bh);
+ mutex_lock(&sb_dqopt(sb)->dqio_mutex);
return -1;
}
od->dq_originodes);
spin_unlock(&dq_data_lock);
mlog(0, "Writing local dquot %u space %lld inodes %lld\n",
- od->dq_dquot.dq_id, dqblk->dqb_spacemod, dqblk->dqb_inodemod);
+ od->dq_dquot.dq_id, (long long)le64_to_cpu(dqblk->dqb_spacemod),
+ (long long)le64_to_cpu(dqblk->dqb_inodemod));
}
/* Write dquot to local quota file */
{
struct super_block *sb = dquot->dq_sb;
struct ocfs2_dquot *od = OCFS2_DQUOT(dquot);
- struct buffer_head *bh;
+ struct buffer_head *bh = NULL;
int status;
- bh = ocfs2_read_quota_block(sb_dqopt(sb)->files[dquot->dq_type],
+ status = ocfs2_read_quota_block(sb_dqopt(sb)->files[dquot->dq_type],
ol_dqblk_file_block(sb, od->dq_local_off),
- &status);
- if (!bh) {
+ &bh);
+ if (status) {
mlog_errno(status);
goto out;
}
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 */
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) {
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);
ocfs2_commit_trans(OCFS2_SB(sb), handle);
out:
brelse(bh);
+ brelse(dbh);
kmem_cache_free(ocfs2_qf_chunk_cachep, chunk);
return ERR_PTR(status);
}
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;
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);
mlog_errno(status);
goto out_trans;
}
+ /* Update file header */
oinfo->dqi_blocks++;
status = ocfs2_local_write_info(sb, type);
if (status < 0) {
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;
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);