Commit 43a9aa64a2f4330a9cb59aaf5c5636566bce067c

Authored by Chuck Lever
Committed by J. Bruce Fields
1 parent 6a85d6c769

NFSD: Fill in WCC data for REMOVE, RMDIR, MKNOD, and MKDIR

Some well-known NFSv3 clients drop their directory entry caches when
they receive replies with no WCC data.  Without this data, they
employ extra READ, LOOKUP, and GETATTR requests to ensure their
directory entry caches are up to date, causing performance to suffer
needlessly.

In order to return WCC data, our server has to have both the pre-op
and the post-op attribute data on hand when a reply is XDR encoded.
The pre-op data is filled in when the incoming fh is locked, and the
post-op data is filled in when the fh is unlocked.

Unfortunately, for REMOVE, RMDIR, MKNOD, and MKDIR, the directory fh
is not unlocked until well after the reply has been XDR encoded.  This
means that encode_wcc_data() does not have wcc_data for the parent
directory, so none is returned to the client after these operations
complete.

By unlocking the parent directory fh immediately after the internal
operations for each NFS procedure is complete, the post-op data is
filled in before XDR encoding starts, so it can be returned to the
client properly.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>

Showing 1 changed file with 4 additions and 2 deletions Side-by-side Diff

... ... @@ -271,7 +271,7 @@
271 271 fh_init(&resp->fh, NFS3_FHSIZE);
272 272 nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
273 273 &argp->attrs, S_IFDIR, 0, &resp->fh);
274   -
  274 + fh_unlock(&resp->dirfh);
275 275 RETURN_STATUS(nfserr);
276 276 }
277 277  
... ... @@ -327,7 +327,7 @@
327 327 type = nfs3_ftypes[argp->ftype];
328 328 nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
329 329 &argp->attrs, type, rdev, &resp->fh);
330   -
  330 + fh_unlock(&resp->dirfh);
331 331 RETURN_STATUS(nfserr);
332 332 }
333 333  
... ... @@ -348,6 +348,7 @@
348 348 /* Unlink. -S_IFDIR means file must not be a directory */
349 349 fh_copy(&resp->fh, &argp->fh);
350 350 nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len);
  351 + fh_unlock(&resp->fh);
351 352 RETURN_STATUS(nfserr);
352 353 }
353 354  
... ... @@ -367,6 +368,7 @@
367 368  
368 369 fh_copy(&resp->fh, &argp->fh);
369 370 nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len);
  371 + fh_unlock(&resp->fh);
370 372 RETURN_STATUS(nfserr);
371 373 }
372 374