From f18df228997fb716990590d248663981a15f17d4 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Tue, 13 Jan 2009 16:43:09 +0100 Subject: quota: Add quota reservation support Delayed allocation defers the block allocation at the dirty pages flush-out time, doing quota charge/check at that time is too late. But we can't charge the quota blocks until blocks are really allocated, otherwise users could get overcharged after reboot from system crash. This patch adds quota reservation for delayed allocation. Quota blocks are reserved in memory, inode and quota won't gets dirtied until later block allocation time. Signed-off-by: Mingming Cao Signed-off-by: Jan Kara --- include/linux/quotaops.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'include/linux/quotaops.h') diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 0b35b3a..3e3a0d2 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -183,6 +183,16 @@ static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr) return ret; } +static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr) +{ + if (sb_any_quota_active(inode->i_sb)) { + /* Used space is updated in alloc_space() */ + if (inode->i_sb->dq_op->reserve_space(inode, nr, 0) == NO_QUOTA) + return 1; + } + return 0; +} + static inline int vfs_dq_alloc_inode(struct inode *inode) { if (sb_any_quota_active(inode->i_sb)) { @@ -339,6 +349,11 @@ static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr) return 0; } +static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr) +{ + return 0; +} + static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr) { inode_sub_bytes(inode, nr); @@ -376,6 +391,12 @@ static inline int vfs_dq_alloc_block(struct inode *inode, qsize_t nr) nr << inode->i_sb->s_blocksize_bits); } +static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr) +{ + return vfs_dq_reserve_space(inode, + nr << inode->i_blkbits); +} + static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr) { vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits); -- cgit v1.1 From 740d9dcd949a986c88886a591054a0cdb89ef669 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Tue, 13 Jan 2009 16:43:14 +0100 Subject: quota: Add quota reservation claim and released operations Reserved quota will be claimed at the block allocation time. Over-booked quota could be returned back with the release callback function. Signed-off-by: Mingming Cao Signed-off-by: Jan Kara --- include/linux/quotaops.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'include/linux/quotaops.h') diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 3e3a0d2..7369d04 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -35,6 +35,11 @@ void dquot_destroy(struct dquot *dquot); int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc); int dquot_alloc_inode(const struct inode *inode, qsize_t number); +int dquot_reserve_space(struct inode *inode, qsize_t number, int prealloc); +int dquot_claim_space(struct inode *inode, qsize_t number); +void dquot_release_reserved_space(struct inode *inode, qsize_t number); +qsize_t dquot_get_reserved_space(struct inode *inode); + int dquot_free_space(struct inode *inode, qsize_t number); int dquot_free_inode(const struct inode *inode, qsize_t number); @@ -203,6 +208,31 @@ static inline int vfs_dq_alloc_inode(struct inode *inode) return 0; } +/* + * Convert in-memory reserved quotas to real consumed quotas + */ +static inline int vfs_dq_claim_space(struct inode *inode, qsize_t nr) +{ + if (sb_any_quota_active(inode->i_sb)) { + if (inode->i_sb->dq_op->claim_space(inode, nr) == NO_QUOTA) + return 1; + } else + inode_add_bytes(inode, nr); + + mark_inode_dirty(inode); + return 0; +} + +/* + * Release reserved (in-memory) quotas + */ +static inline +void vfs_dq_release_reservation_space(struct inode *inode, qsize_t nr) +{ + if (sb_any_quota_active(inode->i_sb)) + inode->i_sb->dq_op->release_rsv(inode, nr); +} + static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr) { if (sb_any_quota_active(inode->i_sb)) @@ -354,6 +384,17 @@ static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr) return 0; } +static inline int vfs_dq_claim_space(struct inode *inode, qsize_t nr) +{ + return vfs_dq_alloc_space(inode, nr); +} + +static inline +int vfs_dq_release_reservation_space(struct inode *inode, qsize_t nr) +{ + return 0; +} + static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr) { inode_sub_bytes(inode, nr); @@ -397,6 +438,18 @@ static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr) nr << inode->i_blkbits); } +static inline int vfs_dq_claim_block(struct inode *inode, qsize_t nr) +{ + return vfs_dq_claim_space(inode, + nr << inode->i_blkbits); +} + +static inline +void vfs_dq_release_reservation_block(struct inode *inode, qsize_t nr) +{ + vfs_dq_release_reservation_space(inode, nr << inode->i_blkbits); +} + static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr) { vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits); -- cgit v1.1 From 9900ba3487f9ba392db30e12d210f768a90abb13 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Wed, 14 Jan 2009 16:18:57 +0100 Subject: quota: Use inode->i_blkbits to get block bits Andrew has suggested to use inode->i_blkbits to get the block bits info, rather than use super block's blockbits. That should be faster and emit less code. Signed-off-by: Mingming Cao Signed-off-by: Jan Kara --- include/linux/quotaops.h | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'include/linux/quotaops.h') diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 7369d04..69b502e 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -410,38 +410,32 @@ static inline void vfs_dq_free_space(struct inode *inode, qsize_t nr) static inline int vfs_dq_prealloc_block_nodirty(struct inode *inode, qsize_t nr) { - return vfs_dq_prealloc_space_nodirty(inode, - nr << inode->i_sb->s_blocksize_bits); + return vfs_dq_prealloc_space_nodirty(inode, nr << inode->i_blkbits); } static inline int vfs_dq_prealloc_block(struct inode *inode, qsize_t nr) { - return vfs_dq_prealloc_space(inode, - nr << inode->i_sb->s_blocksize_bits); + return vfs_dq_prealloc_space(inode, nr << inode->i_blkbits); } static inline int vfs_dq_alloc_block_nodirty(struct inode *inode, qsize_t nr) { - return vfs_dq_alloc_space_nodirty(inode, - nr << inode->i_sb->s_blocksize_bits); + return vfs_dq_alloc_space_nodirty(inode, nr << inode->i_blkbits); } static inline int vfs_dq_alloc_block(struct inode *inode, qsize_t nr) { - return vfs_dq_alloc_space(inode, - nr << inode->i_sb->s_blocksize_bits); + return vfs_dq_alloc_space(inode, nr << inode->i_blkbits); } static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr) { - return vfs_dq_reserve_space(inode, - nr << inode->i_blkbits); + return vfs_dq_reserve_space(inode, nr << inode->i_blkbits); } static inline int vfs_dq_claim_block(struct inode *inode, qsize_t nr) { - return vfs_dq_claim_space(inode, - nr << inode->i_blkbits); + return vfs_dq_claim_space(inode, nr << inode->i_blkbits); } static inline @@ -452,12 +446,12 @@ void vfs_dq_release_reservation_block(struct inode *inode, qsize_t nr) static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr) { - vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits); + vfs_dq_free_space_nodirty(inode, nr << inode->i_blkbits); } static inline void vfs_dq_free_block(struct inode *inode, qsize_t nr) { - vfs_dq_free_space(inode, nr << inode->i_sb->s_blocksize_bits); + vfs_dq_free_space(inode, nr << inode->i_blkbits); } /* -- cgit v1.1 From bf84c82d000b9820b01f516d13d328f354f8a8ee Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 26 Jan 2009 17:37:01 +0100 Subject: quota: Remove uppercase aliases for quota functions. Since all users have been converted, remove uppercase names of quota functions. Signed-off-by: Jan Kara --- include/linux/quotaops.h | 31 ------------------------------- 1 file changed, 31 deletions(-) (limited to 'include/linux/quotaops.h') diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 69b502e..36353d9 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -454,35 +454,4 @@ static inline void vfs_dq_free_block(struct inode *inode, qsize_t nr) vfs_dq_free_space(inode, nr << inode->i_blkbits); } -/* - * Define uppercase equivalents for compatibility with old function names - * Can go away when we think all users have been converted (15/04/2008) - */ -#define DQUOT_INIT(inode) vfs_dq_init(inode) -#define DQUOT_DROP(inode) vfs_dq_drop(inode) -#define DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr) \ - vfs_dq_prealloc_space_nodirty(inode, nr) -#define DQUOT_PREALLOC_SPACE(inode, nr) vfs_dq_prealloc_space(inode, nr) -#define DQUOT_ALLOC_SPACE_NODIRTY(inode, nr) \ - vfs_dq_alloc_space_nodirty(inode, nr) -#define DQUOT_ALLOC_SPACE(inode, nr) vfs_dq_alloc_space(inode, nr) -#define DQUOT_PREALLOC_BLOCK_NODIRTY(inode, nr) \ - vfs_dq_prealloc_block_nodirty(inode, nr) -#define DQUOT_PREALLOC_BLOCK(inode, nr) vfs_dq_prealloc_block(inode, nr) -#define DQUOT_ALLOC_BLOCK_NODIRTY(inode, nr) \ - vfs_dq_alloc_block_nodirty(inode, nr) -#define DQUOT_ALLOC_BLOCK(inode, nr) vfs_dq_alloc_block(inode, nr) -#define DQUOT_ALLOC_INODE(inode) vfs_dq_alloc_inode(inode) -#define DQUOT_FREE_SPACE_NODIRTY(inode, nr) \ - vfs_dq_free_space_nodirty(inode, nr) -#define DQUOT_FREE_SPACE(inode, nr) vfs_dq_free_space(inode, nr) -#define DQUOT_FREE_BLOCK_NODIRTY(inode, nr) \ - vfs_dq_free_block_nodirty(inode, nr) -#define DQUOT_FREE_BLOCK(inode, nr) vfs_dq_free_block(inode, nr) -#define DQUOT_FREE_INODE(inode) vfs_dq_free_inode(inode) -#define DQUOT_TRANSFER(inode, iattr) vfs_dq_transfer(inode, iattr) -#define DQUOT_SYNC(sb) vfs_dq_sync(sb) -#define DQUOT_OFF(sb, remount) vfs_dq_off(sb, remount) -#define DQUOT_ON_REMOUNT(sb) vfs_dq_quota_on_remount(sb) - #endif /* _LINUX_QUOTAOPS_ */ -- cgit v1.1