From: Max Reitz <mreitz@redhat.com>
To: Vivek Goyal <vgoyal@redhat.com>
Cc: virtio-fs-list <virtio-fs@redhat.com>, qemu-devel@nongnu.org
Subject: Re: [Virtio-fs] [PATCH 1/3] virtiofsd: Find original inode ID of mount points
Date: Thu, 27 May 2021 17:00:31 +0200 [thread overview]
Message-ID: <b066027e-1733-8ca3-00e2-68e58aa8e563@redhat.com> (raw)
In-Reply-To: <20210526185017.GB1225492@horse>
On 26.05.21 20:50, Vivek Goyal wrote:
> On Wed, May 26, 2021 at 02:13:24PM -0400, Vivek Goyal wrote:
>> On Wed, May 12, 2021 at 02:55:42PM +0200, Max Reitz wrote:
>>> Mount point directories represent two inodes: On one hand, they are a
>>> normal directory on their parent filesystem. On the other, they are the
>>> root node of the filesystem mounted there. Thus, they have two inode
>>> IDs.
>>>
>>> Right now, we only report the latter inode ID (i.e. the inode ID of the
>>> mounted filesystem's root node). This is fine once the guest has
>>> auto-mounted a submount there (so this inode ID goes with a device ID
>>> that is distinct from the parent filesystem), but before the auto-mount,
>>> they have the device ID of the parent and the inode ID for the submount.
>>> This is problematic because this is likely exactly the same
>>> st_dev/st_ino combination as the parent filesystem's root node. This
>>> leads to problems for example with `find`, which will thus complain
>>> about a filesystem loop if it has visited the parent filesystem's root
>>> node before, and then refuse to descend into the submount.
>>>
>>> There is a way to find the mount directory's original inode ID, and that
>>> is to readdir(3) the parent directory, look for the mount directory, and
>>> read the dirent.d_ino field. Using this, we can let lookup and
>>> readdirplus return that original inode ID, which the guest will thus
>>> show until the submount is auto-mounted.
>>
>>> (Then, it will invoke getattr
>>> and that stat(2) call will return the inode ID for the submount.)
>>
>> Hi Max,
>>
>> How are we sure that GETATTR() will always be called and that will
>> allow us to return inode number in mounted filesystem (instead of
>> parent filesystem). I thought GETATTR will be called only if cached
>> attrs have expired. (1 second default for cache=auto). Otherwise
>> stat() will fill inode->i_no from cache and return. And I am afraid
>> that in that case we will return inode number from parent fs,
>> instead of mounted fs.
>>
>> Say following sequence of events happens pretty fast one after the
>> other. Say /mnt/virtiofs/foo is a mount point in server but client
>> has not created submount yet.
>>
>> A. stat(/mnt/virtiofs/foo, AT_NO_AUTOMOUNT)
>> -> This should get inode number in parent filesystem on host and
>> store in guest inode->i_no and return to user space. Say inode
>> in guest is called a_ino.
>> B. stat(/mnt/virtiofs/foo)
>> -> This should create submount and create new inode (say b_ino), using
>> properties from a_ino. IOW, this should copy a_ino->i_no to
>> b_ino->b_ino given current code, IIUC.
>>
>> -> Assume timeout has not happened and cached attrs have not expired.
>>
>> -> And now b_ino->i_no (or ->orig_ino) will be returned to user space.
Well, I mean, this sounds easy enough to test. For example, this passes
for me:
count=1000
root_st_ino=128
tag=host
mountpoint=/mnt
submount_path=submount
for i in $(seq $count)
do
mount -t virtiofs $tag $mountpoint || break
if [ $(stat -c '%i' $mountpoint/$submount_path) -eq $root_st_ino ]
then
echo 'fail 0'
break
fi
ls $mountpoint/$submount_path > /dev/null
if [ $(stat -c '%i' $mountpoint/$submount_path) -ne $root_st_ino ]
then
echo 'fail 1'
break
fi
umount $mountpoint || break
done
if [ $i -ne $count ]
then
echo 'Something failed'
else
echo 'OK'
fi
>> Am I missing something. Do we need to always expire inode attrs when
>> we create submount so that client is forced to issue GETATTR.
>
> Looks like while initialzing b_ino, we are setting attr_valid=0, which
> should set fi->i_time=0 and force issuing GETATTR later.
>
> fuse_fill_super_submount()
> root = fuse_iget(sb, parent_fi->nodeid, 0, &root_attr, 0, 0);
> ^
> fuse_iget(attr_valid=0)
> fuse_change_attributes(attr_valid=0)
> fuse_change_attributes_common(attr_valid=0)
> fi->i_time = attr_valid;
>
> So may be this will force GETATTR and fetch new inode id when second
> stat() is called.
i_time is at least what fuse_update_get_attr() uses to decide whether to
invoke GETATTR or not – although AT_STATX_DONT_SYNC can override that,
but I don’t think that’s a problem. If i_time is 0, that function will
always invoke GETATTR (unless AT_STATX_DONT_SYNC).
So I think it works in practice. When the inode ID is looked up through
some stat-y function, this should go through fuse_update_get_attr(),
which will fetch the st_ino on the submount. There is still i_ino,
though...
To be absolutely certain, we could invoke fuse_update_attributes() in
fuse_fill_super_submount(), but then again, fuse_fill_super_common()
doesn’t do that either for its root node. It just initializes i_ino to
FUSE_ROOT_ID, i.e. 1.
Max
next prev parent reply other threads:[~2021-05-27 15:03 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-12 12:55 [PATCH 0/3] virtiofsd: Find original inode ID of mount points Max Reitz
2021-05-12 12:55 ` [PATCH 1/3] " Max Reitz
2021-05-12 15:59 ` Connor Kuehl
2021-05-17 14:57 ` Vivek Goyal
2021-05-17 17:26 ` Max Reitz
2021-05-20 11:28 ` Dr. David Alan Gilbert
2021-05-26 18:13 ` Vivek Goyal
2021-05-26 18:50 ` [Virtio-fs] " Vivek Goyal
2021-05-27 15:00 ` Max Reitz [this message]
2021-06-02 18:19 ` Vivek Goyal
2021-06-02 18:59 ` Miklos Szeredi
2021-06-04 16:22 ` Max Reitz
2021-05-12 12:55 ` [PATCH 2/3] virtiofs_submounts.py: Do not generate ssh key Max Reitz
2021-05-12 12:55 ` [PATCH 3/3] virtiofs_submounts.py: Check `find` Max Reitz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b066027e-1733-8ca3-00e2-68e58aa8e563@redhat.com \
--to=mreitz@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=vgoyal@redhat.com \
--cc=virtio-fs@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).