Bug 669632

Summary: In the ext4+delalloc filesystem, repqouta cannot display the right used block value!
Product: Red Hat Enterprise Linux 6 Reporter: Zhang Liang <zhang.liang>
Component: kernelAssignee: Red Hat Kernel Manager <kernel-mgr>
Status: CLOSED NOTABUG QA Contact: Red Hat Kernel QE team <kernel-qe>
Severity: medium Docs Contact:
Priority: low    
Version: 6.0CC: esandeen, rwheeler
Target Milestone: rc   
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2011-01-14 14:42:03 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Attachments:
Description Flags
test script!
none
Dumped aqouta.user files none

Description Zhang Liang 2011-01-14 07:03:23 UTC
Created attachment 473478 [details]
test script!

Description of problem:

In the ext4+delalloc filesystem, repqouta cannot display the rightly have been used block until system run the command sync !


Version-Release number of selected component (if applicable):

redhat enterprise linux 6 beta2 x86_64

How reproducible:
Always!

Steps to Reproduce:
1.#mkdir /mnt/mp1;
2.#userdel quotausr1 (if your system exist user quotausr1);
3.#./repquotatest.sh
  
Actual results:
[root@quota-dxk bangzi]# ./repquotatest.sh
#### first repquota
*** Report for user quotas on device /dev/sdb1
Block grace time: 7days; Inode grace time: 7days
                        Block limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --      20       0       0              2     0     0
quotausr1 --       0       0       0              1     0     0


#### second repquota
*** Report for user quotas on device /dev/sdb1
Block grace time: 7days; Inode grace time: 7days
                        Block limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --      20       0       0              2     0     0
quotausr1 --       0       0       0              1     0     0


#### third repquota
*** Report for user quotas on device /dev/sdb1
Block grace time: 7days; Inode grace time: 7days
                        Block limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --      20       0       0              2     0     0
quotausr1 --    1024       0       0              1     0     0


Expected results:
[root@quota-dxk bangzi]# ./repquotatest.sh
#### first repquota
*** Report for user quotas on device /dev/sdb1
Block grace time: 7days; Inode grace time: 7days
                        Block limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --      20       0       0              2     0     0
quotausr1 --       0       0       0              1     0     0


#### second repquota
*** Report for user quotas on device /dev/sdb1
Block grace time: 7days; Inode grace time: 7days
                        Block limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --      20       0       0              2     0     0
quotausr1 --      1024       0       0              1     0     0


#### third repquota
*** Report for user quotas on device /dev/sdb1
Block grace time: 7days; Inode grace time: 7days
                        Block limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --      20       0       0              2     0     0
quotausr1 --    1024       0       0              1     0     0


Additional info:

[root@quota-dxk bangzi]# lsb_release -a
LSB Version:    :core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch
Distributor ID: RedHatEnterpriseServer
Description:    Red Hat Enterprise Linux Server release 6.0 Beta (Santiago)
Release:        6.0
Codename:       Santiago
[root@quota-dxk bangzi]# uname -r
2.6.32-37.el6.x86_64

Comment 2 Petr Pisar 2011-01-14 11:18:02 UTC
repquota(8) calls quotactl(Q_SYNC|USRQUOTA, ...) to synchronize in-kernel quotas into quota file and then repquota parses the quota file ({a,}quota.user).

quota(1) gets the quotas from running kernel instead and thus it provides up-to-date values.

repquota(8) gets data from the file because it's faster than querying kernel for each user (a syscall for a user).


Per quotaclt(2) manual the quota file should be synchronized after quotacl(Q_SYNC, ...). I thought wasn't for some reason. It looked like a bug in the kernel (2.6.32-94.el6.x86_64 from RHEL-6 and 2.6.35.10-74.fc14.x86_64 from Fedora-14).


I copied and checked aquota.users content before repquota(8), before sync(8) and after sync(8). My testing user has ID 500 (0x1F4) and it owns 1 file with size 1 MiB exactly (0x400 KiB). I found this:

Before repquota:
  No entry in aquota.sync for the user
After repquota, before sync:
  Entry for UID, correct usage size
  0001440 01f4 0000 0000 0000 0000 0000 0001 0000
  0001450 0000 0000 0000 0000 0400 0000 0000 0000
After sync:
  Entry for UID, correct usage size
  0001440 01f4 0000 0000 0000 0000 0000 0001 0000
  0001450 0000 0000 0000 0000 0400 0010 0000 0000

So apparently reqpuota() gets the old data from read(2) buffer as it opens the file and read headers before quotactl(Q_SYNC, ...).

Comment 3 Petr Pisar 2011-01-14 13:47:31 UTC
Created attachment 473523 [details]
Dumped aqouta.user files

Unfortunately the quota file before sync(1) and after sync(1) differs. I let repquota to parse and display those files by repquota and only the after sync(1) one shows correct counters.

I'm attaching those three files. aquota.user.1 is before creating file, aquota.user.2 after quotactl(Q_SYNC, ...) and aquota.user.3 after sync(1).

Also I made a mistake while running strace output for repquota tool. repquota reopens the quota file after syncing quotas:

open("/mnt/ext4/aquota.user", O_RDONLY) = 3
close(3)                                = 0
quotactl(Q_SYNC|USRQUOTA, "/dev/mapper/vg_dhcp0122-ext4", 0, NULL) = 0
open("/mnt/ext4/aquota.user", O_RDONLY) = 3

and it reads counters from the file after that.

Comment 4 Petr Pisar 2011-01-14 13:57:34 UTC
IMHO repquota shows correct data:

Before sync:
                        Block limits                File limits
User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --      13       0       0              2     0     0       
petr      --       1       0       0              1     0     0 


After sync:

User            used    soft    hard  grace    used  soft  hard  grace
----------------------------------------------------------------------
root      --      13       0       0              2     0     0       
petr      --    1025       0       0              1     0     0     

I think the delay is understandable for _delayed_ allocation. If you have a sparse file, quota will count used space---not a size of the file.

However reassigning to kernel to evaluate accounting on delayed ext4 properly.

Comment 5 Ric Wheeler 2011-01-14 14:42:03 UTC
This is actually behaving exactly as it should for delayed allocation - until you sync (or the application issues an fsync or fdatasync), blocks are not really allocated.