[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 14:43:33 +0800
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <1384095977.245087.88.camel@storm>
References: <1384069188.245087.68.camel@storm> <527F63FC.1050005@xxxxxxxxxx> <1384095977.245087.88.camel@storm>
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.1.0
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 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).

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, 
symlink file quota space is accounted according to it's path length. IOWs, it 
be reflect on xfs_quota -xc 'report -[b|h]' if you create it with a longer path 
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.
> What works though is renaming the file:
> localhost backup # mv test/symlinkA test/symlinkAtmp
> localhost backup # mv test/symlinkAtmp test/symlinkA
rename(2) will create a new dentry as well as an inode, hence it would inherit
the projid.

> localhost backup # stat test/symlinkA
>   File: âtest/symlinkAâ -> â/invalid/locationâ
>   Size: 17            Blocks: 0          IO Block: 4096   symbolic link
> Device: fe11h/65041d  Inode: 4364        Links: 1
> Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
> Access: 2013-11-10 15:49:44.870068178 +0100
> Modify: 2013-11-10 15:49:44.870068178 +0100
> Change: 2013-11-10 16:00:54.957571504 +0100
>  Birth: -
> localhost backup # xfs_db -r -c 'inode 4364' -c 'p' /dev/vdb1  | grep
> projid
> core.projid_lo = 42
> core.projid_hi = 0
> localhost backup # cp -al test/symlinkA test/symlinkB
> localhost backup # 
In terms of project quota anyway, hardlink file is only accounted once for the 
of the inode.  It's welcome to report back if you observed different behaviour.


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