Commit 95e8022b authored by Jamie Lokier's avatar Jamie Lokier Committed by Linus Torvalds

[PATCH] Fix protocol bugs with NFS and nanoseconds

NFS with 2.5.75 as both client and server is broken with GNU Make.

The nanosecond field of timestamps of newly touched files is often
negative on the client, which is probably why Make fails.  The value
also bears no relation to the file's nanosecond field on the server.

The culprit is htons() used where htonl() should be:

-	*p++ = htonl((u32) time->tv_sec); *p++ = htons(time->tv_nsec);
+	*p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec);

The rest of this patch corrects nfsd to use microseconds in NFSv2, not
nanoseconds.  (The client already gets this right, but I have
optimised it slightly to avoid division when possible).
parent b4a9a744
...@@ -90,7 +90,7 @@ xdr_encode_time(u32 *p, struct timespec *timep) ...@@ -90,7 +90,7 @@ xdr_encode_time(u32 *p, struct timespec *timep)
{ {
*p++ = htonl(timep->tv_sec); *p++ = htonl(timep->tv_sec);
/* Convert nanoseconds into microseconds */ /* Convert nanoseconds into microseconds */
*p++ = htonl(timep->tv_nsec / 1000); *p++ = htonl(timep->tv_nsec ? timep->tv_nsec / 1000 : 0);
return p; return p;
} }
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
* XDR support for nfsd/protocol version 3. * XDR support for nfsd/protocol version 3.
* *
* Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
*
* 2003-08-09 Jamie Lokier: Use htonl() for nanoseconds, not htons()!
*/ */
#include <linux/types.h> #include <linux/types.h>
...@@ -43,7 +45,7 @@ static u32 nfs3_ftypes[] = { ...@@ -43,7 +45,7 @@ static u32 nfs3_ftypes[] = {
static inline u32 * static inline u32 *
encode_time3(u32 *p, struct timespec *time) encode_time3(u32 *p, struct timespec *time)
{ {
*p++ = htonl((u32) time->tv_sec); *p++ = htons(time->tv_nsec); *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec);
return p; return p;
} }
......
...@@ -123,13 +123,13 @@ decode_sattr(u32 *p, struct iattr *iap) ...@@ -123,13 +123,13 @@ decode_sattr(u32 *p, struct iattr *iap)
if (tmp != (u32)-1 && tmp1 != (u32)-1) { if (tmp != (u32)-1 && tmp1 != (u32)-1) {
iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET; iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
iap->ia_atime.tv_sec = tmp; iap->ia_atime.tv_sec = tmp;
iap->ia_atime.tv_nsec = tmp1; iap->ia_atime.tv_nsec = tmp1 * 1000;
} }
tmp = ntohl(*p++); tmp1 = ntohl(*p++); tmp = ntohl(*p++); tmp1 = ntohl(*p++);
if (tmp != (u32)-1 && tmp1 != (u32)-1) { if (tmp != (u32)-1 && tmp1 != (u32)-1) {
iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET; iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
iap->ia_mtime.tv_sec = tmp; iap->ia_mtime.tv_sec = tmp;
iap->ia_mtime.tv_nsec = tmp1; iap->ia_mtime.tv_nsec = tmp1 * 1000;
} }
return p; return p;
} }
...@@ -171,12 +171,12 @@ encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) ...@@ -171,12 +171,12 @@ encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
*p++ = htonl((u32) stat.dev); *p++ = htonl((u32) stat.dev);
*p++ = htonl((u32) stat.ino); *p++ = htonl((u32) stat.ino);
*p++ = htonl((u32) stat.atime.tv_sec); *p++ = htonl((u32) stat.atime.tv_sec);
*p++ = htons(stat.atime.tv_nsec); *p++ = htonl(stat.atime.tv_nsec ? stat.atime.tv_nsec / 1000 : 0);
lease_get_mtime(dentry->d_inode, &time); lease_get_mtime(dentry->d_inode, &time);
*p++ = htonl((u32) time.tv_sec); *p++ = htonl((u32) time.tv_sec);
*p++ = htons(time.tv_nsec); *p++ = htonl(time.tv_nsec ? time.tv_nsec / 1000 : 0);
*p++ = htonl((u32) stat.ctime.tv_sec); *p++ = htonl((u32) stat.ctime.tv_sec);
*p++ = htons(stat.ctime.tv_nsec); *p++ = htonl(stat.ctime.tv_nsec ? stat.ctime.tv_nsec / 1000 : 0);
return p; return p;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment