Beispiel #1
0
int wind_dentries_2_4(struct dentry * dentry, struct vfsmount * vfsmnt, struct dentry * root, struct vfsmount * rootmnt)
{
	struct dentry * d = dentry;
	struct vfsmount * v = vfsmnt;

	/* wind the dentries onto the stack pages */
	for (;;) {
		/* deleted ? */
		if (!IS_ROOT(d) && list_empty(&d->d_hash))
			return 0;

		/* the root */
		if (d == root && v == rootmnt)
			break;

		if (d == v->mnt_root || IS_ROOT(d)) {
			if (v->mnt_parent == v)
				break;
			/* cross the mount point */
			d = v->mnt_mountpoint;
			v = v->mnt_parent;
		}

		push_dname(&d->d_name);

		d = d->d_parent;
	}

	return 1;
}
Beispiel #2
0
int pohmelfs_path_length(struct pohmelfs_inode *pi)
{
	struct dentry *d, *root, *first;
	int len = 1; 

	first = d = d_find_alias(&pi->vfs_inode);
	if (!d) {
		dprintk("%s: ino: %llu, mode: %o.\n", __func__, pi->ino, pi->vfs_inode.i_mode);
		return -ENOENT;
	}

	read_lock(&current->fs->lock);
	root = dget(current->fs->root.dentry);
	read_unlock(&current->fs->lock);

	spin_lock(&dcache_lock);

	if (!IS_ROOT(d) && d_unhashed(d))
		len += UNHASHED_OBSCURE_STRING_SIZE; 

	while (d && d != root && !IS_ROOT(d)) {
		len += d->d_name.len + 1; 
		d = d->d_parent;
	}
	spin_unlock(&dcache_lock);

	dput(root);
	dput(first);

	return len + 1; 
}
int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
			    struct autofs_sb_info *sbi, int when)
{
	struct dentry *dentry;
	int ret = -EAGAIN;

	if (autofs_type_trigger(sbi->type))
		dentry = autofs4_expire_direct(sb, mnt, sbi, when);
	else
		dentry = autofs4_expire_indirect(sb, mnt, sbi, when);

	if (dentry) {
		struct autofs_info *ino = autofs4_dentry_ino(dentry);

		ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);

		spin_lock(&sbi->fs_lock);
		ino->flags &= ~AUTOFS_INF_EXPIRING;
		spin_lock(&dentry->d_lock);
		if (!ret) {
			if ((IS_ROOT(dentry) ||
			    (autofs_type_indirect(sbi->type) &&
			     IS_ROOT(dentry->d_parent))) &&
			    !(dentry->d_flags & DCACHE_NEED_AUTOMOUNT))
				__managed_dentry_set_automount(dentry);
		}
		spin_unlock(&dentry->d_lock);
		complete_all(&ino->expire_complete);
		spin_unlock(&sbi->fs_lock);
		dput(dentry);
	}

	return ret;
}
Beispiel #4
0
/* Note: caller must free return buffer */
char *
build_path_from_dentry(struct dentry *direntry)
{
    struct dentry *temp;
    int namelen = 0;
    char *full_path;
    char dirsep;

    if(direntry == NULL)
        return NULL;  /* not much we can do if dentry is freed and
		we need to reopen the file after it was closed implicitly
		when the server crashed */

    dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
cifs_bp_rename_retry:
    for (temp = direntry; !IS_ROOT(temp);) {
        namelen += (1 + temp->d_name.len);
        temp = temp->d_parent;
        if(temp == NULL) {
            cERROR(1,("corrupt dentry"));
            return NULL;
        }
    }

    full_path = kmalloc(namelen+1, GFP_KERNEL);
    if(full_path == NULL)
        return full_path;
    full_path[namelen] = 0;	/* trailing null */

    for (temp = direntry; !IS_ROOT(temp);) {
        namelen -= 1 + temp->d_name.len;
        if (namelen < 0) {
            break;
        } else {
            full_path[namelen] = dirsep;
            strncpy(full_path + namelen + 1, temp->d_name.name,
                    temp->d_name.len);
            cFYI(0, (" name: %s ", full_path + namelen));
        }
        temp = temp->d_parent;
        if(temp == NULL) {
            cERROR(1,("corrupt dentry"));
            kfree(full_path);
            return NULL;
        }
    }
    if (namelen != 0) {
        cERROR(1,
               ("We did not end path lookup where we expected namelen is %d",
                namelen));
        /* presumably this is only possible if we were racing with a rename
        of one of the parent directories  (we can not lock the dentries
        above us to prevent this, but retrying should be harmless) */
        kfree(full_path);
        namelen = 0;
        goto cifs_bp_rename_retry;
    }

    return full_path;
}
Beispiel #5
0
/*
 * if valid returns 1, otherwise 0.
 */
static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
{
	int valid, err;
	unsigned int sigen;
	unsigned char do_udba;
	struct super_block *sb;
	struct inode *inode;

	err = -EINVAL;
	sb = dentry->d_sb;
	inode = dentry->d_inode;
	aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW);
	sigen = au_sigen(sb);
	if (au_digen(dentry) != sigen) {
		AuDebugOn(IS_ROOT(dentry));
		if (inode)
			err = au_reval_dpath(dentry, sigen);
		if (unlikely(err))
			goto out_dgrade;
		AuDebugOn(au_digen(dentry) != sigen);
	}
	if (inode && au_iigen(inode) != sigen) {
		AuDebugOn(IS_ROOT(dentry));
		err = au_refresh_hinode(inode, dentry);
		if (unlikely(err))
			goto out_dgrade;
		AuDebugOn(au_iigen(inode) != sigen);
	}
	di_downgrade_lock(dentry, AuLock_IR);

	AuDebugOn(au_digen(dentry) != sigen);
	AuDebugOn(inode && au_iigen(inode) != sigen);
	err = -EINVAL;
	do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
	if (do_udba && inode) {
		aufs_bindex_t bstart = au_ibstart(inode);

		if (bstart >= 0
		    && au_test_higen(inode, au_h_iptr(inode, bstart)))
			goto out;
	}

	err = h_d_revalidate(dentry, inode, nd, do_udba);
	if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
		/* both of real entry and whiteout found */
		err = -EIO;
	goto out;

 out_dgrade:
	di_downgrade_lock(dentry, AuLock_IR);
 out:
	aufs_read_unlock(dentry, AuLock_IR);
	AuTraceErr(err);
	valid = !err;
	if (!valid)
		AuDbg("%.*s invalid\n", AuDLNPair(dentry));
	return valid;
}
Beispiel #6
0
/*
 * decide the branch and the parent dir where we will create a new entry.
 * returns new bindex or an error.
 * copyup the parent dir if needed.
 */
int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
	      struct au_wr_dir_args *args)
{
	int err;
	aufs_bindex_t bcpup, bstart, src_bstart;
	const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
							 ADD_ENTRY);
	struct super_block *sb;
	struct dentry *parent;
	struct au_sbinfo *sbinfo;

	sb = dentry->d_sb;
	sbinfo = au_sbi(sb);
	parent = dget_parent(dentry);
	bstart = au_dbstart(dentry);
	bcpup = bstart;
	if (args->force_btgt < 0) {
		if (src_dentry) {
			src_bstart = au_dbstart(src_dentry);
			if (src_bstart < bstart)
				bcpup = src_bstart;
		} else if (add_entry) {
			err = AuWbrCreate(sbinfo, dentry,
					  au_ftest_wrdir(args->flags, ISDIR));
			bcpup = err;
		}

		if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
			if (add_entry)
				err = AuWbrCopyup(sbinfo, dentry);
			else {
				if (!IS_ROOT(dentry)) {
					di_read_lock_parent(parent, !AuLock_IR);
					err = AuWbrCopyup(sbinfo, dentry);
					di_read_unlock(parent, !AuLock_IR);
				} else
					err = AuWbrCopyup(sbinfo, dentry);
			}
			bcpup = err;
			if (unlikely(err < 0))
				goto out;
		}
	} else {
		bcpup = args->force_btgt;
		AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
	}
	AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
	err = bcpup;
	if (bcpup == bstart)
		goto out; /* success */
	else if (bstart < bcpup)
		au_update_dbrange(dentry, /*do_put_zero*/1);

	/* copyup the new parent into the branch we process */
	err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);

 out:
	dput(parent);
	return err;
}
Beispiel #7
0
/*
 * 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_dentry && ! IS_ROOT(tdentry)) {
		/* make sure parents give x permission to user */
		int err;
		parent = dget_parent(tdentry);
		err = permission(parent->d_inode, MAY_EXEC, NULL);
		if (err < 0) {
			dput(parent);
			break;
		}
		dput(tdentry);
		tdentry = parent;
	}
	if (tdentry != exp->ex_dentry)
		dprintk("nfsd_acceptable failed at %p %s\n", tdentry, tdentry->d_name.name);
	rv = (tdentry == exp->ex_dentry);
	dput(tdentry);
	return rv;
}
Beispiel #8
0
/*
 * nfs_follow_mountpoint - handle crossing a mountpoint on the server
 * @dentry - dentry of mountpoint
 * @nd - nameidata info
 *
 * When we encounter a mountpoint on the server, we want to set up
 * a mountpoint on the client too, to prevent inode numbers from
 * colliding, and to allow "df" to work properly.
 * On NFSv4, we also want to allow for the fact that different
 * filesystems may be migrated to different servers in a failover
 * situation, and that different filesystems may want to use
 * different security flavours.
 */
static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
{
	struct vfsmount *mnt;
	struct nfs_server *server = NFS_SERVER(dentry->d_inode);
	struct dentry *parent;
	struct nfs_fh fh;
	struct nfs_fattr fattr;
	int err;

	dprintk("--> nfs_follow_mountpoint()\n");

	BUG_ON(IS_ROOT(dentry));
	dprintk("%s: enter\n", __FUNCTION__);
	dput(nd->dentry);
	nd->dentry = dget(dentry);

	/* Look it up again */
	parent = dget_parent(nd->dentry);
	err = server->nfs_client->rpc_ops->lookup(parent->d_inode,
						  &nd->dentry->d_name,
						  &fh, &fattr);
	dput(parent);
	if (err != 0)
		goto out_err;

	if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL)
		mnt = nfs_do_refmount(nd->mnt, nd->dentry);
	else
		mnt = nfs_do_submount(nd->mnt, nd->dentry, &fh, &fattr);
	err = PTR_ERR(mnt);
	if (IS_ERR(mnt))
		goto out_err;

	mntget(mnt);
	err = do_add_mount(mnt, nd, nd->mnt->mnt_flags|MNT_SHRINKABLE, &nfs_automount_list);
	if (err < 0) {
		mntput(mnt);
		if (err == -EBUSY)
			goto out_follow;
		goto out_err;
	}
	mntput(nd->mnt);
	dput(nd->dentry);
	nd->mnt = mnt;
	nd->dentry = dget(mnt->mnt_root);
	schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout);
out:
	dprintk("%s: done, returned %d\n", __FUNCTION__, err);

	dprintk("<-- nfs_follow_mountpoint() = %d\n", err);
	return ERR_PTR(err);
out_err:
	path_release(nd);
	goto out;
out_follow:
	while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry))
		;
	err = 0;
	goto out;
}
int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
		       int do_include, au_dpages_test test, void *arg)
{
	int err;

	err = 0;
	write_seqlock(&rename_lock);
	spin_lock(&dentry->d_lock);
	if (do_include
	    && d_count(dentry)
	    && (!test || test(dentry, arg)))
		err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
	spin_unlock(&dentry->d_lock);
	if (unlikely(err))
		goto out;

	/*
	 * RCU for vfsmount is unnecessary since this is a traverse in a single
	 * mount
	 */
	while (!IS_ROOT(dentry)) {
		dentry = dentry->d_parent; /* rename_lock is locked */
		spin_lock(&dentry->d_lock);
		if (d_count(dentry)
		    && (!test || test(dentry, arg)))
			err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
		spin_unlock(&dentry->d_lock);
		if (unlikely(err))
			break;
	}

out:
	write_sequnlock(&rename_lock);
	return err;
}
Beispiel #10
0
int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
		       int do_include, au_dpages_test test, void *arg)
{
	int err;

	err = 0;
	spin_lock(&dcache_lock);
	if (do_include && (!test || test(dentry, arg))) {
		err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
		if (unlikely(err))
			goto out;
	}
	while (!IS_ROOT(dentry)) {
		dentry = dentry->d_parent; /* dcache_lock is locked */
		if (!test || test(dentry, arg)) {
			err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
			if (unlikely(err))
				break;
		}
	}

out:
	spin_unlock(&dcache_lock);

	return err;
}
Beispiel #11
0
/*
 * Takes a file ptr and checks if any parent is under watch
 * fileptr can be obtained from an fd and from a file name too and then
 * passed to this function
 * Assumes filePtr is a valid file pointer
 */
unsigned long check_if_any_parent_is_watched_filp(struct file *filePtr)
{
    unsigned long parentInodeNo = 0, tempno = 0;
    struct dentry *parentPtr = NULL;

    /* To Prevent the parent dentry loop from going in an infinite loop */
    int i = 0;

    /* Get the dentry of the parent of the open file */
    parentPtr = filePtr->f_path.dentry->d_parent;
    while (parentPtr != NULL && i < 20) {
        tempno = parentPtr->d_inode->i_ino;
        if (is_stat(tempno)) {
            parentInodeNo = tempno;
            break;
        } else if (IS_ROOT(parentPtr)) {
            break;
        } else {
            i++;
            parentPtr = parentPtr->d_parent;
        }
    }

    return parentInodeNo;
}
/* main function for updating derived permission */
inline void update_derived_permission(struct dentry *dentry)
{
	struct dentry *parent;

    struct sdcardfs_sb_info *sbi;
    int mask = 0;

	if(!dentry || !dentry->d_inode) {
		printk(KERN_ERR "sdcardfs: %s: invalid dentry\n", __func__);
		return;
	}
	/* FIXME:
	 * 1. need to check whether the dentry is updated or not
	 * 2. remove the root dentry update
	 */
	if(IS_ROOT(dentry)) {
		//setup_default_pre_root_state(dentry->d_inode);
	} else {
		parent = dget_parent(dentry);
		if(parent) {
			get_derived_permission(parent, dentry);
			dput(parent);
		}
	}
    sbi = SDCARDFS_SB(dentry->d_sb);
    mask = sbi->options.sdfs_mask;
    fix_derived_permission(dentry->d_inode, mask);
}
Beispiel #13
0
/*
 * nfs_d_automount - Handle crossing a mountpoint on the server
 * @path - The mountpoint
 *
 * When we encounter a mountpoint on the server, we want to set up
 * a mountpoint on the client too, to prevent inode numbers from
 * colliding, and to allow "df" to work properly.
 * On NFSv4, we also want to allow for the fact that different
 * filesystems may be migrated to different servers in a failover
 * situation, and that different filesystems may want to use
 * different security flavours.
 */
struct vfsmount *nfs_d_automount(struct path *path)
{
	struct vfsmount *mnt;
	struct nfs_server *server = NFS_SERVER(d_inode(path->dentry));
	struct nfs_fh *fh = NULL;
	struct nfs_fattr *fattr = NULL;

	if (IS_ROOT(path->dentry))
		return ERR_PTR(-ESTALE);

	mnt = ERR_PTR(-ENOMEM);
	fh = nfs_alloc_fhandle();
	fattr = nfs_alloc_fattr();
	if (fh == NULL || fattr == NULL)
		goto out;

	mnt = server->nfs_client->rpc_ops->submount(server, path->dentry, fh, fattr);
	if (IS_ERR(mnt))
		goto out;

	mntget(mnt); /* prevent immediate expiration */
	mnt_set_expiry(mnt, &nfs_automount_list);
	schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout);

out:
	nfs_free_fattr(fattr);
	nfs_free_fhandle(fh);
	return mnt;
}
Beispiel #14
0
Datei: dir.c Projekt: 274914765/C
static int
smb_dir_open(struct inode *dir, struct file *file)
{
    struct dentry *dentry = file->f_path.dentry;
    struct smb_sb_info *server;
    int error = 0;

    VERBOSE("(%s/%s)\n", dentry->d_parent->d_name.name,
        file->f_path.dentry->d_name.name);

    /*
     * Directory timestamps in the core protocol aren't updated
     * when a file is added, so we give them a very short TTL.
     */
    lock_kernel();
    server = server_from_dentry(dentry);
    if (server->opt.protocol < SMB_PROTOCOL_LANMAN2) {
        unsigned long age = jiffies - SMB_I(dir)->oldmtime;
        if (age > 2*HZ)
            smb_invalid_dir_cache(dir);
    }

    /*
     * Note: in order to allow the smbmount process to open the
     * mount point, we only revalidate if the connection is valid or
     * if the process is trying to access something other than the root.
     */
    if (server->state == CONN_VALID || !IS_ROOT(dentry))
        error = smb_revalidate_inode(dentry);
    unlock_kernel();
    return error;
}
Beispiel #15
0
void
renew_parental_timestamps(struct dentry *direntry)
{
	/* BB check if there is a way to get the kernel to do this or if we really need this */
	do {
		direntry->d_time = jiffies;
		direntry = direntry->d_parent;
	} while (!IS_ROOT(direntry));	
}
/*
 * A check for whether or not the parent directory has changed.
 * In the case it has, we assume that the dentries are untrustworthy
 * and may need to be looked up again.
 */
static inline int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
{
	if (IS_ROOT(dentry))
		return 1;
	if ((NFS_FLAGS(dir) & NFS_INO_INVALID_ATTR) != 0
			|| nfs_attribute_timeout(dir))
		return 0;
	return nfs_verify_change_attribute(dir, (unsigned long)dentry->d_fsdata);
}
Beispiel #17
0
static int is_ancestor(const struct dentry *d1, const struct dentry *d2)
{
	do {
		if (d1 == d2)
			return 1;
		d1 = d1->d_parent;
	} while (!IS_ROOT(d1));
	return 0;
}
/*
 * A check for whether or not the parent directory has changed.
 * In the case it has, we assume that the dentries are untrustworthy
 * and may need to be looked up again.
 */
static inline
int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
{
	if (IS_ROOT(dentry))
		return 1;
	if (nfs_revalidate_inode(NFS_SERVER(dir), dir))
		return 0;
	return time_after(dentry->d_time, NFS_MTIME_UPDATE(dir));
}
Beispiel #19
0
/*
 * nfs_d_automount - Handle crossing a mountpoint on the server
 * @path - The mountpoint
 *
 * When we encounter a mountpoint on the server, we want to set up
 * a mountpoint on the client too, to prevent inode numbers from
 * colliding, and to allow "df" to work properly.
 * On NFSv4, we also want to allow for the fact that different
 * filesystems may be migrated to different servers in a failover
 * situation, and that different filesystems may want to use
 * different security flavours.
 */
struct vfsmount *nfs_d_automount(struct path *path)
{
	struct vfsmount *mnt;
	struct nfs_server *server = NFS_SERVER(path->dentry->d_inode);
	struct dentry *parent;
	struct nfs_fh *fh = NULL;
	struct nfs_fattr *fattr = NULL;
	int err;
	rpc_authflavor_t flavor = RPC_AUTH_UNIX;

	dprintk("--> nfs_d_automount()\n");

	mnt = ERR_PTR(-ESTALE);
	if (IS_ROOT(path->dentry))
		goto out_nofree;

	mnt = ERR_PTR(-ENOMEM);
	fh = nfs_alloc_fhandle();
	fattr = nfs_alloc_fattr();
	if (fh == NULL || fattr == NULL)
		goto out;

	dprintk("%s: enter\n", __func__);

	/* Look it up again to get its attributes */
	parent = dget_parent(path->dentry);
	err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode,
						  &path->dentry->d_name,
						  fh, fattr);
	if (err == -EPERM && NFS_PROTO(parent->d_inode)->secinfo != NULL)
		err = nfs_lookup_with_sec(server, parent, path->dentry, path, fh, fattr, &flavor);
	dput(parent);
	if (err != 0) {
		mnt = ERR_PTR(err);
		goto out;
	}

	if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
		mnt = nfs_do_refmount(path->dentry);
	else
		mnt = nfs_do_submount(path->dentry, fh, fattr, flavor);
	if (IS_ERR(mnt))
		goto out;

	dprintk("%s: done, success\n", __func__);
	mntget(mnt); /* prevent immediate expiration */
	mnt_set_expiry(mnt, &nfs_automount_list);
	schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout);

out:
	nfs_free_fattr(fattr);
	nfs_free_fhandle(fh);
out_nofree:
	dprintk("<-- nfs_follow_mountpoint() = %p\n", mnt);
	return mnt;
}
Beispiel #20
0
/* common functions to regular file and dir */
struct file *hidden_open(struct dentry *dentry, aufs_bindex_t bindex, int flags)
{
	struct dentry *hidden_dentry;
	struct inode *hidden_inode;
	struct super_block *sb;
	struct vfsmount *hidden_mnt;
	struct file *hidden_file;
	struct aufs_branch *br;
	loff_t old_size;
	int udba;

	LKTRTrace("%.*s, b%d, flags 0%o\n", DLNPair(dentry), bindex, flags);
	DEBUG_ON(!dentry);
	hidden_dentry = au_h_dptr_i(dentry, bindex);
	DEBUG_ON(!hidden_dentry);
	hidden_inode = hidden_dentry->d_inode;
	DEBUG_ON(!hidden_inode);

	sb = dentry->d_sb;
	udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
	if (unlikely(udba)) {
		// test here?
	}

	br = stobr(sb, bindex);
	br_get(br);
	/* drop flags for writing */
	if (test_ro(sb, bindex, dentry->d_inode))
		flags = au_file_roflags(flags);
	flags &= ~O_CREAT;
	spin_lock(&hidden_inode->i_lock);
	old_size = i_size_read(hidden_inode);
	spin_unlock(&hidden_inode->i_lock);

	//DbgSleep(3);

	dget(hidden_dentry);
	hidden_mnt = mntget(br->br_mnt);
	hidden_file = dentry_open(hidden_dentry, hidden_mnt, flags);
	//if (LktrCond) {fput(hidden_file); hidden_file = ERR_PTR(-1);}

	if (!IS_ERR(hidden_file)) {
#if 0 // remove this
		if (/* old_size && */ (flags & O_TRUNC)) {
			au_direval_dec(dentry);
			if (!IS_ROOT(dentry))
				au_direval_dec(dentry->d_parent);
		}
#endif
		return hidden_file;
	}

	br_put(br);
	TraceErrPtr(hidden_file);
	return hidden_file;
}
Beispiel #21
0
void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
{
	struct dentry *parent;

	parent = dget_parent(dentry);
	AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
	AuDebugOn(IS_ROOT(dentry));
	AuDebugOn(au_digen_test(parent, sigen));
	dput(parent);
}
Beispiel #22
0
struct vfsmount *nfs_d_automount(struct path *path)
{
	struct vfsmount *mnt;
	struct dentry *parent;
	struct nfs_fh *fh = NULL;
	struct nfs_fattr *fattr = NULL;
	struct rpc_clnt *client;

	dprintk("--> nfs_d_automount()\n");

	mnt = ERR_PTR(-ESTALE);
	if (IS_ROOT(path->dentry))
		goto out_nofree;

	mnt = ERR_PTR(-ENOMEM);
	fh = nfs_alloc_fhandle();
	fattr = nfs_alloc_fattr();
	if (fh == NULL || fattr == NULL)
		goto out;

	dprintk("%s: enter\n", __func__);

	
	parent = dget_parent(path->dentry);
	client = nfs_lookup_mountpoint(parent->d_inode, &path->dentry->d_name, fh, fattr);
	dput(parent);
	if (IS_ERR(client)) {
		mnt = ERR_CAST(client);
		goto out;
	}

	if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
		mnt = nfs_do_refmount(client, path->dentry);
	else
		mnt = nfs_do_submount(path->dentry, fh, fattr, client->cl_auth->au_flavor);
	rpc_shutdown_client(client);

	if (IS_ERR(mnt))
		goto out;

	dprintk("%s: done, success\n", __func__);
	mntget(mnt); 
	mnt_set_expiry(mnt, &nfs_automount_list);
	schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout);

out:
	nfs_free_fattr(fattr);
	nfs_free_fhandle(fh);
out_nofree:
	if (IS_ERR(mnt))
		dprintk("<-- %s(): error %ld\n", __func__, PTR_ERR(mnt));
	else
		dprintk("<-- %s() = %p\n", __func__, mnt);
	return mnt;
}
Beispiel #23
0
char *
build_wildcard_path_from_dentry(struct dentry *direntry)
{
	struct dentry *temp;
	int namelen = 0;
	char *full_path;

	for (temp = direntry; !IS_ROOT(temp);) {
		namelen += (1 + temp->d_name.len);
		temp = temp->d_parent;
	}
	namelen += 3;		/* allow for trailing null and wildcard (slash and *) */
	full_path = kmalloc(namelen, GFP_KERNEL);
	namelen--;
	full_path[namelen] = 0;	/* trailing null */
	namelen--;
	full_path[namelen] = '*';
	namelen--;
	full_path[namelen] = '\\';

	for (temp = direntry; !IS_ROOT(temp);) {
		namelen -= 1 + temp->d_name.len;
		if (namelen < 0) {
			break;
		} else {
			full_path[namelen] = '\\';
			strncpy(full_path + namelen + 1, temp->d_name.name,
				temp->d_name.len);
		}
		temp = temp->d_parent;
	}
	if (namelen != 0)
		cERROR(1,
		       ("We did not end path lookup where we expected namelen is %d",
			namelen));

	return full_path;
}
Beispiel #24
0
int pohmelfs_path_length(struct pohmelfs_inode *pi)
{
	struct dentry *d, *root, *first;
	int len;
	unsigned seq;

	first = d_find_alias(&pi->vfs_inode);
	if (!first) {
;
		return -ENOENT;
	}

	spin_lock(&current->fs->lock);
	root = dget(current->fs->root.dentry);
	spin_unlock(&current->fs->lock);

rename_retry:
	len = 1; /* Root slash */
	d = first;
	seq = read_seqbegin(&rename_lock);
	rcu_read_lock();

	if (!IS_ROOT(d) && d_unhashed(d))
		len += UNHASHED_OBSCURE_STRING_SIZE; /* Obscure " (deleted)" string */

	while (d && d != root && !IS_ROOT(d)) {
		len += d->d_name.len + 1; /* Plus slash */
		d = d->d_parent;
	}
	rcu_read_unlock();
	if (read_seqretry(&rename_lock, seq))
		goto rename_retry;

	dput(root);
	dput(first);

	return len + 1; /* Including zero-byte */
}
Beispiel #25
0
/* this routine links an IS_ROOT dentry into the dcache tree.  It gains "parent"
 * as a parent and "name" as a name
 * It should possibly go in dcache.c
 */
int d_splice(struct dentry *target, struct dentry *parent, struct qstr *name)
{
	struct dentry *tdentry;
#ifdef NFSD_PARANOIA
	if (!IS_ROOT(target))
		printk("nfsd: d_splice with no-root target: %s/%s\n", parent->d_name.name, name->name);
	if (!(target->d_flags & DCACHE_NFSD_DISCONNECTED))
		printk("nfsd: d_splice with non-DISCONNECTED target: %s/%s\n", parent->d_name.name, name->name);
#endif
	tdentry = d_alloc(parent, name);
	if (tdentry == NULL)
		return -ENOMEM;
	d_move(target, tdentry);

	/* tdentry will have been made a "child" of target (the parent of target)
	 * make it an IS_ROOT instead
	 */
	spin_lock(&dcache_lock);
	list_del_init(&tdentry->d_child);
	tdentry->d_parent = tdentry;
	spin_unlock(&dcache_lock);
	d_rehash(target);
	dput(tdentry);

	/* if parent is properly connected, then we can assert that
	 * the children are connected, but it must be a singluar (non-forking)
	 * branch
	 */
	if (!(parent->d_flags & DCACHE_NFSD_DISCONNECTED)) {
		while (target) {
			target->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
			parent = target;
			spin_lock(&dcache_lock);
			if (list_empty(&parent->d_subdirs))
				target = NULL;
			else {
				target = list_entry(parent->d_subdirs.next, struct dentry, d_child);
#ifdef NFSD_PARANOIA
				/* must be only child */
				if (target->d_child.next != &parent->d_subdirs
				    || target->d_child.prev != &parent->d_subdirs)
					printk("nfsd: d_splice found non-singular disconnected branch: %s/%s\n",
					       parent->d_name.name, target->d_name.name);
#endif
			}
			spin_unlock(&dcache_lock);
		}
	}
	return 0;
}
Beispiel #26
0
/**
 * Close file
 *
 * @v This			File handle
 * @ret Status		EFI status code
 */
static EFI_STATUS EFIAPI
FileClose(EFI_FILE_HANDLE This)
{
	EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);

	PrintInfo(L"Close(%llx|'%s') %s\n", (UINT64) This, FileName(File),
		IS_ROOT(File)?L"<ROOT>":L"");

	/* Nothing to do it this is the root */
	if (IS_ROOT(File))
		return EFI_SUCCESS;

	if (--File->RefCount == 0) {
		/* Close the file if it's a regular one */
		if (!File->IsDir)
			GrubClose(File);
		/* NB: basename points into File->path and does not need to be freed */
		FreePool(File->path);
		GrubDestroyFile(File);
	}

	return EFI_SUCCESS;
}
Beispiel #27
0
void *prlfs_get_path(struct dentry *dentry, void *buf, int *plen)
{
	int len;
	char *p;

	DPRINTK("ENTER\n");
	len = *plen;
	p = buf;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
	if ((dentry->d_name.len > NAME_MAX) || (len < 2)) {
		p = ERR_PTR(-ENAMETOOLONG);
		goto out;
	}
	p += --len;
	*p = '\0';
	spin_lock(&dcache_lock);
	while (!IS_ROOT(dentry)) {
		int nlen;
		struct dentry *parent;

                parent = dentry->d_parent;
		prefetch(parent);
		nlen = dentry->d_name.len;
		if (len < nlen + 1) {
			p = ERR_PTR(-ENAMETOOLONG);
			goto out_lock;
		}
		len -= nlen + 1;
		p -= nlen;
		memcpy(p, dentry->d_name.name, nlen);
		*(--p) = '/';
		dentry = parent;
	}
	if (*p != '/') {
		*(--p) = '/';
		--len;
	}
out_lock:
	spin_unlock(&dcache_lock);
	if (!IS_ERR(p))
		*plen -= len;
out:
#else
	p = dentry_path_raw(dentry, p, len);
	*plen = strnlen(p, PAGE_SIZE-1) + 1;
#endif
	DPRINTK("EXIT returning %p\n", p);
	return p;
}
Beispiel #28
0
int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
		   au_dpages_test test, void *arg)
{
	int err;
	struct dentry *this_parent = root;
	struct list_head *next;
	struct super_block *sb = root->d_sb;

	err = 0;
	spin_lock(&dcache_lock);
repeat:
	next = this_parent->d_subdirs.next;
resume:
	if (this_parent->d_sb == sb
	    && !IS_ROOT(this_parent)
	    && au_di(this_parent)
	    && (!test || test(this_parent, arg))) {
		err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
		if (unlikely(err))
			goto out;
	}

	while (next != &this_parent->d_subdirs) {
		struct list_head *tmp = next;
		struct dentry *dentry = list_entry(tmp, struct dentry,
						   d_u.d_child);
		next = tmp->next;
		if (!list_empty(&dentry->d_subdirs)) {
			this_parent = dentry;
			goto repeat;
		}
		if (dentry->d_sb == sb
		    && au_di(dentry)
		    && (!test || test(dentry, arg))) {
			err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
			if (unlikely(err))
				goto out;
		}
	}

	if (this_parent != root) {
		next = this_parent->d_u.d_child.next;
		this_parent = this_parent->d_parent; /* dcache_lock is locked */
		goto resume;
	}
out:
	spin_unlock(&dcache_lock);
	return err;
}
Beispiel #29
0
/* Makes an absolute path from nameidata, and allocates a string for it */
static char* absolutePath(struct dentry *dentry, struct vfsmount *mnt)
{
    char* path;
    size_t path_size = 0;
    char* absolute = NULL;
    ISystemRoot* root;
    char* apath;


    path = talpa_alloc_path(&path_size);

    if ( !path )
    {
        return NULL;
    }

    root = TALPA_Portability()->systemRoot();
    apath = talpa__d_path(dentry, mnt, root->directoryEntry(root->object), root->mountPoint(root->object), path, path_size);

    if (unlikely( apath == NULL ))
    {
        bool isDeleted = false;
        if ( dentry )
        {
            isDeleted = (!IS_ROOT(dentry) && d_unhashed(dentry));
        }
        critical("talpa__d_path failed for mnt=0x%p fstype=%s, dentry=0x%p deleted=%d",
            mnt,
            (const char *)mnt->mnt_sb->s_type->name,
            dentry,
            isDeleted);
    }
    else if (unlikely (IS_ERR(apath)))
    {
        apath = NULL;
    }
    else
    {
        absolute = talpa_alloc(strlen(apath) + 1);
        if ( absolute )
        {
            strcpy(absolute, apath);
        }
    }

    talpa_free_path(path);

    return absolute;
}
Beispiel #30
0
/*===========================================================================*
 *				make_path				     *
 *===========================================================================*/
int make_path(char path[PATH_MAX], struct inode *ino)
{
/* Given an inode, construct the path identifying that inode.
 */
  char buf[PATH_MAX], *p, *prefix;
  size_t len, plen, total;

  p = &buf[sizeof(buf) - 1];
  p[0] = 0;

  dprintf(("%s: make_path: constructing path for inode %d\n",
	sffs_name, ino->i_num));

  /* Get the length of the prefix, skipping any leading slashes. */
  for (prefix = sffs_params->p_prefix; prefix[0] == '/'; prefix++);
  plen = strlen(prefix);

  /* Construct the path right-to-left in a temporary buffer first. */
  for (total = plen; ino != NULL && !IS_ROOT(ino); ino = ino->i_parent) {
	len = strlen(ino->i_name);

	total += len + 1;
	p -= len + 1;

	if (total >= sizeof(buf))
		return ENAMETOOLONG;

	p[0] = '/';
	memcpy(p + 1, ino->i_name, len);
  }

  /* If any of the intermediate inodes has no parent, the final inode is no
   * longer addressable by name.
   */
  if (ino == NULL)
	return ENOENT;

  /* Put the result in the actual buffer. We need the leading slash in the
   * temporary buffer only when the prefix is not empty.
   */
  if (!prefix[0] && p[0] == '/') p++;

  strlcpy(path, prefix, PATH_MAX);
  strlcpy(&path[plen], p, PATH_MAX - plen);

  dprintf(("%s: make_path: resulting path is '%s'\n", sffs_name, path));

  return OK;
}