Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d39ab9de authored by Bryan Schumaker's avatar Bryan Schumaker Committed by Trond Myklebust
Browse files

NFS: re-add readdir plus



This patch adds readdir plus support to the cache array.

Signed-off-by: default avatarBryan Schumaker <bjschuma@netapp.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent baf57a09
Loading
Loading
Loading
Loading
+67 −0
Original line number Original line Diff line number Diff line
@@ -370,6 +370,71 @@ int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, __be32 *
	return 0;
	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 */
/* Perform conversion from xdr to cache array */
static
static
void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry,
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
	while (xdr_decode(desc, entry, &ptr) == 0) {
	while (xdr_decode(desc, entry, &ptr) == 0) {
		if (nfs_readdir_add_to_array(entry, page) == -1)
		if (nfs_readdir_add_to_array(entry, page) == -1)
			break;
			break;
		if (desc->plus == 1)
			nfs_prime_dcache(desc->file->f_path.dentry, entry);
	}
	}
	kunmap(xdr_page);
	kunmap(xdr_page);
}
}