Messages in this thread Patch in this message | | | Date | Wed, 20 Oct 2004 16:09:56 +0200 | From | Jan Kasprzak <> | Subject | [Solved, patch]: NFS mount hang (no response to getattr) |
| |
Jan Kasprzak wrote: : I have ran into the following problem with Linux NFS code. Following : examples are the simplest test (meaningless) cases, the real /etc/exports : is more complicated, of course. [...]
I have found why this is happening to me, but I am not sure about the solution. The problem is, that mountd joins all the host/subnet/wild-card names which match the IP address from all /etc/exports (not only from the appropriate line in exports), and then sends this as a ip->name translation to the kernel via /proc/net/rpc/auth.unix.ip/channel. Now the problem occurs when the "FQDN+aliases+wildcards" part is 50 characters or more. Kernel then replies to write() with EINVAL, which mountd ignores.
So the bug is probably in linux/net/sunrpc/svcauth_unix.c - the number 50 is hardcoded there several times (ugly, ugly, ...) and it is too low anyway - the _single_componet_ of FQDN can be up to 63 chars, FQDN can be up to 255 chars, and I am not counting possible aliases/wildcards/subnets which mountd decides to add there.
And the bug is in mountd as well, because it should at least report to syslog when the write to /proc/.../channel returns EINVAL.
I propose the following patch to svcauth_unix.c. It is relative to 2.6.8.1-mm2. I have additionally made the "class" and "buf" variables static, thus shaving 100 bytes off the kernel stack. NFS maintaners, please verify this and apply.
-Yenya
--- linux-2.6.8.1-mm2/net/sunrpc/svcauth_unix.c.orig 2004-08-19 22:29:13.000000000 +0200 +++ linux-2.6.8.1-mm2/net/sunrpc/svcauth_unix.c 2004-10-20 15:51:49.495844584 +0200 @@ -151,11 +151,13 @@ } static struct ip_map *ip_map_lookup(struct ip_map *, int); +#define DOMAINNAME_MAX 1024 /* FQDN + possible aliases/subnets/wildcards */ +#define CLASS_MAX 50 static int ip_map_parse(struct cache_detail *cd, char *mesg, int mlen) { /* class ipaddress [domainname] */ - char class[50], buf[50]; + static char class[CLASS_MAX], buf[DOMAINNAME_MAX]; int len; int b1,b2,b3,b4; char c; @@ -168,11 +170,11 @@ mesg[mlen-1] = 0; /* class */ - len = qword_get(&mesg, class, 50); + len = qword_get(&mesg, class, CLASS_MAX); if (len <= 0) return -EINVAL; /* ip address */ - len = qword_get(&mesg, buf, 50); + len = qword_get(&mesg, buf, DOMAINNAME_MAX); if (len <= 0) return -EINVAL; if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4) @@ -183,7 +185,7 @@ return -EINVAL; /* domainname, or empty for NEGATIVE */ - len = qword_get(&mesg, buf, 50); + len = qword_get(&mesg, buf, DOMAINNAME_MAX); if (len < 0) return -EINVAL; if (len) {
-- | Jan "Yenya" Kasprzak <kas at {fi.muni.cz - work | yenya.net - private}> | | GPG: ID 1024/D3498839 Fingerprint 0D99A7FB206605D7 8B35FCDE05B18A5E | | http://www.fi.muni.cz/~kas/ Czech Linux Homepage: http://www.linux.cz/ | btw, David, I'm wondering about this loop: [...] Is this a busy-wait-until-someone-plugs-in-more-ram-chips thing? ;) --Andrew Morton - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |