xfs
[Top] [All Lists]

Re: Setting project quotas on special files

To: tiziano.mueller@xxxxxxxxxxxxxxxxx, xfs@xxxxxxxxxxx
Subject: Re: Setting project quotas on special files
From: Jeff Liu <jeff.liu@xxxxxxxxxx>
Date: Mon, 11 Nov 2013 16:26:36 +0800
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <1384155489.245087.112.camel@storm>
References: <1384069188.245087.68.camel@storm> <527F63FC.1050005@xxxxxxxxxx> <1384095977.245087.88.camel@storm> <52807C95.7010501@xxxxxxxxxx> <1384155489.245087.112.camel@storm>
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.1.0
On 11/11 2013 15:38 PM, Tiziano MÃller wrote:
> Hi Jeff
> 
> Am Montag, den 11.11.2013, 14:43 +0800 schrieb Jeff Liu:
>> Hi Tiziano,
>>
>> On 11/10 2013 23:06 PM, Tiziano MÃller wrote:
>>>
>>> Hi Jeff
>>>
>>> Sorry for top-posting, but it may be better to illustrate this with an
>>> isolated example:
>>>
>>> I have a volume named "backup" mounted with option "pquota", then I do
>>> the following inside that mountpoint:
>>>
>>> localhost backup # mkdir test
>>> localhost backup # ln -s /invalid/location test/symlinkA
>>> localhost backup # echo 42:/var/backup/test >> /etc/projects
>>> localhost backup # echo test:42 >> /etc/projid
>>> localhost backup # xfs_quota -x -c 'project -s test' /var/backup
>>> Setting up project test (path /var/backup/test)...
>>> xfs_quota: skipping special file /var/backup/test/symlinkA
>> So the symlink file is skipped.
>>
>>> Processed 1 (/etc/projects and cmdline) paths for project test with 
>>> recursion depth infinite (-1).
>>> localhost backup # cp -al test/symlinkA test/symlinkB
>>> cp: cannot create hard link "test/symlinkB" to "test/symlinkA": Invalid 
>>> cross-device link
>> This is expected as you attempting to create a hardlink file upon a symlink
>> which is located at a different volume
> 
> No, 'cp -al' does not follow the symlink (which is invalid in this
> example btw) but tries to create a hardlink for that symlink.
> 
>>  and the symlink was not inherited
>> from the project id(42 in this case) at this stage(i.e, it's projid is 0 as
>> a default projid, which is different to 42).
> 
> Yes.
> 
>>
>> This restriction can be got from xfs_vn_link():
>>
>> /*
>>  * If we are using project inheritance, we only allow hard link
>>  * creation in our tree when the project IDs are the same; else
>>  * the tree quota mechanism could be circumvented.
>>  */
>>  if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
>>      (xfs_get_projid(tdp) != xfs_get_projid(sip)))) {
>>      error = XFS_ERROR(EXDEV);
>>      goto error_return;
>>  }
>>
>>> localhost backup # 
>>>
>>> Creating a symlink after setting up project quotas in the same directory
>>> yields a different behaviour:
>>>
>>> localhost backup # ln -s /invalid/location test/symlinkC
>> So a symlink file is created and it is inherited the projid in this case, 
>> because
>> symlink file quota space is accounted according to it's path length. IOWs, 
>> it would
>> be reflect on xfs_quota -xc 'report -[b|h]' if you create it with a longer 
>> path name
>> exceeds the inline inode space.
>>
>>> localhost backup # cp -al test/symlinkC test/symlinkD
>> Therefore create a hardlink from this symlink file with an inherited projid 
>> is
>> desired to succeed.
>>
>>> localhost backup # 
>>>
>>> The following shows that a symlink alone (and not its target) can have a
>>> project id assigned and that the project id must be assigned to be able
>>> to create a hardlink of a symlink (no matter where it points to).
>>>
>>> For each of the symlinks test/symlink{A,B} run `stat` to get the inode
>>> then use xfs_db on that inode to get the attributes:
>>>
>>> localhost backup #  xfs_db -r -c 'inode 4362' -c 'p' /dev/vdb1  | grep 
>>> projid
>>> core.projid_lo = 0
>>> core.projid_hi = 0
>>> localhost backup #  xfs_db -r -c 'inode 4363' -c 'p' /dev/vdb1  | grep 
>>> projid
>>> core.projid_lo = 42
>>> core.projid_hi = 0
>> Just as above mentioned...
>>
>>> Unfortunately xfs_io tries to follow the symlinks so it can not be used
>>> to set the project manually.
>> Well, why you want to set project quota via xfs_io manually? :-P.
> 
> To set the project id for special files which did not get the project id
> set during "xfs_quota -x -c 'project -s test'", which was leaving my
> tree in a somewhat inconsistent state wrt the project id.
Oh, now I can understand that you want to set projid to special files.
> 
> As Dave wrote me on IRC, the following works (I only tested it, credit
> goes to him):
> 
> 1. find the inode of all special files where the project id was not set
> 2. determine the project id to be set by recording their parent
> directorie's project id. You will end up with a tuple (for 16 bit
> project ids): (inode, projid_lo), resp. a triple (for 32 bit project
> ids): (inode, projid_lo, projid_hi)
> 3. umount the volume
> 4. use 'xfs_db -x -c "inode <inode>" -c "write core.projid_lo
> <projid_lo>" -c "write core.projid_hi <projid_hi>" <dev>' to set the
> project id on those inodes manually
> 5. mount the volume but without "pquota" and umount again (this will
> trigger a quotacheck on the next mount with pquota)
> 6. mount the volume with the "pquota" option again
> 
> As for the "why can xfs_quota not set the project id on special files":
> it does it via ioctl(2), which needs a file handle, which is retrieved
> via open(2), which "follows" the symlinks/device files.
Thank for letting me know this as well, I have been blocked for logging into IRC
these days due to network issue.

Thanks,
-Jeff

<Prev in Thread] Current Thread [Next in Thread>