Commit f64dd44e authored by Jan Kara's avatar Jan Kara

ocfs2: Do not map blocks from local quota file on each write

There is no need to map offset of local dquot structure to on disk block
in each quota write. It is enough to map it just once and store the physical
block number in quota structure in memory. Moreover this simplifies locking
as we do not have to take ip_alloc_sem from quota write path.
Acked-by: default avatarJoel Becker <Joel.Becker@oracle.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent bc8e5f07
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
struct ocfs2_dquot { struct ocfs2_dquot {
struct dquot dq_dquot; /* Generic VFS dquot */ struct dquot dq_dquot; /* Generic VFS dquot */
loff_t dq_local_off; /* Offset in the local quota file */ loff_t dq_local_off; /* Offset in the local quota file */
u64 dq_local_phys_blk; /* Physical block carrying quota structure */
struct ocfs2_quota_chunk *dq_chunk; /* Chunk dquot is in */ struct ocfs2_quota_chunk *dq_chunk; /* Chunk dquot is in */
unsigned int dq_use_count; /* Number of nodes having reference to this entry in global quota file */ unsigned int dq_use_count; /* Number of nodes having reference to this entry in global quota file */
s64 dq_origspace; /* Last globally synced space usage */ s64 dq_origspace; /* Last globally synced space usage */
...@@ -104,6 +105,8 @@ int ocfs2_lock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex); ...@@ -104,6 +105,8 @@ int ocfs2_lock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex);
void ocfs2_unlock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex); void ocfs2_unlock_global_qf(struct ocfs2_mem_dqinfo *oinfo, int ex);
int ocfs2_read_quota_block(struct inode *inode, u64 v_block, int ocfs2_read_quota_block(struct inode *inode, u64 v_block,
struct buffer_head **bh); struct buffer_head **bh);
int ocfs2_read_quota_phys_block(struct inode *inode, u64 p_block,
struct buffer_head **bh);
extern const struct dquot_operations ocfs2_quota_operations; extern const struct dquot_operations ocfs2_quota_operations;
extern struct quota_format_type ocfs2_quota_format; extern struct quota_format_type ocfs2_quota_format;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "dlmglue.h" #include "dlmglue.h"
#include "uptodate.h" #include "uptodate.h"
#include "super.h" #include "super.h"
#include "buffer_head_io.h"
#include "quota.h" #include "quota.h"
static struct workqueue_struct *ocfs2_quota_wq = NULL; static struct workqueue_struct *ocfs2_quota_wq = NULL;
...@@ -137,6 +138,19 @@ int ocfs2_read_quota_block(struct inode *inode, u64 v_block, ...@@ -137,6 +138,19 @@ int ocfs2_read_quota_block(struct inode *inode, u64 v_block,
return rc; return rc;
} }
int ocfs2_read_quota_phys_block(struct inode *inode, u64 p_block,
struct buffer_head **bhp)
{
int rc;
*bhp = NULL;
rc = ocfs2_read_blocks(INODE_CACHE(inode), p_block, 1, bhp, 0,
ocfs2_validate_quota_block);
if (rc)
mlog_errno(rc);
return rc;
}
static int ocfs2_get_quota_block(struct inode *inode, int block, static int ocfs2_get_quota_block(struct inode *inode, int block,
struct buffer_head **bh) struct buffer_head **bh)
{ {
......
...@@ -862,18 +862,17 @@ static int ocfs2_local_write_dquot(struct dquot *dquot) ...@@ -862,18 +862,17 @@ static int ocfs2_local_write_dquot(struct dquot *dquot)
{ {
struct super_block *sb = dquot->dq_sb; struct super_block *sb = dquot->dq_sb;
struct ocfs2_dquot *od = OCFS2_DQUOT(dquot); struct ocfs2_dquot *od = OCFS2_DQUOT(dquot);
struct buffer_head *bh = NULL; struct buffer_head *bh;
struct inode *lqinode = sb_dqopt(sb)->files[dquot->dq_type];
int status; int status;
status = ocfs2_read_quota_block(sb_dqopt(sb)->files[dquot->dq_type], status = ocfs2_read_quota_phys_block(lqinode, od->dq_local_phys_blk,
ol_dqblk_file_block(sb, od->dq_local_off), &bh);
&bh);
if (status) { if (status) {
mlog_errno(status); mlog_errno(status);
goto out; goto out;
} }
status = ocfs2_modify_bh(sb_dqopt(sb)->files[dquot->dq_type], bh, status = ocfs2_modify_bh(lqinode, bh, olq_set_dquot, od);
olq_set_dquot, od);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
goto out; goto out;
...@@ -1197,17 +1196,27 @@ static int ocfs2_create_local_dquot(struct dquot *dquot) ...@@ -1197,17 +1196,27 @@ static int ocfs2_create_local_dquot(struct dquot *dquot)
struct ocfs2_dquot *od = OCFS2_DQUOT(dquot); struct ocfs2_dquot *od = OCFS2_DQUOT(dquot);
int offset; int offset;
int status; int status;
u64 pcount;
down_write(&OCFS2_I(lqinode)->ip_alloc_sem);
chunk = ocfs2_find_free_entry(sb, type, &offset); chunk = ocfs2_find_free_entry(sb, type, &offset);
if (!chunk) { if (!chunk) {
chunk = ocfs2_extend_local_quota_file(sb, type, &offset); chunk = ocfs2_extend_local_quota_file(sb, type, &offset);
if (IS_ERR(chunk)) if (IS_ERR(chunk)) {
return PTR_ERR(chunk); status = PTR_ERR(chunk);
goto out;
}
} else if (IS_ERR(chunk)) { } else if (IS_ERR(chunk)) {
return PTR_ERR(chunk); status = PTR_ERR(chunk);
goto out;
} }
od->dq_local_off = ol_dqblk_off(sb, chunk->qc_num, offset); od->dq_local_off = ol_dqblk_off(sb, chunk->qc_num, offset);
od->dq_chunk = chunk; od->dq_chunk = chunk;
status = ocfs2_extent_map_get_blocks(lqinode,
ol_dqblk_block(sb, chunk->qc_num, offset),
&od->dq_local_phys_blk,
&pcount,
NULL);
/* Initialize dquot structure on disk */ /* Initialize dquot structure on disk */
status = ocfs2_local_write_dquot(dquot); status = ocfs2_local_write_dquot(dquot);
...@@ -1224,6 +1233,7 @@ static int ocfs2_create_local_dquot(struct dquot *dquot) ...@@ -1224,6 +1233,7 @@ static int ocfs2_create_local_dquot(struct dquot *dquot)
goto out; goto out;
} }
out: out:
up_write(&OCFS2_I(lqinode)->ip_alloc_sem);
return status; return status;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment