Use file_inode helper.
Add NULL extra arg to vfs_* methods and notify_change where it takes a
delegated inode.
Check DCACHE_OP_REVALIDATE flag in ->d_revalidate.
->setattr implemented, but not used yet.
Force our root dentry to be of type DIR.
Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
dput(tmp_dentry);
err = copyup_named_file(parent->d_inode, file, name, bstart, bindex,
- i_size_read(file->f_path.dentry->d_inode));
+ i_size_read(file_inode(file)));
if (err) {
if (unlikely(err == -EEXIST))
goto retry;
lower_dentry->d_inode);
}
lower_dir_dentry = lock_parent(lower_dentry);
- err = vfs_unlink(lower_dir_dentry->d_inode, lower_dentry);
+ err = vfs_unlink(lower_dir_dentry->d_inode, lower_dentry, NULL);
unlock_dir(lower_dir_dentry);
out:
if (!err)
unionfs_check_file(file);
fileinfo = UNIONFS_F(file);
- BUG_ON(file->f_path.dentry->d_inode != inode);
+ BUG_ON(file_inode(file) != inode);
inodeinfo = UNIONFS_I(inode);
/* fput all the lower files */
ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_FORCE |
ATTR_GID | ATTR_UID;
mutex_lock(&new_lower_dentry->d_inode->i_mutex);
- err = notify_change(new_lower_dentry, &newattrs);
+ err = notify_change(new_lower_dentry, &newattrs, NULL);
if (err)
goto out;
/* now try to change the mode and ignore EOPNOTSUPP on symlinks */
newattrs.ia_mode = i->i_mode;
newattrs.ia_valid = ATTR_MODE | ATTR_FORCE;
- err = notify_change(new_lower_dentry, &newattrs);
+ err = notify_change(new_lower_dentry, &newattrs, NULL);
if (err == -EOPNOTSUPP &&
S_ISLNK(new_lower_dentry->d_inode->i_mode)) {
printk(KERN_WARNING
* quota, or something else happened so let's unlink; we don't
* really care about the return value of vfs_unlink
*/
- vfs_unlink(new_lower_parent_dentry->d_inode, new_lower_dentry);
+ vfs_unlink(new_lower_parent_dentry->d_inode, new_lower_dentry, NULL);
if (copyup_file) {
/* need to close the file */
bool valid = true;
int err = 1; /* 1 means valid for the VFS */
struct dentry *parent;
+ struct dentry *lower_dentry;
if (flags & LOOKUP_RCU)
return -ECHILD;
parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
+ lower_dentry = unionfs_lower_dentry(dentry);
+ if (!(lower_dentry->d_flags & DCACHE_OP_REVALIDATE))
+ goto out;
+
valid = __unionfs_d_revalidate(dentry, parent, false, flags);
if (valid) {
unionfs_postcopyup_setmnt(dentry);
d_drop(dentry);
err = valid;
}
+
+out:
unionfs_unlock_dentry(dentry);
unionfs_unlock_parent(dentry, parent);
unionfs_read_unlock(dentry->d_sb);
uds->dirpos = offset;
/* Copy the atime. */
- fsstack_copy_attr_atime(inode,
- lower_file->f_path.dentry->d_inode);
+ fsstack_copy_attr_atime(inode, file_inode(lower_file));
if (err < 0)
goto out;
/* update our inode atime upon a successful lower read */
if (err >= 0) {
fsstack_copy_attr_atime(dentry->d_inode,
- lower_file->f_path.dentry->d_inode);
+ file_inode(lower_file));
unionfs_check_file(file);
}
/* update our inode times+sizes upon a successful lower write */
if (err >= 0) {
fsstack_copy_inode_size(dentry->d_inode,
- lower_file->f_path.dentry->d_inode);
+ file_inode(lower_file));
fsstack_copy_attr_times(dentry->d_inode,
- lower_file->f_path.dentry->d_inode);
+ file_inode(lower_file));
UNIONFS_F(file)->wrote_to_file = true; /* for delayed copyup */
unionfs_check_file(file);
}
/* update our inode atime upon a successful lower splice-read */
if (err >= 0) {
fsstack_copy_attr_atime(dentry->d_inode,
- lower_file->f_path.dentry->d_inode);
+ file_inode(lower_file));
unionfs_check_file(file);
}
/* update our inode times+sizes upon a successful lower write */
if (err >= 0) {
fsstack_copy_inode_size(dentry->d_inode,
- lower_file->f_path.dentry->d_inode);
+ file_inode(lower_file));
fsstack_copy_attr_times(dentry->d_inode,
- lower_file->f_path.dentry->d_inode);
+ file_inode(lower_file));
unionfs_check_file(file);
}
/* see Documentation/filesystems/unionfs/issues.txt */
lockdep_off();
err = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
- lower_new_dentry);
+ lower_new_dentry, NULL);
lockdep_on();
}
unlock_dir(lower_dir_dentry);
/* do vfs_link */
err = vfs_link(lower_old_dentry,
lower_dir_dentry->d_inode,
- lower_new_dentry);
+ lower_new_dentry, NULL);
lockdep_on();
unlock_dir(lower_dir_dentry);
goto check_link;
}
mutex_lock(&lower_dentry->d_inode->i_mutex);
- err = notify_change(lower_dentry, &lower_ia);
+ err = notify_change(lower_dentry, &lower_ia, NULL);
mutex_unlock(&lower_dentry->d_inode->i_mutex);
if (err)
goto out;
return err;
}
+#if 0
+// XXX: may need this code in future
+static int unionfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat)
+{
+ int err;
+ struct dentry *parent;
+ struct kstat lower_stat;
+ struct path lower_path;
+
+ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
+ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
+ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
+
+ if (unlikely(!__unionfs_d_revalidate(dentry, parent, false, 0))) {
+ err = -ESTALE;
+ goto out;
+ }
+
+ lower_path.dentry = unionfs_lower_dentry(dentry);
+ lower_path.mnt = unionfs_lower_mnt(dentry);
+ err = vfs_getattr(&lower_path, &lower_stat);
+ if (err)
+ goto out;
+ fsstack_copy_attr_all(dentry->d_inode,
+ lower_path.dentry->d_inode);
+ generic_fillattr(dentry->d_inode, stat);
+ stat->blocks = lower_stat.blocks;
+
+out:
+ unionfs_check_dentry(dentry);
+ unionfs_unlock_dentry(dentry);
+ unionfs_unlock_parent(dentry, parent);
+ unionfs_read_unlock(dentry->d_sb);
+
+ return err;
+}
+#endif
+
struct inode_operations unionfs_symlink_iops = {
.readlink = unionfs_readlink,
.permission = unionfs_permission,
err = PTR_ERR(inode);
goto out_dput;
}
+ /*
+ * Have to set DIR mode temporarily on inode and dentry, before
+ * calling make_root, because make_root sets the
+ * DCACHE_DIRECTORY_TYPE dentry flag only if the inode is of type
+ * dir. Now, later below, we'll be copying the lower inode
+ * attributes anyway, which'll set our inode's mode to type==DIR,
+ * but it's too late for the dentry to have the
+ * DCACHE_DIRECTORY_TYPE flag set.
+ */
+ inode->i_mode = S_IFDIR | 0755;
sb->s_root = d_make_root(inode);
+ d_set_type(sb->s_root, DCACHE_DIRECTORY_TYPE);
if (unlikely(!sb->s_root)) {
err = -ENOMEM;
goto out_iput;
(sizeof(unsigned int) + sizeof(unsigned int)));
BUG_ON(UNIONFS_F(file)->rdstate != NULL);
- UNIONFS_F(file)->rdstate = alloc_rdstate(file->f_path.dentry->d_inode,
+ UNIONFS_F(file)->rdstate = alloc_rdstate(file_inode(file),
fbstart(file));
return (UNIONFS_F(file)->rdstate ? 0 : -ENOMEM);
goto out_err_unlock;
}
err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
- lower_new_dir_dentry->d_inode, lower_new_dentry);
+ lower_new_dir_dentry->d_inode, lower_new_dentry,
+ NULL);
out_err_unlock:
if (!err) {
/* update parent dir times */
err = is_robranch_super(old_dir->i_sb, bindex);
if (!err)
err = vfs_unlink(unlink_dir_dentry->d_inode,
- unlink_dentry);
+ unlink_dentry, NULL);
fsstack_copy_attr_times(new_parent->d_inode,
unlink_dir_dentry->d_inode);
struct sioq_args *args = container_of(work, struct sioq_args, work);
struct unlink_args *u = &args->unlink;
- args->err = vfs_unlink(u->parent, u->dentry);
+ args->err = vfs_unlink(u->parent, u->dentry, NULL);
complete(&args->comp);
}
lockdep_off();
if (!S_ISDIR(lower_dentry->d_inode->i_mode))
err = vfs_unlink(lower_dir_dentry->d_inode,
- lower_dentry);
+ lower_dentry, NULL);
else
err = vfs_rmdir(lower_dir_dentry->d_inode,
- lower_dentry);
+ lower_dentry);
lockdep_on();
}
/* see Documentation/filesystems/unionfs/issues.txt */
lockdep_off();
- err = vfs_unlink(lower_dir_dentry->d_inode, wh_dentry);
+ err = vfs_unlink(lower_dir_dentry->d_inode, wh_dentry, NULL);
lockdep_on();
unlock_dir(lower_dir_dentry);
break;
}
if (lower_dentry->d_inode)
- err = vfs_unlink(lower_dir, lower_dentry);
+ err = vfs_unlink(lower_dir, lower_dentry,
+ NULL);
dput(lower_dentry);
if (err)
break;