Exemple #1
0
static int unionfs_fsync(struct file *file, struct dentry *dentry, int datasync)
{
	int err;
	struct file *hidden_file = NULL;

	print_entry_location();

	if ((err = unionfs_file_revalidate(file, 1)))
		goto out;

	PASSERT(ftopd(file));
	hidden_file = ftohf(file);

	err = -EINVAL;
	if (!hidden_file->f_op || !hidden_file->f_op->fsync)
		goto out;

	down(&hidden_file->f_dentry->d_inode->i_sem);
	err = hidden_file->f_op->fsync(hidden_file, hidden_file->f_dentry,
				       datasync);
	up(&hidden_file->f_dentry->d_inode->i_sem);

      out:
	print_exit_status(err);
	return err;
}
Exemple #2
0
int unionfs_ioctl_branchcount(struct file *file, unsigned int cmd,
			      unsigned long arg)
{
	int err = 0;
	int bstart, bend;
	int i;
	struct super_block *sb = file->f_dentry->d_sb;

	print_entry_location();

	bstart = sbstart(sb);
	bend = sbend(sb);

	err = bend + 1;
	if (!arg)
		goto out;

	for (i = bstart; i <= bend; i++) {
		if (put_user(branch_count(sb, i), ((int *)arg) + i)) {
			err = -EFAULT;
			goto out;
		}
	}

      out:
	print_exit_status(err);
	return err;
}
Exemple #3
0
STATIC int
base0fs_readlink(struct dentry *dentry, char *buf, int bufsiz)
{
        int err;
        struct dentry *lower_dentry;

        print_entry_location();
        lower_dentry = base0fs_lower_dentry(dentry);/* CPW: Moved below print_entry_location */
        fist_print_dentry("base0fs_readlink IN", dentry);

        if (!lower_dentry->d_inode->i_op ||
             !lower_dentry->d_inode->i_op->readlink) {
                err = -EINVAL;
                goto out;
        }

        err = lower_dentry->d_inode->i_op->readlink(lower_dentry,
                                                    buf,
                                                    bufsiz);
        if (err > 0)
                fist_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode);

out:
        print_exit_status(err);
        return err;
}
Exemple #4
0
ssize_t unionfs_read(struct file * file, char *buf, size_t count, loff_t * ppos)
{
	int err = -EINVAL;
	struct file *hidden_file = NULL;
	loff_t pos = *ppos;

	print_entry_location();

	if ((err = unionfs_file_revalidate(file, 0)))
		goto out;

	fist_print_file("entering read()", file);

	PASSERT(ftopd(file));
	hidden_file = ftohf(file);
	PASSERT(hidden_file);

	if (!hidden_file->f_op || !hidden_file->f_op->read)
		goto out;

	err = hidden_file->f_op->read(hidden_file, buf, count, &pos);
	*ppos = pos;
	if (err >= 0) {
		/* atime should also be updated for reads of size zero or more */
		fist_copy_attr_atime(file->f_dentry->d_inode,
				     hidden_file->f_dentry->d_inode);
	}
	memcpy(&(file->f_ra), &(hidden_file->f_ra),
	       sizeof(struct file_ra_state));

      out:
	fist_print_file("leaving read()", file);
	print_exit_status(err);
	return err;
}
Exemple #5
0
int unionfs_readlink(struct dentry *dentry, char __user * buf, int bufsiz)
{
	int err;
	struct dentry *hidden_dentry;

	print_entry_location();
	lock_dentry(dentry);
	hidden_dentry = dtohd(dentry);
	fist_print_dentry("unionfs_readlink IN", dentry);

	if (!hidden_dentry->d_inode->i_op ||
	    !hidden_dentry->d_inode->i_op->readlink) {
		err = -EINVAL;
		goto out;
	}

	err = hidden_dentry->d_inode->i_op->readlink(hidden_dentry,
						     buf, bufsiz);
	if (err > 0)
		fist_copy_attr_atime(dentry->d_inode, hidden_dentry->d_inode);

      out:
	unlock_dentry(dentry);
	print_exit_status(err);
	return err;
}
Exemple #6
0
STATIC int
base0fs_mknod(inode_t *dir, struct dentry *dentry, int mode, dev_t dev)
{
        int err;
        struct dentry *lower_dentry;
        struct dentry *lower_dir_dentry;

        print_entry_location();
        lower_dentry = base0fs_lower_dentry(dentry);	/* CPW: Moved below print_entry_location */
        fist_checkinode(dir, "base0fs_mknod-dir");

        lower_dir_dentry = base0fs_lock_parent(lower_dentry);

        err = VFS_MKNOD(lower_dir_dentry->d_inode,
                        lower_dentry,
                        mode,
                        dev);
        if (err || !lower_dentry->d_inode)
                goto out;

        err = base0fs_interpose(lower_dentry, dentry, dir->i_sb, 0);
        if (err)
                goto out;
        fist_copy_attr_timesizes(dir, lower_dir_dentry->d_inode);

out:
        unlock_dir(lower_dir_dentry);
        if (!dentry->d_inode)
                d_drop(dentry);

        fist_checkinode(dir, "post base0fs_mknod-dir");
        print_exit_status(err);
        return err;
}
Exemple #7
0
/* BKL held by caller.
 * dentry->d_inode->i_sem down
 */
int
unionfs_setxattr(struct dentry *dentry, const char *name, const void *value,
		 size_t size, int flags)
{
	struct dentry *hidden_dentry = NULL;
	int err = -EOPNOTSUPP;

	print_entry_location();

	lock_dentry(dentry);
	hidden_dentry = dtohd(dentry);

	fist_dprint(8, "setxattr: name=\"%s\", value %lu bytes, flags=%x\n",
		    name, (unsigned long)size, flags);

	if (hidden_dentry->d_inode->i_op->setxattr) {
		down(&hidden_dentry->d_inode->i_sem);
		/* lock_kernel() already done by caller. */
		err = hidden_dentry->d_inode->i_op->
		    setxattr(hidden_dentry, name, value, size, flags);
		/* unlock_kernel() will be done by caller. */
		up(&hidden_dentry->d_inode->i_sem);
	}

	unlock_dentry(dentry);
	print_exit_status(err);
	return err;
}
Exemple #8
0
/* BKL held by caller.
 * dentry->d_inode->i_sem down
 */
int unionfs_removexattr(struct dentry *dentry, const char *name)
{
	struct dentry *hidden_dentry = NULL;
	int err = -EOPNOTSUPP;
	char *encoded_name;
	print_entry_location();

	lock_dentry(dentry);
	hidden_dentry = dtohd(dentry);

	fist_dprint(8, "removexattr: name=\"%s\"\n", name);

	if (hidden_dentry->d_inode->i_op->removexattr) {
		encoded_name = (char *)name;

		down(&hidden_dentry->d_inode->i_sem);
		/* lock_kernel() already done by caller. */
		err =
		    hidden_dentry->d_inode->i_op->removexattr(hidden_dentry,
							      encoded_name);
		/* unlock_kernel() will be done by caller. */
		up(&hidden_dentry->d_inode->i_sem);
	}

	unlock_dentry(dentry);
	print_exit_status(err);
	return err;
}
Exemple #9
0
/* The rest of these are utility functions for lookup. */
static int is_opaque_dir(struct dentry *dentry, int bindex)
{
	int err = 0;
	struct dentry *hidden_dentry;
	struct dentry *wh_hidden_dentry;
	struct inode *hidden_inode;
	uid_t saved_uid = current->fsuid;
	gid_t saved_gid = current->fsgid;

	print_entry_location();

	hidden_dentry = dtohd_index(dentry, bindex);
	hidden_inode = hidden_dentry->d_inode;

	BUG_ON(!S_ISDIR(hidden_inode->i_mode));

	current->fsuid = hidden_inode->i_uid;
	current->fsgid = hidden_inode->i_gid;
	wh_hidden_dentry = LOOKUP_ONE_LEN(UNIONFS_DIR_OPAQUE, hidden_dentry,
					  sizeof(UNIONFS_DIR_OPAQUE) - 1);
	current->fsuid = saved_uid;
	current->fsgid = saved_gid;
	if (IS_ERR(wh_hidden_dentry)) {
		err = PTR_ERR(wh_hidden_dentry);
		fist_dprint(1, "LOOKUP_ONE_LEN returned: %d\n", err);
		goto out;
	}
	if (wh_hidden_dentry->d_inode)
		err = 1;
	DPUT(wh_hidden_dentry);
      out:
	print_exit_status(err);
	return err;
}
Exemple #10
0
int
kdb3fs_d_delete(dentry_t *dentry)
{
	dentry_t *hidden_dentry;
	int err = 0;

	print_entry_location();
#if 0
	/* this could be a negative dentry, so check first */
	if (!dtopd(dentry)) {
		fist_dprint(6, "dentry without private data: %*s", dentry->d_name.len, dentry->d_name.name);
		goto out;
	}

	if (!(hidden_dentry = dtohd(dentry))) {
		fist_dprint(6, "dentry without hidden_dentry: %*s", dentry->d_name.len, dentry->d_name.name);
		goto out;
	}

	//    fist_print_dentry("D_DELETE IN", dentry);
	/* added b/c of changes to dput(): it calls d_drop on us */
	if (hidden_dentry->d_op &&
	    hidden_dentry->d_op->d_delete) {
		err = hidden_dentry->d_op->d_delete(hidden_dentry);
	}
#endif
out:
	print_exit_status(err);
	return err;
}
Exemple #11
0
/* FIST-LITE special version of mmap */
static int unionfs_mmap(struct file *file, struct vm_area_struct *vma)
{
	int err = 0;
	struct file *hidden_file = NULL;
	int willwrite;

	print_entry_location();

	/* This might could be deferred to mmap's writepage. */
	willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);
	if ((err = unionfs_file_revalidate(file, willwrite)))
		goto out;

	PASSERT(ftopd(file));
	hidden_file = ftohf(file);

	err = -ENODEV;
	if (!hidden_file->f_op || !hidden_file->f_op->mmap)
		goto out;

	PASSERT(hidden_file);
	PASSERT(hidden_file->f_op);
	PASSERT(hidden_file->f_op->mmap);

	vma->vm_file = hidden_file;
	err = hidden_file->f_op->mmap(hidden_file, vma);
	get_file(hidden_file);	/* make sure it doesn't get freed on us */
	fput(file);		/* no need to keep extra ref on ours */

      out:
	print_exit_status(err);
	return err;
}
Exemple #12
0
STATIC int
base0fs_setattr(struct dentry *dentry, struct iattr *ia)
{
        int err = 0;
        struct dentry *lower_dentry;
        inode_t *inode;
        inode_t *lower_inode;

        print_entry_location();
        lower_dentry = base0fs_lower_dentry(dentry);
        inode = dentry->d_inode;
        lower_inode = INODE_TO_LOWER(inode);
        fist_checkinode(inode, "base0fs_setattr");


        err = notify_change(lower_dentry, 
#ifdef HAVE_3_ARG_NOTIFY_CHANGE
                DENTRY_TO_LVFSMNT(dentry),
#endif
                ia);

#if defined(FIST_FILTER_DATA) || defined(FIST_FILTER_SCA)
out:
#endif /* FIST_FILTER_DATA || FIST_FILTER_SCA */
        /*
         * The lower file system might has changed the attributes, even if
         * notify_change above resulted in an error(!)  so we copy the
         * lower_inode's attributes (and a few more) to our inode.
         */
        fist_copy_attr_all(inode, lower_inode);

        fist_checkinode(inode, "post base0fs_setattr");
        print_exit_status(err);
        return err;
}
Exemple #13
0
/* BKL held by caller.
 * dentry->d_inode->i_sem down
 */
ssize_t unionfs_listxattr(struct dentry * dentry, char *list, size_t size)
{
	struct dentry *hidden_dentry = NULL;
	int err = -EOPNOTSUPP;
	char *encoded_list = NULL;

	print_entry_location();
	lock_dentry(dentry);

	hidden_dentry = dtohd(dentry);

	if (hidden_dentry->d_inode->i_op->listxattr) {
		encoded_list = list;
		down(&hidden_dentry->d_inode->i_sem);
		/* lock_kernel() already done by caller. */
		err =
		    hidden_dentry->d_inode->i_op->listxattr(hidden_dentry,
							    encoded_list, size);
		/* unlock_kernel() will be done by caller. */
		up(&hidden_dentry->d_inode->i_sem);
	}

	unlock_dentry(dentry);
	print_exit_status(err);
	return err;
}
Exemple #14
0
/*
 * BKL held by caller.
 * dentry->d_inode->i_{sem,mutex} down
 */
STATIC ssize_t
base0fs_listxattr(struct dentry *dentry, char *list, size_t size)
{
        struct dentry *lower_dentry = NULL;
        int err = -ENOTSUPP;
        char *encoded_list = NULL;

        print_entry_location();

        lower_dentry = DENTRY_TO_LOWER(dentry);

        BUG_ON(!lower_dentry);
        BUG_ON(!lower_dentry->d_inode);
        BUG_ON(!lower_dentry->d_inode->i_op);

        if (lower_dentry->d_inode->i_op->listxattr) {
                encoded_list = list;
                lock_inode(lower_dentry->d_inode);
                /* lock_kernel() already done by caller. */
                err = lower_dentry->d_inode->i_op->listxattr(lower_dentry, encoded_list, size);
                /* unlock_kernel() will be done by caller. */
                unlock_inode(lower_dentry->d_inode);
        }

out:
        print_exit_status(err);
        return err;
}
Exemple #15
0
static unsigned int unionfs_poll(struct file *file, poll_table * wait)
{
	unsigned int mask = DEFAULT_POLLMASK;
	struct file *hidden_file = NULL;

	print_entry_location();

	if (unionfs_file_revalidate(file, 0)) {
		/* We should pretend an error happend. */
		mask = POLLERR | POLLIN | POLLOUT;
		goto out;
	}

	if (ftopd(file) != NULL)
		hidden_file = ftohf(file);

	if (!hidden_file->f_op || !hidden_file->f_op->poll)
		goto out;

	mask = hidden_file->f_op->poll(hidden_file, wait);

      out:
	print_exit_status(mask);
	return mask;
}
Exemple #16
0
/*
 * BKL held by caller.
 * dentry->d_inode->i_{sem,mutex} down
 */
STATIC int
base0fs_removexattr(struct dentry *dentry, const char *name)
{
        struct dentry *lower_dentry = NULL;
        int err = -ENOTSUPP;
        char *encoded_name;
        print_entry_location();

        lower_dentry = DENTRY_TO_LOWER(dentry);

        BUG_ON(!lower_dentry);
        BUG_ON(!lower_dentry->d_inode);
        BUG_ON(!lower_dentry->d_inode->i_op);

        fist_dprint(18, "removexattr: name=\"%s\"\n", name);

        if (lower_dentry->d_inode->i_op->removexattr) {
                encoded_name = (char *)name;

                lock_inode(lower_dentry->d_inode);
                /* lock_kernel() already done by caller. */
                err = lower_dentry->d_inode->i_op->removexattr(lower_dentry, encoded_name);
                /* unlock_kernel() will be done by caller. */
                unlock_inode(lower_dentry->d_inode);
        }

out:
        print_exit_status(err);
        return err;
}
Exemple #17
0
STATIC int
base0fs_permission(inode_t *inode, int mask, struct nameidata* nd)
{
        inode_t *lower_inode;
        int err;
	struct dentry *lower_dentry;
	struct vfsmount *lower_mount;
	FIST_ND_DECLARATIONS;

        print_entry_location();
        lower_inode = INODE_TO_LOWER(inode);

	if(nd)
	{
	    BUG_ON(!NAMEIDATA_TO_DENTRY(nd)); /* needed to find lower_dentry */
	    lower_dentry = base0fs_lower_dentry(NAMEIDATA_TO_DENTRY(nd));
	    lower_mount = DENTRY_TO_LVFSMNT(NAMEIDATA_TO_DENTRY(nd));
	    BUG_ON(!SUPERBLOCK_TO_PRIVATE(NAMEIDATA_TO_DENTRY(nd)->d_sb)); /* needed in FIST_ND_SAVE_ARGS macro */
	    FIST_ND_SAVE_ARGS(NAMEIDATA_TO_DENTRY(nd), lower_dentry, lower_mount);
	}

	err = permission(lower_inode, mask, nd);

	if(nd)
	{
	    FIST_ND_RESTORE_ARGS;
	}

out:
        print_exit_status(err);
        return err;
}
Exemple #18
0
static int unionfs_file_readdir(struct file *file, void *dirent,
				filldir_t filldir)
{
	int err = -ENOTDIR;
	print_entry_location();
	print_exit_status(err);
	return err;
}
Exemple #19
0
int
main(int argc, char *argv[])
{
	int retc = 0;
	int opt;
	int errflg = 0;

	if ((command = strrchr(argv[0], '/')) != NULL)
		command++;
	else
		command = argv[0];

	while ((opt = getopt(argc, argv, "F")) != EOF) {
		switch (opt) {
		case 'F':		/* force grabbing (no O_EXCL) */
			Fflag = PGRAB_FORCE;
			break;
		default:
			errflg = 1;
			break;
		}
	}

	argc -= optind;
	argv += optind;

	if (errflg || argc <= 0) {
		(void) fprintf(stderr, "usage:  %s pid ...\n", command);
		(void) fprintf(stderr, "  (Reap a defunct process by forcing "
		    "its parent to wait(2) for it)\n");
		exit(2);
	}

	/* catch signals from terminal */
	if (sigset(SIGHUP, SIG_IGN) == SIG_DFL)
		(void) sigset(SIGHUP, intr);
	if (sigset(SIGINT, SIG_IGN) == SIG_DFL)
		(void) sigset(SIGINT, intr);
	if (sigset(SIGPIPE, SIG_IGN) == SIG_DFL)
		(void) sigset(SIGPIPE, intr);
	if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL)
		(void) sigset(SIGQUIT, intr);
	(void) sigset(SIGTERM, intr);

	while (--argc >= 0 && !interrupt) {
		pid_t pid;
		int wstat, r;

		retc += r = reap(*argv++, &pid, &wstat);

		if (r == 0)
			print_exit_status(pid, wstat);
	}

	if (interrupt && retc == 0)
		retc++;
	return (retc == 0 ? 0 : 1);
}
Exemple #20
0
/*
 * Rename all occurences of source except for the leftmost destination
 */
static int __rename_all(struct inode *old_dir, struct dentry *old_dentry,
			struct inode *new_dir, struct dentry *new_dentry,
			fd_set * success_mask, struct rename_info *info)
{
	int bindex;

	int err = 0;

	print_entry_location();

	/* Loop through all the branches from right to left and rename all
	 * instances of source to destination, except the leftmost destination
	 */
	for (bindex = info->old_bend; bindex >= info->old_bstart; bindex--) {
		/* We don't rename if there is no source. */
		if (dtohd_index(old_dentry, bindex) == NULL)
			continue;

		/* we rename the bstart of destination only at the last of
		 * all operations, so that we don't lose it on error
		 */
		if (info->clobber && (bindex == info->new_bstart))
			continue;

		DPUT(info->wh_old);
		info->bwh_old = bindex;
		/* We shouldn't have a handle on this if there is no inode. */
		err =
		    do_rename(old_dir, old_dentry, new_dir, new_dentry, bindex,
			      &info->wh_old);
		if (!err) {
			/* For reverting. */
			FD_SET(bindex, success_mask);
			/* So we know not to copyup on failures the right */
			info->rename_ok = bindex;
		} else if (IS_COPYUP_ERR(err)) {
			if (info->isdir) {
				err = -EXDEV;
				break;
			}

			/* we need a whiteout... */
			info->do_whiteout = bindex - 1;

			if (bindex == info->old_bstart)
				/* ...and a copyup */
				info->do_copyup = bindex - 1;

			err = 0;	/* reset error */
		} else
			break;	/* error is set by do_rename */
	}

	print_exit_status(err);
	return err;
}
Exemple #21
0
static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry)
{
	struct dentry *hidden_dentry;
	struct dentry *hidden_dir_dentry;
	int bindex;
	int err = 0;

	print_entry_location();

	if ((err = unionfs_partial_lookup(dentry)))
		goto out;

	bindex = dbstart(dentry);

	hidden_dentry = dtohd_index(dentry, bindex);
	if (!hidden_dentry)
		goto out;

	hidden_dir_dentry = lock_parent(hidden_dentry);

	/* avoid destroying the hidden inode if the file is in use */
	DGET(hidden_dentry);
	if (!(err = is_robranch_super(dentry->d_sb, bindex)))
		err = vfs_unlink(hidden_dir_dentry->d_inode, hidden_dentry);
	DPUT(hidden_dentry);
	fist_copy_attr_times(dir, hidden_dir_dentry->d_inode);
	unlock_dir(hidden_dir_dentry);

	if (err) {
		if (!IS_COPYUP_ERR(err))
			goto out;
	}

	if (err) {
		if (dbstart(dentry) == 0) {
			goto out;
		}
		err = create_whiteout(dentry, dbstart(dentry) - 1);
	} else if (dbopaque(dentry) != -1) {
		/* There is a hidden lower-priority file with the same name. */
		err = create_whiteout(dentry, dbopaque(dentry));
	} else {
		err = create_whiteout(dentry, dbstart(dentry));
	}
      out:
	if (!err)
		dentry->d_inode->i_nlink--;
	/* We don't want to leave negative leftover dentries for revalidate. */
	if (!err && (dbopaque(dentry) != -1))
		update_bstart(dentry);

	print_exit_status(err);
	return err;

}
Exemple #22
0
/* this unionfs_write() does not modify data pages! */
ssize_t unionfs_write(struct file * file, const char *buf, size_t count,
		      loff_t * ppos)
{
	int err = -EINVAL;
	struct file *hidden_file = NULL;
	struct inode *inode;
	struct inode *hidden_inode;
	loff_t pos = *ppos;
	int bstart, bend;

	print_entry_location();

	if ((err = unionfs_file_revalidate(file, 1)))
		goto out;

	inode = file->f_dentry->d_inode;

	bstart = fbstart(file);
	bend = fbend(file);

	ASSERT(bstart != -1);
	PASSERT(ftopd(file));
	PASSERT(ftohf(file));

	hidden_file = ftohf(file);
	hidden_inode = hidden_file->f_dentry->d_inode;

	if (!hidden_file->f_op || !hidden_file->f_op->write)
		goto out;

	/* adjust for append -- seek to the end of the file */
	if (file->f_flags & O_APPEND)
		pos = inode->i_size;

	err = hidden_file->f_op->write(hidden_file, buf, count, &pos);

	/*
	 * copy ctime and mtime from lower layer attributes
	 * atime is unchanged for both layers
	 */
	if (err >= 0)
		fist_copy_attr_times(inode, hidden_inode);

	*ppos = pos;

	/* update this inode's size */
	if (pos > inode->i_size)
		inode->i_size = pos;

      out:
	print_exit_status(err);
	return err;
}
Exemple #23
0
int unionfs_ioctl_rdwrbranch(struct inode *inode, unsigned int cmd,
			     unsigned long arg)
{
	int err;
	struct unionfs_rdwrbranch_args *rdwrargs = NULL;
	int gen;

	print_entry_location();

	unionfs_write_lock(inode->i_sb);
	lock_dentry(inode->i_sb->s_root);

	if ((err = newputmap(inode->i_sb)))
		goto out;

	err = -ENOMEM;
	rdwrargs = KMALLOC(sizeof(struct unionfs_rdwrbranch_args), GFP_KERNEL);
	if (!rdwrargs)
		goto out;

	err = -EFAULT;
	if (copy_from_user
	    (rdwrargs, (const void __user *)arg,
	     sizeof(struct unionfs_rdwrbranch_args)))
		goto out;

	err = -EINVAL;
	if (rdwrargs->rwb_branch < 0
	    || (rdwrargs->rwb_branch > (sbend(inode->i_sb) + 1)))
		goto out;
	if (rdwrargs->rwb_perms & ~(MAY_READ | MAY_WRITE | MAY_NFSRO))
		goto out;
	if (!(rdwrargs->rwb_perms & MAY_READ))
		goto out;

	set_branchperms(inode->i_sb, rdwrargs->rwb_branch, rdwrargs->rwb_perms);

	atomic_inc(&stopd(inode->i_sb)->usi_generation);
	gen = atomic_read(&stopd(inode->i_sb)->usi_generation);
	atomic_set(&dtopd(inode->i_sb->s_root)->udi_generation, gen);
	atomic_set(&itopd(inode->i_sb->s_root->d_inode)->uii_generation, gen);

	err = 0;

      out:
	unlock_dentry(inode->i_sb->s_root);
	unionfs_write_unlock(inode->i_sb);
	KFREE(rdwrargs);

	print_exit_status(err);

	return err;
}
Exemple #24
0
STATIC int
base0fs_permission(inode_t *inode, int mask)
{
        inode_t *lower_inode;
        int err;

        print_entry_location();
        lower_inode = INODE_TO_LOWER(inode);
	err = inode_permission(lower_inode, mask);
        print_exit_status(err);
        return err;
}
Exemple #25
0
/*
 * Unlink all destinations (if they exist) to the left of the left-most
 * source
 */
static int __rename_all_unlink(struct inode *old_dir, struct dentry *old_dentry,
			       struct inode *new_dir, struct dentry *new_dentry,
			       struct rename_info *info)
{
	int bindex;

	struct dentry *unlink_dentry;
	struct dentry *unlink_dir_dentry;

	int err = 0;

	print_entry_location();

	for (bindex = info->old_bstart - 1; bindex > info->new_bstart; bindex--) {
		unlink_dentry = dtohd_index(new_dentry, bindex);
		if (!unlink_dentry)
			continue;

		/* lock, unlink if possible, copyup times, unlock */
		unlink_dir_dentry = lock_parent(unlink_dentry);
		if (!(err = is_robranch_super(old_dir->i_sb, bindex)))
			err =
			    vfs_unlink(unlink_dir_dentry->d_inode,
				       unlink_dentry);

		fist_copy_attr_times(new_dentry->d_parent->d_inode,
				     unlink_dir_dentry->d_inode);
		new_dentry->d_parent->d_inode->i_nlink =
		    get_nlinks(new_dentry->d_parent->d_inode);

		unlock_dir(unlink_dir_dentry);

		if (!err) {
			if (bindex != info->new_bstart) {
				DPUT(unlink_dentry);
				set_dtohd_index(new_dentry, bindex, NULL);
			}
		} else if (IS_COPYUP_ERR(err)) {
			if (info->isdir) {
				err = -EXDEV;
				break;
			}
			info->do_copyup = bindex - 1;

			err = 0;	/* reset error */
		} else
			break;	/* err is set by is_ro_branch_super or vfs_unlink */
	}

	print_exit_status(err);
	return err;
}
Exemple #26
0
int unionfs_rmdir(struct inode *dir, struct dentry *dentry)
{
	int err = 0;
	struct unionfs_dir_state *namelist = NULL;

	print_entry_location();
	lock_dentry(dentry);
	fist_print_dentry("IN unionfs_rmdir: ", dentry);

	/* check if this unionfs directory is empty or not */
	err = check_empty(dentry, &namelist);
	if (err) {
		goto out;
	}

	if (IS_SET(dir->i_sb, DELETE_WHITEOUT)) {
		/* Delete the first directory. */
		err = unionfs_rmdir_first(dir, dentry, namelist);
		/* create whiteout */
		if (!err) {
			err = create_whiteout(dentry, dbstart(dentry));
		} else {
			int new_err;

			if (dbstart(dentry) == 0)
				goto out;

			/* exit if the error returned was NOT -EROFS */
			if (!IS_COPYUP_ERR(err))
				goto out;

			new_err = create_whiteout(dentry, dbstart(dentry) - 1);
			if (new_err != -EEXIST)
				err = new_err;
		}
	} else {
		/* delete all. */
		err = unionfs_rmdir_all(dir, dentry, namelist);
	}

      out:
	/* call d_drop so the system "forgets" about us */
	if (!err)
		d_drop(dentry);

	if (namelist)
		free_rdstate(namelist);

	unlock_dentry(dentry);
	print_exit_status(err);
	return err;
}
Exemple #27
0
int unionfs_d_revalidate_wrap(struct dentry *dentry, struct nameidata *nd)
{
	int err;

	print_entry_location();
	lock_dentry(dentry);

	err = unionfs_d_revalidate(dentry, nd);

	unlock_dentry(dentry);
	print_exit_status(err);
	return err;
}
Exemple #28
0
static int unionfs_permission(struct inode *inode, int mask,
			      struct nameidata *nd)
{
	struct inode *hidden_inode = NULL;
	int err = 0;
	int bindex, bstart, bend;
	const int is_file = !S_ISDIR(inode->i_mode);
	const int write_mask = (mask & MAY_WRITE) && !(mask & MAY_READ);

	print_entry_location();

	bstart = ibstart(inode);
	bend = ibend(inode);

	fist_print_inode("IN unionfs_permission", inode);

	for (bindex = bstart; bindex <= bend; bindex++) {
		hidden_inode = itohi_index(inode, bindex);
		if (!hidden_inode)
			continue;

		/* check the condition for D-F-D underlying files/directories,
		 * we dont have to check for files, if we are checking for
		 * directories.
		 */
		if (!is_file && !S_ISDIR(hidden_inode->i_mode))
			continue;
		/* We use our own special version of permission, such that 
		 * only the first branch returns -EROFS. */
		err = inode_permission(hidden_inode, mask, nd, bindex);
		/* The permissions are an intersection of the overall directory
		 * permissions, so we fail if one fails. */
		if (err)
			goto out;
		/* only the leftmost file matters. */
		if (is_file || write_mask) {
			if (is_file && write_mask) {
				err = get_write_access(hidden_inode);
				if (!err)
					put_write_access(hidden_inode);
			}
			break;
		}
	}

      out:
	print_exit_status(err);
	return err;
}
Exemple #29
0
STATIC int
base0fs_unlink(inode_t *dir, struct dentry *dentry)
{
        int err = 0;
        inode_t *lower_dir;
        struct dentry *lower_dentry;
        struct dentry *lower_dir_dentry;

        print_entry_location();

        lower_dir = INODE_TO_LOWER(dir); /* CPW: Moved below print_entry_location */
        lower_dentry = base0fs_lower_dentry(dentry);

        BUG_ON(!lower_dentry);
        fist_checkinode(dir, "base0fs_unlink-dir");

        dget(dentry);
        lower_dir_dentry = base0fs_lock_parent(lower_dentry);


        /* avoid destroying the lower inode if the file is in use */
        dget(lower_dentry);
        err = VFS_UNLINK(lower_dir, lower_dentry);
        dput(lower_dentry);

        if (!err)			  /* vfs_unlink does that */
                d_delete(lower_dentry);

out_lock:
        fist_copy_attr_times(dir, lower_dir);
        /* propagate number of hard-links */
        dentry->d_inode->i_nlink = INODE_TO_LOWER(dentry->d_inode)->i_nlink;
    	fist_copy_attr_ctime(dentry->d_inode, dir);

        unlock_dir(lower_dir_dentry);

        /*
         * call d_drop so the system "forgets" about us
         */
        if (!err) {
                d_drop(dentry);
        }

        dput(dentry);

        fist_checkinode(dir, "post base0fs_unlink-dir");
        print_exit_status(err);
        return err;
}
Exemple #30
0
        /*
         * call d_drop so the system "forgets" about us
         */
        if (!err)
                d_drop(dentry);

        dput(dentry);

        print_exit_status(err);
        return err;
}


STATIC int
base0fs_mknod(inode_t *dir, struct dentry *dentry, int mode, dev_t dev)
{
        int err;
        struct dentry *lower_dentry;
        struct dentry *lower_dir_dentry;

        print_entry_location();
        lower_dentry = base0fs_lower_dentry(dentry);	/* CPW: Moved below print_entry_location */
        fist_checkinode(dir, "base0fs_mknod-dir");

        lower_dir_dentry = base0fs_lock_parent(lower_dentry);

        err = VFS_MKNOD(lower_dir_dentry->d_inode,
                        lower_dentry,
                        mode,
                        dev);
        if (err || !lower_dentry->d_inode)
                goto out;

        err = base0fs_interpose(lower_dentry, dentry, dir->i_sb, 0);
        if (err)
                goto out;
        fist_copy_attr_timesizes(dir, lower_dir_dentry->d_inode);

out:
        unlock_dir(lower_dir_dentry);
        if (!dentry->d_inode)
                d_drop(dentry);

        fist_checkinode(dir, "post base0fs_mknod-dir");
        print_exit_status(err);
        return err;
}


STATIC int
base0fs_rename(inode_t *old_dir, struct dentry *old_dentry,
              inode_t *new_dir, struct dentry *new_dentry)
{
        int err;
        struct dentry *lower_old_dentry;
        struct dentry *lower_new_dentry;
        struct dentry *lower_old_dir_dentry;
        struct dentry *lower_new_dir_dentry;

        print_entry_location();

        lower_old_dentry = base0fs_lower_dentry(old_dentry);/* CPW: Moved below print_entry_location */
        lower_new_dentry = base0fs_lower_dentry(new_dentry);

        fist_checkinode(old_dir, "base0fs_rename-old_dir");
        fist_checkinode(new_dir, "base0fs_rename-new_dir");

        dget(lower_old_dentry);
        dget(lower_new_dentry);
        lower_old_dir_dentry = dget_parent(lower_old_dentry);
        lower_new_dir_dentry = dget_parent(lower_new_dentry);
        lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);


        err = VFS_RENAME(lower_old_dir_dentry->d_inode, lower_old_dentry,
                         lower_new_dir_dentry->d_inode, lower_new_dentry);
        if (err)
                goto out_lock;

        fist_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
        if (new_dir != old_dir)
                fist_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);

out_lock:
        // unlock_rename will dput the new/old parent dentries whose refcnts
        // were incremented via dget_parent above.
        dput(lower_new_dentry);
        dput(lower_old_dentry);
        unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);

        fist_checkinode(new_dir, "post base0fs_rename-new_dir");
        print_exit_status(err);
        return err;
}


STATIC int
base0fs_readlink(struct dentry *dentry, char *buf, int bufsiz)
{
        int err;
        struct dentry *lower_dentry;

        print_entry_location();
        lower_dentry = base0fs_lower_dentry(dentry);/* CPW: Moved below print_entry_location */
        fist_print_dentry("base0fs_readlink IN", dentry);

        if (!lower_dentry->d_inode->i_op ||
             !lower_dentry->d_inode->i_op->readlink) {
                err = -EINVAL;
                goto out;
        }

        err = lower_dentry->d_inode->i_op->readlink(lower_dentry,
                                                    buf,
                                                    bufsiz);
        if (err > 0)
                fist_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode);

out:
        print_exit_status(err);
        return err;
}

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
STATIC int
base0fs_follow_link(struct dentry *dentry, struct nameidata *nd)
#else /* 2.6.13 or newer */
STATIC void *
base0fs_follow_link(struct dentry *dentry, struct nameidata *nd)
#endif /* 2.6.13 or newer */
{
        char *buf;
        int len = PAGE_SIZE, err;
        mm_segment_t old_fs;
	struct dentry *lower_dentry;

        print_entry_location();
        //    fist_print_dentry("base0fs_follow_link dentry IN", dentry);

	/* buf is allocated here, and freed when VFS calls our put_link method */
	err = -ENOMEM;
        buf = KMALLOC(len, GFP_KERNEL);
        if (!buf)
                goto out;

        old_fs = get_fs();
        set_fs(KERNEL_DS);
        err = dentry->d_inode->i_op->readlink(dentry, buf, len);
        set_fs(old_fs);
        if (err < 0)
                goto out_free;

        buf[err] = 0;	// terminate the buffer -- XXX still needed?
	err = 0;
	nd_set_link(nd,buf);
	goto out;

out_free:
	KFREE(buf);
out:
#if 0
        if (err < 0) {
                dput(nd->dentry);
                printk("EZK follow_link() mnt_cnt %d\n", 
                        (int) atomic_read(&nd->mnt->mnt_count));
                mntput(nd->mnt);
        }
#endif

        print_exit_status(err);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
        return err;
#else /* 2.6.13 or newer */
        return ERR_PTR(err);
#endif /* 2.6.13 or newer */
}