Exemplo n.º 1
0
int main(int argc, char **argv)
{
	int fd_0, fd_1, fd_2, ret = 0;

	test_init(argc, argv);

	m = get_cwd_mnt_info();
	if (!m) {
		pr_perror("Can't fetch mountinfo");
		return -1;
	}
	if (!strcmp(m->fsname, "btrfs"))
		m->s_dev = kdev_to_odev(m->s_dev);

	if (open_all_files(&fd_0, &fd_1, &fd_2))
		return -1;

	flock(fd_0, LOCK_SH);
	flock(fd_1, LOCK_EX);
	flock(fd_2, LOCK_MAND | LOCK_READ);

	test_daemon();
	test_waitsig();

	if (check_file_lock(fd_0, "ADVISORY", "READ", dev, inodes[0])) {
		fail("Failed on fd %d", fd_0);
		ret |= 1;
	}
	if (check_file_lock(fd_1, "ADVISORY", "WRITE", dev, inodes[1])) {
		fail("Failed on fd %d", fd_1);
		ret |= 1;
	}
	if (check_file_lock(fd_2, "MSNFS", "READ", dev, inodes[2])) {
		fail("Failed on fd %d", fd_2);
		ret |= 1;
	}

	if (!ret)
		pass();

	close(fd_0);
	close(fd_1);
	close(fd_2);
	unlink(file0);
	unlink(file1);
	unlink(file2);

	return ret;
}
Exemplo n.º 2
0
int main(int argc, char **argv)
{
	int fd_0, fd_1, fd_2;

	test_init(argc, argv);

	m = get_cwd_mnt_info();
	if (!m) {
		pr_perror("Can't fetch mountinfo");
		return -1;
	}
	if (!strcmp(m->fsname, "btrfs"))
		m->s_dev = kdev_to_odev(m->s_dev);

	if (open_all_files(&fd_0, &fd_1, &fd_2))
		return -1;

	flock(fd_0, LOCK_SH);
	flock(fd_1, LOCK_EX);
	flock(fd_2, LOCK_MAND | LOCK_READ);

	test_daemon();
	test_waitsig();

	if (check_file_locks())
		fail("Flock file locks check failed");
	else
		pass();

	close(fd_0);
	close(fd_1);
	close(fd_2);
	unlink(file0);
	unlink(file1);
	unlink(file2);

	return 0;
}
Exemplo n.º 3
0
/*
 * Helper function for unionfs_file_revalidate/locked.
 * Expects dentry/parent to be locked already, and revalidated.
 */
static int __unionfs_file_revalidate(struct file *file, struct dentry *dentry,
				     struct dentry *parent,
				     struct super_block *sb, int sbgen,
				     int dgen, bool willwrite)
{
	int fgen;
	int bstart, bend, orig_brid;
	int size;
	int err = 0;

	fgen = atomic_read(&UNIONFS_F(file)->generation);

	/*
	 * There are two cases we are interested in.  The first is if the
	 * generation is lower than the super-block.  The second is if
	 * someone has copied up this file from underneath us, we also need
	 * to refresh things.
	 */
	if (d_deleted(dentry) ||
	    (sbgen <= fgen &&
	     dbstart(dentry) == fbstart(file) &&
	     unionfs_lower_file(file)))
		goto out_may_copyup;

	/* save orig branch ID */
	orig_brid = UNIONFS_F(file)->saved_branch_ids[fbstart(file)];

	/* First we throw out the existing files. */
	cleanup_file(file);

	/* Now we reopen the file(s) as in unionfs_open. */
	bstart = fbstart(file) = dbstart(dentry);
	bend = fbend(file) = dbend(dentry);

	size = sizeof(struct file *) * sbmax(sb);
	UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
	if (unlikely(!UNIONFS_F(file)->lower_files)) {
		err = -ENOMEM;
		goto out;
	}
	size = sizeof(int) * sbmax(sb);
	UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
	if (unlikely(!UNIONFS_F(file)->saved_branch_ids)) {
		err = -ENOMEM;
		goto out;
	}

	if (S_ISDIR(dentry->d_inode->i_mode)) {
		/* We need to open all the files. */
		err = open_all_files(file);
		if (err)
			goto out;
	} else {
		int new_brid;
		/* We only open the highest priority branch. */
		err = open_highest_file(file, willwrite);
		if (err)
			goto out;
		new_brid = UNIONFS_F(file)->saved_branch_ids[fbstart(file)];
		if (unlikely(new_brid != orig_brid && sbgen > fgen)) {
			/*
			 * If we re-opened the file on a different branch
			 * than the original one, and this was due to a new
			 * branch inserted, then update the mnt counts of
			 * the old and new branches accordingly.
			 */
			unionfs_mntget(dentry, bstart);
			unionfs_mntput(sb->s_root,
				       branch_id_to_idx(sb, orig_brid));
		}
		/* regular files have only one open lower file */
		fbend(file) = fbstart(file);
	}
	atomic_set(&UNIONFS_F(file)->generation,
		   atomic_read(&UNIONFS_I(dentry->d_inode)->generation));

out_may_copyup:
	/* Copyup on the first write to a file on a readonly branch. */
	if (willwrite && IS_WRITE_FLAG(file->f_flags) &&
	    !IS_WRITE_FLAG(unionfs_lower_file(file)->f_flags) &&
	    is_robranch(dentry)) {
		pr_debug("unionfs: do delay copyup of \"%s\"\n",
			 dentry->d_name.name);
		err = do_delayed_copyup(file, parent);
		/* regular files have only one open lower file */
		if (!err && !S_ISDIR(dentry->d_inode->i_mode))
			fbend(file) = fbstart(file);
	}

out:
	if (err) {
		kfree(UNIONFS_F(file)->lower_files);
		kfree(UNIONFS_F(file)->saved_branch_ids);
	}
	return err;
}