diff options
| author | Bryan Schumaker <bjschuma@netapp.com> | 2010-09-24 18:50:01 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-10-23 15:27:31 -0400 |
| commit | d39ab9de3b80da5835049b1c3b49da4e84e01c07 (patch) | |
| tree | 8ffd7947d927f94bc467fd509c64d563b6f0110d | |
| parent | baf57a09e9d87b14be5e2788828169394a2525ab (diff) | |
NFS: re-add readdir plus
This patch adds readdir plus support to the cache array.
Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
| -rw-r--r-- | fs/nfs/dir.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 33b0ce7a97be..fd30f185ec01 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -370,6 +370,71 @@ int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, __be32 * | |||
| 370 | return 0; | 370 | return 0; |
| 371 | } | 371 | } |
| 372 | 372 | ||
| 373 | static | ||
| 374 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) | ||
| 375 | { | ||
| 376 | struct nfs_inode *node; | ||
| 377 | if (dentry->d_inode == NULL) | ||
| 378 | goto different; | ||
| 379 | node = NFS_I(dentry->d_inode); | ||
| 380 | if (node->fh.size != entry->fh->size) | ||
| 381 | goto different; | ||
| 382 | if (strncmp(node->fh.data, entry->fh->data, node->fh.size) != 0) | ||
| 383 | goto different; | ||
| 384 | return 1; | ||
| 385 | different: | ||
| 386 | return 0; | ||
| 387 | } | ||
| 388 | |||
| 389 | static | ||
| 390 | void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | ||
| 391 | { | ||
| 392 | struct qstr filename; | ||
| 393 | struct dentry *dentry = NULL; | ||
| 394 | struct dentry *alias = NULL; | ||
| 395 | struct inode *dir = parent->d_inode; | ||
| 396 | struct inode *inode; | ||
| 397 | |||
| 398 | nfs_readdir_make_qstr(&filename, entry->name, entry->len); | ||
| 399 | if (filename.len == 1 && filename.name[0] == '.') | ||
| 400 | dentry = dget(parent); | ||
| 401 | else if (filename.len == 2 && filename.name[0] == '.' | ||
| 402 | && filename.name[1] == '.') | ||
| 403 | dentry = dget_parent(parent); | ||
| 404 | else | ||
| 405 | dentry = d_lookup(parent, &filename); | ||
| 406 | |||
| 407 | if (dentry != NULL) { | ||
| 408 | if (nfs_same_file(dentry, entry)) { | ||
| 409 | nfs_refresh_inode(dentry->d_inode, entry->fattr); | ||
| 410 | goto out; | ||
| 411 | } else { | ||
| 412 | d_drop(dentry); | ||
| 413 | dput(dentry); | ||
| 414 | } | ||
| 415 | } | ||
| 416 | |||
| 417 | dentry = d_alloc(parent, &filename); | ||
| 418 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | ||
| 419 | inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr); | ||
| 420 | if (IS_ERR(inode)) | ||
| 421 | goto out; | ||
| 422 | |||
| 423 | alias = d_materialise_unique(dentry, inode); | ||
| 424 | if (IS_ERR(alias)) | ||
| 425 | goto out; | ||
| 426 | else if (alias) { | ||
| 427 | nfs_set_verifier(alias, nfs_save_change_attribute(dir)); | ||
| 428 | dput(alias); | ||
| 429 | } else | ||
| 430 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 431 | |||
| 432 | out: | ||
| 433 | dput(dentry); | ||
| 434 | kfree(filename.name); | ||
| 435 | return; | ||
| 436 | } | ||
| 437 | |||
| 373 | /* Perform conversion from xdr to cache array */ | 438 | /* Perform conversion from xdr to cache array */ |
| 374 | static | 439 | static |
| 375 | void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, | 440 | void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, |
| @@ -379,6 +444,8 @@ void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *e | |||
| 379 | while (xdr_decode(desc, entry, &ptr) == 0) { | 444 | while (xdr_decode(desc, entry, &ptr) == 0) { |
| 380 | if (nfs_readdir_add_to_array(entry, page) == -1) | 445 | if (nfs_readdir_add_to_array(entry, page) == -1) |
| 381 | break; | 446 | break; |
| 447 | if (desc->plus == 1) | ||
| 448 | nfs_prime_dcache(desc->file->f_path.dentry, entry); | ||
| 382 | } | 449 | } |
| 383 | kunmap(xdr_page); | 450 | kunmap(xdr_page); |
| 384 | } | 451 | } |
