diff options
author | Eric Sandeen <sandeen@redhat.com> | 2008-10-28 00:08:17 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2008-10-28 00:08:17 -0400 |
commit | a996031c87e093017c0763326a08896a3a4817f4 (patch) | |
tree | 74550b7108b1b1fd87393801de56bd9e1e8b1012 /fs/ext4 | |
parent | 8c3bf8a01c005385e9be0bc992e10abfb355278c (diff) |
delay capable() check in ext4_has_free_blocks()
As reported by Eric Paris, the capable() check in ext4_has_free_blocks()
sometimes causes SELinux denials.
We can rearrange the logic so that we only try to use the root-reserved
blocks when necessary, and even then we can move the capable() test
to last, to avoid the check most of the time.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/balloc.c | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index e28203ec45bd..d2003cdc36aa 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -599,18 +599,13 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, | |||
599 | */ | 599 | */ |
600 | int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks) | 600 | int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks) |
601 | { | 601 | { |
602 | s64 free_blocks, dirty_blocks; | 602 | s64 free_blocks, dirty_blocks, root_blocks; |
603 | s64 root_blocks = 0; | ||
604 | struct percpu_counter *fbc = &sbi->s_freeblocks_counter; | 603 | struct percpu_counter *fbc = &sbi->s_freeblocks_counter; |
605 | struct percpu_counter *dbc = &sbi->s_dirtyblocks_counter; | 604 | struct percpu_counter *dbc = &sbi->s_dirtyblocks_counter; |
606 | 605 | ||
607 | free_blocks = percpu_counter_read_positive(fbc); | 606 | free_blocks = percpu_counter_read_positive(fbc); |
608 | dirty_blocks = percpu_counter_read_positive(dbc); | 607 | dirty_blocks = percpu_counter_read_positive(dbc); |
609 | 608 | root_blocks = ext4_r_blocks_count(sbi->s_es); | |
610 | if (!capable(CAP_SYS_RESOURCE) && | ||
611 | sbi->s_resuid != current->fsuid && | ||
612 | (sbi->s_resgid == 0 || !in_group_p(sbi->s_resgid))) | ||
613 | root_blocks = ext4_r_blocks_count(sbi->s_es); | ||
614 | 609 | ||
615 | if (free_blocks - (nblocks + root_blocks + dirty_blocks) < | 610 | if (free_blocks - (nblocks + root_blocks + dirty_blocks) < |
616 | EXT4_FREEBLOCKS_WATERMARK) { | 611 | EXT4_FREEBLOCKS_WATERMARK) { |
@@ -623,13 +618,20 @@ int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks) | |||
623 | } | 618 | } |
624 | } | 619 | } |
625 | /* Check whether we have space after | 620 | /* Check whether we have space after |
626 | * accounting for current dirty blocks | 621 | * accounting for current dirty blocks & root reserved blocks. |
627 | */ | 622 | */ |
628 | if (free_blocks < ((root_blocks + nblocks) + dirty_blocks)) | 623 | if (free_blocks >= ((root_blocks + nblocks) + dirty_blocks)) |
629 | /* we don't have free space */ | 624 | return 1; |
630 | return 0; | ||
631 | 625 | ||
632 | return 1; | 626 | /* Hm, nope. Are (enough) root reserved blocks available? */ |
627 | if (sbi->s_resuid == current->fsuid || | ||
628 | ((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) || | ||
629 | capable(CAP_SYS_RESOURCE)) { | ||
630 | if (free_blocks >= (nblocks + dirty_blocks)) | ||
631 | return 1; | ||
632 | } | ||
633 | |||
634 | return 0; | ||
633 | } | 635 | } |
634 | 636 | ||
635 | int ext4_claim_free_blocks(struct ext4_sb_info *sbi, | 637 | int ext4_claim_free_blocks(struct ext4_sb_info *sbi, |