Subject: Implementing POSIX stat(2), df(1) with NFSv4

From: David Mazieres <[email-masked]>
Date: Mon, 6 Mar 2000 15:52:59 -0500 (EST)

From reading the NFS4 draft, it is not clear how exactly clients might
reasonably deal with the fsid attribute.  This is relevant when
implementing stat(2) and df(1) as required by POSIX.

The POSIX 1003.1 spec, in section 5.6.1, line 687, says "File serial
number and device ID taken together uniquely identify the file within
the system."  In other words, stat(2) must return a unique pair of
values (st_dev, st_ino) for each distinct file on the system.

Several UNIX utilities (e.g. pwd, cp) actually rely on the stat system
call returning aunique st_dev/st_ino pairs.  If there is a plan for
letting clients do this in NFS4, it might be worth describing as an
example in the RFC.

In previous versions of NFS, providing unique st_dev/st_ino pairs
wasn't a problem because clients mounted each file system on the
server separately.  Thus, NFS clients could ignore the fsid field of
the NFS fattr structure, assign a unique st_dev value to all files on
each NFS mount point, and use the NFS fileid value as the st_ino.

What I can't figure out from the draft spec is what reasonable mapping
one could use from NFS4 fileid/fsid attributes to st_dev/st_ino fields
in the stat structure.  Several obvious possibilities have problems:

 1. st_ino = fileid; st_dev = fsid;

    There are two problems here.  One is that fsid4 is huge--128 bits.
    In fact, a separate question might be why fsid4 needs to be larger
    than specdata4.  At any rate, you probably can't hope for more
    64-bits in a stat structure's st_dev field, so there is no way
    just to assign fsid to st_dev.

    Another problem is that there is no way to guarantee uniqueness
    across multiple servers (and file systems other than NFS).

 2. st_ino = fileid; st_dev = dynamic_map (server, fsid)

    Keep a dynamic mapping between server/fsid pairs and st_dev
    values.  Basically allocate a new st_dev value each time you run
    across a new fsid value on a given server.

    Here the problem is that the server could use a huge number of
    fsid values, particularly over time.  Is there anything in the
    spec preventing every single directory on a server from having a
    different fsid?  This could run the client out of space.

 3. st_dev = map (server); st_ino = hash (fileid, fsid)

    Map each server to a unique st_dev value (as was done with each
    mount point in NFS2-3).  Make st_ino a hash value of fileid and
    fsid.

    Here the problem is that you can hope for at most 64-bits of
    st_ino, which is too small to guarantee you will never have a
    collision.

If there is a better solution, I think it would make sense to put it
in the RFC as an example.

There is this somewhat cryptic statement in section 14.2.13:

  Unix clients that detect a mountpoint crossing will need to mount
  the server's filesystem.

This could conceivably be the same as option 2 above, but then how
does unmounting work?

A related question is how to implement the POSIX df(1) utility.  When
no arguments are specified, "information shall be written for all file
systems" (POSIX 1003.2, sec. 5.8.2, lines 814-815).  It's not clear
how even to determine "all file systems" on an NFS4 server.  Part of
the point of section 7.2 of the draft spec is that "There is a
drawback to [the old way of doing things]: it is static.  If the
server administrator adds a new export the client will be unaware of
it."  Is there some way to determine all file systems at any given
point?

The answers to both these questions may have to do with some sort of
plan for automounting built into NFS4.  I don't think it's clear what
to do without a more detailed suggestion in the document.

David

---

From: Mike Eisler <[email-masked]>
Date: Mon, 6 Mar 2000 13:17:56 -0800 (PST)

> letting clients do this in NFS4, it might be worth describing as an

Possibly, but it seems quite O/S specific to consider it. 

> in the stat structure.  Several obvious possibilities have problems:

You can't directly map a server's fsid to an st_dev, unless st_dev is > 128
bits on your system. When the UNIX client crosses a server mount moint, the
new fsid tells it is has crossed mount points. UNIX clients in NFSv[23]
generate unqiue, if not random, values for for st_dev that have no correlation
with the contests of server's fsid's, and NFSv4 UNIX clients could do the same
thing.

> This could conceivably be the same as option 2 above, but then how

No it means the UNIX client creates a new NFS mounted file system.

> does unmounting work?

An implementation detail. For a system like Solaris 8, with in-kernel
mnttab, this is straightforward.

> systems" (POSIX 1003.2, sec. 5.8.2, lines 814-815).  It's not clear

I hope it means all mounted file ssytems. With dynamic mounting and unmounting,
this is implementable in UNIX NFSv4 clients.

> it."  Is there some way to determine all file systems at any given

Even NFSv[23] clients have this problem. You only see what's mounted.
If the client doesn't access the new export, it's not mounted.

	-mre