I was concerned that too much memory might be consumed by the kernel.
I'd like to seee some kind of auto-expire negative entries. I took the
easiest way out. We should do better.
>
> But on to the more relevant stuff:
>
> - nfsd_netlink_notify ( which is called when an export entry cannot be
> found) constructs a message consisting of:
> . The sockaddr_in of the client that is making a request.
> . the knfs_fh file handle (the 32byte filehandle in a suitable
> structure) of the request
> . The path name of the file being accessed
> . The path name of the filesystem containing the file (these two
> are grouped together into a single char[] array.)
>
> Then in utils/mountd/mountd.c:
> nlfd_handler (which is given these messages when they arrive):
>
> - calls get_rootfh with the client address and file pathname, much
> as mountd does when responding to the MOUNTD_MNT request, which
> will try to find a relevant export entry and will feed it to the
> kernel. If this worked and the export entry has the same
> xdev/xino as the filehandle, then all is ok. This seems fine.
>
> But what happens if it doesn't find an appropriate mount entry,
> or if the the xdev/xino is wrong?
>
> First to clarify what needs to happen here:
> A NFSEXP_NEGATIVE export entry needs to be given to the kernel
> with an appropriate client, and with exactly the xdev/xino out
> of the filehandle. If not, then when this request is
> retransmitted, the same process will be repeated.
>
> So what does nlfd_handler do? First it stats the path to the
> file being accessed to see if it has the right xdev/xino. The
> chances of this are probably "poor" in general, though it might
> work in certain senarios.
> If it isn't the right xdev/xino, then it stats the filesystem
> that contained the filehandle, and assumes that this will have
> the right dev/ino. If it was the root of the filesystem that was
> exported, this will work fine (as would previous versions). If
> it wasn't then this will not have the right dev/ino.
>
> In either case, the dev and ino of the last stat is used to
> create a negative export entry which is feed to the kernel.
>
> So, what happens when we:
>
> have a filesystem /a
> export /a/b to fred
> on fred, mount /a/b as /ab
> on fred, cd /ab/c (which we assume exists)
> on server, unexport /a/b to fred
> on fred, ls -l .
>
> Fred will send some sort of request with the filehandle it got
> for /a/b/c. This will have a dev/ino referring to /a/b/c and an
> xdev/xino referring to /a/b.
>
> knfsd will pass the filehandle and path names up to mountd which
> will:
> try to see if /a/b/c (or any parent thereof) is currently
> exported to fred. It won't be.
> see if /a/b/c has the same dev/ino as the file handle. It wont.
> use the dev/ino for /a assuming it is right. It won't be.
>
> Then it gives a NFSEXP_NEGATIVE export for /a to the kernel.
>
> fred timesout and resends. knfsd will look for an export entry
> for client fred, referring to dev/ino of /a/b, and wont find one,
> so we go around the loop again.
>
>
> So maybe you can see how I wonder at your usage of the verb "fixed".
Here is a patch for the problem. It may not solve all cases. But I
think it covers most ones.
>
> Maybe we should have a bit of discussion (in nfs-devel) about
> whether this is all a good idea, what filehandles should look-like in
> order to support it best, whether the up-call should use RPC (as
> solaris does) and related issues before we flail around with too much
> alpha-quality code. There are other bits of knfsd that need some
> work first, such as the filehandle->dentry mapping and the issue of
> whether filehandles really need to contain the inode number of the
> parent.
>
I see 1.5.x as alpha. Nothing is final yet. The reason I like it is it
gets rid of /var/lib/nfs/rmtab. However, that means we have to find a
way for kernel to communicate to mountd. Maybe RPC is a better choice.
Anyone wants to implement it?
Thanks.
H.J.
---
Index: utils/mountd/mountd.c
===================================================================
RCS file: /home/cvsroot/knfsd/utils/mountd/mountd.c,v
retrieving revision 1.21
diff -u -p -r1.21 mountd.c
--- mountd.c 1999/10/01 20:37:05 1.21
+++ mountd.c 1999/10/07 22:43:45
@@ -51,6 +51,7 @@ void nlfd_handler(int fd)
struct stat stb;
int err;
char *p = buf.path;
+ char epath[MAXPATHLEN+1];
xlog(L_NOTICE, "NFS request from unknown host\n");
@@ -69,17 +70,41 @@ void nlfd_handler(int fd)
fh->fh_xino);
}
- /* Put in a negative export for the right directory. */
- if (stat(p, &stb) < 0) {
- xlog(L_ERROR, "Cannot stat %s for making negative exportent.",
- p);
- return;
+ /* Put in a negative export for the right directory. We should
+ find a match for dev/ino. Try the longest matching pathname.
+ */
+ strncpy(epath, p, sizeof (epath) - 1);
+ epath[sizeof (epath) - 1] = '\0';
+ for (p = NULL;;) {
+ if (stat(epath, &stb) < 0) {
+ xlog(L_ERROR, "Cannot stat %s for making negative exportent.", p);
+ return;
+ }
+ if (stb.st_dev == buf.fh.fh_xdev
+ && stb.st_ino == buf.fh.fh_xino) {
+ p = epath;
+ break;
+ }
+ else {
+ /* We have to treat the root, "/", specially. */
+ if (p == &epath[1]) break;
+ p = strrchr(epath, '/');
+ if (p == epath) p++;
+ *p = '\0';
+ }
}
+
if (stb.st_dev != buf.fh.fh_xdev
|| stb.st_ino != buf.fh.fh_xino) {
p = &buf.path[buf.devlen + 1];
if (stat(p, &stb) < 0) {
xlog(L_ERROR, "Cannot stat %s for making negative exportent.", p);
+ return;
+ }
+ if (stb.st_dev != buf.fh.fh_xdev
+ || stb.st_ino != buf.fh.fh_xino) {
+ xlog(L_NOTICE, "No matching exported directory from nfsd netlink: %d/%d",
+ buf.fh.fh_xdev, buf.fh.fh_xino);
return;
}
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/