/* our acceptability function. if NOSUBTREECHECK, accept anything if not, require that we can walk up to exp->ex_dentry doing some checks on the 'x' bits  */
static int nfsd_acceptable(void *expv, struct dentry *dentry)
/* our acceptability function. if NOSUBTREECHECK, accept anything if not, require that we can walk up to exp->ex_dentry doing some checks on the 'x' bits  */
static int nfsd_acceptable(void *expv, struct dentry *dentry)
{
	struct svc_export *exp = expv;
	int rv;
	struct dentry *tdentry;
	struct dentry *parent;
	if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
		return 1;
	tdentry = dget(dentry);
	while (tdentry != exp->ex_path.dentry && !IS_ROOT(tdentry)) {
		int err;
		parent = dget_parent(tdentry);
		err = inode_permission(parent->d_inode, MAY_EXEC);
		if (err < 0) {
			dput(parent);
			break;
		}
		dput(tdentry);
		tdentry = parent;
	}
	if (tdentry != exp->ex_path.dentry)
		dprintk("nfsd_acceptable failed at %p %s\n", tdentry, tdentry->d_name.name);
	rv = (tdentry == exp->ex_path.dentry);
	dput(tdentry);
	return rv;
}