quota: provide interface for readding allocated space into reserved space

commit 1c8924eb106c1ac755d5d35ce9b3ff42e89e2511 upstream.

ext4 needs to convert allocated (metadata) blocks back into blocks
reserved for delayed allocation. Add functions into quota code for
supporting such operation.

Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: Josh Hunt <johunt@akamai.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Jan Kara 2013-08-17 09:32:32 -04:00 committed by Greg Kroah-Hartman
parent a659ea97f7
commit 4e9eb2afbc
4 changed files with 71 additions and 2 deletions

View File

@ -1102,6 +1102,14 @@ static void dquot_claim_reserved_space(struct dquot *dquot, qsize_t number)
dquot->dq_dqb.dqb_rsvspace -= number;
}
static void dquot_reclaim_reserved_space(struct dquot *dquot, qsize_t number)
{
if (WARN_ON_ONCE(dquot->dq_dqb.dqb_curspace < number))
number = dquot->dq_dqb.dqb_curspace;
dquot->dq_dqb.dqb_rsvspace += number;
dquot->dq_dqb.dqb_curspace -= number;
}
static inline
void dquot_free_reserved_space(struct dquot *dquot, qsize_t number)
{
@ -1536,6 +1544,15 @@ void inode_claim_rsv_space(struct inode *inode, qsize_t number)
}
EXPORT_SYMBOL(inode_claim_rsv_space);
void inode_reclaim_rsv_space(struct inode *inode, qsize_t number)
{
spin_lock(&inode->i_lock);
*inode_reserved_space(inode) += number;
__inode_sub_bytes(inode, number);
spin_unlock(&inode->i_lock);
}
EXPORT_SYMBOL(inode_reclaim_rsv_space);
void inode_sub_rsv_space(struct inode *inode, qsize_t number)
{
spin_lock(&inode->i_lock);
@ -1709,6 +1726,35 @@ int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
}
EXPORT_SYMBOL(dquot_claim_space_nodirty);
/*
* Convert allocated space back to in-memory reserved quotas
*/
void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
{
int cnt;
if (!dquot_active(inode)) {
inode_reclaim_rsv_space(inode, number);
return;
}
down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
spin_lock(&dq_data_lock);
/* Claim reserved quotas to allocated quotas */
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (inode->i_dquot[cnt])
dquot_reclaim_reserved_space(inode->i_dquot[cnt],
number);
}
/* Update inode bytes */
inode_reclaim_rsv_space(inode, number);
spin_unlock(&dq_data_lock);
mark_all_dquot_dirty(inode->i_dquot);
up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
return;
}
EXPORT_SYMBOL(dquot_reclaim_space_nodirty);
/*
* This operation can block, but only after everything is updated
*/

View File

@ -447,9 +447,8 @@ void inode_add_bytes(struct inode *inode, loff_t bytes)
EXPORT_SYMBOL(inode_add_bytes);
void inode_sub_bytes(struct inode *inode, loff_t bytes)
void __inode_sub_bytes(struct inode *inode, loff_t bytes)
{
spin_lock(&inode->i_lock);
inode->i_blocks -= bytes >> 9;
bytes &= 511;
if (inode->i_bytes < bytes) {
@ -457,6 +456,14 @@ void inode_sub_bytes(struct inode *inode, loff_t bytes)
inode->i_bytes += 512;
}
inode->i_bytes -= bytes;
}
EXPORT_SYMBOL(__inode_sub_bytes);
void inode_sub_bytes(struct inode *inode, loff_t bytes)
{
spin_lock(&inode->i_lock);
__inode_sub_bytes(inode, bytes);
spin_unlock(&inode->i_lock);
}

View File

@ -2489,6 +2489,7 @@ extern void generic_fillattr(struct inode *, struct kstat *);
extern int vfs_getattr(struct path *, struct kstat *);
void __inode_add_bytes(struct inode *inode, loff_t bytes);
void inode_add_bytes(struct inode *inode, loff_t bytes);
void __inode_sub_bytes(struct inode *inode, loff_t bytes);
void inode_sub_bytes(struct inode *inode, loff_t bytes);
loff_t inode_get_bytes(struct inode *inode);
void inode_set_bytes(struct inode *inode, loff_t bytes);

View File

@ -41,6 +41,7 @@ void __quota_error(struct super_block *sb, const char *func,
void inode_add_rsv_space(struct inode *inode, qsize_t number);
void inode_claim_rsv_space(struct inode *inode, qsize_t number);
void inode_sub_rsv_space(struct inode *inode, qsize_t number);
void inode_reclaim_rsv_space(struct inode *inode, qsize_t number);
void dquot_initialize(struct inode *inode);
void dquot_drop(struct inode *inode);
@ -59,6 +60,7 @@ int dquot_alloc_inode(const struct inode *inode);
int dquot_claim_space_nodirty(struct inode *inode, qsize_t number);
void dquot_free_inode(const struct inode *inode);
void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number);
int dquot_disable(struct super_block *sb, int type, unsigned int flags);
/* Suspend quotas on remount RO */
@ -238,6 +240,13 @@ static inline int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
return 0;
}
static inline int dquot_reclaim_space_nodirty(struct inode *inode,
qsize_t number)
{
inode_sub_bytes(inode, number);
return 0;
}
static inline int dquot_disable(struct super_block *sb, int type,
unsigned int flags)
{
@ -336,6 +345,12 @@ static inline int dquot_claim_block(struct inode *inode, qsize_t nr)
return ret;
}
static inline void dquot_reclaim_block(struct inode *inode, qsize_t nr)
{
dquot_reclaim_space_nodirty(inode, nr << inode->i_blkbits);
mark_inode_dirty_sync(inode);
}
static inline void dquot_free_space_nodirty(struct inode *inode, qsize_t nr)
{
__dquot_free_space(inode, nr, 0);