Loading fs/nfs/dir.c +67 −0 Original line number Diff line number Diff line Loading @@ -370,6 +370,71 @@ int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, __be32 * return 0; } static int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) { struct nfs_inode *node; if (dentry->d_inode == NULL) goto different; node = NFS_I(dentry->d_inode); if (node->fh.size != entry->fh->size) goto different; if (strncmp(node->fh.data, entry->fh->data, node->fh.size) != 0) goto different; return 1; different: return 0; } static void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) { struct qstr filename; struct dentry *dentry = NULL; struct dentry *alias = NULL; struct inode *dir = parent->d_inode; struct inode *inode; nfs_readdir_make_qstr(&filename, entry->name, entry->len); if (filename.len == 1 && filename.name[0] == '.') dentry = dget(parent); else if (filename.len == 2 && filename.name[0] == '.' && filename.name[1] == '.') dentry = dget_parent(parent); else dentry = d_lookup(parent, &filename); if (dentry != NULL) { if (nfs_same_file(dentry, entry)) { nfs_refresh_inode(dentry->d_inode, entry->fattr); goto out; } else { d_drop(dentry); dput(dentry); } } dentry = d_alloc(parent, &filename); dentry->d_op = NFS_PROTO(dir)->dentry_ops; inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr); if (IS_ERR(inode)) goto out; alias = d_materialise_unique(dentry, inode); if (IS_ERR(alias)) goto out; else if (alias) { nfs_set_verifier(alias, nfs_save_change_attribute(dir)); dput(alias); } else nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); out: dput(dentry); kfree(filename.name); return; } /* Perform conversion from xdr to cache array */ static void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, Loading @@ -379,6 +444,8 @@ void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *e while (xdr_decode(desc, entry, &ptr) == 0) { if (nfs_readdir_add_to_array(entry, page) == -1) break; if (desc->plus == 1) nfs_prime_dcache(desc->file->f_path.dentry, entry); } kunmap(xdr_page); } Loading Loading
fs/nfs/dir.c +67 −0 Original line number Diff line number Diff line Loading @@ -370,6 +370,71 @@ int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, __be32 * return 0; } static int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) { struct nfs_inode *node; if (dentry->d_inode == NULL) goto different; node = NFS_I(dentry->d_inode); if (node->fh.size != entry->fh->size) goto different; if (strncmp(node->fh.data, entry->fh->data, node->fh.size) != 0) goto different; return 1; different: return 0; } static void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) { struct qstr filename; struct dentry *dentry = NULL; struct dentry *alias = NULL; struct inode *dir = parent->d_inode; struct inode *inode; nfs_readdir_make_qstr(&filename, entry->name, entry->len); if (filename.len == 1 && filename.name[0] == '.') dentry = dget(parent); else if (filename.len == 2 && filename.name[0] == '.' && filename.name[1] == '.') dentry = dget_parent(parent); else dentry = d_lookup(parent, &filename); if (dentry != NULL) { if (nfs_same_file(dentry, entry)) { nfs_refresh_inode(dentry->d_inode, entry->fattr); goto out; } else { d_drop(dentry); dput(dentry); } } dentry = d_alloc(parent, &filename); dentry->d_op = NFS_PROTO(dir)->dentry_ops; inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr); if (IS_ERR(inode)) goto out; alias = d_materialise_unique(dentry, inode); if (IS_ERR(alias)) goto out; else if (alias) { nfs_set_verifier(alias, nfs_save_change_attribute(dir)); dput(alias); } else nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); out: dput(dentry); kfree(filename.name); return; } /* Perform conversion from xdr to cache array */ static void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, Loading @@ -379,6 +444,8 @@ void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *e while (xdr_decode(desc, entry, &ptr) == 0) { if (nfs_readdir_add_to_array(entry, page) == -1) break; if (desc->plus == 1) nfs_prime_dcache(desc->file->f_path.dentry, entry); } kunmap(xdr_page); } Loading