dget(hidden_dentry);
unionfs_mntget(dentry, bindex);
+ unionfs_read_lock(sb);
branchget(sb, bindex);
+ unionfs_read_unlock(sb);
hidden_file = dentry_open(hidden_dentry,
unionfs_lower_mnt_idx(dentry, bindex),
dget(hidden_dentry);
unionfs_mntget(dentry, bstart);
+ unionfs_read_lock(sb);
branchget(sb, bstart);
+ unionfs_read_unlock(sb);
hidden_file = dentry_open(hidden_dentry,
unionfs_lower_mnt_idx(dentry, bstart), file->f_flags);
if (IS_ERR(hidden_file)) {
bend = fbend(file);
for (bindex = bstart; bindex <= bend; bindex++) {
if (unionfs_lower_file_idx(file, bindex)) {
+ unionfs_read_lock(dentry->d_sb);
branchput(dentry->d_sb, bindex);
+ unionfs_read_unlock(dentry->d_sb);
fput(unionfs_lower_file_idx(file, bindex));
unionfs_set_lower_file_idx(file, bindex, NULL);
}
/* The branchget goes after the open, because otherwise
* we would miss the reference on release.
*/
+ unionfs_read_lock(inode->i_sb);
branchget(inode->i_sb, bindex);
+ unionfs_read_unlock(inode->i_sb);
}
return 0;
return PTR_ERR(hidden_file);
unionfs_set_lower_file(file, hidden_file);
+ unionfs_read_lock(inode->i_sb);
branchget(inode->i_sb, bstart);
+ unionfs_read_unlock(inode->i_sb);
return 0;
}
int bindex = 0, bstart = 0, bend = 0;
int size;
+ unionfs_read_lock(inode->i_sb);
file->private_data = kzalloc(sizeof(struct unionfs_file_info), GFP_KERNEL);
if (!UNIONFS_F(file)) {
err = -ENOMEM;
dentry = file->f_dentry;
unionfs_lock_dentry(dentry);
- unionfs_read_lock(inode->i_sb);
bstart = fbstart(file) = dbstart(dentry);
bend = fbend(file) = dbend(dentry);
if (!hidden_file)
continue;
+ unionfs_read_lock(file->f_dentry->d_sb);
branchput(file->f_dentry->d_sb, bindex);
+ unionfs_read_unlock(file->f_dentry->d_sb);
/* fput calls dput for hidden_dentry */
fput(hidden_file);
}
}
unionfs_unlock_dentry(dentry);
- unionfs_read_unlock(inode->i_sb);
out:
if (err) {
kfree(UNIONFS_F(file));
}
out_nofree:
+ unionfs_read_unlock(inode->i_sb);
return err;
}
int bindex, bstart, bend;
int fgen;
+ unionfs_read_lock(inode->i_sb);
/* fput all the hidden files */
fgen = atomic_read(&fileinfo->generation);
bstart = fbstart(file);
fileinfo->rdstate = NULL;
}
kfree(fileinfo);
+ unionfs_read_unlock(inode->i_sb);
return 0;
}
}
out:
+ unionfs_read_unlock(file->f_dentry->d_sb);
return err;
}
{
long err;
+ unionfs_read_lock(file->f_dentry->d_sb);
if ((err = unionfs_file_revalidate(file, 1)))
goto out;
struct dentry *dentry = file->f_dentry;
int bindex, bstart, bend;
+ unionfs_read_lock(file->f_dentry->d_sb);
+
if ((err = unionfs_file_revalidate(file, 1)))
goto out;
+
if (!atomic_dec_and_test(&UNIONFS_I(dentry->d_inode)->totalopens))
goto out;
out_lock:
unionfs_unlock_dentry(dentry);
out:
+ unionfs_read_unlock(file->f_dentry->d_sb);
return err;
}
-
/* open old file */
unionfs_mntget(dentry, old_bindex);
+ unionfs_read_lock(sb);
branchget(sb, old_bindex);
+ unionfs_read_unlock(sb);
input_file = dentry_open(old_hidden_dentry,
unionfs_lower_mnt_idx(dentry, old_bindex),
O_RDONLY | O_LARGEFILE);
/* open new file */
dget(new_hidden_dentry);
unionfs_mntget(dentry, new_bindex);
+ unionfs_read_lock(sb);
branchget(sb, new_bindex);
+ unionfs_read_unlock(sb);
output_file = dentry_open(new_hidden_dentry,
unionfs_lower_mnt_idx(dentry, new_bindex),
O_WRONLY | O_LARGEFILE);
fput(output_file);
out_close_in2:
+ unionfs_read_lock(sb);
branchput(sb, new_bindex);
+ unionfs_read_unlock(sb);
out_close_in:
fput(input_file);
out:
+ unionfs_read_lock(sb);
branchput(sb, old_bindex);
+ unionfs_read_unlock(sb);
return err;
}
sb = dir->i_sb;
- unionfs_read_lock(sb);
-
if ((err = is_robranch_super(sb, new_bindex)))
goto out;
/* need to close the file */
fput(*copyup_file);
+ unionfs_read_lock(sb);
branchput(sb, new_bindex);
+ unionfs_read_unlock(sb);
}
/*
kfree(symbuf);
out:
- unionfs_read_unlock(sb);
-
return err;
}
int bend;
loff_t offset;
+ unionfs_read_lock(file->f_dentry->d_sb);
if ((err = unionfs_file_revalidate(file, 0)))
goto out;
file->f_pos = rdstate2offset(uds);
out:
+ unionfs_read_unlock(file->f_dentry->d_sb);
return err;
}
struct unionfs_dir_state *rdstate;
loff_t err;
+ unionfs_read_lock(file->f_dentry->d_sb);
if ((err = unionfs_file_revalidate(file, 0)))
goto out;
}
out:
+ unionfs_read_unlock(file->f_dentry->d_sb);
return err;
}
dget(hidden_dentry);
unionfs_mntget(dentry, bindex);
+ unionfs_read_lock(sb);
branchget(sb, bindex);
+ unionfs_read_unlock(sb);
hidden_file =
dentry_open(hidden_dentry, unionfs_lower_mnt_idx(dentry, bindex),
O_RDONLY);
if (IS_ERR(hidden_file)) {
err = PTR_ERR(hidden_file);
dput(hidden_dentry);
+ unionfs_read_lock(sb);
branchput(sb, bindex);
+ unionfs_read_unlock(sb);
goto out;
}
/* fput calls dput for hidden_dentry */
fput(hidden_file);
+ unionfs_read_lock(sb);
branchput(sb, bindex);
+ unionfs_read_unlock(sb);
if (err < 0)
goto out;
loff_t err;
struct file *hidden_file = NULL;
+ unionfs_read_lock(file->f_dentry->d_sb);
if ((err = unionfs_file_revalidate(file, 0)))
goto out;
file->f_version++;
}
out:
+ unionfs_read_unlock(file->f_dentry->d_sb);
return err;
}
loff_t pos = *ppos;
int err;
+ unionfs_read_lock(file->f_dentry->d_sb);
if ((err = unionfs_file_revalidate(file, 0)))
goto out;
*ppos = pos;
out:
+ unionfs_read_unlock(file->f_dentry->d_sb);
return err;
}
{
int err = 0;
+ unionfs_read_lock(file->f_dentry->d_sb);
if ((err = unionfs_file_revalidate(file, 1)))
goto out;
err = __unionfs_write(file, buf, count, ppos);
out:
+ unionfs_read_unlock(file->f_dentry->d_sb);
return err;
}
unsigned int mask = DEFAULT_POLLMASK;
struct file *hidden_file = NULL;
+ unionfs_read_lock(file->f_dentry->d_sb);
if (unionfs_file_revalidate(file, 0)) {
/* We should pretend an error happend. */
mask = POLLERR | POLLIN | POLLOUT;
mask = hidden_file->f_op->poll(hidden_file, wait);
out:
+ unionfs_read_unlock(file->f_dentry->d_sb);
return mask;
}
int err = 0;
int willwrite;
+ unionfs_read_lock(file->f_dentry->d_sb);
/* 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)))
err = __do_mmap(file, vma);
out:
+ unionfs_read_unlock(file->f_dentry->d_sb);
return err;
}
int err;
struct file *hidden_file = NULL;
+ unionfs_read_lock(file->f_dentry->d_sb);
if ((err = unionfs_file_revalidate(file, 1)))
goto out;
mutex_unlock(&hidden_file->f_dentry->d_inode->i_mutex);
out:
+ unionfs_read_unlock(file->f_dentry->d_sb);
return err;
}
int err = 0;
struct file *hidden_file = NULL;
+ unionfs_read_lock(file->f_dentry->d_sb);
if ((err = unionfs_file_revalidate(file, 1)))
goto out;
err = hidden_file->f_op->fasync(fd, hidden_file, flag);
out:
+ unionfs_read_unlock(file->f_dentry->d_sb);
return err;
}
retval = inode->i_op->permission(inode, submask, nd);
if ((retval == -EACCES) && (submask & MAY_WRITE) &&
(!strcmp("nfs", (inode)->i_sb->s_type->name)) &&
- (nd) && (nd->mnt) && (nd->mnt->mnt_sb) &&
- (branchperms(nd->mnt->mnt_sb, bindex) & MAY_NFSRO)) {
- retval = generic_permission(inode, submask, NULL);
+ (nd) && (nd->mnt) && (nd->mnt->mnt_sb)) {
+ int perms;
+ unionfs_read_lock(nd->mnt->mnt_sb);
+ perms = branchperms(nd->mnt->mnt_sb, bindex);
+ unionfs_read_unlock(nd->mnt->mnt_sb);
+ if (perms & MAY_NFSRO)
+ retval = generic_permission(inode, submask, NULL);
}
} else
retval = generic_permission(inode, submask, NULL);
d = hidden_root_info->lower_paths[bindex].dentry;
+ unionfs_write_lock(sb);
unionfs_set_lower_super_idx(sb, bindex, d->d_sb);
+ unionfs_write_unlock(sb);
}
/* Unionfs: Max Bytes is the maximum bytes from highest priority branch */
+ unionfs_read_lock(sb);
sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes;
+ unionfs_read_unlock(sb);
sb->s_op = &unionfs_sops;
sb = dentry->d_sb;
+ unionfs_read_lock(sb);
hidden_sb = unionfs_lower_super_idx(sb, sbstart(sb));
+ unionfs_read_unlock(sb);
err = vfs_statfs(hidden_sb->s_root, buf);
buf->f_type = UNIONFS_SUPER_MAGIC;
bend = sbend(sb);
for (bindex = bstart; bindex <= bend; bindex++) {
hidden_mnt = unionfs_lower_mnt_idx(sb->s_root, bindex);
+ unionfs_read_lock(sb);
hidden_sb = unionfs_lower_super_idx(sb, bindex);
+ unionfs_read_unlock(sb);
if (hidden_mnt && hidden_sb && hidden_sb->s_op &&
hidden_sb->s_op->umount_begin)
goto out;
}
+ unionfs_read_lock(sb);
perms = branchperms(sb, bindex);
+ unionfs_read_unlock(sb);
seq_printf(m, "%s=%s", path,
perms & MAY_WRITE ? "rw" : "ro");
int unionfs_unlink(struct inode *dir, struct dentry *dentry);
int unionfs_rmdir(struct inode *dir, struct dentry *dentry);
-int __unionfs_d_revalidate(struct dentry *dentry, struct nameidata *nd);
int __unionfs_d_revalidate_chain(struct dentry *dentry, struct nameidata *nd);
/* The values for unionfs_interpose's flag. */
/* Is this file on a read-only branch? */
static inline int is_robranch_super(const struct super_block *sb, int index)
{
- return (!(branchperms(sb, index) & MAY_WRITE)) ? -EROFS : 0;
+ int ret;
+ unionfs_read_lock(sb);
+ ret = (!(branchperms(sb, index) & MAY_WRITE)) ? -EROFS : 0;
+ unionfs_read_unlock(sb);
+ return ret;
}
/* Is this file on a read-only branch? */
BUG_ON(index < 0);
+ unionfs_read_lock(dentry->d_sb);
if ((!(branchperms(dentry->d_sb, index) & MAY_WRITE)) ||
IS_RDONLY(unionfs_lower_dentry_idx(dentry, index)->d_inode))
err = -EROFS;
-
+ unionfs_read_unlock(dentry->d_sb);
return err;
}