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; }
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; }
/* * 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; }