Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Apr 2014 21:03:57 -0500
From:      Bryan Drewery <bdrewery@FreeBSD.org>
To:        freebsd-fs@FreeBSD.org
Subject:   getdirentries cookies usage outside of UFS
Message-ID:  <53489F0D.1020702@FreeBSD.org>

next in thread | raw e-mail | index | archive | help
This is an OpenPGP/MIME signed message (RFC 4880 and 3156)
--XrrQWNhbOJ2nFQ0pcgF29OwHuLlcSWJmL
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

Recently I was working on a compat syscall for sys_getdirentries() that
converts between our dirent and the FreeBSD dirent struct. We had never
tried using this on TMPFS and when we did ran into weird issues (hence
my recent commits to TMPFS to clarify some of the getdirentries() code).
We were not using cookies, so I referenced the Linux compat module
(linux_file.c getdents_common())

I ran across this code:

>     /*
>      * When using cookies, the vfs has the option of reading from
>      * a different offset than that supplied (UFS truncates the
>      * offset to a block boundary to make sure that it never reads
>      * partway through a directory entry, even if the directory
>      * has been compacted).
>      */
>     while (len > 0 && ncookies > 0 && *cookiep <=3D off) {
>             bdp =3D (struct dirent *) inp;
>             len -=3D bdp->d_reclen;
>             inp +=3D bdp->d_reclen;
>             cookiep++;
>             ncookies--;
>     }=20


At first it looked innocuous but then it occurred to me it was the root
of the issue I was having as it was eating my cookies based on their
value, despite tmpfs cookies being random hash values that have no
sequential relation. So I looked at how NFS was handling the same code
and found this lovely hack from r216691:

> not_zfs =3D strcmp(vp->v_mount->mnt_vfc->vfc_name, "zfs");
=2E..
>  while (cpos < cend && ncookies > 0 &&
>      (dp->d_fileno =3D=3D 0 || dp->d_type =3D=3D DT_WHT ||
>       (not_zfs !=3D 0 && ((u_quad_t)(*cookiep)) <=3D toff))) {
>          cpos +=3D dp->d_reclen;
>          dp =3D (struct dirent *)cpos;
>          cookiep++;
>          ncookies--;
>  }

I ended up doing the opposite, only running the code if getting dirents
from "ufs".

So there's multiple issue here.

1. NFS is broken on TMPFS. I can see why it's gone so long unnoticed,
why would you do that? Still probably worth fixing.

2. Linux and SVR4 getdirentries() are both broken on TMPFS/ZFS. I am
surprised Linux+ZFS has not been noticed by now. I am aware the SVR4 is
full of other bugs too. I ran across many just reviewing the
getdirentries code alone.

Do any other file systems besides UFS do this offset/cookie
truncation/rewind? If UFS is the only one it may be acceptable to change
this zfs check to !ufs and add it to the other modules. If we don't like
that, or there are potentially other file systems doing this too, how
about adding a flag to somewhere to indicate the file system has
monotonically increasing offsets and needs this rewind support. I'm not
sure where that is best done, struct vfsconf?

--=20
Regards,
Bryan Drewery


--XrrQWNhbOJ2nFQ0pcgF29OwHuLlcSWJmL
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQEcBAEBAgAGBQJTSJ8NAAoJEDXXcbtuRpfPZZAIAN7eTl1evOll1APi2j+M8LBW
rLW9ngE498ZVF6aDnIrQ/+q/fvACvoa28aF+i0E0+IR9LQ4OsBGM0tPr/AMQd/Dt
NIZ8ByMQyewhUx7vCiVTU2NF2uLlpixFu7f4SrlguEe1tzWudbAow8Dgf1urUx6v
tbpypDdHGGwTLvffP5rfDl8W3PATBJZdKx80ba+Dj9ZOsc+ZBeZxr8htHWcp5WJp
nDT5waI49F0xKBR4U30WN1srWyK/g6UVBmbAhlYT6/x20vr4j7L7tyzv6MnglBJ9
ywi52G5lXuyNzD5U7p1Wo9/bvkOyeT0SbwmmAzSfbM1Lr2d7sKwuM1SeT5kzoRk=
=06qd
-----END PGP SIGNATURE-----

--XrrQWNhbOJ2nFQ0pcgF29OwHuLlcSWJmL--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?53489F0D.1020702>