quota: provide interface for readding allocated space into reserved space
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>
This commit is contained in:
parent
19883bd965
commit
1c8924eb10
4 changed files with 71 additions and 2 deletions
|
@ -1094,6 +1094,14 @@ static void dquot_claim_reserved_space(struct dquot *dquot, qsize_t number)
|
||||||
dquot->dq_dqb.dqb_rsvspace -= 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
|
static inline
|
||||||
void dquot_free_reserved_space(struct dquot *dquot, qsize_t number)
|
void dquot_free_reserved_space(struct dquot *dquot, qsize_t number)
|
||||||
{
|
{
|
||||||
|
@ -1528,6 +1536,15 @@ void inode_claim_rsv_space(struct inode *inode, qsize_t number)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(inode_claim_rsv_space);
|
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)
|
void inode_sub_rsv_space(struct inode *inode, qsize_t number)
|
||||||
{
|
{
|
||||||
spin_lock(&inode->i_lock);
|
spin_lock(&inode->i_lock);
|
||||||
|
@ -1701,6 +1718,35 @@ int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dquot_claim_space_nodirty);
|
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
|
* This operation can block, but only after everything is updated
|
||||||
*/
|
*/
|
||||||
|
|
11
fs/stat.c
11
fs/stat.c
|
@ -447,9 +447,8 @@ void inode_add_bytes(struct inode *inode, loff_t bytes)
|
||||||
|
|
||||||
EXPORT_SYMBOL(inode_add_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;
|
inode->i_blocks -= bytes >> 9;
|
||||||
bytes &= 511;
|
bytes &= 511;
|
||||||
if (inode->i_bytes < bytes) {
|
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 += 512;
|
||||||
}
|
}
|
||||||
inode->i_bytes -= bytes;
|
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);
|
spin_unlock(&inode->i_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2503,6 +2503,7 @@ extern void generic_fillattr(struct inode *, struct kstat *);
|
||||||
extern int vfs_getattr(struct path *, 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_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);
|
void inode_sub_bytes(struct inode *inode, loff_t bytes);
|
||||||
loff_t inode_get_bytes(struct inode *inode);
|
loff_t inode_get_bytes(struct inode *inode);
|
||||||
void inode_set_bytes(struct inode *inode, loff_t bytes);
|
void inode_set_bytes(struct inode *inode, loff_t bytes);
|
||||||
|
|
|
@ -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_add_rsv_space(struct inode *inode, qsize_t number);
|
||||||
void inode_claim_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_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_initialize(struct inode *inode);
|
||||||
void dquot_drop(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);
|
int dquot_claim_space_nodirty(struct inode *inode, qsize_t number);
|
||||||
void dquot_free_inode(const struct inode *inode);
|
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);
|
int dquot_disable(struct super_block *sb, int type, unsigned int flags);
|
||||||
/* Suspend quotas on remount RO */
|
/* Suspend quotas on remount RO */
|
||||||
|
@ -238,6 +240,13 @@ static inline int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
|
||||||
return 0;
|
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,
|
static inline int dquot_disable(struct super_block *sb, int type,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
|
@ -336,6 +345,12 @@ static inline int dquot_claim_block(struct inode *inode, qsize_t nr)
|
||||||
return ret;
|
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)
|
static inline void dquot_free_space_nodirty(struct inode *inode, qsize_t nr)
|
||||||
{
|
{
|
||||||
__dquot_free_space(inode, nr, 0);
|
__dquot_free_space(inode, nr, 0);
|
||||||
|
|
Loading…
Reference in a new issue