diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-07 18:19:35 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-07 18:19:35 -0400 |
| commit | ae8ac6b7dbfd67f883050421fd195c153d02f5f3 (patch) | |
| tree | 162db451c57aa9be511aeb704f7a4301e3ea2225 | |
| parent | 460352c2f18e18accc993a9127a03e903ed8e0ed (diff) | |
| parent | 6c83fd5142c68294acb0e857b7bac2ce8a5077f7 (diff) | |
Merge branch 'quota_scaling' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull quota scaling updates from Jan Kara:
"This contains changes to make the quota subsystem more scalable.
Reportedly it improves number of files created per second on ext4
filesystem on fast storage by about a factor of 2x"
* 'quota_scaling' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: (28 commits)
quota: Add lock annotations to struct members
quota: Reduce contention on dq_data_lock
fs: Provide __inode_get_bytes()
quota: Inline dquot_[re]claim_reserved_space() into callsite
quota: Inline inode_{incr,decr}_space() into callsites
quota: Inline functions into their callsites
ext4: Disable dirty list tracking of dquots when journalling quotas
quota: Allow disabling tracking of dirty dquots in a list
quota: Remove dq_wait_unused from dquot
quota: Move locking into clear_dquot_dirty()
quota: Do not dirty bad dquots
quota: Fix possible corruption of dqi_flags
quota: Propagate ->quota_read errors from v2_read_file_info()
quota: Fix error codes in v2_read_file_info()
quota: Push dqio_sem down to ->read_file_info()
quota: Push dqio_sem down to ->write_file_info()
quota: Push dqio_sem down to ->get_next_id()
quota: Push dqio_sem down to ->release_dqblk()
quota: Remove locking for writing to the old quota format
quota: Do not acquire dqio_sem for dquot overwrites in v2 format
...
| -rw-r--r-- | fs/ext4/super.c | 26 | ||||
| -rw-r--r-- | fs/ocfs2/quota_global.c | 36 | ||||
| -rw-r--r-- | fs/ocfs2/quota_local.c | 17 | ||||
| -rw-r--r-- | fs/quota/dquot.c | 504 | ||||
| -rw-r--r-- | fs/quota/quota_tree.c | 10 | ||||
| -rw-r--r-- | fs/quota/quota_v1.c | 11 | ||||
| -rw-r--r-- | fs/quota/quota_v2.c | 95 | ||||
| -rw-r--r-- | fs/stat.c | 2 | ||||
| -rw-r--r-- | fs/super.c | 2 | ||||
| -rw-r--r-- | include/linux/fs.h | 4 | ||||
| -rw-r--r-- | include/linux/quota.h | 31 | ||||
| -rw-r--r-- | include/linux/quotaops.h | 5 |
12 files changed, 413 insertions, 330 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index c9e7be58756b..93aece6891f2 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -5215,7 +5215,7 @@ static int ext4_statfs_project(struct super_block *sb, | |||
| 5215 | dquot = dqget(sb, qid); | 5215 | dquot = dqget(sb, qid); |
| 5216 | if (IS_ERR(dquot)) | 5216 | if (IS_ERR(dquot)) |
| 5217 | return PTR_ERR(dquot); | 5217 | return PTR_ERR(dquot); |
| 5218 | spin_lock(&dq_data_lock); | 5218 | spin_lock(&dquot->dq_dqb_lock); |
| 5219 | 5219 | ||
| 5220 | limit = (dquot->dq_dqb.dqb_bsoftlimit ? | 5220 | limit = (dquot->dq_dqb.dqb_bsoftlimit ? |
| 5221 | dquot->dq_dqb.dqb_bsoftlimit : | 5221 | dquot->dq_dqb.dqb_bsoftlimit : |
| @@ -5238,7 +5238,7 @@ static int ext4_statfs_project(struct super_block *sb, | |||
| 5238 | (buf->f_files - dquot->dq_dqb.dqb_curinodes) : 0; | 5238 | (buf->f_files - dquot->dq_dqb.dqb_curinodes) : 0; |
| 5239 | } | 5239 | } |
| 5240 | 5240 | ||
| 5241 | spin_unlock(&dq_data_lock); | 5241 | spin_unlock(&dquot->dq_dqb_lock); |
| 5242 | dqput(dquot); | 5242 | dqput(dquot); |
| 5243 | return 0; | 5243 | return 0; |
| 5244 | } | 5244 | } |
| @@ -5284,18 +5284,13 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 5284 | return 0; | 5284 | return 0; |
| 5285 | } | 5285 | } |
| 5286 | 5286 | ||
| 5287 | /* Helper function for writing quotas on sync - we need to start transaction | ||
| 5288 | * before quota file is locked for write. Otherwise the are possible deadlocks: | ||
| 5289 | * Process 1 Process 2 | ||
| 5290 | * ext4_create() quota_sync() | ||
| 5291 | * jbd2_journal_start() write_dquot() | ||
| 5292 | * dquot_initialize() down(dqio_mutex) | ||
| 5293 | * down(dqio_mutex) jbd2_journal_start() | ||
| 5294 | * | ||
| 5295 | */ | ||
| 5296 | 5287 | ||
| 5297 | #ifdef CONFIG_QUOTA | 5288 | #ifdef CONFIG_QUOTA |
| 5298 | 5289 | ||
| 5290 | /* | ||
| 5291 | * Helper functions so that transaction is started before we acquire dqio_sem | ||
| 5292 | * to keep correct lock ordering of transaction > dqio_sem | ||
| 5293 | */ | ||
| 5299 | static inline struct inode *dquot_to_inode(struct dquot *dquot) | 5294 | static inline struct inode *dquot_to_inode(struct dquot *dquot) |
| 5300 | { | 5295 | { |
| 5301 | return sb_dqopt(dquot->dq_sb)->files[dquot->dq_id.type]; | 5296 | return sb_dqopt(dquot->dq_sb)->files[dquot->dq_id.type]; |
| @@ -5430,6 +5425,13 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, | |||
| 5430 | ext4_msg(sb, KERN_WARNING, | 5425 | ext4_msg(sb, KERN_WARNING, |
| 5431 | "Quota file not on filesystem root. " | 5426 | "Quota file not on filesystem root. " |
| 5432 | "Journaled quota will not work"); | 5427 | "Journaled quota will not work"); |
| 5428 | sb_dqopt(sb)->flags |= DQUOT_NOLIST_DIRTY; | ||
| 5429 | } else { | ||
| 5430 | /* | ||
| 5431 | * Clear the flag just in case mount options changed since | ||
| 5432 | * last time. | ||
| 5433 | */ | ||
| 5434 | sb_dqopt(sb)->flags &= ~DQUOT_NOLIST_DIRTY; | ||
| 5433 | } | 5435 | } |
| 5434 | 5436 | ||
| 5435 | /* | 5437 | /* |
| @@ -5526,7 +5528,7 @@ static int ext4_enable_quotas(struct super_block *sb) | |||
| 5526 | test_opt(sb, PRJQUOTA), | 5528 | test_opt(sb, PRJQUOTA), |
| 5527 | }; | 5529 | }; |
| 5528 | 5530 | ||
| 5529 | sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE; | 5531 | sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE | DQUOT_NOLIST_DIRTY; |
| 5530 | for (type = 0; type < EXT4_MAXQUOTAS; type++) { | 5532 | for (type = 0; type < EXT4_MAXQUOTAS; type++) { |
| 5531 | if (qf_inums[type]) { | 5533 | if (qf_inums[type]) { |
| 5532 | err = ext4_quota_enable(sb, type, QFMT_VFS_V1, | 5534 | err = ext4_quota_enable(sb, type, QFMT_VFS_V1, |
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index cec495a921e3..c94b6baaa551 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c | |||
| @@ -33,7 +33,7 @@ | |||
| 33 | * Locking of quotas with OCFS2 is rather complex. Here are rules that | 33 | * Locking of quotas with OCFS2 is rather complex. Here are rules that |
| 34 | * should be obeyed by all the functions: | 34 | * should be obeyed by all the functions: |
| 35 | * - any write of quota structure (either to local or global file) is protected | 35 | * - any write of quota structure (either to local or global file) is protected |
| 36 | * by dqio_mutex or dquot->dq_lock. | 36 | * by dqio_sem or dquot->dq_lock. |
| 37 | * - any modification of global quota file holds inode cluster lock, i_mutex, | 37 | * - any modification of global quota file holds inode cluster lock, i_mutex, |
| 38 | * and ip_alloc_sem of the global quota file (achieved by | 38 | * and ip_alloc_sem of the global quota file (achieved by |
| 39 | * ocfs2_lock_global_qf). It also has to hold qinfo_lock. | 39 | * ocfs2_lock_global_qf). It also has to hold qinfo_lock. |
| @@ -42,9 +42,9 @@ | |||
| 42 | * | 42 | * |
| 43 | * A rough sketch of locking dependencies (lf = local file, gf = global file): | 43 | * A rough sketch of locking dependencies (lf = local file, gf = global file): |
| 44 | * Normal filesystem operation: | 44 | * Normal filesystem operation: |
| 45 | * start_trans -> dqio_mutex -> write to lf | 45 | * start_trans -> dqio_sem -> write to lf |
| 46 | * Syncing of local and global file: | 46 | * Syncing of local and global file: |
| 47 | * ocfs2_lock_global_qf -> start_trans -> dqio_mutex -> qinfo_lock -> | 47 | * ocfs2_lock_global_qf -> start_trans -> dqio_sem -> qinfo_lock -> |
| 48 | * write to gf | 48 | * write to gf |
| 49 | * -> write to lf | 49 | * -> write to lf |
| 50 | * Acquire dquot for the first time: | 50 | * Acquire dquot for the first time: |
| @@ -60,7 +60,7 @@ | |||
| 60 | * Recovery: | 60 | * Recovery: |
| 61 | * inode cluster lock of recovered lf | 61 | * inode cluster lock of recovered lf |
| 62 | * -> read bitmaps -> ip_alloc_sem of lf | 62 | * -> read bitmaps -> ip_alloc_sem of lf |
| 63 | * -> ocfs2_lock_global_qf -> start_trans -> dqio_mutex -> qinfo_lock -> | 63 | * -> ocfs2_lock_global_qf -> start_trans -> dqio_sem -> qinfo_lock -> |
| 64 | * write to gf | 64 | * write to gf |
| 65 | */ | 65 | */ |
| 66 | 66 | ||
| @@ -443,13 +443,17 @@ static int __ocfs2_global_write_info(struct super_block *sb, int type) | |||
| 443 | int ocfs2_global_write_info(struct super_block *sb, int type) | 443 | int ocfs2_global_write_info(struct super_block *sb, int type) |
| 444 | { | 444 | { |
| 445 | int err; | 445 | int err; |
| 446 | struct ocfs2_mem_dqinfo *info = sb_dqinfo(sb, type)->dqi_priv; | 446 | struct quota_info *dqopt = sb_dqopt(sb); |
| 447 | struct ocfs2_mem_dqinfo *info = dqopt->info[type].dqi_priv; | ||
| 447 | 448 | ||
| 449 | down_write(&dqopt->dqio_sem); | ||
| 448 | err = ocfs2_qinfo_lock(info, 1); | 450 | err = ocfs2_qinfo_lock(info, 1); |
| 449 | if (err < 0) | 451 | if (err < 0) |
| 450 | return err; | 452 | goto out_sem; |
| 451 | err = __ocfs2_global_write_info(sb, type); | 453 | err = __ocfs2_global_write_info(sb, type); |
| 452 | ocfs2_qinfo_unlock(info, 1); | 454 | ocfs2_qinfo_unlock(info, 1); |
| 455 | out_sem: | ||
| 456 | up_write(&dqopt->dqio_sem); | ||
| 453 | return err; | 457 | return err; |
| 454 | } | 458 | } |
| 455 | 459 | ||
| @@ -500,7 +504,7 @@ int __ocfs2_sync_dquot(struct dquot *dquot, int freeing) | |||
| 500 | /* Update space and inode usage. Get also other information from | 504 | /* Update space and inode usage. Get also other information from |
| 501 | * global quota file so that we don't overwrite any changes there. | 505 | * global quota file so that we don't overwrite any changes there. |
| 502 | * We are */ | 506 | * We are */ |
| 503 | spin_lock(&dq_data_lock); | 507 | spin_lock(&dquot->dq_dqb_lock); |
| 504 | spacechange = dquot->dq_dqb.dqb_curspace - | 508 | spacechange = dquot->dq_dqb.dqb_curspace - |
| 505 | OCFS2_DQUOT(dquot)->dq_origspace; | 509 | OCFS2_DQUOT(dquot)->dq_origspace; |
| 506 | inodechange = dquot->dq_dqb.dqb_curinodes - | 510 | inodechange = dquot->dq_dqb.dqb_curinodes - |
| @@ -556,7 +560,7 @@ int __ocfs2_sync_dquot(struct dquot *dquot, int freeing) | |||
| 556 | __clear_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags); | 560 | __clear_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags); |
| 557 | OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace; | 561 | OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace; |
| 558 | OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes; | 562 | OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes; |
| 559 | spin_unlock(&dq_data_lock); | 563 | spin_unlock(&dquot->dq_dqb_lock); |
| 560 | err = ocfs2_qinfo_lock(info, freeing); | 564 | err = ocfs2_qinfo_lock(info, freeing); |
| 561 | if (err < 0) { | 565 | if (err < 0) { |
| 562 | mlog(ML_ERROR, "Failed to lock quota info, losing quota write" | 566 | mlog(ML_ERROR, "Failed to lock quota info, losing quota write" |
| @@ -611,7 +615,7 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type) | |||
| 611 | mlog_errno(status); | 615 | mlog_errno(status); |
| 612 | goto out_ilock; | 616 | goto out_ilock; |
| 613 | } | 617 | } |
| 614 | mutex_lock(&sb_dqopt(sb)->dqio_mutex); | 618 | down_write(&sb_dqopt(sb)->dqio_sem); |
| 615 | status = ocfs2_sync_dquot(dquot); | 619 | status = ocfs2_sync_dquot(dquot); |
| 616 | if (status < 0) | 620 | if (status < 0) |
| 617 | mlog_errno(status); | 621 | mlog_errno(status); |
| @@ -619,7 +623,7 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type) | |||
| 619 | status = ocfs2_local_write_dquot(dquot); | 623 | status = ocfs2_local_write_dquot(dquot); |
| 620 | if (status < 0) | 624 | if (status < 0) |
| 621 | mlog_errno(status); | 625 | mlog_errno(status); |
| 622 | mutex_unlock(&sb_dqopt(sb)->dqio_mutex); | 626 | up_write(&sb_dqopt(sb)->dqio_sem); |
| 623 | ocfs2_commit_trans(osb, handle); | 627 | ocfs2_commit_trans(osb, handle); |
| 624 | out_ilock: | 628 | out_ilock: |
| 625 | ocfs2_unlock_global_qf(oinfo, 1); | 629 | ocfs2_unlock_global_qf(oinfo, 1); |
| @@ -666,9 +670,9 @@ static int ocfs2_write_dquot(struct dquot *dquot) | |||
| 666 | mlog_errno(status); | 670 | mlog_errno(status); |
| 667 | goto out; | 671 | goto out; |
| 668 | } | 672 | } |
| 669 | mutex_lock(&sb_dqopt(dquot->dq_sb)->dqio_mutex); | 673 | down_write(&sb_dqopt(dquot->dq_sb)->dqio_sem); |
| 670 | status = ocfs2_local_write_dquot(dquot); | 674 | status = ocfs2_local_write_dquot(dquot); |
| 671 | mutex_unlock(&sb_dqopt(dquot->dq_sb)->dqio_mutex); | 675 | up_write(&sb_dqopt(dquot->dq_sb)->dqio_sem); |
| 672 | ocfs2_commit_trans(osb, handle); | 676 | ocfs2_commit_trans(osb, handle); |
| 673 | out: | 677 | out: |
| 674 | return status; | 678 | return status; |
| @@ -920,10 +924,10 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot) | |||
| 920 | 924 | ||
| 921 | /* In case user set some limits, sync dquot immediately to global | 925 | /* In case user set some limits, sync dquot immediately to global |
| 922 | * quota file so that information propagates quicker */ | 926 | * quota file so that information propagates quicker */ |
| 923 | spin_lock(&dq_data_lock); | 927 | spin_lock(&dquot->dq_dqb_lock); |
| 924 | if (dquot->dq_flags & mask) | 928 | if (dquot->dq_flags & mask) |
| 925 | sync = 1; | 929 | sync = 1; |
| 926 | spin_unlock(&dq_data_lock); | 930 | spin_unlock(&dquot->dq_dqb_lock); |
| 927 | /* This is a slight hack but we can't afford getting global quota | 931 | /* This is a slight hack but we can't afford getting global quota |
| 928 | * lock if we already have a transaction started. */ | 932 | * lock if we already have a transaction started. */ |
| 929 | if (!sync || journal_current_handle()) { | 933 | if (!sync || journal_current_handle()) { |
| @@ -939,7 +943,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot) | |||
| 939 | mlog_errno(status); | 943 | mlog_errno(status); |
| 940 | goto out_ilock; | 944 | goto out_ilock; |
| 941 | } | 945 | } |
| 942 | mutex_lock(&sb_dqopt(sb)->dqio_mutex); | 946 | down_write(&sb_dqopt(sb)->dqio_sem); |
| 943 | status = ocfs2_sync_dquot(dquot); | 947 | status = ocfs2_sync_dquot(dquot); |
| 944 | if (status < 0) { | 948 | if (status < 0) { |
| 945 | mlog_errno(status); | 949 | mlog_errno(status); |
| @@ -948,7 +952,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot) | |||
| 948 | /* Now write updated local dquot structure */ | 952 | /* Now write updated local dquot structure */ |
| 949 | status = ocfs2_local_write_dquot(dquot); | 953 | status = ocfs2_local_write_dquot(dquot); |
| 950 | out_dlock: | 954 | out_dlock: |
| 951 | mutex_unlock(&sb_dqopt(sb)->dqio_mutex); | 955 | up_write(&sb_dqopt(sb)->dqio_sem); |
| 952 | ocfs2_commit_trans(osb, handle); | 956 | ocfs2_commit_trans(osb, handle); |
| 953 | out_ilock: | 957 | out_ilock: |
| 954 | ocfs2_unlock_global_qf(oinfo, 1); | 958 | ocfs2_unlock_global_qf(oinfo, 1); |
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index 32c5a40c1257..aa700fd10610 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c | |||
| @@ -520,8 +520,8 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, | |||
| 520 | mlog_errno(status); | 520 | mlog_errno(status); |
| 521 | goto out_drop_lock; | 521 | goto out_drop_lock; |
| 522 | } | 522 | } |
| 523 | mutex_lock(&sb_dqopt(sb)->dqio_mutex); | 523 | down_write(&sb_dqopt(sb)->dqio_sem); |
| 524 | spin_lock(&dq_data_lock); | 524 | spin_lock(&dquot->dq_dqb_lock); |
| 525 | /* Add usage from quota entry into quota changes | 525 | /* Add usage from quota entry into quota changes |
| 526 | * of our node. Auxiliary variables are important | 526 | * of our node. Auxiliary variables are important |
| 527 | * due to signedness */ | 527 | * due to signedness */ |
| @@ -529,7 +529,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, | |||
| 529 | inodechange = le64_to_cpu(dqblk->dqb_inodemod); | 529 | inodechange = le64_to_cpu(dqblk->dqb_inodemod); |
| 530 | dquot->dq_dqb.dqb_curspace += spacechange; | 530 | dquot->dq_dqb.dqb_curspace += spacechange; |
| 531 | dquot->dq_dqb.dqb_curinodes += inodechange; | 531 | dquot->dq_dqb.dqb_curinodes += inodechange; |
| 532 | spin_unlock(&dq_data_lock); | 532 | spin_unlock(&dquot->dq_dqb_lock); |
| 533 | /* We want to drop reference held by the crashed | 533 | /* We want to drop reference held by the crashed |
| 534 | * node. Since we have our own reference we know | 534 | * node. Since we have our own reference we know |
| 535 | * global structure actually won't be freed. */ | 535 | * global structure actually won't be freed. */ |
| @@ -553,7 +553,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, | |||
| 553 | unlock_buffer(qbh); | 553 | unlock_buffer(qbh); |
| 554 | ocfs2_journal_dirty(handle, qbh); | 554 | ocfs2_journal_dirty(handle, qbh); |
| 555 | out_commit: | 555 | out_commit: |
| 556 | mutex_unlock(&sb_dqopt(sb)->dqio_mutex); | 556 | up_write(&sb_dqopt(sb)->dqio_sem); |
| 557 | ocfs2_commit_trans(OCFS2_SB(sb), handle); | 557 | ocfs2_commit_trans(OCFS2_SB(sb), handle); |
| 558 | out_drop_lock: | 558 | out_drop_lock: |
| 559 | ocfs2_unlock_global_qf(oinfo, 1); | 559 | ocfs2_unlock_global_qf(oinfo, 1); |
| @@ -691,9 +691,6 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) | |||
| 691 | struct ocfs2_quota_recovery *rec; | 691 | struct ocfs2_quota_recovery *rec; |
| 692 | int locked = 0; | 692 | int locked = 0; |
| 693 | 693 | ||
| 694 | /* We don't need the lock and we have to acquire quota file locks | ||
| 695 | * which will later depend on this lock */ | ||
| 696 | mutex_unlock(&sb_dqopt(sb)->dqio_mutex); | ||
| 697 | info->dqi_max_spc_limit = 0x7fffffffffffffffLL; | 694 | info->dqi_max_spc_limit = 0x7fffffffffffffffLL; |
| 698 | info->dqi_max_ino_limit = 0x7fffffffffffffffLL; | 695 | info->dqi_max_ino_limit = 0x7fffffffffffffffLL; |
| 699 | oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS); | 696 | oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS); |
| @@ -772,7 +769,6 @@ static int ocfs2_local_read_info(struct super_block *sb, int type) | |||
| 772 | goto out_err; | 769 | goto out_err; |
| 773 | } | 770 | } |
| 774 | 771 | ||
| 775 | mutex_lock(&sb_dqopt(sb)->dqio_mutex); | ||
| 776 | return 0; | 772 | return 0; |
| 777 | out_err: | 773 | out_err: |
| 778 | if (oinfo) { | 774 | if (oinfo) { |
| @@ -786,7 +782,6 @@ out_err: | |||
| 786 | kfree(oinfo); | 782 | kfree(oinfo); |
| 787 | } | 783 | } |
| 788 | brelse(bh); | 784 | brelse(bh); |
| 789 | mutex_lock(&sb_dqopt(sb)->dqio_mutex); | ||
| 790 | return -1; | 785 | return -1; |
| 791 | } | 786 | } |
| 792 | 787 | ||
| @@ -882,12 +877,12 @@ static void olq_set_dquot(struct buffer_head *bh, void *private) | |||
| 882 | 877 | ||
| 883 | dqblk->dqb_id = cpu_to_le64(from_kqid(&init_user_ns, | 878 | dqblk->dqb_id = cpu_to_le64(from_kqid(&init_user_ns, |
| 884 | od->dq_dquot.dq_id)); | 879 | od->dq_dquot.dq_id)); |
| 885 | spin_lock(&dq_data_lock); | 880 | spin_lock(&od->dq_dquot.dq_dqb_lock); |
| 886 | dqblk->dqb_spacemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curspace - | 881 | dqblk->dqb_spacemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curspace - |
| 887 | od->dq_origspace); | 882 | od->dq_origspace); |
| 888 | dqblk->dqb_inodemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curinodes - | 883 | dqblk->dqb_inodemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curinodes - |
| 889 | od->dq_originodes); | 884 | od->dq_originodes); |
| 890 | spin_unlock(&dq_data_lock); | 885 | spin_unlock(&od->dq_dquot.dq_dqb_lock); |
| 891 | trace_olq_set_dquot( | 886 | trace_olq_set_dquot( |
| 892 | (unsigned long long)le64_to_cpu(dqblk->dqb_spacemod), | 887 | (unsigned long long)le64_to_cpu(dqblk->dqb_spacemod), |
| 893 | (unsigned long long)le64_to_cpu(dqblk->dqb_inodemod), | 888 | (unsigned long long)le64_to_cpu(dqblk->dqb_inodemod), |
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 566e6ef99f07..8381db9db6d9 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
| @@ -82,16 +82,19 @@ | |||
| 82 | #include <linux/uaccess.h> | 82 | #include <linux/uaccess.h> |
| 83 | 83 | ||
| 84 | /* | 84 | /* |
| 85 | * There are three quota SMP locks. dq_list_lock protects all lists with quotas | 85 | * There are five quota SMP locks: |
| 86 | * and quota formats. | 86 | * * dq_list_lock protects all lists with quotas and quota formats. |
| 87 | * dq_data_lock protects data from dq_dqb and also mem_dqinfo structures and | 87 | * * dquot->dq_dqb_lock protects data from dq_dqb |
| 88 | * also guards consistency of dquot->dq_dqb with inode->i_blocks, i_bytes. | 88 | * * inode->i_lock protects inode->i_blocks, i_bytes and also guards |
| 89 | * i_blocks and i_bytes updates itself are guarded by i_lock acquired directly | 89 | * consistency of dquot->dq_dqb with inode->i_blocks, i_bytes so that |
| 90 | * in inode_add_bytes() and inode_sub_bytes(). dq_state_lock protects | 90 | * dquot_transfer() can stabilize amount it transfers |
| 91 | * modifications of quota state (on quotaon and quotaoff) and readers who care | 91 | * * dq_data_lock protects mem_dqinfo structures and modifications of dquot |
| 92 | * about latest values take it as well. | 92 | * pointers in the inode |
| 93 | * * dq_state_lock protects modifications of quota state (on quotaon and | ||
| 94 | * quotaoff) and readers who care about latest values take it as well. | ||
| 93 | * | 95 | * |
| 94 | * The spinlock ordering is hence: dq_data_lock > dq_list_lock > i_lock, | 96 | * The spinlock ordering is hence: |
| 97 | * dq_data_lock > dq_list_lock > i_lock > dquot->dq_dqb_lock, | ||
| 95 | * dq_list_lock > dq_state_lock | 98 | * dq_list_lock > dq_state_lock |
| 96 | * | 99 | * |
| 97 | * Note that some things (eg. sb pointer, type, id) doesn't change during | 100 | * Note that some things (eg. sb pointer, type, id) doesn't change during |
| @@ -110,17 +113,14 @@ | |||
| 110 | * sure they cannot race with quotaon which first sets S_NOQUOTA flag and | 113 | * sure they cannot race with quotaon which first sets S_NOQUOTA flag and |
| 111 | * then drops all pointers to dquots from an inode. | 114 | * then drops all pointers to dquots from an inode. |
| 112 | * | 115 | * |
| 113 | * Each dquot has its dq_lock mutex. Locked dquots might not be referenced | 116 | * Each dquot has its dq_lock mutex. Dquot is locked when it is being read to |
| 114 | * from inodes (dquot_alloc_space() and such don't check the dq_lock). | 117 | * memory (or space for it is being allocated) on the first dqget(), when it is |
| 115 | * Currently dquot is locked only when it is being read to memory (or space for | 118 | * being written out, and when it is being released on the last dqput(). The |
| 116 | * it is being allocated) on the first dqget() and when it is being released on | 119 | * allocation and release operations are serialized by the dq_lock and by |
| 117 | * the last dqput(). The allocation and release oparations are serialized by | 120 | * checking the use count in dquot_release(). |
| 118 | * the dq_lock and by checking the use count in dquot_release(). Write | ||
| 119 | * operations on dquots don't hold dq_lock as they copy data under dq_data_lock | ||
| 120 | * spinlock to internal buffers before writing. | ||
| 121 | * | 121 | * |
| 122 | * Lock ordering (including related VFS locks) is the following: | 122 | * Lock ordering (including related VFS locks) is the following: |
| 123 | * s_umount > i_mutex > journal_lock > dquot->dq_lock > dqio_mutex | 123 | * s_umount > i_mutex > journal_lock > dquot->dq_lock > dqio_sem |
| 124 | */ | 124 | */ |
| 125 | 125 | ||
| 126 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock); | 126 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock); |
| @@ -129,6 +129,8 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_data_lock); | |||
| 129 | EXPORT_SYMBOL(dq_data_lock); | 129 | EXPORT_SYMBOL(dq_data_lock); |
| 130 | DEFINE_STATIC_SRCU(dquot_srcu); | 130 | DEFINE_STATIC_SRCU(dquot_srcu); |
| 131 | 131 | ||
| 132 | static DECLARE_WAIT_QUEUE_HEAD(dquot_ref_wq); | ||
| 133 | |||
| 132 | void __quota_error(struct super_block *sb, const char *func, | 134 | void __quota_error(struct super_block *sb, const char *func, |
| 133 | const char *fmt, ...) | 135 | const char *fmt, ...) |
| 134 | { | 136 | { |
| @@ -247,6 +249,7 @@ struct dqstats dqstats; | |||
| 247 | EXPORT_SYMBOL(dqstats); | 249 | EXPORT_SYMBOL(dqstats); |
| 248 | 250 | ||
| 249 | static qsize_t inode_get_rsv_space(struct inode *inode); | 251 | static qsize_t inode_get_rsv_space(struct inode *inode); |
| 252 | static qsize_t __inode_get_rsv_space(struct inode *inode); | ||
| 250 | static int __dquot_initialize(struct inode *inode, int type); | 253 | static int __dquot_initialize(struct inode *inode, int type); |
| 251 | 254 | ||
| 252 | static inline unsigned int | 255 | static inline unsigned int |
| @@ -342,6 +345,12 @@ int dquot_mark_dquot_dirty(struct dquot *dquot) | |||
| 342 | { | 345 | { |
| 343 | int ret = 1; | 346 | int ret = 1; |
| 344 | 347 | ||
| 348 | if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) | ||
| 349 | return 0; | ||
| 350 | |||
| 351 | if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NOLIST_DIRTY) | ||
| 352 | return test_and_set_bit(DQ_MOD_B, &dquot->dq_flags); | ||
| 353 | |||
| 345 | /* If quota is dirty already, we don't have to acquire dq_list_lock */ | 354 | /* If quota is dirty already, we don't have to acquire dq_list_lock */ |
| 346 | if (test_bit(DQ_MOD_B, &dquot->dq_flags)) | 355 | if (test_bit(DQ_MOD_B, &dquot->dq_flags)) |
| 347 | return 1; | 356 | return 1; |
| @@ -381,18 +390,26 @@ static inline void dqput_all(struct dquot **dquot) | |||
| 381 | dqput(dquot[cnt]); | 390 | dqput(dquot[cnt]); |
| 382 | } | 391 | } |
| 383 | 392 | ||
| 384 | /* This function needs dq_list_lock */ | ||
| 385 | static inline int clear_dquot_dirty(struct dquot *dquot) | 393 | static inline int clear_dquot_dirty(struct dquot *dquot) |
| 386 | { | 394 | { |
| 387 | if (!test_and_clear_bit(DQ_MOD_B, &dquot->dq_flags)) | 395 | if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NOLIST_DIRTY) |
| 396 | return test_and_clear_bit(DQ_MOD_B, &dquot->dq_flags); | ||
| 397 | |||
| 398 | spin_lock(&dq_list_lock); | ||
| 399 | if (!test_and_clear_bit(DQ_MOD_B, &dquot->dq_flags)) { | ||
| 400 | spin_unlock(&dq_list_lock); | ||
| 388 | return 0; | 401 | return 0; |
| 402 | } | ||
| 389 | list_del_init(&dquot->dq_dirty); | 403 | list_del_init(&dquot->dq_dirty); |
| 404 | spin_unlock(&dq_list_lock); | ||
| 390 | return 1; | 405 | return 1; |
| 391 | } | 406 | } |
| 392 | 407 | ||
| 393 | void mark_info_dirty(struct super_block *sb, int type) | 408 | void mark_info_dirty(struct super_block *sb, int type) |
| 394 | { | 409 | { |
| 395 | set_bit(DQF_INFO_DIRTY_B, &sb_dqopt(sb)->info[type].dqi_flags); | 410 | spin_lock(&dq_data_lock); |
| 411 | sb_dqopt(sb)->info[type].dqi_flags |= DQF_INFO_DIRTY; | ||
| 412 | spin_unlock(&dq_data_lock); | ||
| 396 | } | 413 | } |
| 397 | EXPORT_SYMBOL(mark_info_dirty); | 414 | EXPORT_SYMBOL(mark_info_dirty); |
| 398 | 415 | ||
| @@ -406,7 +423,6 @@ int dquot_acquire(struct dquot *dquot) | |||
| 406 | struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); | 423 | struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); |
| 407 | 424 | ||
| 408 | mutex_lock(&dquot->dq_lock); | 425 | mutex_lock(&dquot->dq_lock); |
| 409 | mutex_lock(&dqopt->dqio_mutex); | ||
| 410 | if (!test_bit(DQ_READ_B, &dquot->dq_flags)) | 426 | if (!test_bit(DQ_READ_B, &dquot->dq_flags)) |
| 411 | ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot); | 427 | ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot); |
| 412 | if (ret < 0) | 428 | if (ret < 0) |
| @@ -436,7 +452,6 @@ int dquot_acquire(struct dquot *dquot) | |||
| 436 | smp_mb__before_atomic(); | 452 | smp_mb__before_atomic(); |
| 437 | set_bit(DQ_ACTIVE_B, &dquot->dq_flags); | 453 | set_bit(DQ_ACTIVE_B, &dquot->dq_flags); |
| 438 | out_iolock: | 454 | out_iolock: |
| 439 | mutex_unlock(&dqopt->dqio_mutex); | ||
| 440 | mutex_unlock(&dquot->dq_lock); | 455 | mutex_unlock(&dquot->dq_lock); |
| 441 | return ret; | 456 | return ret; |
| 442 | } | 457 | } |
| @@ -450,21 +465,17 @@ int dquot_commit(struct dquot *dquot) | |||
| 450 | int ret = 0; | 465 | int ret = 0; |
| 451 | struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); | 466 | struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); |
| 452 | 467 | ||
| 453 | mutex_lock(&dqopt->dqio_mutex); | 468 | mutex_lock(&dquot->dq_lock); |
| 454 | spin_lock(&dq_list_lock); | 469 | if (!clear_dquot_dirty(dquot)) |
| 455 | if (!clear_dquot_dirty(dquot)) { | 470 | goto out_lock; |
| 456 | spin_unlock(&dq_list_lock); | ||
| 457 | goto out_sem; | ||
| 458 | } | ||
| 459 | spin_unlock(&dq_list_lock); | ||
| 460 | /* Inactive dquot can be only if there was error during read/init | 471 | /* Inactive dquot can be only if there was error during read/init |
| 461 | * => we have better not writing it */ | 472 | * => we have better not writing it */ |
| 462 | if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) | 473 | if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) |
| 463 | ret = dqopt->ops[dquot->dq_id.type]->commit_dqblk(dquot); | 474 | ret = dqopt->ops[dquot->dq_id.type]->commit_dqblk(dquot); |
| 464 | else | 475 | else |
| 465 | ret = -EIO; | 476 | ret = -EIO; |
| 466 | out_sem: | 477 | out_lock: |
| 467 | mutex_unlock(&dqopt->dqio_mutex); | 478 | mutex_unlock(&dquot->dq_lock); |
| 468 | return ret; | 479 | return ret; |
| 469 | } | 480 | } |
| 470 | EXPORT_SYMBOL(dquot_commit); | 481 | EXPORT_SYMBOL(dquot_commit); |
| @@ -481,7 +492,6 @@ int dquot_release(struct dquot *dquot) | |||
| 481 | /* Check whether we are not racing with some other dqget() */ | 492 | /* Check whether we are not racing with some other dqget() */ |
| 482 | if (atomic_read(&dquot->dq_count) > 1) | 493 | if (atomic_read(&dquot->dq_count) > 1) |
| 483 | goto out_dqlock; | 494 | goto out_dqlock; |
| 484 | mutex_lock(&dqopt->dqio_mutex); | ||
| 485 | if (dqopt->ops[dquot->dq_id.type]->release_dqblk) { | 495 | if (dqopt->ops[dquot->dq_id.type]->release_dqblk) { |
| 486 | ret = dqopt->ops[dquot->dq_id.type]->release_dqblk(dquot); | 496 | ret = dqopt->ops[dquot->dq_id.type]->release_dqblk(dquot); |
| 487 | /* Write the info */ | 497 | /* Write the info */ |
| @@ -493,7 +503,6 @@ int dquot_release(struct dquot *dquot) | |||
| 493 | ret = ret2; | 503 | ret = ret2; |
| 494 | } | 504 | } |
| 495 | clear_bit(DQ_ACTIVE_B, &dquot->dq_flags); | 505 | clear_bit(DQ_ACTIVE_B, &dquot->dq_flags); |
| 496 | mutex_unlock(&dqopt->dqio_mutex); | ||
| 497 | out_dqlock: | 506 | out_dqlock: |
| 498 | mutex_unlock(&dquot->dq_lock); | 507 | mutex_unlock(&dquot->dq_lock); |
| 499 | return ret; | 508 | return ret; |
| @@ -530,22 +539,18 @@ restart: | |||
| 530 | continue; | 539 | continue; |
| 531 | /* Wait for dquot users */ | 540 | /* Wait for dquot users */ |
| 532 | if (atomic_read(&dquot->dq_count)) { | 541 | if (atomic_read(&dquot->dq_count)) { |
| 533 | DEFINE_WAIT(wait); | ||
| 534 | |||
| 535 | dqgrab(dquot); | 542 | dqgrab(dquot); |
| 536 | prepare_to_wait(&dquot->dq_wait_unused, &wait, | ||
| 537 | TASK_UNINTERRUPTIBLE); | ||
| 538 | spin_unlock(&dq_list_lock); | 543 | spin_unlock(&dq_list_lock); |
| 539 | /* Once dqput() wakes us up, we know it's time to free | 544 | /* |
| 545 | * Once dqput() wakes us up, we know it's time to free | ||
| 540 | * the dquot. | 546 | * the dquot. |
| 541 | * IMPORTANT: we rely on the fact that there is always | 547 | * IMPORTANT: we rely on the fact that there is always |
| 542 | * at most one process waiting for dquot to free. | 548 | * at most one process waiting for dquot to free. |
| 543 | * Otherwise dq_count would be > 1 and we would never | 549 | * Otherwise dq_count would be > 1 and we would never |
| 544 | * wake up. | 550 | * wake up. |
| 545 | */ | 551 | */ |
| 546 | if (atomic_read(&dquot->dq_count) > 1) | 552 | wait_event(dquot_ref_wq, |
| 547 | schedule(); | 553 | atomic_read(&dquot->dq_count) == 1); |
| 548 | finish_wait(&dquot->dq_wait_unused, &wait); | ||
| 549 | dqput(dquot); | 554 | dqput(dquot); |
| 550 | /* At this moment dquot() need not exist (it could be | 555 | /* At this moment dquot() need not exist (it could be |
| 551 | * reclaimed by prune_dqcache(). Hence we must | 556 | * reclaimed by prune_dqcache(). Hence we must |
| @@ -629,11 +634,9 @@ int dquot_writeback_dquots(struct super_block *sb, int type) | |||
| 629 | while (!list_empty(dirty)) { | 634 | while (!list_empty(dirty)) { |
| 630 | dquot = list_first_entry(dirty, struct dquot, | 635 | dquot = list_first_entry(dirty, struct dquot, |
| 631 | dq_dirty); | 636 | dq_dirty); |
| 632 | /* Dirty and inactive can be only bad dquot... */ | 637 | |
| 633 | if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) { | 638 | WARN_ON(!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)); |
| 634 | clear_dquot_dirty(dquot); | 639 | |
| 635 | continue; | ||
| 636 | } | ||
| 637 | /* Now we have active dquot from which someone is | 640 | /* Now we have active dquot from which someone is |
| 638 | * holding reference so we can safely just increase | 641 | * holding reference so we can safely just increase |
| 639 | * use count */ | 642 | * use count */ |
| @@ -759,12 +762,12 @@ we_slept: | |||
| 759 | /* Releasing dquot during quotaoff phase? */ | 762 | /* Releasing dquot during quotaoff phase? */ |
| 760 | if (!sb_has_quota_active(dquot->dq_sb, dquot->dq_id.type) && | 763 | if (!sb_has_quota_active(dquot->dq_sb, dquot->dq_id.type) && |
| 761 | atomic_read(&dquot->dq_count) == 1) | 764 | atomic_read(&dquot->dq_count) == 1) |
| 762 | wake_up(&dquot->dq_wait_unused); | 765 | wake_up(&dquot_ref_wq); |
| 763 | spin_unlock(&dq_list_lock); | 766 | spin_unlock(&dq_list_lock); |
| 764 | return; | 767 | return; |
| 765 | } | 768 | } |
| 766 | /* Need to release dquot? */ | 769 | /* Need to release dquot? */ |
| 767 | if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && dquot_dirty(dquot)) { | 770 | if (dquot_dirty(dquot)) { |
| 768 | spin_unlock(&dq_list_lock); | 771 | spin_unlock(&dq_list_lock); |
| 769 | /* Commit dquot before releasing */ | 772 | /* Commit dquot before releasing */ |
| 770 | ret = dquot->dq_sb->dq_op->write_dquot(dquot); | 773 | ret = dquot->dq_sb->dq_op->write_dquot(dquot); |
| @@ -776,14 +779,10 @@ we_slept: | |||
| 776 | * We clear dirty bit anyway, so that we avoid | 779 | * We clear dirty bit anyway, so that we avoid |
| 777 | * infinite loop here | 780 | * infinite loop here |
| 778 | */ | 781 | */ |
| 779 | spin_lock(&dq_list_lock); | ||
| 780 | clear_dquot_dirty(dquot); | 782 | clear_dquot_dirty(dquot); |
| 781 | spin_unlock(&dq_list_lock); | ||
| 782 | } | 783 | } |
| 783 | goto we_slept; | 784 | goto we_slept; |
| 784 | } | 785 | } |
| 785 | /* Clear flag in case dquot was inactive (something bad happened) */ | ||
| 786 | clear_dquot_dirty(dquot); | ||
| 787 | if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) { | 786 | if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) { |
| 788 | spin_unlock(&dq_list_lock); | 787 | spin_unlock(&dq_list_lock); |
| 789 | dquot->dq_sb->dq_op->release_dquot(dquot); | 788 | dquot->dq_sb->dq_op->release_dquot(dquot); |
| @@ -818,10 +817,10 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type) | |||
| 818 | INIT_LIST_HEAD(&dquot->dq_inuse); | 817 | INIT_LIST_HEAD(&dquot->dq_inuse); |
| 819 | INIT_HLIST_NODE(&dquot->dq_hash); | 818 | INIT_HLIST_NODE(&dquot->dq_hash); |
| 820 | INIT_LIST_HEAD(&dquot->dq_dirty); | 819 | INIT_LIST_HEAD(&dquot->dq_dirty); |
| 821 | init_waitqueue_head(&dquot->dq_wait_unused); | ||
| 822 | dquot->dq_sb = sb; | 820 | dquot->dq_sb = sb; |
| 823 | dquot->dq_id = make_kqid_invalid(type); | 821 | dquot->dq_id = make_kqid_invalid(type); |
| 824 | atomic_set(&dquot->dq_count, 1); | 822 | atomic_set(&dquot->dq_count, 1); |
| 823 | spin_lock_init(&dquot->dq_dqb_lock); | ||
| 825 | 824 | ||
| 826 | return dquot; | 825 | return dquot; |
| 827 | } | 826 | } |
| @@ -1079,42 +1078,6 @@ static void drop_dquot_ref(struct super_block *sb, int type) | |||
| 1079 | } | 1078 | } |
| 1080 | } | 1079 | } |
| 1081 | 1080 | ||
| 1082 | static inline void dquot_incr_inodes(struct dquot *dquot, qsize_t number) | ||
| 1083 | { | ||
| 1084 | dquot->dq_dqb.dqb_curinodes += number; | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | static inline void dquot_incr_space(struct dquot *dquot, qsize_t number) | ||
| 1088 | { | ||
| 1089 | dquot->dq_dqb.dqb_curspace += number; | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | static inline void dquot_resv_space(struct dquot *dquot, qsize_t number) | ||
| 1093 | { | ||
| 1094 | dquot->dq_dqb.dqb_rsvspace += number; | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | /* | ||
| 1098 | * Claim reserved quota space | ||
| 1099 | */ | ||
| 1100 | static void dquot_claim_reserved_space(struct dquot *dquot, qsize_t number) | ||
| 1101 | { | ||
| 1102 | if (dquot->dq_dqb.dqb_rsvspace < number) { | ||
| 1103 | WARN_ON_ONCE(1); | ||
| 1104 | number = dquot->dq_dqb.dqb_rsvspace; | ||
| 1105 | } | ||
| 1106 | dquot->dq_dqb.dqb_curspace += number; | ||
| 1107 | dquot->dq_dqb.dqb_rsvspace -= number; | ||
| 1108 | } | ||
| 1109 | |||
| 1110 | static void dquot_reclaim_reserved_space(struct dquot *dquot, qsize_t number) | ||
| 1111 | { | ||
| 1112 | if (WARN_ON_ONCE(dquot->dq_dqb.dqb_curspace < number)) | ||
| 1113 | number = dquot->dq_dqb.dqb_curspace; | ||
| 1114 | dquot->dq_dqb.dqb_rsvspace += number; | ||
| 1115 | dquot->dq_dqb.dqb_curspace -= number; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | static inline | 1081 | static inline |
| 1119 | void dquot_free_reserved_space(struct dquot *dquot, qsize_t number) | 1082 | void dquot_free_reserved_space(struct dquot *dquot, qsize_t number) |
| 1120 | { | 1083 | { |
| @@ -1278,21 +1241,24 @@ static int ignore_hardlimit(struct dquot *dquot) | |||
| 1278 | !(info->dqi_flags & DQF_ROOT_SQUASH)); | 1241 | !(info->dqi_flags & DQF_ROOT_SQUASH)); |
| 1279 | } | 1242 | } |
| 1280 | 1243 | ||
| 1281 | /* needs dq_data_lock */ | 1244 | static int dquot_add_inodes(struct dquot *dquot, qsize_t inodes, |
| 1282 | static int check_idq(struct dquot *dquot, qsize_t inodes, | 1245 | struct dquot_warn *warn) |
| 1283 | struct dquot_warn *warn) | ||
| 1284 | { | 1246 | { |
| 1285 | qsize_t newinodes = dquot->dq_dqb.dqb_curinodes + inodes; | 1247 | qsize_t newinodes; |
| 1248 | int ret = 0; | ||
| 1286 | 1249 | ||
| 1250 | spin_lock(&dquot->dq_dqb_lock); | ||
| 1251 | newinodes = dquot->dq_dqb.dqb_curinodes + inodes; | ||
| 1287 | if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_id.type) || | 1252 | if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_id.type) || |
| 1288 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) | 1253 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) |
| 1289 | return 0; | 1254 | goto add; |
| 1290 | 1255 | ||
| 1291 | if (dquot->dq_dqb.dqb_ihardlimit && | 1256 | if (dquot->dq_dqb.dqb_ihardlimit && |
| 1292 | newinodes > dquot->dq_dqb.dqb_ihardlimit && | 1257 | newinodes > dquot->dq_dqb.dqb_ihardlimit && |
| 1293 | !ignore_hardlimit(dquot)) { | 1258 | !ignore_hardlimit(dquot)) { |
| 1294 | prepare_warning(warn, dquot, QUOTA_NL_IHARDWARN); | 1259 | prepare_warning(warn, dquot, QUOTA_NL_IHARDWARN); |
| 1295 | return -EDQUOT; | 1260 | ret = -EDQUOT; |
| 1261 | goto out; | ||
| 1296 | } | 1262 | } |
| 1297 | 1263 | ||
| 1298 | if (dquot->dq_dqb.dqb_isoftlimit && | 1264 | if (dquot->dq_dqb.dqb_isoftlimit && |
| @@ -1301,7 +1267,8 @@ static int check_idq(struct dquot *dquot, qsize_t inodes, | |||
| 1301 | ktime_get_real_seconds() >= dquot->dq_dqb.dqb_itime && | 1267 | ktime_get_real_seconds() >= dquot->dq_dqb.dqb_itime && |
| 1302 | !ignore_hardlimit(dquot)) { | 1268 | !ignore_hardlimit(dquot)) { |
| 1303 | prepare_warning(warn, dquot, QUOTA_NL_ISOFTLONGWARN); | 1269 | prepare_warning(warn, dquot, QUOTA_NL_ISOFTLONGWARN); |
| 1304 | return -EDQUOT; | 1270 | ret = -EDQUOT; |
| 1271 | goto out; | ||
| 1305 | } | 1272 | } |
| 1306 | 1273 | ||
| 1307 | if (dquot->dq_dqb.dqb_isoftlimit && | 1274 | if (dquot->dq_dqb.dqb_isoftlimit && |
| @@ -1311,30 +1278,40 @@ static int check_idq(struct dquot *dquot, qsize_t inodes, | |||
| 1311 | dquot->dq_dqb.dqb_itime = ktime_get_real_seconds() + | 1278 | dquot->dq_dqb.dqb_itime = ktime_get_real_seconds() + |
| 1312 | sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type].dqi_igrace; | 1279 | sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type].dqi_igrace; |
| 1313 | } | 1280 | } |
| 1281 | add: | ||
| 1282 | dquot->dq_dqb.dqb_curinodes = newinodes; | ||
| 1314 | 1283 | ||
| 1315 | return 0; | 1284 | out: |
| 1285 | spin_unlock(&dquot->dq_dqb_lock); | ||
| 1286 | return ret; | ||
| 1316 | } | 1287 | } |
| 1317 | 1288 | ||
| 1318 | /* needs dq_data_lock */ | 1289 | static int dquot_add_space(struct dquot *dquot, qsize_t space, |
| 1319 | static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, | 1290 | qsize_t rsv_space, unsigned int flags, |
| 1320 | struct dquot_warn *warn) | 1291 | struct dquot_warn *warn) |
| 1321 | { | 1292 | { |
| 1322 | qsize_t tspace; | 1293 | qsize_t tspace; |
| 1323 | struct super_block *sb = dquot->dq_sb; | 1294 | struct super_block *sb = dquot->dq_sb; |
| 1295 | int ret = 0; | ||
| 1324 | 1296 | ||
| 1297 | spin_lock(&dquot->dq_dqb_lock); | ||
| 1325 | if (!sb_has_quota_limits_enabled(sb, dquot->dq_id.type) || | 1298 | if (!sb_has_quota_limits_enabled(sb, dquot->dq_id.type) || |
| 1326 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) | 1299 | test_bit(DQ_FAKE_B, &dquot->dq_flags)) |
| 1327 | return 0; | 1300 | goto add; |
| 1328 | 1301 | ||
| 1329 | tspace = dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace | 1302 | tspace = dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace |
| 1330 | + space; | 1303 | + space + rsv_space; |
| 1304 | |||
| 1305 | if (flags & DQUOT_SPACE_NOFAIL) | ||
| 1306 | goto add; | ||
| 1331 | 1307 | ||
| 1332 | if (dquot->dq_dqb.dqb_bhardlimit && | 1308 | if (dquot->dq_dqb.dqb_bhardlimit && |
| 1333 | tspace > dquot->dq_dqb.dqb_bhardlimit && | 1309 | tspace > dquot->dq_dqb.dqb_bhardlimit && |
| 1334 | !ignore_hardlimit(dquot)) { | 1310 | !ignore_hardlimit(dquot)) { |
| 1335 | if (!prealloc) | 1311 | if (flags & DQUOT_SPACE_WARN) |
| 1336 | prepare_warning(warn, dquot, QUOTA_NL_BHARDWARN); | 1312 | prepare_warning(warn, dquot, QUOTA_NL_BHARDWARN); |
| 1337 | return -EDQUOT; | 1313 | ret = -EDQUOT; |
| 1314 | goto out; | ||
| 1338 | } | 1315 | } |
| 1339 | 1316 | ||
| 1340 | if (dquot->dq_dqb.dqb_bsoftlimit && | 1317 | if (dquot->dq_dqb.dqb_bsoftlimit && |
| @@ -1342,28 +1319,34 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, | |||
| 1342 | dquot->dq_dqb.dqb_btime && | 1319 | dquot->dq_dqb.dqb_btime && |
| 1343 | ktime_get_real_seconds() >= dquot->dq_dqb.dqb_btime && | 1320 | ktime_get_real_seconds() >= dquot->dq_dqb.dqb_btime && |
| 1344 | !ignore_hardlimit(dquot)) { | 1321 | !ignore_hardlimit(dquot)) { |
| 1345 | if (!prealloc) | 1322 | if (flags & DQUOT_SPACE_WARN) |
| 1346 | prepare_warning(warn, dquot, QUOTA_NL_BSOFTLONGWARN); | 1323 | prepare_warning(warn, dquot, QUOTA_NL_BSOFTLONGWARN); |
| 1347 | return -EDQUOT; | 1324 | ret = -EDQUOT; |
| 1325 | goto out; | ||
| 1348 | } | 1326 | } |
| 1349 | 1327 | ||
| 1350 | if (dquot->dq_dqb.dqb_bsoftlimit && | 1328 | if (dquot->dq_dqb.dqb_bsoftlimit && |
| 1351 | tspace > dquot->dq_dqb.dqb_bsoftlimit && | 1329 | tspace > dquot->dq_dqb.dqb_bsoftlimit && |
| 1352 | dquot->dq_dqb.dqb_btime == 0) { | 1330 | dquot->dq_dqb.dqb_btime == 0) { |
| 1353 | if (!prealloc) { | 1331 | if (flags & DQUOT_SPACE_WARN) { |
| 1354 | prepare_warning(warn, dquot, QUOTA_NL_BSOFTWARN); | 1332 | prepare_warning(warn, dquot, QUOTA_NL_BSOFTWARN); |
| 1355 | dquot->dq_dqb.dqb_btime = ktime_get_real_seconds() + | 1333 | dquot->dq_dqb.dqb_btime = ktime_get_real_seconds() + |
| 1356 | sb_dqopt(sb)->info[dquot->dq_id.type].dqi_bgrace; | 1334 | sb_dqopt(sb)->info[dquot->dq_id.type].dqi_bgrace; |
| 1357 | } | 1335 | } else { |
| 1358 | else | ||
| 1359 | /* | 1336 | /* |
| 1360 | * We don't allow preallocation to exceed softlimit so exceeding will | 1337 | * We don't allow preallocation to exceed softlimit so exceeding will |
| 1361 | * be always printed | 1338 | * be always printed |
| 1362 | */ | 1339 | */ |
| 1363 | return -EDQUOT; | 1340 | ret = -EDQUOT; |
| 1341 | goto out; | ||
| 1342 | } | ||
| 1364 | } | 1343 | } |
| 1365 | 1344 | add: | |
| 1366 | return 0; | 1345 | dquot->dq_dqb.dqb_rsvspace += rsv_space; |
| 1346 | dquot->dq_dqb.dqb_curspace += space; | ||
| 1347 | out: | ||
| 1348 | spin_unlock(&dquot->dq_dqb_lock); | ||
| 1349 | return ret; | ||
| 1367 | } | 1350 | } |
| 1368 | 1351 | ||
| 1369 | static int info_idq_free(struct dquot *dquot, qsize_t inodes) | 1352 | static int info_idq_free(struct dquot *dquot, qsize_t inodes) |
| @@ -1502,8 +1485,15 @@ static int __dquot_initialize(struct inode *inode, int type) | |||
| 1502 | * did a write before quota was turned on | 1485 | * did a write before quota was turned on |
| 1503 | */ | 1486 | */ |
| 1504 | rsv = inode_get_rsv_space(inode); | 1487 | rsv = inode_get_rsv_space(inode); |
| 1505 | if (unlikely(rsv)) | 1488 | if (unlikely(rsv)) { |
| 1506 | dquot_resv_space(dquots[cnt], rsv); | 1489 | spin_lock(&inode->i_lock); |
| 1490 | /* Get reservation again under proper lock */ | ||
| 1491 | rsv = __inode_get_rsv_space(inode); | ||
| 1492 | spin_lock(&dquots[cnt]->dq_dqb_lock); | ||
| 1493 | dquots[cnt]->dq_dqb.dqb_rsvspace += rsv; | ||
| 1494 | spin_unlock(&dquots[cnt]->dq_dqb_lock); | ||
| 1495 | spin_unlock(&inode->i_lock); | ||
| 1496 | } | ||
| 1507 | } | 1497 | } |
| 1508 | } | 1498 | } |
| 1509 | out_lock: | 1499 | out_lock: |
| @@ -1598,39 +1588,12 @@ static qsize_t *inode_reserved_space(struct inode * inode) | |||
| 1598 | return inode->i_sb->dq_op->get_reserved_space(inode); | 1588 | return inode->i_sb->dq_op->get_reserved_space(inode); |
| 1599 | } | 1589 | } |
| 1600 | 1590 | ||
| 1601 | void inode_add_rsv_space(struct inode *inode, qsize_t number) | 1591 | static qsize_t __inode_get_rsv_space(struct inode *inode) |
| 1602 | { | ||
| 1603 | spin_lock(&inode->i_lock); | ||
| 1604 | *inode_reserved_space(inode) += number; | ||
| 1605 | spin_unlock(&inode->i_lock); | ||
| 1606 | } | ||
| 1607 | EXPORT_SYMBOL(inode_add_rsv_space); | ||
| 1608 | |||
| 1609 | void inode_claim_rsv_space(struct inode *inode, qsize_t number) | ||
| 1610 | { | 1592 | { |
| 1611 | spin_lock(&inode->i_lock); | 1593 | if (!inode->i_sb->dq_op->get_reserved_space) |
| 1612 | *inode_reserved_space(inode) -= number; | 1594 | return 0; |
| 1613 | __inode_add_bytes(inode, number); | 1595 | return *inode_reserved_space(inode); |
| 1614 | spin_unlock(&inode->i_lock); | ||
| 1615 | } | ||
| 1616 | EXPORT_SYMBOL(inode_claim_rsv_space); | ||
| 1617 | |||
| 1618 | void inode_reclaim_rsv_space(struct inode *inode, qsize_t number) | ||
| 1619 | { | ||
| 1620 | spin_lock(&inode->i_lock); | ||
| 1621 | *inode_reserved_space(inode) += number; | ||
| 1622 | __inode_sub_bytes(inode, number); | ||
| 1623 | spin_unlock(&inode->i_lock); | ||
| 1624 | } | ||
| 1625 | EXPORT_SYMBOL(inode_reclaim_rsv_space); | ||
| 1626 | |||
| 1627 | void inode_sub_rsv_space(struct inode *inode, qsize_t number) | ||
| 1628 | { | ||
| 1629 | spin_lock(&inode->i_lock); | ||
| 1630 | *inode_reserved_space(inode) -= number; | ||
| 1631 | spin_unlock(&inode->i_lock); | ||
| 1632 | } | 1596 | } |
| 1633 | EXPORT_SYMBOL(inode_sub_rsv_space); | ||
| 1634 | 1597 | ||
| 1635 | static qsize_t inode_get_rsv_space(struct inode *inode) | 1598 | static qsize_t inode_get_rsv_space(struct inode *inode) |
| 1636 | { | 1599 | { |
| @@ -1639,28 +1602,11 @@ static qsize_t inode_get_rsv_space(struct inode *inode) | |||
| 1639 | if (!inode->i_sb->dq_op->get_reserved_space) | 1602 | if (!inode->i_sb->dq_op->get_reserved_space) |
| 1640 | return 0; | 1603 | return 0; |
| 1641 | spin_lock(&inode->i_lock); | 1604 | spin_lock(&inode->i_lock); |
| 1642 | ret = *inode_reserved_space(inode); | 1605 | ret = __inode_get_rsv_space(inode); |
| 1643 | spin_unlock(&inode->i_lock); | 1606 | spin_unlock(&inode->i_lock); |
| 1644 | return ret; | 1607 | return ret; |
| 1645 | } | 1608 | } |
| 1646 | 1609 | ||
| 1647 | static void inode_incr_space(struct inode *inode, qsize_t number, | ||
| 1648 | int reserve) | ||
| 1649 | { | ||
| 1650 | if (reserve) | ||
| 1651 | inode_add_rsv_space(inode, number); | ||
| 1652 | else | ||
| 1653 | inode_add_bytes(inode, number); | ||
| 1654 | } | ||
| 1655 | |||
| 1656 | static void inode_decr_space(struct inode *inode, qsize_t number, int reserve) | ||
| 1657 | { | ||
| 1658 | if (reserve) | ||
| 1659 | inode_sub_rsv_space(inode, number); | ||
| 1660 | else | ||
| 1661 | inode_sub_bytes(inode, number); | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | /* | 1610 | /* |
| 1665 | * This functions updates i_blocks+i_bytes fields and quota information | 1611 | * This functions updates i_blocks+i_bytes fields and quota information |
| 1666 | * (together with appropriate checks). | 1612 | * (together with appropriate checks). |
| @@ -1682,7 +1628,13 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags) | |||
| 1682 | struct dquot **dquots; | 1628 | struct dquot **dquots; |
| 1683 | 1629 | ||
| 1684 | if (!dquot_active(inode)) { | 1630 | if (!dquot_active(inode)) { |
| 1685 | inode_incr_space(inode, number, reserve); | 1631 | if (reserve) { |
| 1632 | spin_lock(&inode->i_lock); | ||
| 1633 | *inode_reserved_space(inode) += number; | ||
| 1634 | spin_unlock(&inode->i_lock); | ||
| 1635 | } else { | ||
| 1636 | inode_add_bytes(inode, number); | ||
| 1637 | } | ||
| 1686 | goto out; | 1638 | goto out; |
| 1687 | } | 1639 | } |
| 1688 | 1640 | ||
| @@ -1691,27 +1643,41 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags) | |||
| 1691 | 1643 | ||
| 1692 | dquots = i_dquot(inode); | 1644 | dquots = i_dquot(inode); |
| 1693 | index = srcu_read_lock(&dquot_srcu); | 1645 | index = srcu_read_lock(&dquot_srcu); |
| 1694 | spin_lock(&dq_data_lock); | 1646 | spin_lock(&inode->i_lock); |
| 1695 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1647 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
| 1696 | if (!dquots[cnt]) | 1648 | if (!dquots[cnt]) |
| 1697 | continue; | 1649 | continue; |
| 1698 | ret = check_bdq(dquots[cnt], number, | 1650 | if (flags & DQUOT_SPACE_RESERVE) { |
| 1699 | !(flags & DQUOT_SPACE_WARN), &warn[cnt]); | 1651 | ret = dquot_add_space(dquots[cnt], 0, number, flags, |
| 1700 | if (ret && !(flags & DQUOT_SPACE_NOFAIL)) { | 1652 | &warn[cnt]); |
| 1701 | spin_unlock(&dq_data_lock); | 1653 | } else { |
| 1654 | ret = dquot_add_space(dquots[cnt], number, 0, flags, | ||
| 1655 | &warn[cnt]); | ||
| 1656 | } | ||
| 1657 | if (ret) { | ||
| 1658 | /* Back out changes we already did */ | ||
| 1659 | for (cnt--; cnt >= 0; cnt--) { | ||
| 1660 | if (!dquots[cnt]) | ||
| 1661 | continue; | ||
| 1662 | spin_lock(&dquots[cnt]->dq_dqb_lock); | ||
| 1663 | if (flags & DQUOT_SPACE_RESERVE) { | ||
| 1664 | dquots[cnt]->dq_dqb.dqb_rsvspace -= | ||
| 1665 | number; | ||
| 1666 | } else { | ||
| 1667 | dquots[cnt]->dq_dqb.dqb_curspace -= | ||
| 1668 | number; | ||
| 1669 | } | ||
| 1670 | spin_unlock(&dquots[cnt]->dq_dqb_lock); | ||
| 1671 | } | ||
| 1672 | spin_unlock(&inode->i_lock); | ||
| 1702 | goto out_flush_warn; | 1673 | goto out_flush_warn; |
| 1703 | } | 1674 | } |
| 1704 | } | 1675 | } |
| 1705 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1676 | if (reserve) |
| 1706 | if (!dquots[cnt]) | 1677 | *inode_reserved_space(inode) += number; |
| 1707 | continue; | 1678 | else |
| 1708 | if (reserve) | 1679 | __inode_add_bytes(inode, number); |
| 1709 | dquot_resv_space(dquots[cnt], number); | 1680 | spin_unlock(&inode->i_lock); |
| 1710 | else | ||
| 1711 | dquot_incr_space(dquots[cnt], number); | ||
| 1712 | } | ||
| 1713 | inode_incr_space(inode, number, reserve); | ||
| 1714 | spin_unlock(&dq_data_lock); | ||
| 1715 | 1681 | ||
| 1716 | if (reserve) | 1682 | if (reserve) |
| 1717 | goto out_flush_warn; | 1683 | goto out_flush_warn; |
| @@ -1740,23 +1706,26 @@ int dquot_alloc_inode(struct inode *inode) | |||
| 1740 | 1706 | ||
| 1741 | dquots = i_dquot(inode); | 1707 | dquots = i_dquot(inode); |
| 1742 | index = srcu_read_lock(&dquot_srcu); | 1708 | index = srcu_read_lock(&dquot_srcu); |
| 1743 | spin_lock(&dq_data_lock); | 1709 | spin_lock(&inode->i_lock); |
| 1744 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1710 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
| 1745 | if (!dquots[cnt]) | 1711 | if (!dquots[cnt]) |
| 1746 | continue; | 1712 | continue; |
| 1747 | ret = check_idq(dquots[cnt], 1, &warn[cnt]); | 1713 | ret = dquot_add_inodes(dquots[cnt], 1, &warn[cnt]); |
| 1748 | if (ret) | 1714 | if (ret) { |
| 1715 | for (cnt--; cnt >= 0; cnt--) { | ||
| 1716 | if (!dquots[cnt]) | ||
| 1717 | continue; | ||
| 1718 | /* Back out changes we already did */ | ||
| 1719 | spin_lock(&dquots[cnt]->dq_dqb_lock); | ||
| 1720 | dquots[cnt]->dq_dqb.dqb_curinodes--; | ||
| 1721 | spin_unlock(&dquots[cnt]->dq_dqb_lock); | ||
| 1722 | } | ||
| 1749 | goto warn_put_all; | 1723 | goto warn_put_all; |
| 1750 | } | 1724 | } |
| 1751 | |||
| 1752 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | ||
| 1753 | if (!dquots[cnt]) | ||
| 1754 | continue; | ||
| 1755 | dquot_incr_inodes(dquots[cnt], 1); | ||
| 1756 | } | 1725 | } |
| 1757 | 1726 | ||
| 1758 | warn_put_all: | 1727 | warn_put_all: |
| 1759 | spin_unlock(&dq_data_lock); | 1728 | spin_unlock(&inode->i_lock); |
| 1760 | if (ret == 0) | 1729 | if (ret == 0) |
| 1761 | mark_all_dquot_dirty(dquots); | 1730 | mark_all_dquot_dirty(dquots); |
| 1762 | srcu_read_unlock(&dquot_srcu, index); | 1731 | srcu_read_unlock(&dquot_srcu, index); |
| @@ -1774,21 +1743,33 @@ int dquot_claim_space_nodirty(struct inode *inode, qsize_t number) | |||
| 1774 | int cnt, index; | 1743 | int cnt, index; |
| 1775 | 1744 | ||
| 1776 | if (!dquot_active(inode)) { | 1745 | if (!dquot_active(inode)) { |
| 1777 | inode_claim_rsv_space(inode, number); | 1746 | spin_lock(&inode->i_lock); |
| 1747 | *inode_reserved_space(inode) -= number; | ||
| 1748 | __inode_add_bytes(inode, number); | ||
| 1749 | spin_unlock(&inode->i_lock); | ||
| 1778 | return 0; | 1750 | return 0; |
| 1779 | } | 1751 | } |
| 1780 | 1752 | ||
| 1781 | dquots = i_dquot(inode); | 1753 | dquots = i_dquot(inode); |
| 1782 | index = srcu_read_lock(&dquot_srcu); | 1754 | index = srcu_read_lock(&dquot_srcu); |
| 1783 | spin_lock(&dq_data_lock); | 1755 | spin_lock(&inode->i_lock); |
| 1784 | /* Claim reserved quotas to allocated quotas */ | 1756 | /* Claim reserved quotas to allocated quotas */ |
| 1785 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1757 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
| 1786 | if (dquots[cnt]) | 1758 | if (dquots[cnt]) { |
| 1787 | dquot_claim_reserved_space(dquots[cnt], number); | 1759 | struct dquot *dquot = dquots[cnt]; |
| 1760 | |||
| 1761 | spin_lock(&dquot->dq_dqb_lock); | ||
| 1762 | if (WARN_ON_ONCE(dquot->dq_dqb.dqb_rsvspace < number)) | ||
| 1763 | number = dquot->dq_dqb.dqb_rsvspace; | ||
| 1764 | dquot->dq_dqb.dqb_curspace += number; | ||
| 1765 | dquot->dq_dqb.dqb_rsvspace -= number; | ||
| 1766 | spin_unlock(&dquot->dq_dqb_lock); | ||
| 1767 | } | ||
| 1788 | } | 1768 | } |
| 1789 | /* Update inode bytes */ | 1769 | /* Update inode bytes */ |
| 1790 | inode_claim_rsv_space(inode, number); | 1770 | *inode_reserved_space(inode) -= number; |
| 1791 | spin_unlock(&dq_data_lock); | 1771 | __inode_add_bytes(inode, number); |
| 1772 | spin_unlock(&inode->i_lock); | ||
| 1792 | mark_all_dquot_dirty(dquots); | 1773 | mark_all_dquot_dirty(dquots); |
| 1793 | srcu_read_unlock(&dquot_srcu, index); | 1774 | srcu_read_unlock(&dquot_srcu, index); |
| 1794 | return 0; | 1775 | return 0; |
| @@ -1804,21 +1785,33 @@ void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number) | |||
| 1804 | int cnt, index; | 1785 | int cnt, index; |
| 1805 | 1786 | ||
| 1806 | if (!dquot_active(inode)) { | 1787 | if (!dquot_active(inode)) { |
| 1807 | inode_reclaim_rsv_space(inode, number); | 1788 | spin_lock(&inode->i_lock); |
| 1789 | *inode_reserved_space(inode) += number; | ||
| 1790 | __inode_sub_bytes(inode, number); | ||
| 1791 | spin_unlock(&inode->i_lock); | ||
| 1808 | return; | 1792 | return; |
| 1809 | } | 1793 | } |
| 1810 | 1794 | ||
| 1811 | dquots = i_dquot(inode); | 1795 | dquots = i_dquot(inode); |
| 1812 | index = srcu_read_lock(&dquot_srcu); | 1796 | index = srcu_read_lock(&dquot_srcu); |
| 1813 | spin_lock(&dq_data_lock); | 1797 | spin_lock(&inode->i_lock); |
| 1814 | /* Claim reserved quotas to allocated quotas */ | 1798 | /* Claim reserved quotas to allocated quotas */ |
| 1815 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1799 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
| 1816 | if (dquots[cnt]) | 1800 | if (dquots[cnt]) { |
| 1817 | dquot_reclaim_reserved_space(dquots[cnt], number); | 1801 | struct dquot *dquot = dquots[cnt]; |
| 1802 | |||
| 1803 | spin_lock(&dquot->dq_dqb_lock); | ||
| 1804 | if (WARN_ON_ONCE(dquot->dq_dqb.dqb_curspace < number)) | ||
| 1805 | number = dquot->dq_dqb.dqb_curspace; | ||
| 1806 | dquot->dq_dqb.dqb_rsvspace += number; | ||
| 1807 | dquot->dq_dqb.dqb_curspace -= number; | ||
| 1808 | spin_unlock(&dquot->dq_dqb_lock); | ||
| 1809 | } | ||
| 1818 | } | 1810 | } |
| 1819 | /* Update inode bytes */ | 1811 | /* Update inode bytes */ |
| 1820 | inode_reclaim_rsv_space(inode, number); | 1812 | *inode_reserved_space(inode) += number; |
| 1821 | spin_unlock(&dq_data_lock); | 1813 | __inode_sub_bytes(inode, number); |
| 1814 | spin_unlock(&inode->i_lock); | ||
| 1822 | mark_all_dquot_dirty(dquots); | 1815 | mark_all_dquot_dirty(dquots); |
| 1823 | srcu_read_unlock(&dquot_srcu, index); | 1816 | srcu_read_unlock(&dquot_srcu, index); |
| 1824 | return; | 1817 | return; |
| @@ -1836,19 +1829,26 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags) | |||
| 1836 | int reserve = flags & DQUOT_SPACE_RESERVE, index; | 1829 | int reserve = flags & DQUOT_SPACE_RESERVE, index; |
| 1837 | 1830 | ||
| 1838 | if (!dquot_active(inode)) { | 1831 | if (!dquot_active(inode)) { |
| 1839 | inode_decr_space(inode, number, reserve); | 1832 | if (reserve) { |
| 1833 | spin_lock(&inode->i_lock); | ||
| 1834 | *inode_reserved_space(inode) -= number; | ||
| 1835 | spin_unlock(&inode->i_lock); | ||
| 1836 | } else { | ||
| 1837 | inode_sub_bytes(inode, number); | ||
| 1838 | } | ||
| 1840 | return; | 1839 | return; |
| 1841 | } | 1840 | } |
| 1842 | 1841 | ||
| 1843 | dquots = i_dquot(inode); | 1842 | dquots = i_dquot(inode); |
| 1844 | index = srcu_read_lock(&dquot_srcu); | 1843 | index = srcu_read_lock(&dquot_srcu); |
| 1845 | spin_lock(&dq_data_lock); | 1844 | spin_lock(&inode->i_lock); |
| 1846 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1845 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
| 1847 | int wtype; | 1846 | int wtype; |
| 1848 | 1847 | ||
| 1849 | warn[cnt].w_type = QUOTA_NL_NOWARN; | 1848 | warn[cnt].w_type = QUOTA_NL_NOWARN; |
| 1850 | if (!dquots[cnt]) | 1849 | if (!dquots[cnt]) |
| 1851 | continue; | 1850 | continue; |
| 1851 | spin_lock(&dquots[cnt]->dq_dqb_lock); | ||
| 1852 | wtype = info_bdq_free(dquots[cnt], number); | 1852 | wtype = info_bdq_free(dquots[cnt], number); |
| 1853 | if (wtype != QUOTA_NL_NOWARN) | 1853 | if (wtype != QUOTA_NL_NOWARN) |
| 1854 | prepare_warning(&warn[cnt], dquots[cnt], wtype); | 1854 | prepare_warning(&warn[cnt], dquots[cnt], wtype); |
| @@ -1856,9 +1856,13 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags) | |||
| 1856 | dquot_free_reserved_space(dquots[cnt], number); | 1856 | dquot_free_reserved_space(dquots[cnt], number); |
| 1857 | else | 1857 | else |
| 1858 | dquot_decr_space(dquots[cnt], number); | 1858 | dquot_decr_space(dquots[cnt], number); |
| 1859 | spin_unlock(&dquots[cnt]->dq_dqb_lock); | ||
| 1859 | } | 1860 | } |
| 1860 | inode_decr_space(inode, number, reserve); | 1861 | if (reserve) |
| 1861 | spin_unlock(&dq_data_lock); | 1862 | *inode_reserved_space(inode) -= number; |
| 1863 | else | ||
| 1864 | __inode_sub_bytes(inode, number); | ||
| 1865 | spin_unlock(&inode->i_lock); | ||
| 1862 | 1866 | ||
| 1863 | if (reserve) | 1867 | if (reserve) |
| 1864 | goto out_unlock; | 1868 | goto out_unlock; |
| @@ -1884,19 +1888,21 @@ void dquot_free_inode(struct inode *inode) | |||
| 1884 | 1888 | ||
| 1885 | dquots = i_dquot(inode); | 1889 | dquots = i_dquot(inode); |
| 1886 | index = srcu_read_lock(&dquot_srcu); | 1890 | index = srcu_read_lock(&dquot_srcu); |
| 1887 | spin_lock(&dq_data_lock); | 1891 | spin_lock(&inode->i_lock); |
| 1888 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1892 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
| 1889 | int wtype; | 1893 | int wtype; |
| 1890 | 1894 | ||
| 1891 | warn[cnt].w_type = QUOTA_NL_NOWARN; | 1895 | warn[cnt].w_type = QUOTA_NL_NOWARN; |
| 1892 | if (!dquots[cnt]) | 1896 | if (!dquots[cnt]) |
| 1893 | continue; | 1897 | continue; |
| 1898 | spin_lock(&dquots[cnt]->dq_dqb_lock); | ||
| 1894 | wtype = info_idq_free(dquots[cnt], 1); | 1899 | wtype = info_idq_free(dquots[cnt], 1); |
| 1895 | if (wtype != QUOTA_NL_NOWARN) | 1900 | if (wtype != QUOTA_NL_NOWARN) |
| 1896 | prepare_warning(&warn[cnt], dquots[cnt], wtype); | 1901 | prepare_warning(&warn[cnt], dquots[cnt], wtype); |
| 1897 | dquot_decr_inodes(dquots[cnt], 1); | 1902 | dquot_decr_inodes(dquots[cnt], 1); |
| 1903 | spin_unlock(&dquots[cnt]->dq_dqb_lock); | ||
| 1898 | } | 1904 | } |
| 1899 | spin_unlock(&dq_data_lock); | 1905 | spin_unlock(&inode->i_lock); |
| 1900 | mark_all_dquot_dirty(dquots); | 1906 | mark_all_dquot_dirty(dquots); |
| 1901 | srcu_read_unlock(&dquot_srcu, index); | 1907 | srcu_read_unlock(&dquot_srcu, index); |
| 1902 | flush_warnings(warn); | 1908 | flush_warnings(warn); |
| @@ -1917,7 +1923,7 @@ EXPORT_SYMBOL(dquot_free_inode); | |||
| 1917 | */ | 1923 | */ |
| 1918 | int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) | 1924 | int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) |
| 1919 | { | 1925 | { |
| 1920 | qsize_t space, cur_space; | 1926 | qsize_t cur_space; |
| 1921 | qsize_t rsv_space = 0; | 1927 | qsize_t rsv_space = 0; |
| 1922 | qsize_t inode_usage = 1; | 1928 | qsize_t inode_usage = 1; |
| 1923 | struct dquot *transfer_from[MAXQUOTAS] = {}; | 1929 | struct dquot *transfer_from[MAXQUOTAS] = {}; |
| @@ -1944,14 +1950,18 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) | |||
| 1944 | } | 1950 | } |
| 1945 | 1951 | ||
| 1946 | spin_lock(&dq_data_lock); | 1952 | spin_lock(&dq_data_lock); |
| 1953 | spin_lock(&inode->i_lock); | ||
| 1947 | if (IS_NOQUOTA(inode)) { /* File without quota accounting? */ | 1954 | if (IS_NOQUOTA(inode)) { /* File without quota accounting? */ |
| 1955 | spin_unlock(&inode->i_lock); | ||
| 1948 | spin_unlock(&dq_data_lock); | 1956 | spin_unlock(&dq_data_lock); |
| 1949 | return 0; | 1957 | return 0; |
| 1950 | } | 1958 | } |
| 1951 | cur_space = inode_get_bytes(inode); | 1959 | cur_space = __inode_get_bytes(inode); |
| 1952 | rsv_space = inode_get_rsv_space(inode); | 1960 | rsv_space = __inode_get_rsv_space(inode); |
| 1953 | space = cur_space + rsv_space; | 1961 | /* |
| 1954 | /* Build the transfer_from list and check the limits */ | 1962 | * Build the transfer_from list, check limits, and update usage in |
| 1963 | * the target structures. | ||
| 1964 | */ | ||
| 1955 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1965 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
| 1956 | /* | 1966 | /* |
| 1957 | * Skip changes for same uid or gid or for turned off quota-type. | 1967 | * Skip changes for same uid or gid or for turned off quota-type. |
| @@ -1963,28 +1973,33 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) | |||
| 1963 | continue; | 1973 | continue; |
| 1964 | is_valid[cnt] = 1; | 1974 | is_valid[cnt] = 1; |
| 1965 | transfer_from[cnt] = i_dquot(inode)[cnt]; | 1975 | transfer_from[cnt] = i_dquot(inode)[cnt]; |
| 1966 | ret = check_idq(transfer_to[cnt], inode_usage, &warn_to[cnt]); | 1976 | ret = dquot_add_inodes(transfer_to[cnt], inode_usage, |
| 1977 | &warn_to[cnt]); | ||
| 1967 | if (ret) | 1978 | if (ret) |
| 1968 | goto over_quota; | 1979 | goto over_quota; |
| 1969 | ret = check_bdq(transfer_to[cnt], space, 0, &warn_to[cnt]); | 1980 | ret = dquot_add_space(transfer_to[cnt], cur_space, rsv_space, 0, |
| 1970 | if (ret) | 1981 | &warn_to[cnt]); |
| 1982 | if (ret) { | ||
| 1983 | dquot_decr_inodes(transfer_to[cnt], inode_usage); | ||
| 1971 | goto over_quota; | 1984 | goto over_quota; |
| 1985 | } | ||
| 1972 | } | 1986 | } |
| 1973 | 1987 | ||
| 1974 | /* | 1988 | /* Decrease usage for source structures and update quota pointers */ |
| 1975 | * Finally perform the needed transfer from transfer_from to transfer_to | ||
| 1976 | */ | ||
| 1977 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 1989 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
| 1978 | if (!is_valid[cnt]) | 1990 | if (!is_valid[cnt]) |
| 1979 | continue; | 1991 | continue; |
| 1980 | /* Due to IO error we might not have transfer_from[] structure */ | 1992 | /* Due to IO error we might not have transfer_from[] structure */ |
| 1981 | if (transfer_from[cnt]) { | 1993 | if (transfer_from[cnt]) { |
| 1982 | int wtype; | 1994 | int wtype; |
| 1995 | |||
| 1996 | spin_lock(&transfer_from[cnt]->dq_dqb_lock); | ||
| 1983 | wtype = info_idq_free(transfer_from[cnt], inode_usage); | 1997 | wtype = info_idq_free(transfer_from[cnt], inode_usage); |
| 1984 | if (wtype != QUOTA_NL_NOWARN) | 1998 | if (wtype != QUOTA_NL_NOWARN) |
| 1985 | prepare_warning(&warn_from_inodes[cnt], | 1999 | prepare_warning(&warn_from_inodes[cnt], |
| 1986 | transfer_from[cnt], wtype); | 2000 | transfer_from[cnt], wtype); |
| 1987 | wtype = info_bdq_free(transfer_from[cnt], space); | 2001 | wtype = info_bdq_free(transfer_from[cnt], |
| 2002 | cur_space + rsv_space); | ||
| 1988 | if (wtype != QUOTA_NL_NOWARN) | 2003 | if (wtype != QUOTA_NL_NOWARN) |
| 1989 | prepare_warning(&warn_from_space[cnt], | 2004 | prepare_warning(&warn_from_space[cnt], |
| 1990 | transfer_from[cnt], wtype); | 2005 | transfer_from[cnt], wtype); |
| @@ -1992,14 +2007,11 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) | |||
| 1992 | dquot_decr_space(transfer_from[cnt], cur_space); | 2007 | dquot_decr_space(transfer_from[cnt], cur_space); |
| 1993 | dquot_free_reserved_space(transfer_from[cnt], | 2008 | dquot_free_reserved_space(transfer_from[cnt], |
| 1994 | rsv_space); | 2009 | rsv_space); |
| 2010 | spin_unlock(&transfer_from[cnt]->dq_dqb_lock); | ||
| 1995 | } | 2011 | } |
| 1996 | |||
| 1997 | dquot_incr_inodes(transfer_to[cnt], inode_usage); | ||
| 1998 | dquot_incr_space(transfer_to[cnt], cur_space); | ||
| 1999 | dquot_resv_space(transfer_to[cnt], rsv_space); | ||
| 2000 | |||
| 2001 | i_dquot(inode)[cnt] = transfer_to[cnt]; | 2012 | i_dquot(inode)[cnt] = transfer_to[cnt]; |
| 2002 | } | 2013 | } |
| 2014 | spin_unlock(&inode->i_lock); | ||
| 2003 | spin_unlock(&dq_data_lock); | 2015 | spin_unlock(&dq_data_lock); |
| 2004 | 2016 | ||
| 2005 | mark_all_dquot_dirty(transfer_from); | 2017 | mark_all_dquot_dirty(transfer_from); |
| @@ -2013,6 +2025,17 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to) | |||
| 2013 | transfer_to[cnt] = transfer_from[cnt]; | 2025 | transfer_to[cnt] = transfer_from[cnt]; |
| 2014 | return 0; | 2026 | return 0; |
| 2015 | over_quota: | 2027 | over_quota: |
| 2028 | /* Back out changes we already did */ | ||
| 2029 | for (cnt--; cnt >= 0; cnt--) { | ||
| 2030 | if (!is_valid[cnt]) | ||
| 2031 | continue; | ||
| 2032 | spin_lock(&transfer_to[cnt]->dq_dqb_lock); | ||
| 2033 | dquot_decr_inodes(transfer_to[cnt], inode_usage); | ||
| 2034 | dquot_decr_space(transfer_to[cnt], cur_space); | ||
| 2035 | dquot_free_reserved_space(transfer_to[cnt], rsv_space); | ||
| 2036 | spin_unlock(&transfer_to[cnt]->dq_dqb_lock); | ||
| 2037 | } | ||
| 2038 | spin_unlock(&inode->i_lock); | ||
| 2016 | spin_unlock(&dq_data_lock); | 2039 | spin_unlock(&dq_data_lock); |
| 2017 | flush_warnings(warn_to); | 2040 | flush_warnings(warn_to); |
| 2018 | return ret; | 2041 | return ret; |
| @@ -2066,29 +2089,21 @@ EXPORT_SYMBOL(dquot_transfer); | |||
| 2066 | */ | 2089 | */ |
| 2067 | int dquot_commit_info(struct super_block *sb, int type) | 2090 | int dquot_commit_info(struct super_block *sb, int type) |
| 2068 | { | 2091 | { |
| 2069 | int ret; | ||
| 2070 | struct quota_info *dqopt = sb_dqopt(sb); | 2092 | struct quota_info *dqopt = sb_dqopt(sb); |
| 2071 | 2093 | ||
| 2072 | mutex_lock(&dqopt->dqio_mutex); | 2094 | return dqopt->ops[type]->write_file_info(sb, type); |
| 2073 | ret = dqopt->ops[type]->write_file_info(sb, type); | ||
| 2074 | mutex_unlock(&dqopt->dqio_mutex); | ||
| 2075 | return ret; | ||
| 2076 | } | 2095 | } |
| 2077 | EXPORT_SYMBOL(dquot_commit_info); | 2096 | EXPORT_SYMBOL(dquot_commit_info); |
| 2078 | 2097 | ||
| 2079 | int dquot_get_next_id(struct super_block *sb, struct kqid *qid) | 2098 | int dquot_get_next_id(struct super_block *sb, struct kqid *qid) |
| 2080 | { | 2099 | { |
| 2081 | struct quota_info *dqopt = sb_dqopt(sb); | 2100 | struct quota_info *dqopt = sb_dqopt(sb); |
| 2082 | int err; | ||
| 2083 | 2101 | ||
| 2084 | if (!sb_has_quota_active(sb, qid->type)) | 2102 | if (!sb_has_quota_active(sb, qid->type)) |
| 2085 | return -ESRCH; | 2103 | return -ESRCH; |
| 2086 | if (!dqopt->ops[qid->type]->get_next_id) | 2104 | if (!dqopt->ops[qid->type]->get_next_id) |
| 2087 | return -ENOSYS; | 2105 | return -ENOSYS; |
| 2088 | mutex_lock(&dqopt->dqio_mutex); | 2106 | return dqopt->ops[qid->type]->get_next_id(sb, qid); |
| 2089 | err = dqopt->ops[qid->type]->get_next_id(sb, qid); | ||
| 2090 | mutex_unlock(&dqopt->dqio_mutex); | ||
| 2091 | return err; | ||
| 2092 | } | 2107 | } |
| 2093 | EXPORT_SYMBOL(dquot_get_next_id); | 2108 | EXPORT_SYMBOL(dquot_get_next_id); |
| 2094 | 2109 | ||
| @@ -2337,15 +2352,14 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
| 2337 | dqopt->info[type].dqi_format = fmt; | 2352 | dqopt->info[type].dqi_format = fmt; |
| 2338 | dqopt->info[type].dqi_fmt_id = format_id; | 2353 | dqopt->info[type].dqi_fmt_id = format_id; |
| 2339 | INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list); | 2354 | INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list); |
| 2340 | mutex_lock(&dqopt->dqio_mutex); | ||
| 2341 | error = dqopt->ops[type]->read_file_info(sb, type); | 2355 | error = dqopt->ops[type]->read_file_info(sb, type); |
| 2342 | if (error < 0) { | 2356 | if (error < 0) |
| 2343 | mutex_unlock(&dqopt->dqio_mutex); | ||
| 2344 | goto out_file_init; | 2357 | goto out_file_init; |
| 2345 | } | 2358 | if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) { |
| 2346 | if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) | 2359 | spin_lock(&dq_data_lock); |
| 2347 | dqopt->info[type].dqi_flags |= DQF_SYS_FILE; | 2360 | dqopt->info[type].dqi_flags |= DQF_SYS_FILE; |
| 2348 | mutex_unlock(&dqopt->dqio_mutex); | 2361 | spin_unlock(&dq_data_lock); |
| 2362 | } | ||
| 2349 | spin_lock(&dq_state_lock); | 2363 | spin_lock(&dq_state_lock); |
| 2350 | dqopt->flags |= dquot_state_flag(flags, type); | 2364 | dqopt->flags |= dquot_state_flag(flags, type); |
| 2351 | spin_unlock(&dq_state_lock); | 2365 | spin_unlock(&dq_state_lock); |
| @@ -2572,7 +2586,7 @@ static void do_get_dqblk(struct dquot *dquot, struct qc_dqblk *di) | |||
| 2572 | struct mem_dqblk *dm = &dquot->dq_dqb; | 2586 | struct mem_dqblk *dm = &dquot->dq_dqb; |
| 2573 | 2587 | ||
| 2574 | memset(di, 0, sizeof(*di)); | 2588 | memset(di, 0, sizeof(*di)); |
| 2575 | spin_lock(&dq_data_lock); | 2589 | spin_lock(&dquot->dq_dqb_lock); |
| 2576 | di->d_spc_hardlimit = dm->dqb_bhardlimit; | 2590 | di->d_spc_hardlimit = dm->dqb_bhardlimit; |
| 2577 | di->d_spc_softlimit = dm->dqb_bsoftlimit; | 2591 | di->d_spc_softlimit = dm->dqb_bsoftlimit; |
| 2578 | di->d_ino_hardlimit = dm->dqb_ihardlimit; | 2592 | di->d_ino_hardlimit = dm->dqb_ihardlimit; |
| @@ -2581,7 +2595,7 @@ static void do_get_dqblk(struct dquot *dquot, struct qc_dqblk *di) | |||
| 2581 | di->d_ino_count = dm->dqb_curinodes; | 2595 | di->d_ino_count = dm->dqb_curinodes; |
| 2582 | di->d_spc_timer = dm->dqb_btime; | 2596 | di->d_spc_timer = dm->dqb_btime; |
| 2583 | di->d_ino_timer = dm->dqb_itime; | 2597 | di->d_ino_timer = dm->dqb_itime; |
| 2584 | spin_unlock(&dq_data_lock); | 2598 | spin_unlock(&dquot->dq_dqb_lock); |
| 2585 | } | 2599 | } |
| 2586 | 2600 | ||
| 2587 | int dquot_get_dqblk(struct super_block *sb, struct kqid qid, | 2601 | int dquot_get_dqblk(struct super_block *sb, struct kqid qid, |
| @@ -2645,7 +2659,7 @@ static int do_set_dqblk(struct dquot *dquot, struct qc_dqblk *di) | |||
| 2645 | (di->d_ino_hardlimit > dqi->dqi_max_ino_limit))) | 2659 | (di->d_ino_hardlimit > dqi->dqi_max_ino_limit))) |
| 2646 | return -ERANGE; | 2660 | return -ERANGE; |
| 2647 | 2661 | ||
| 2648 | spin_lock(&dq_data_lock); | 2662 | spin_lock(&dquot->dq_dqb_lock); |
| 2649 | if (di->d_fieldmask & QC_SPACE) { | 2663 | if (di->d_fieldmask & QC_SPACE) { |
| 2650 | dm->dqb_curspace = di->d_space - dm->dqb_rsvspace; | 2664 | dm->dqb_curspace = di->d_space - dm->dqb_rsvspace; |
| 2651 | check_blim = 1; | 2665 | check_blim = 1; |
| @@ -2711,7 +2725,7 @@ static int do_set_dqblk(struct dquot *dquot, struct qc_dqblk *di) | |||
| 2711 | clear_bit(DQ_FAKE_B, &dquot->dq_flags); | 2725 | clear_bit(DQ_FAKE_B, &dquot->dq_flags); |
| 2712 | else | 2726 | else |
| 2713 | set_bit(DQ_FAKE_B, &dquot->dq_flags); | 2727 | set_bit(DQ_FAKE_B, &dquot->dq_flags); |
| 2714 | spin_unlock(&dq_data_lock); | 2728 | spin_unlock(&dquot->dq_dqb_lock); |
| 2715 | mark_dquot_dirty(dquot); | 2729 | mark_dquot_dirty(dquot); |
| 2716 | 2730 | ||
| 2717 | return 0; | 2731 | return 0; |
diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c index 0738972e8d3f..bb3f59bcfcf5 100644 --- a/fs/quota/quota_tree.c +++ b/fs/quota/quota_tree.c | |||
| @@ -379,7 +379,7 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) | |||
| 379 | if (!ddquot) | 379 | if (!ddquot) |
| 380 | return -ENOMEM; | 380 | return -ENOMEM; |
| 381 | 381 | ||
| 382 | /* dq_off is guarded by dqio_mutex */ | 382 | /* dq_off is guarded by dqio_sem */ |
| 383 | if (!dquot->dq_off) { | 383 | if (!dquot->dq_off) { |
| 384 | ret = dq_insert_tree(info, dquot); | 384 | ret = dq_insert_tree(info, dquot); |
| 385 | if (ret < 0) { | 385 | if (ret < 0) { |
| @@ -389,9 +389,9 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) | |||
| 389 | return ret; | 389 | return ret; |
| 390 | } | 390 | } |
| 391 | } | 391 | } |
| 392 | spin_lock(&dq_data_lock); | 392 | spin_lock(&dquot->dq_dqb_lock); |
| 393 | info->dqi_ops->mem2disk_dqblk(ddquot, dquot); | 393 | info->dqi_ops->mem2disk_dqblk(ddquot, dquot); |
| 394 | spin_unlock(&dq_data_lock); | 394 | spin_unlock(&dquot->dq_dqb_lock); |
| 395 | ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size, | 395 | ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size, |
| 396 | dquot->dq_off); | 396 | dquot->dq_off); |
| 397 | if (ret != info->dqi_entry_size) { | 397 | if (ret != info->dqi_entry_size) { |
| @@ -649,14 +649,14 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) | |||
| 649 | kfree(ddquot); | 649 | kfree(ddquot); |
| 650 | goto out; | 650 | goto out; |
| 651 | } | 651 | } |
| 652 | spin_lock(&dq_data_lock); | 652 | spin_lock(&dquot->dq_dqb_lock); |
| 653 | info->dqi_ops->disk2mem_dqblk(dquot, ddquot); | 653 | info->dqi_ops->disk2mem_dqblk(dquot, ddquot); |
| 654 | if (!dquot->dq_dqb.dqb_bhardlimit && | 654 | if (!dquot->dq_dqb.dqb_bhardlimit && |
| 655 | !dquot->dq_dqb.dqb_bsoftlimit && | 655 | !dquot->dq_dqb.dqb_bsoftlimit && |
| 656 | !dquot->dq_dqb.dqb_ihardlimit && | 656 | !dquot->dq_dqb.dqb_ihardlimit && |
| 657 | !dquot->dq_dqb.dqb_isoftlimit) | 657 | !dquot->dq_dqb.dqb_isoftlimit) |
| 658 | set_bit(DQ_FAKE_B, &dquot->dq_flags); | 658 | set_bit(DQ_FAKE_B, &dquot->dq_flags); |
| 659 | spin_unlock(&dq_data_lock); | 659 | spin_unlock(&dquot->dq_dqb_lock); |
| 660 | kfree(ddquot); | 660 | kfree(ddquot); |
| 661 | out: | 661 | out: |
| 662 | dqstats_inc(DQST_READS); | 662 | dqstats_inc(DQST_READS); |
diff --git a/fs/quota/quota_v1.c b/fs/quota/quota_v1.c index 8fe79beced5c..7ac5298aba70 100644 --- a/fs/quota/quota_v1.c +++ b/fs/quota/quota_v1.c | |||
| @@ -56,8 +56,9 @@ static int v1_read_dqblk(struct dquot *dquot) | |||
| 56 | { | 56 | { |
| 57 | int type = dquot->dq_id.type; | 57 | int type = dquot->dq_id.type; |
| 58 | struct v1_disk_dqblk dqblk; | 58 | struct v1_disk_dqblk dqblk; |
| 59 | struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); | ||
| 59 | 60 | ||
| 60 | if (!sb_dqopt(dquot->dq_sb)->files[type]) | 61 | if (!dqopt->files[type]) |
| 61 | return -EINVAL; | 62 | return -EINVAL; |
| 62 | 63 | ||
| 63 | /* Set structure to 0s in case read fails/is after end of file */ | 64 | /* Set structure to 0s in case read fails/is after end of file */ |
| @@ -160,6 +161,7 @@ static int v1_read_file_info(struct super_block *sb, int type) | |||
| 160 | struct v1_disk_dqblk dqblk; | 161 | struct v1_disk_dqblk dqblk; |
| 161 | int ret; | 162 | int ret; |
| 162 | 163 | ||
| 164 | down_read(&dqopt->dqio_sem); | ||
| 163 | ret = sb->s_op->quota_read(sb, type, (char *)&dqblk, | 165 | ret = sb->s_op->quota_read(sb, type, (char *)&dqblk, |
| 164 | sizeof(struct v1_disk_dqblk), v1_dqoff(0)); | 166 | sizeof(struct v1_disk_dqblk), v1_dqoff(0)); |
| 165 | if (ret != sizeof(struct v1_disk_dqblk)) { | 167 | if (ret != sizeof(struct v1_disk_dqblk)) { |
| @@ -176,6 +178,7 @@ static int v1_read_file_info(struct super_block *sb, int type) | |||
| 176 | dqopt->info[type].dqi_bgrace = | 178 | dqopt->info[type].dqi_bgrace = |
| 177 | dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME; | 179 | dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME; |
| 178 | out: | 180 | out: |
| 181 | up_read(&dqopt->dqio_sem); | ||
| 179 | return ret; | 182 | return ret; |
| 180 | } | 183 | } |
| 181 | 184 | ||
| @@ -185,7 +188,7 @@ static int v1_write_file_info(struct super_block *sb, int type) | |||
| 185 | struct v1_disk_dqblk dqblk; | 188 | struct v1_disk_dqblk dqblk; |
| 186 | int ret; | 189 | int ret; |
| 187 | 190 | ||
| 188 | dqopt->info[type].dqi_flags &= ~DQF_INFO_DIRTY; | 191 | down_write(&dqopt->dqio_sem); |
| 189 | ret = sb->s_op->quota_read(sb, type, (char *)&dqblk, | 192 | ret = sb->s_op->quota_read(sb, type, (char *)&dqblk, |
| 190 | sizeof(struct v1_disk_dqblk), v1_dqoff(0)); | 193 | sizeof(struct v1_disk_dqblk), v1_dqoff(0)); |
| 191 | if (ret != sizeof(struct v1_disk_dqblk)) { | 194 | if (ret != sizeof(struct v1_disk_dqblk)) { |
| @@ -193,8 +196,11 @@ static int v1_write_file_info(struct super_block *sb, int type) | |||
| 193 | ret = -EIO; | 196 | ret = -EIO; |
| 194 | goto out; | 197 | goto out; |
| 195 | } | 198 | } |
| 199 | spin_lock(&dq_data_lock); | ||
| 200 | dqopt->info[type].dqi_flags &= ~DQF_INFO_DIRTY; | ||
| 196 | dqblk.dqb_itime = dqopt->info[type].dqi_igrace; | 201 | dqblk.dqb_itime = dqopt->info[type].dqi_igrace; |
| 197 | dqblk.dqb_btime = dqopt->info[type].dqi_bgrace; | 202 | dqblk.dqb_btime = dqopt->info[type].dqi_bgrace; |
| 203 | spin_unlock(&dq_data_lock); | ||
| 198 | ret = sb->s_op->quota_write(sb, type, (char *)&dqblk, | 204 | ret = sb->s_op->quota_write(sb, type, (char *)&dqblk, |
| 199 | sizeof(struct v1_disk_dqblk), v1_dqoff(0)); | 205 | sizeof(struct v1_disk_dqblk), v1_dqoff(0)); |
| 200 | if (ret == sizeof(struct v1_disk_dqblk)) | 206 | if (ret == sizeof(struct v1_disk_dqblk)) |
| @@ -202,6 +208,7 @@ static int v1_write_file_info(struct super_block *sb, int type) | |||
| 202 | else if (ret > 0) | 208 | else if (ret > 0) |
| 203 | ret = -EIO; | 209 | ret = -EIO; |
| 204 | out: | 210 | out: |
| 211 | up_write(&dqopt->dqio_sem); | ||
| 205 | return ret; | 212 | return ret; |
| 206 | } | 213 | } |
| 207 | 214 | ||
diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c index 2259329616b7..c0187cda2c1e 100644 --- a/fs/quota/quota_v2.c +++ b/fs/quota/quota_v2.c | |||
| @@ -65,9 +65,11 @@ static int v2_read_header(struct super_block *sb, int type, | |||
| 65 | if (size != sizeof(struct v2_disk_dqheader)) { | 65 | if (size != sizeof(struct v2_disk_dqheader)) { |
| 66 | quota_error(sb, "Failed header read: expected=%zd got=%zd", | 66 | quota_error(sb, "Failed header read: expected=%zd got=%zd", |
| 67 | sizeof(struct v2_disk_dqheader), size); | 67 | sizeof(struct v2_disk_dqheader), size); |
| 68 | return 0; | 68 | if (size < 0) |
| 69 | return size; | ||
| 70 | return -EIO; | ||
| 69 | } | 71 | } |
| 70 | return 1; | 72 | return 0; |
| 71 | } | 73 | } |
| 72 | 74 | ||
| 73 | /* Check whether given file is really vfsv0 quotafile */ | 75 | /* Check whether given file is really vfsv0 quotafile */ |
| @@ -77,7 +79,7 @@ static int v2_check_quota_file(struct super_block *sb, int type) | |||
| 77 | static const uint quota_magics[] = V2_INITQMAGICS; | 79 | static const uint quota_magics[] = V2_INITQMAGICS; |
| 78 | static const uint quota_versions[] = V2_INITQVERSIONS; | 80 | static const uint quota_versions[] = V2_INITQVERSIONS; |
| 79 | 81 | ||
| 80 | if (!v2_read_header(sb, type, &dqhead)) | 82 | if (v2_read_header(sb, type, &dqhead)) |
| 81 | return 0; | 83 | return 0; |
| 82 | if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] || | 84 | if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] || |
| 83 | le32_to_cpu(dqhead.dqh_version) > quota_versions[type]) | 85 | le32_to_cpu(dqhead.dqh_version) > quota_versions[type]) |
| @@ -90,28 +92,39 @@ static int v2_read_file_info(struct super_block *sb, int type) | |||
| 90 | { | 92 | { |
| 91 | struct v2_disk_dqinfo dinfo; | 93 | struct v2_disk_dqinfo dinfo; |
| 92 | struct v2_disk_dqheader dqhead; | 94 | struct v2_disk_dqheader dqhead; |
| 93 | struct mem_dqinfo *info = sb_dqinfo(sb, type); | 95 | struct quota_info *dqopt = sb_dqopt(sb); |
| 96 | struct mem_dqinfo *info = &dqopt->info[type]; | ||
| 94 | struct qtree_mem_dqinfo *qinfo; | 97 | struct qtree_mem_dqinfo *qinfo; |
| 95 | ssize_t size; | 98 | ssize_t size; |
| 96 | unsigned int version; | 99 | unsigned int version; |
| 100 | int ret; | ||
| 97 | 101 | ||
| 98 | if (!v2_read_header(sb, type, &dqhead)) | 102 | down_read(&dqopt->dqio_sem); |
| 99 | return -1; | 103 | ret = v2_read_header(sb, type, &dqhead); |
| 104 | if (ret < 0) | ||
| 105 | goto out; | ||
| 100 | version = le32_to_cpu(dqhead.dqh_version); | 106 | version = le32_to_cpu(dqhead.dqh_version); |
| 101 | if ((info->dqi_fmt_id == QFMT_VFS_V0 && version != 0) || | 107 | if ((info->dqi_fmt_id == QFMT_VFS_V0 && version != 0) || |
| 102 | (info->dqi_fmt_id == QFMT_VFS_V1 && version != 1)) | 108 | (info->dqi_fmt_id == QFMT_VFS_V1 && version != 1)) { |
| 103 | return -1; | 109 | ret = -EINVAL; |
| 110 | goto out; | ||
| 111 | } | ||
| 104 | 112 | ||
| 105 | size = sb->s_op->quota_read(sb, type, (char *)&dinfo, | 113 | size = sb->s_op->quota_read(sb, type, (char *)&dinfo, |
| 106 | sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); | 114 | sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); |
| 107 | if (size != sizeof(struct v2_disk_dqinfo)) { | 115 | if (size != sizeof(struct v2_disk_dqinfo)) { |
| 108 | quota_error(sb, "Can't read info structure"); | 116 | quota_error(sb, "Can't read info structure"); |
| 109 | return -1; | 117 | if (size < 0) |
| 118 | ret = size; | ||
| 119 | else | ||
| 120 | ret = -EIO; | ||
| 121 | goto out; | ||
| 110 | } | 122 | } |
| 111 | info->dqi_priv = kmalloc(sizeof(struct qtree_mem_dqinfo), GFP_NOFS); | 123 | info->dqi_priv = kmalloc(sizeof(struct qtree_mem_dqinfo), GFP_NOFS); |
| 112 | if (!info->dqi_priv) | 124 | if (!info->dqi_priv) { |
| 113 | return -ENOMEM; | 125 | ret = -ENOMEM; |
| 114 | 126 | goto out; | |
| 127 | } | ||
| 115 | qinfo = info->dqi_priv; | 128 | qinfo = info->dqi_priv; |
| 116 | if (version == 0) { | 129 | if (version == 0) { |
| 117 | /* limits are stored as unsigned 32-bit data */ | 130 | /* limits are stored as unsigned 32-bit data */ |
| @@ -145,17 +158,22 @@ static int v2_read_file_info(struct super_block *sb, int type) | |||
| 145 | qinfo->dqi_entry_size = sizeof(struct v2r1_disk_dqblk); | 158 | qinfo->dqi_entry_size = sizeof(struct v2r1_disk_dqblk); |
| 146 | qinfo->dqi_ops = &v2r1_qtree_ops; | 159 | qinfo->dqi_ops = &v2r1_qtree_ops; |
| 147 | } | 160 | } |
| 148 | return 0; | 161 | ret = 0; |
| 162 | out: | ||
| 163 | up_read(&dqopt->dqio_sem); | ||
| 164 | return ret; | ||
| 149 | } | 165 | } |
| 150 | 166 | ||
| 151 | /* Write information header to quota file */ | 167 | /* Write information header to quota file */ |
| 152 | static int v2_write_file_info(struct super_block *sb, int type) | 168 | static int v2_write_file_info(struct super_block *sb, int type) |
| 153 | { | 169 | { |
| 154 | struct v2_disk_dqinfo dinfo; | 170 | struct v2_disk_dqinfo dinfo; |
| 155 | struct mem_dqinfo *info = sb_dqinfo(sb, type); | 171 | struct quota_info *dqopt = sb_dqopt(sb); |
| 172 | struct mem_dqinfo *info = &dqopt->info[type]; | ||
| 156 | struct qtree_mem_dqinfo *qinfo = info->dqi_priv; | 173 | struct qtree_mem_dqinfo *qinfo = info->dqi_priv; |
| 157 | ssize_t size; | 174 | ssize_t size; |
| 158 | 175 | ||
| 176 | down_write(&dqopt->dqio_sem); | ||
| 159 | spin_lock(&dq_data_lock); | 177 | spin_lock(&dq_data_lock); |
| 160 | info->dqi_flags &= ~DQF_INFO_DIRTY; | 178 | info->dqi_flags &= ~DQF_INFO_DIRTY; |
| 161 | dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace); | 179 | dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace); |
| @@ -168,6 +186,7 @@ static int v2_write_file_info(struct super_block *sb, int type) | |||
| 168 | dinfo.dqi_free_entry = cpu_to_le32(qinfo->dqi_free_entry); | 186 | dinfo.dqi_free_entry = cpu_to_le32(qinfo->dqi_free_entry); |
| 169 | size = sb->s_op->quota_write(sb, type, (char *)&dinfo, | 187 | size = sb->s_op->quota_write(sb, type, (char *)&dinfo, |
| 170 | sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); | 188 | sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); |
| 189 | up_write(&dqopt->dqio_sem); | ||
| 171 | if (size != sizeof(struct v2_disk_dqinfo)) { | 190 | if (size != sizeof(struct v2_disk_dqinfo)) { |
| 172 | quota_error(sb, "Can't write info structure"); | 191 | quota_error(sb, "Can't write info structure"); |
| 173 | return -1; | 192 | return -1; |
| @@ -283,17 +302,51 @@ static int v2r1_is_id(void *dp, struct dquot *dquot) | |||
| 283 | 302 | ||
| 284 | static int v2_read_dquot(struct dquot *dquot) | 303 | static int v2_read_dquot(struct dquot *dquot) |
| 285 | { | 304 | { |
| 286 | return qtree_read_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, dquot); | 305 | struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); |
| 306 | int ret; | ||
| 307 | |||
| 308 | down_read(&dqopt->dqio_sem); | ||
| 309 | ret = qtree_read_dquot( | ||
| 310 | sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, | ||
| 311 | dquot); | ||
| 312 | up_read(&dqopt->dqio_sem); | ||
| 313 | return ret; | ||
| 287 | } | 314 | } |
| 288 | 315 | ||
| 289 | static int v2_write_dquot(struct dquot *dquot) | 316 | static int v2_write_dquot(struct dquot *dquot) |
| 290 | { | 317 | { |
| 291 | return qtree_write_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, dquot); | 318 | struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); |
| 319 | int ret; | ||
| 320 | bool alloc = false; | ||
| 321 | |||
| 322 | /* | ||
| 323 | * If space for dquot is already allocated, we don't need any | ||
| 324 | * protection as we'll only overwrite the place of dquot. We are | ||
| 325 | * still protected by concurrent writes of the same dquot by | ||
| 326 | * dquot->dq_lock. | ||
| 327 | */ | ||
| 328 | if (!dquot->dq_off) { | ||
| 329 | alloc = true; | ||
| 330 | down_write(&dqopt->dqio_sem); | ||
| 331 | } | ||
| 332 | ret = qtree_write_dquot( | ||
| 333 | sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, | ||
| 334 | dquot); | ||
| 335 | if (alloc) | ||
| 336 | up_write(&dqopt->dqio_sem); | ||
| 337 | return ret; | ||
| 292 | } | 338 | } |
| 293 | 339 | ||
| 294 | static int v2_release_dquot(struct dquot *dquot) | 340 | static int v2_release_dquot(struct dquot *dquot) |
| 295 | { | 341 | { |
| 296 | return qtree_release_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, dquot); | 342 | struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); |
| 343 | int ret; | ||
| 344 | |||
| 345 | down_write(&dqopt->dqio_sem); | ||
| 346 | ret = qtree_release_dquot(sb_dqinfo(dquot->dq_sb, dquot->dq_id.type)->dqi_priv, dquot); | ||
| 347 | up_write(&dqopt->dqio_sem); | ||
| 348 | |||
| 349 | return ret; | ||
| 297 | } | 350 | } |
| 298 | 351 | ||
| 299 | static int v2_free_file_info(struct super_block *sb, int type) | 352 | static int v2_free_file_info(struct super_block *sb, int type) |
| @@ -304,7 +357,13 @@ static int v2_free_file_info(struct super_block *sb, int type) | |||
| 304 | 357 | ||
| 305 | static int v2_get_next_id(struct super_block *sb, struct kqid *qid) | 358 | static int v2_get_next_id(struct super_block *sb, struct kqid *qid) |
| 306 | { | 359 | { |
| 307 | return qtree_get_next_id(sb_dqinfo(sb, qid->type)->dqi_priv, qid); | 360 | struct quota_info *dqopt = sb_dqopt(sb); |
| 361 | int ret; | ||
| 362 | |||
| 363 | down_read(&dqopt->dqio_sem); | ||
| 364 | ret = qtree_get_next_id(sb_dqinfo(sb, qid->type)->dqi_priv, qid); | ||
| 365 | up_read(&dqopt->dqio_sem); | ||
| 366 | return ret; | ||
| 308 | } | 367 | } |
| 309 | 368 | ||
| 310 | static const struct quota_format_ops v2_format_ops = { | 369 | static const struct quota_format_ops v2_format_ops = { |
| @@ -710,7 +710,7 @@ loff_t inode_get_bytes(struct inode *inode) | |||
| 710 | loff_t ret; | 710 | loff_t ret; |
| 711 | 711 | ||
| 712 | spin_lock(&inode->i_lock); | 712 | spin_lock(&inode->i_lock); |
| 713 | ret = (((loff_t)inode->i_blocks) << 9) + inode->i_bytes; | 713 | ret = __inode_get_bytes(inode); |
| 714 | spin_unlock(&inode->i_lock); | 714 | spin_unlock(&inode->i_lock); |
| 715 | return ret; | 715 | return ret; |
| 716 | } | 716 | } |
diff --git a/fs/super.c b/fs/super.c index 6bc3352adcf3..221cfa1f4e92 100644 --- a/fs/super.c +++ b/fs/super.c | |||
| @@ -242,7 +242,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags, | |||
| 242 | atomic_set(&s->s_active, 1); | 242 | atomic_set(&s->s_active, 1); |
| 243 | mutex_init(&s->s_vfs_rename_mutex); | 243 | mutex_init(&s->s_vfs_rename_mutex); |
| 244 | lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key); | 244 | lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key); |
| 245 | mutex_init(&s->s_dquot.dqio_mutex); | 245 | init_rwsem(&s->s_dquot.dqio_sem); |
| 246 | s->s_maxbytes = MAX_NON_LFS; | 246 | s->s_maxbytes = MAX_NON_LFS; |
| 247 | s->s_op = &default_op; | 247 | s->s_op = &default_op; |
| 248 | s->s_time_gran = 1000000000; | 248 | s->s_time_gran = 1000000000; |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 7d6079dceb39..509434aaf5a4 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -3015,6 +3015,10 @@ void __inode_add_bytes(struct inode *inode, loff_t bytes); | |||
| 3015 | void inode_add_bytes(struct inode *inode, loff_t bytes); | 3015 | void inode_add_bytes(struct inode *inode, loff_t bytes); |
| 3016 | void __inode_sub_bytes(struct inode *inode, loff_t bytes); | 3016 | void __inode_sub_bytes(struct inode *inode, loff_t bytes); |
| 3017 | void inode_sub_bytes(struct inode *inode, loff_t bytes); | 3017 | void inode_sub_bytes(struct inode *inode, loff_t bytes); |
| 3018 | static inline loff_t __inode_get_bytes(struct inode *inode) | ||
| 3019 | { | ||
| 3020 | return (((loff_t)inode->i_blocks) << 9) + inode->i_bytes; | ||
| 3021 | } | ||
| 3018 | loff_t inode_get_bytes(struct inode *inode); | 3022 | loff_t inode_get_bytes(struct inode *inode); |
| 3019 | void inode_set_bytes(struct inode *inode, loff_t bytes); | 3023 | void inode_set_bytes(struct inode *inode, loff_t bytes); |
| 3020 | const char *simple_get_link(struct dentry *, struct inode *, | 3024 | const char *simple_get_link(struct dentry *, struct inode *, |
diff --git a/include/linux/quota.h b/include/linux/quota.h index bfd077ca6ac3..5ac9de4fcd6f 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h | |||
| @@ -223,12 +223,12 @@ struct mem_dqinfo { | |||
| 223 | struct quota_format_type *dqi_format; | 223 | struct quota_format_type *dqi_format; |
| 224 | int dqi_fmt_id; /* Id of the dqi_format - used when turning | 224 | int dqi_fmt_id; /* Id of the dqi_format - used when turning |
| 225 | * quotas on after remount RW */ | 225 | * quotas on after remount RW */ |
| 226 | struct list_head dqi_dirty_list; /* List of dirty dquots */ | 226 | struct list_head dqi_dirty_list; /* List of dirty dquots [dq_list_lock] */ |
| 227 | unsigned long dqi_flags; | 227 | unsigned long dqi_flags; /* DFQ_ flags [dq_data_lock] */ |
| 228 | unsigned int dqi_bgrace; | 228 | unsigned int dqi_bgrace; /* Space grace time [dq_data_lock] */ |
| 229 | unsigned int dqi_igrace; | 229 | unsigned int dqi_igrace; /* Inode grace time [dq_data_lock] */ |
| 230 | qsize_t dqi_max_spc_limit; | 230 | qsize_t dqi_max_spc_limit; /* Maximum space limit [static] */ |
| 231 | qsize_t dqi_max_ino_limit; | 231 | qsize_t dqi_max_ino_limit; /* Maximum inode limit [static] */ |
| 232 | void *dqi_priv; | 232 | void *dqi_priv; |
| 233 | }; | 233 | }; |
| 234 | 234 | ||
| @@ -293,18 +293,18 @@ static inline void dqstats_dec(unsigned int type) | |||
| 293 | * clear them when it sees fit. */ | 293 | * clear them when it sees fit. */ |
| 294 | 294 | ||
| 295 | struct dquot { | 295 | struct dquot { |
| 296 | struct hlist_node dq_hash; /* Hash list in memory */ | 296 | struct hlist_node dq_hash; /* Hash list in memory [dq_list_lock] */ |
| 297 | struct list_head dq_inuse; /* List of all quotas */ | 297 | struct list_head dq_inuse; /* List of all quotas [dq_list_lock] */ |
| 298 | struct list_head dq_free; /* Free list element */ | 298 | struct list_head dq_free; /* Free list element [dq_list_lock] */ |
| 299 | struct list_head dq_dirty; /* List of dirty dquots */ | 299 | struct list_head dq_dirty; /* List of dirty dquots [dq_list_lock] */ |
| 300 | struct mutex dq_lock; /* dquot IO lock */ | 300 | struct mutex dq_lock; /* dquot IO lock */ |
| 301 | spinlock_t dq_dqb_lock; /* Lock protecting dq_dqb changes */ | ||
| 301 | atomic_t dq_count; /* Use count */ | 302 | atomic_t dq_count; /* Use count */ |
| 302 | wait_queue_head_t dq_wait_unused; /* Wait queue for dquot to become unused */ | ||
| 303 | struct super_block *dq_sb; /* superblock this applies to */ | 303 | struct super_block *dq_sb; /* superblock this applies to */ |
| 304 | struct kqid dq_id; /* ID this applies to (uid, gid, projid) */ | 304 | struct kqid dq_id; /* ID this applies to (uid, gid, projid) */ |
| 305 | loff_t dq_off; /* Offset of dquot on disk */ | 305 | loff_t dq_off; /* Offset of dquot on disk [dq_lock, stable once set] */ |
| 306 | unsigned long dq_flags; /* See DQ_* */ | 306 | unsigned long dq_flags; /* See DQ_* */ |
| 307 | struct mem_dqblk dq_dqb; /* Diskquota usage */ | 307 | struct mem_dqblk dq_dqb; /* Diskquota usage [dq_dqb_lock] */ |
| 308 | }; | 308 | }; |
| 309 | 309 | ||
| 310 | /* Operations which must be implemented by each quota format */ | 310 | /* Operations which must be implemented by each quota format */ |
| @@ -491,6 +491,9 @@ enum { | |||
| 491 | */ | 491 | */ |
| 492 | #define DQUOT_NEGATIVE_USAGE (1 << (DQUOT_STATE_LAST + 1)) | 492 | #define DQUOT_NEGATIVE_USAGE (1 << (DQUOT_STATE_LAST + 1)) |
| 493 | /* Allow negative quota usage */ | 493 | /* Allow negative quota usage */ |
| 494 | /* Do not track dirty dquots in a list */ | ||
| 495 | #define DQUOT_NOLIST_DIRTY (1 << (DQUOT_STATE_LAST + 2)) | ||
| 496 | |||
| 494 | static inline unsigned int dquot_state_flag(unsigned int flags, int type) | 497 | static inline unsigned int dquot_state_flag(unsigned int flags, int type) |
| 495 | { | 498 | { |
| 496 | return flags << type; | 499 | return flags << type; |
| @@ -521,7 +524,7 @@ static inline void quota_send_warning(struct kqid qid, dev_t dev, | |||
| 521 | 524 | ||
| 522 | struct quota_info { | 525 | struct quota_info { |
| 523 | unsigned int flags; /* Flags for diskquotas on this device */ | 526 | unsigned int flags; /* Flags for diskquotas on this device */ |
| 524 | struct mutex dqio_mutex; /* lock device while I/O in progress */ | 527 | struct rw_semaphore dqio_sem; /* Lock quota file while I/O in progress */ |
| 525 | struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */ | 528 | struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */ |
| 526 | struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ | 529 | struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ |
| 527 | const struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ | 530 | const struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ |
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index dda22f45fc1b..0ce6fc49962e 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h | |||
| @@ -38,11 +38,6 @@ void __quota_error(struct super_block *sb, const char *func, | |||
| 38 | /* | 38 | /* |
| 39 | * declaration of quota_function calls in kernel. | 39 | * declaration of quota_function calls in kernel. |
| 40 | */ | 40 | */ |
| 41 | void inode_add_rsv_space(struct inode *inode, qsize_t number); | ||
| 42 | void inode_claim_rsv_space(struct inode *inode, qsize_t number); | ||
| 43 | void inode_sub_rsv_space(struct inode *inode, qsize_t number); | ||
| 44 | void inode_reclaim_rsv_space(struct inode *inode, qsize_t number); | ||
| 45 | |||
| 46 | int dquot_initialize(struct inode *inode); | 41 | int dquot_initialize(struct inode *inode); |
| 47 | bool dquot_initialize_needed(struct inode *inode); | 42 | bool dquot_initialize_needed(struct inode *inode); |
| 48 | void dquot_drop(struct inode *inode); | 43 | void dquot_drop(struct inode *inode); |
