* [PATCH] NFSv3 server side create modes
@ 2006-11-09 20:10 Peter Staubach
0 siblings, 0 replies; only message in thread
From: Peter Staubach @ 2006-11-09 20:10 UTC (permalink / raw)
To: NFS List; +Cc: Neil Brown
[-- Attachment #1: Type: text/plain, Size: 4458 bytes --]
Hi.
The attached patch will address a problem where the NFSv3 server
incorrectly sets the mode of a newly created file. This can occur
when the directory, which contains the newly created file, has a
default ACL on it which causes the mode to changed from that which
was specified in the over the wire attributes.
This problem results from some changes made to the NFSv3 server to
address an interoperability problem which occurred when the Solaris
NFS client was modified to treat file times as signed quantities
instead of unsigned quantities and to return errors to its
applications which it sees file times which appear to be negative.
The NFSv3 exclusive create mechanism works by the client sending
a 64 bit verifier in the over the wire CREATE request. The Linux
server then breaks up this 64 bit verifier into two 32 bit quantities
and stores them as the initial values for the mtime and atime fields
for the newly created file. If another CREATE request comes in, the
NFS server can then compare the mtime and atime fields against the
verifier in the new CREATE request in order to determine how to
correctly handle the request. The server will either fail the
request with EEXIST or treat it as a retransmitted and proceed as
if it is the original request. After the client successfully receives
a response to its exclusive CREATE request, it is responsible for
sending an over the wire SETATTR to set the mtime and atime fields
to the current time.
The problem with the Solaris client was that it was receiving the
intermediate attributes, ie. the ones that contained the verifier
that it itself had constructed, and based on these attributes,
was failing the exclusive create system call. This is a bug in
the Solaris NFS client. A workaround has been implemented in the
Solaris client to ensure that the sign bit in the 64 bit verifier
is not set. The correct fix would have been to ensure that it just
didn't fail the CREATE call based on the intermediate attributes.
However, this situation was worked around in the Linux NFS server.
The solution was to ensure that the mtime and atime fields were
not negative by masking the two halves of the verifier. The
leftover two bits were then stored in the mode field.
This then causes the problem which is being seen by NFSv3 clients.
The mode, from the initial attributes in the CREATE request, is
used and is then modified by the contents of the default ACL to
construct the mode of the new file. The NFS server then changes
the mode to the mode contained in the initial attributes in the
CREATE request. This can cause the mode to be different than it
should have been. Thus, the mode comes out differently, based
on whether the file was created locally on the server or via NFS
from a client.
This problem was then worked around in the Linux NFS client by
having it send an NFS_ACL SETACL request making the default ACL
on the directory to be the access ACL on the newly created file.
This causes the mode to be set back to the correct value again.
This solution works for clients who know to send the extra
NFS_ACL call. It does not work for any other clients, NFS_ACL
aware or not. It also introduces a performance penalty due to
the extra over the wire operation.
The solution is to modify the Linux NFS server to just mask off
the two sign bits of the halves of the verifier which are stored
in the mtime and atime fields and forget about the two sign bits.
This leaves the mode computations alone and thus, the mode comes
out correctly. This solution works for clients who don't know
to send the extra NFS_ACL request, clients who don't know anything
about NFS_ACL, and the updated clients who are sending the extra
NFS_ACL request.
This does introduce a slight danger if the client really was
depending upon these two bits to differentiate between different
exclusive CREATE requests. However, given the algorithms used
by most clients, where one half is the current time on the
client and the other half is the pid of the process or the IP
address of the client, then this danger is minimal.
The attached patch removes the support for the use of the mode
field to store the two bits of the verifier. It has been tested
using the Connectathon testsuite as well as the test scenario
described in the Red Hat bugzilla:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=128616
Thanx...
ps
Signed-off-by: Peter Staubach <staubach@redhat.com>
[-- Attachment #2: nfsd_create_v3.devel --]
[-- Type: text/plain, Size: 2262 bytes --]
--- linux-2.6.18.i686/fs/nfsd/vfs.c.org
+++ linux-2.6.18.i686/fs/nfsd/vfs.c
@@ -1244,7 +1244,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
__be32 err;
int host_err;
__u32 v_mtime=0, v_atime=0;
- int v_mode=0;
err = nfserr_perm;
if (!flen)
@@ -1281,16 +1280,11 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
goto out;
if (createmode == NFS3_CREATE_EXCLUSIVE) {
- /* while the verifier would fit in mtime+atime,
- * solaris7 gets confused (bugid 4218508) if these have
- * the high bit set, so we use the mode as well
+ /* solaris7 gets confused (bugid 4218508) if these have
+ * the high bit set, so just clear the high bits.
*/
v_mtime = verifier[0]&0x7fffffff;
v_atime = verifier[1]&0x7fffffff;
- v_mode = S_IFREG
- | ((verifier[0]&0x80000000) >> (32-7)) /* u+x */
- | ((verifier[1]&0x80000000) >> (32-9)) /* u+r */
- ;
}
if (dchild->d_inode) {
@@ -1318,7 +1312,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
case NFS3_CREATE_EXCLUSIVE:
if ( dchild->d_inode->i_mtime.tv_sec == v_mtime
&& dchild->d_inode->i_atime.tv_sec == v_atime
- && dchild->d_inode->i_mode == v_mode
&& dchild->d_inode->i_size == 0 )
break;
/* fallthru */
@@ -1338,26 +1331,22 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
}
if (createmode == NFS3_CREATE_EXCLUSIVE) {
- /* Cram the verifier into atime/mtime/mode */
+ /* Cram the verifier into atime/mtime */
iap->ia_valid = ATTR_MTIME|ATTR_ATIME
- | ATTR_MTIME_SET|ATTR_ATIME_SET
- | ATTR_MODE;
+ | ATTR_MTIME_SET|ATTR_ATIME_SET;
/* XXX someone who knows this better please fix it for nsec */
iap->ia_mtime.tv_sec = v_mtime;
iap->ia_atime.tv_sec = v_atime;
iap->ia_mtime.tv_nsec = 0;
iap->ia_atime.tv_nsec = 0;
- iap->ia_mode = v_mode;
}
/* Set file attributes.
- * Mode has already been set but we might need to reset it
- * for CREATE_EXCLUSIVE
* Irix appears to send along the gid when it tries to
* implement setgid directories via NFS. Clear out all that cruft.
*/
set_attr:
- if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) {
+ if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) {
__be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
if (err2)
err = err2;
[-- Attachment #3: Type: text/plain, Size: 373 bytes --]
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
[-- Attachment #4: Type: text/plain, Size: 140 bytes --]
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2006-11-09 20:10 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-09 20:10 [PATCH] NFSv3 server side create modes Peter Staubach
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox