diff options
| author | Dmitry Monakhov <dmonakhov@openvz.org> | 2010-02-09 11:53:36 -0500 |
|---|---|---|
| committer | Jan Kara <jack@suse.cz> | 2010-03-04 18:20:21 -0500 |
| commit | c469070aea5a0ada45a836937c776fd3083dae2b (patch) | |
| tree | 8c36117b34aba28a73c2fe4e03c7e89c2f43aef3 | |
| parent | c7e8d4d6dceeb6fd236991f590d3fa6f97c59874 (diff) | |
quota: manage reserved space when quota is not active [v2]
Since we implemented generic reserved space management interface,
then it is possible to account reserved space even when quota
is not active (similar to i_blocks/i_bytes).
Without this patch following testcase result in massive comlain from
WARN_ON in dquot_claim_space()
TEST_CASE:
mount /dev/sdb /mnt -oquota
dd if=/dev/zero of=/mnt/test bs=1M count=1
quotaon /mnt
# fs_reserved_spave == 1Mb
# quota_reserved_space == 0, because quota was disabled
dd if=/dev/zero of=/mnt/test seek=1 bs=1M count=1
# fs_reserved_spave == 2Mb
# quota_reserved_space == 1Mb
sync # ->dquot_claim_space() -> WARN_ON
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: Jan Kara <jack@suse.cz>
| -rw-r--r-- | fs/quota/dquot.c | 10 | ||||
| -rw-r--r-- | include/linux/quotaops.h | 11 |
2 files changed, 15 insertions, 6 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index f6eaf0d8fd6a..f11255b18b58 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
| @@ -1354,28 +1354,30 @@ static qsize_t *inode_reserved_space(struct inode * inode) | |||
| 1354 | return inode->i_sb->dq_op->get_reserved_space(inode); | 1354 | return inode->i_sb->dq_op->get_reserved_space(inode); |
| 1355 | } | 1355 | } |
| 1356 | 1356 | ||
| 1357 | static void inode_add_rsv_space(struct inode *inode, qsize_t number) | 1357 | void inode_add_rsv_space(struct inode *inode, qsize_t number) |
| 1358 | { | 1358 | { |
| 1359 | spin_lock(&inode->i_lock); | 1359 | spin_lock(&inode->i_lock); |
| 1360 | *inode_reserved_space(inode) += number; | 1360 | *inode_reserved_space(inode) += number; |
| 1361 | spin_unlock(&inode->i_lock); | 1361 | spin_unlock(&inode->i_lock); |
| 1362 | } | 1362 | } |
| 1363 | EXPORT_SYMBOL(inode_add_rsv_space); | ||
| 1363 | 1364 | ||
| 1364 | 1365 | void inode_claim_rsv_space(struct inode *inode, qsize_t number) | |
| 1365 | static void inode_claim_rsv_space(struct inode *inode, qsize_t number) | ||
| 1366 | { | 1366 | { |
| 1367 | spin_lock(&inode->i_lock); | 1367 | spin_lock(&inode->i_lock); |
| 1368 | *inode_reserved_space(inode) -= number; | 1368 | *inode_reserved_space(inode) -= number; |
| 1369 | __inode_add_bytes(inode, number); | 1369 | __inode_add_bytes(inode, number); |
| 1370 | spin_unlock(&inode->i_lock); | 1370 | spin_unlock(&inode->i_lock); |
| 1371 | } | 1371 | } |
| 1372 | EXPORT_SYMBOL(inode_claim_rsv_space); | ||
| 1372 | 1373 | ||
| 1373 | static void inode_sub_rsv_space(struct inode *inode, qsize_t number) | 1374 | void inode_sub_rsv_space(struct inode *inode, qsize_t number) |
| 1374 | { | 1375 | { |
| 1375 | spin_lock(&inode->i_lock); | 1376 | spin_lock(&inode->i_lock); |
| 1376 | *inode_reserved_space(inode) -= number; | 1377 | *inode_reserved_space(inode) -= number; |
| 1377 | spin_unlock(&inode->i_lock); | 1378 | spin_unlock(&inode->i_lock); |
| 1378 | } | 1379 | } |
| 1380 | EXPORT_SYMBOL(inode_sub_rsv_space); | ||
| 1379 | 1381 | ||
| 1380 | static qsize_t inode_get_rsv_space(struct inode *inode) | 1382 | static qsize_t inode_get_rsv_space(struct inode *inode) |
| 1381 | { | 1383 | { |
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 3ebb23153640..a529d86e7e73 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h | |||
| @@ -26,6 +26,10 @@ static inline void writeout_quota_sb(struct super_block *sb, int type) | |||
| 26 | sb->s_qcop->quota_sync(sb, type); | 26 | sb->s_qcop->quota_sync(sb, type); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | void inode_add_rsv_space(struct inode *inode, qsize_t number); | ||
| 30 | void inode_claim_rsv_space(struct inode *inode, qsize_t number); | ||
| 31 | void inode_sub_rsv_space(struct inode *inode, qsize_t number); | ||
| 32 | |||
| 29 | int dquot_initialize(struct inode *inode, int type); | 33 | int dquot_initialize(struct inode *inode, int type); |
| 30 | int dquot_drop(struct inode *inode); | 34 | int dquot_drop(struct inode *inode); |
| 31 | struct dquot *dqget(struct super_block *sb, unsigned int id, int type); | 35 | struct dquot *dqget(struct super_block *sb, unsigned int id, int type); |
| @@ -42,7 +46,6 @@ int dquot_alloc_inode(const struct inode *inode, qsize_t number); | |||
| 42 | int dquot_reserve_space(struct inode *inode, qsize_t number, int prealloc); | 46 | int dquot_reserve_space(struct inode *inode, qsize_t number, int prealloc); |
| 43 | int dquot_claim_space(struct inode *inode, qsize_t number); | 47 | int dquot_claim_space(struct inode *inode, qsize_t number); |
| 44 | void dquot_release_reserved_space(struct inode *inode, qsize_t number); | 48 | void dquot_release_reserved_space(struct inode *inode, qsize_t number); |
| 45 | qsize_t dquot_get_reserved_space(struct inode *inode); | ||
| 46 | 49 | ||
| 47 | int dquot_free_space(struct inode *inode, qsize_t number); | 50 | int dquot_free_space(struct inode *inode, qsize_t number); |
| 48 | int dquot_free_inode(const struct inode *inode, qsize_t number); | 51 | int dquot_free_inode(const struct inode *inode, qsize_t number); |
| @@ -199,6 +202,8 @@ static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr) | |||
| 199 | if (inode->i_sb->dq_op->reserve_space(inode, nr, 0) == NO_QUOTA) | 202 | if (inode->i_sb->dq_op->reserve_space(inode, nr, 0) == NO_QUOTA) |
| 200 | return 1; | 203 | return 1; |
| 201 | } | 204 | } |
| 205 | else | ||
| 206 | inode_add_rsv_space(inode, nr); | ||
| 202 | return 0; | 207 | return 0; |
| 203 | } | 208 | } |
| 204 | 209 | ||
| @@ -221,7 +226,7 @@ static inline int vfs_dq_claim_space(struct inode *inode, qsize_t nr) | |||
| 221 | if (inode->i_sb->dq_op->claim_space(inode, nr) == NO_QUOTA) | 226 | if (inode->i_sb->dq_op->claim_space(inode, nr) == NO_QUOTA) |
| 222 | return 1; | 227 | return 1; |
| 223 | } else | 228 | } else |
| 224 | inode_add_bytes(inode, nr); | 229 | inode_claim_rsv_space(inode, nr); |
| 225 | 230 | ||
| 226 | mark_inode_dirty(inode); | 231 | mark_inode_dirty(inode); |
| 227 | return 0; | 232 | return 0; |
| @@ -235,6 +240,8 @@ void vfs_dq_release_reservation_space(struct inode *inode, qsize_t nr) | |||
| 235 | { | 240 | { |
| 236 | if (sb_any_quota_active(inode->i_sb)) | 241 | if (sb_any_quota_active(inode->i_sb)) |
| 237 | inode->i_sb->dq_op->release_rsv(inode, nr); | 242 | inode->i_sb->dq_op->release_rsv(inode, nr); |
| 243 | else | ||
| 244 | inode_sub_rsv_space(inode, nr); | ||
| 238 | } | 245 | } |
| 239 | 246 | ||
| 240 | static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr) | 247 | static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr) |
