From 5ebfd99e69ee54b24f159812c400b5c3217d55cb Mon Sep 17 00:00:00 2001 From: Erez_Zadok Date: Fri, 16 Nov 2007 14:10:16 -0500 Subject: [PATCH] Unionfs: cache-coherency calls to maintain the time invariants This patch represents several types of related changes. First, we invoke functions to synchronize the upper and lower times as and when needed. Many of these were bug fixes which were discovered during the development of the cache-coherency code. That is, Unionfs itself wasn't maintaining appropriate times in some places, which if not fixed would have been detected by the invariant-checking code as a false positive (incorrectly considered as if a user modified the lower objects directly). Second, we do not call invariant-validation functions (unionfs_check_file, unionfs_check_dentry, etc.) until *after* we've revalidated them. Otherwise we produced false positives. Third, we pass a flag "willwrite" to __unionfs_d_revalidate_chain to tell it to purge data pages if the inode lower times appear to be newer. See Documentation/filesystems/unionfs/concepts.txt under the "Cache Coherency" section for more details of this design and implementation. Signed-off-by: Erez Zadok --- fs/unionfs/commonfops.c | 18 +++++++++++----- fs/unionfs/copyup.c | 8 +++++++ fs/unionfs/dentry.c | 8 +++---- fs/unionfs/file.c | 26 +++++++++++++++-------- fs/unionfs/inode.c | 47 +++++++++++++++++++++++++---------------- fs/unionfs/main.c | 2 +- fs/unionfs/mmap.c | 41 +++++++++++++++++++---------------- fs/unionfs/rename.c | 9 ++++++-- fs/unionfs/super.c | 4 ++-- fs/unionfs/unlink.c | 21 +++++++++++++----- fs/unionfs/xattr.c | 8 +++---- 11 files changed, 123 insertions(+), 69 deletions(-) diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c index b3791a5acc..acda073822 100644 --- a/fs/unionfs/commonfops.c +++ b/fs/unionfs/commonfops.c @@ -390,7 +390,7 @@ int unionfs_file_revalidate(struct file *file, int willwrite) * but not unhashed dentries. */ if (!d_deleted(dentry) && - !__unionfs_d_revalidate_chain(dentry, NULL)) { + !__unionfs_d_revalidate_chain(dentry, NULL, willwrite)) { err = -ESTALE; goto out_nofree; } @@ -671,7 +671,10 @@ out: out_nofree: unionfs_read_unlock(inode->i_sb); unionfs_check_inode(inode); - unionfs_check_file(file); + if (!err) { + unionfs_check_file(file); + unionfs_check_dentry(file->f_dentry->d_parent); + } return err; } @@ -684,7 +687,6 @@ int unionfs_file_release(struct inode *inode, struct file *file) int bindex, bstart, bend; int fgen, err = 0; - unionfs_check_file(file); unionfs_read_lock(sb); /* * Yes, we have to revalidate this file even if it's being released. @@ -693,6 +695,7 @@ int unionfs_file_release(struct inode *inode, struct file *file) */ if ((err = unionfs_file_revalidate(file, 1))) goto out; + unionfs_check_file(file); fileinfo = UNIONFS_F(file); BUG_ON(file->f_dentry->d_inode != inode); @@ -852,7 +855,7 @@ int unionfs_flush(struct file *file, fl_owner_t id) struct dentry *dentry = file->f_dentry; int bindex, bstart, bend; - unionfs_read_lock(file->f_dentry->d_sb); + unionfs_read_lock(dentry->d_sb); if ((err = unionfs_file_revalidate(file, 1))) goto out; @@ -884,10 +887,15 @@ int unionfs_flush(struct file *file, fl_owner_t id) } + /* on success, update our times */ + unionfs_copy_attr_times(dentry->d_inode); + /* parent time could have changed too (async) */ + unionfs_copy_attr_times(dentry->d_parent->d_inode); + out_lock: unionfs_unlock_dentry(dentry); out: - unionfs_read_unlock(file->f_dentry->d_sb); + unionfs_read_unlock(dentry->d_sb); unionfs_check_file(file); return err; } diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c index 351541c1a8..cd33c5a93f 100644 --- a/fs/unionfs/copyup.c +++ b/fs/unionfs/copyup.c @@ -503,6 +503,8 @@ out_free: } } unionfs_inherit_mnt(dentry); + /* sync inode times from copied-up inode to our inode */ + unionfs_copy_attr_times(dentry->d_inode); unionfs_check_inode(dir); unionfs_check_dentry(dentry); out: @@ -803,6 +805,12 @@ begin: __set_inode(child_dentry, lower_dentry, bindex); __set_dentry(child_dentry, lower_dentry, bindex); + /* + * update times of this dentry, but also the parent, because if + * we changed, the parent may have changed too. + */ + unionfs_copy_attr_times(parent_dentry->d_inode); + unionfs_copy_attr_times(child_dentry->d_inode); parent_dentry = child_dentry; child_dentry = path[--count]; diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c index da94cbc19b..d38f1ae2c1 100644 --- a/fs/unionfs/dentry.c +++ b/fs/unionfs/dentry.c @@ -188,9 +188,8 @@ static int __unionfs_d_revalidate_one(struct dentry *dentry, * caller (__unionfs_d_revalidate_chain) by calling * purge_inode_data. */ - fsstack_copy_attr_all(dentry->d_inode, - unionfs_lower_inode(dentry->d_inode), - unionfs_get_nlinks); + unionfs_copy_attr_all(dentry->d_inode, + unionfs_lower_inode(dentry->d_inode)); fsstack_copy_inode_size(dentry->d_inode, unionfs_lower_inode(dentry->d_inode)); } @@ -425,9 +424,8 @@ static int unionfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) { int err; - unionfs_check_dentry(dentry); unionfs_lock_dentry(dentry); - err = __unionfs_d_revalidate_chain(dentry, nd); + err = __unionfs_d_revalidate_chain(dentry, nd, 0); unionfs_unlock_dentry(dentry); unionfs_check_dentry(dentry); diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c index 62da4e4268..df413ebfa7 100644 --- a/fs/unionfs/file.c +++ b/fs/unionfs/file.c @@ -24,9 +24,9 @@ static ssize_t unionfs_read(struct file *file, char __user *buf, int err; unionfs_read_lock(file->f_dentry->d_sb); - unionfs_check_file(file); if ((err = unionfs_file_revalidate(file, 0))) goto out; + unionfs_check_file(file); err = do_sync_read(file, buf, count, ppos); @@ -47,9 +47,9 @@ static ssize_t unionfs_aio_read(struct kiocb *iocb, const struct iovec *iov, struct file *file = iocb->ki_filp; unionfs_read_lock(file->f_dentry->d_sb); - unionfs_check_file(file); if ((err = unionfs_file_revalidate(file, 0))) goto out; + unionfs_check_file(file); err = generic_file_aio_read(iocb, iov, nr_segs, pos); @@ -65,21 +65,26 @@ out: unionfs_check_file(file); return err; } -static ssize_t unionfs_write(struct file * file, const char __user * buf, + +static ssize_t unionfs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { int err = 0; unionfs_read_lock(file->f_dentry->d_sb); - unionfs_check_file(file); if ((err = unionfs_file_revalidate(file, 1))) goto out; + unionfs_check_file(file); err = do_sync_write(file, buf, count, ppos); + /* update our inode times upon a successful lower write */ + if (err >= 0) { + unionfs_copy_attr_times(file->f_dentry->d_inode); + unionfs_check_file(file); + } out: unionfs_read_unlock(file->f_dentry->d_sb); - unionfs_check_file(file); return err; } @@ -96,14 +101,12 @@ static int unionfs_mmap(struct file *file, struct vm_area_struct *vma) struct file *lower_file; unionfs_read_lock(file->f_dentry->d_sb); - unionfs_check_file(file); - if ((err = unionfs_file_revalidate(file, 1))) - goto out; /* This might 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; + unionfs_check_file(file); /* * File systems which do not implement ->writepage may use @@ -128,7 +131,12 @@ static int unionfs_mmap(struct file *file, struct vm_area_struct *vma) out: unionfs_read_unlock(file->f_dentry->d_sb); - unionfs_check_file(file); + if (!err) { + /* copyup could cause parent dir times to change */ + unionfs_copy_attr_times(file->f_dentry->d_parent->d_inode); + unionfs_check_file(file); + unionfs_check_dentry(file->f_dentry->d_parent); + } return err; } diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c index e3961ff3b0..c99f325ce7 100644 --- a/fs/unionfs/inode.c +++ b/fs/unionfs/inode.c @@ -41,13 +41,13 @@ static int unionfs_create(struct inode *parent, struct dentry *dentry, unionfs_lock_dentry(dentry); unionfs_lock_dentry(dentry->d_parent); - valid = __unionfs_d_revalidate_chain(dentry->d_parent, nd); + valid = __unionfs_d_revalidate_chain(dentry->d_parent, nd, 0); unionfs_unlock_dentry(dentry->d_parent); if (!valid) { err = -ESTALE; /* same as what real_lookup does */ goto out; } - valid = __unionfs_d_revalidate_chain(dentry, nd); + valid = __unionfs_d_revalidate_chain(dentry, nd, 0); /* * It's only a bug if this dentry was not negative and couldn't be * revalidated (shouldn't happen). @@ -108,8 +108,7 @@ static int unionfs_create(struct inode *parent, struct dentry *dentry, err = PTR_ERR(unionfs_interpose(dentry, parent->i_sb, 0)); if (!err) { - fsstack_copy_attr_times(parent, - lower_parent_dentry->d_inode); + unionfs_copy_attr_times(parent); fsstack_copy_inode_size(parent, lower_parent_dentry->d_inode); /* update number of links on parent directory */ @@ -125,7 +124,8 @@ out: unionfs_read_unlock(dentry->d_sb); unionfs_check_inode(parent); - unionfs_check_dentry(dentry->d_parent); + if (!err) + unionfs_check_dentry(dentry->d_parent); unionfs_check_dentry(dentry); return err; } @@ -160,10 +160,13 @@ static struct dentry *unionfs_lookup(struct inode *parent, if (!IS_ERR(ret)) { if (ret) dentry = ret; + /* parent times may have changed */ + unionfs_copy_attr_times(dentry->d_parent->d_inode); } unionfs_check_inode(parent); unionfs_check_dentry(dentry); + unionfs_check_dentry(dentry->d_parent); return ret; } @@ -177,12 +180,12 @@ static int unionfs_link(struct dentry *old_dentry, struct inode *dir, unionfs_double_lock_dentry(new_dentry, old_dentry); - if (!__unionfs_d_revalidate_chain(old_dentry, NULL)) { + if (!__unionfs_d_revalidate_chain(old_dentry, NULL, 0)) { err = -ESTALE; goto out; } if (new_dentry->d_inode && - !__unionfs_d_revalidate_chain(new_dentry, NULL)) { + !__unionfs_d_revalidate_chain(new_dentry, NULL, 0)) { err = -ESTALE; goto out; } @@ -284,8 +287,7 @@ check_link: /* Its a hard link, so use the same inode */ new_dentry->d_inode = igrab(old_dentry->d_inode); d_instantiate(new_dentry, new_dentry->d_inode); - fsstack_copy_attr_all(dir, lower_new_dentry->d_parent->d_inode, - unionfs_get_nlinks); + unionfs_copy_attr_all(dir, lower_new_dentry->d_parent->d_inode); fsstack_copy_inode_size(dir, lower_new_dentry->d_parent->d_inode); /* update odf, FIXME: what to do in case of err? */ err = odf_link(old_dentry, new_dentry); @@ -293,6 +295,8 @@ check_link: /* propagate number of hard-links */ old_dentry->d_inode->i_nlink = unionfs_get_nlinks(old_dentry->d_inode); + /* new dentry's ctime may have changed due to hard-link counts */ + unionfs_copy_attr_times(new_dentry->d_inode); out: if (!new_dentry->d_inode) @@ -322,7 +326,7 @@ static int unionfs_symlink(struct inode *dir, struct dentry *dentry, unionfs_lock_dentry(dentry); if (dentry->d_inode && - !__unionfs_d_revalidate_chain(dentry, NULL)) { + !__unionfs_d_revalidate_chain(dentry, NULL, 0)) { err = -ESTALE; goto out; } @@ -416,7 +420,7 @@ static int unionfs_mkdir(struct inode *parent, struct dentry *dentry, int mode) unionfs_lock_dentry(dentry); if (dentry->d_inode && - !__unionfs_d_revalidate_chain(dentry, NULL)) { + !__unionfs_d_revalidate_chain(dentry, NULL, 0)) { err = -ESTALE; goto out; } @@ -502,6 +506,8 @@ out: kfree(name); + if (!err) + unionfs_copy_attr_times(dentry->d_inode); unionfs_unlock_dentry(dentry); unionfs_check_inode(parent); unionfs_check_dentry(dentry); @@ -519,7 +525,7 @@ static int unionfs_mknod(struct inode *dir, struct dentry *dentry, int mode, unionfs_lock_dentry(dentry); if (dentry->d_inode && - !__unionfs_d_revalidate_chain(dentry, NULL)) { + !__unionfs_d_revalidate_chain(dentry, NULL, 0)) { err = -ESTALE; goto out; } @@ -605,7 +611,7 @@ static int unionfs_readlink(struct dentry *dentry, char __user *buf, unionfs_lock_dentry(dentry); - if (!__unionfs_d_revalidate_chain(dentry, NULL)) { + if (!__unionfs_d_revalidate_chain(dentry, NULL, 0)) { err = -ESTALE; goto out; } @@ -640,7 +646,7 @@ static void *unionfs_follow_link(struct dentry *dentry, struct nameidata *nd) unionfs_lock_dentry(dentry); if (dentry->d_inode && - !__unionfs_d_revalidate_chain(dentry, nd)) { + !__unionfs_d_revalidate_chain(dentry, nd, 0)) { err = -ESTALE; goto out; } @@ -676,7 +682,7 @@ static void unionfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) { unionfs_lock_dentry(dentry); - if (!__unionfs_d_revalidate_chain(dentry, nd)) + if (!__unionfs_d_revalidate_chain(dentry, nd, 0)) printk("unionfs: put_link failed to revalidate dentry\n"); unionfs_unlock_dentry(dentry); @@ -817,6 +823,8 @@ static int unionfs_permission(struct inode *inode, int mask, break; } } + /* sync times which may have changed (asynchronously) below */ + unionfs_copy_attr_times(inode); out: if (!list_empty(&UNIONFS_SB(inode->i_sb)->rwsem.wait_list)) @@ -837,7 +845,7 @@ static int unionfs_setattr(struct dentry *dentry, struct iattr *ia) unionfs_lock_dentry(dentry); - if (!__unionfs_d_revalidate_chain(dentry, NULL)) { + if (!__unionfs_d_revalidate_chain(dentry, NULL, 0)) { err = -ESTALE; goto out; } @@ -900,12 +908,15 @@ static int unionfs_setattr(struct dentry *dentry, struct iattr *ia) } /* get the size from the first lower inode */ - lower_inode = unionfs_lower_inode(dentry->d_inode); - fsstack_copy_attr_all(inode, lower_inode, unionfs_get_nlinks); + lower_inode = unionfs_lower_inode(inode); + unionfs_copy_attr_all(inode, lower_inode); fsstack_copy_inode_size(inode, lower_inode); + /* if setattr succeeded, then parent dir may have changed */ + unionfs_copy_attr_times(dentry->d_parent->d_inode); out: unionfs_unlock_dentry(dentry); unionfs_check_dentry(dentry); + unionfs_check_dentry(dentry->d_parent); return err; } diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c index cf12d496d6..e8eb67c6bf 100644 --- a/fs/unionfs/main.c +++ b/fs/unionfs/main.c @@ -149,7 +149,7 @@ fill_i_info: lower_inode->i_rdev); /* all well, copy inode attributes */ - fsstack_copy_attr_all(inode, lower_inode, unionfs_get_nlinks); + unionfs_copy_attr_all(inode, lower_inode); fsstack_copy_inode_size(inode, lower_inode); if(spliced) diff --git a/fs/unionfs/mmap.c b/fs/unionfs/mmap.c index f5a1242252..7b4a6f5699 100644 --- a/fs/unionfs/mmap.c +++ b/fs/unionfs/mmap.c @@ -88,19 +88,16 @@ int unionfs_writepage(struct page *page, struct writeback_control *wbc) err = lower_inode->i_mapping->a_ops->writepage(lower_page, wbc); wbc->for_writepages = saved_for_writepages; /* restore value */ - /* - * update mtime and ctime of lower level file system - * unionfs' mtime and ctime are updated by generic_file_write - */ - lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; - /* b/c grab_cache_page increased refcnt */ page_cache_release(lower_page); if (err) ClearPageUptodate(page); - else + else { SetPageUptodate(page); + /* lower mtimes has changed: update ours */ + unionfs_copy_attr_times(inode); + } out: unlock_page(page); @@ -204,15 +201,17 @@ int unionfs_readpage(struct file *file, struct page *page) int err; unionfs_read_lock(file->f_dentry->d_sb); - unionfs_check_file(file); if ((err = unionfs_file_revalidate(file, 0))) goto out; + unionfs_check_file(file); err = unionfs_do_readpage(file, page); - if (!err) + if (!err) { touch_atime(unionfs_lower_mnt(file->f_path.dentry), unionfs_lower_dentry(file->f_path.dentry)); + unionfs_copy_attr_times(file->f_dentry->d_inode); + } /* * we have to unlock our page, b/c we _might_ have gotten a locked @@ -233,7 +232,18 @@ int unionfs_prepare_write(struct file *file, struct page *page, unsigned from, int err; unionfs_read_lock(file->f_dentry->d_sb); - unionfs_check_file(file); + /* + * This is the only place where we unconditionally copy the lower + * attribute times before calling unionfs_file_revalidate. The + * reason is that our ->write calls do_sync_write which in turn will + * call our ->prepare_write and then ->commit_write. Before our + * ->write is called, the lower mtimes are in sync, but by the time + * the VFS calls our ->commit_write, the lower mtimes have changed. + * Therefore, the only reasonable time for us to sync up from the + * changed lower mtimes, and avoid an invariant violation warning, + * is here, in ->prepare_write. + */ + unionfs_copy_attr_times(file->f_dentry->d_inode); err = unionfs_file_revalidate(file, 1); unionfs_check_file(file); unionfs_read_unlock(file->f_dentry->d_sb); @@ -255,9 +265,9 @@ int unionfs_commit_write(struct file *file, struct page *page, unsigned from, BUG_ON(file == NULL); unionfs_read_lock(file->f_dentry->d_sb); - unionfs_check_file(file); if ((err = unionfs_file_revalidate(file, 1))) goto out; + unionfs_check_file(file); inode = page->mapping->host; lower_inode = unionfs_lower_inode(inode); @@ -294,13 +304,8 @@ int unionfs_commit_write(struct file *file, struct page *page, unsigned from, pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + to; if (pos > i_size_read(inode)) i_size_write(inode, pos); - - /* - * update mtime and ctime of lower level file system - * unionfs' mtime and ctime are updated by generic_file_write - */ - lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME; - + /* if vfs_write succeeded above, sync up our times */ + unionfs_copy_attr_times(inode); mark_inode_dirty_sync(inode); out: diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c index 2488ebe866..3a4827a360 100644 --- a/fs/unionfs/rename.c +++ b/fs/unionfs/rename.c @@ -349,12 +349,12 @@ int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry, unionfs_double_lock_dentry(old_dentry, new_dentry); - if (!__unionfs_d_revalidate_chain(old_dentry, NULL)) { + if (!__unionfs_d_revalidate_chain(old_dentry, NULL, 0)) { err = -ESTALE; goto out; } if (!d_deleted(new_dentry) && new_dentry->d_inode && - !__unionfs_d_revalidate_chain(new_dentry, NULL)) { + !__unionfs_d_revalidate_chain(new_dentry, NULL, 0)) { err = -ESTALE; goto out; } @@ -453,6 +453,11 @@ out: } } + /* if all of this renaming succeeded, update our times */ + unionfs_copy_attr_times(old_dir); + unionfs_copy_attr_times(new_dir); + unionfs_copy_attr_times(old_dentry->d_inode); + unionfs_copy_attr_times(new_dentry->d_inode); unionfs_check_inode(old_dir); unionfs_check_inode(new_dir); unionfs_check_dentry(old_dentry); diff --git a/fs/unionfs/super.c b/fs/unionfs/super.c index 7859609015..bb0f9d4b0a 100644 --- a/fs/unionfs/super.c +++ b/fs/unionfs/super.c @@ -117,13 +117,13 @@ static int unionfs_statfs(struct dentry *dentry, struct kstatfs *buf) struct super_block *sb; struct dentry *lower_dentry; - unionfs_check_dentry(dentry); unionfs_lock_dentry(dentry); - if (!__unionfs_d_revalidate_chain(dentry, NULL)) { + if (!__unionfs_d_revalidate_chain(dentry, NULL, 0)) { err = -ESTALE; goto out; } + unionfs_check_dentry(dentry); sb = dentry->d_sb; diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c index 53259bb569..b0d7be9328 100644 --- a/fs/unionfs/unlink.c +++ b/fs/unionfs/unlink.c @@ -49,6 +49,9 @@ static int unionfs_do_unlink(struct inode *dir, struct dentry *dentry) lower_dentry); else err = -EROFS; + /* if vfs_unlink succeeded, update our inode's times */ + if (!err) + unionfs_copy_attr_times(dentry->d_inode); dput(lower_dentry); fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); unlock_dir(lower_dir_dentry); @@ -99,13 +102,13 @@ int unionfs_unlink(struct inode *dir, struct dentry *dentry) { int err = 0; - unionfs_check_dentry(dentry); unionfs_lock_dentry(dentry); - if (!__unionfs_d_revalidate_chain(dentry, NULL)) { + if (!__unionfs_d_revalidate_chain(dentry, NULL, 0)) { err = -ESTALE; goto out; } + unionfs_check_dentry(dentry); err = unionfs_do_unlink(dir, dentry); @@ -123,11 +126,19 @@ int unionfs_unlink(struct inode *dir, struct dentry *dentry) if (!err) { if (!S_ISDIR(dentry->d_inode->i_mode)) unionfs_purge_extras(dentry); - unionfs_check_dentry(dentry); d_drop(dentry); + /* + * if unlink/whiteout succeeded, parent dir mtime has + * changed + */ + unionfs_copy_attr_times(dir); } out: + if (!err) { + unionfs_check_dentry(dentry); + unionfs_check_inode(dir); + } unionfs_unlock_dentry(dentry); return err; } @@ -212,13 +223,13 @@ int unionfs_rmdir(struct inode *dir, struct dentry *dentry) int err = 0; struct unionfs_dir_state *namelist = NULL; - unionfs_check_dentry(dentry); unionfs_lock_dentry(dentry); - if (!__unionfs_d_revalidate_chain(dentry, NULL)) { + if (!__unionfs_d_revalidate_chain(dentry, NULL, 0)) { err = -ESTALE; goto out; } + unionfs_check_dentry(dentry); /* check if this unionfs directory is empty or not */ err = check_empty(dentry, &namelist); diff --git a/fs/unionfs/xattr.c b/fs/unionfs/xattr.c index 02a87c5399..b5ae59c64e 100644 --- a/fs/unionfs/xattr.c +++ b/fs/unionfs/xattr.c @@ -59,7 +59,7 @@ ssize_t unionfs_getxattr(struct dentry *dentry, const char *name, void *value, unionfs_lock_dentry(dentry); - if (!__unionfs_d_revalidate_chain(dentry, NULL)) { + if (!__unionfs_d_revalidate_chain(dentry, NULL, 0)) { err = -ESTALE; goto out; } @@ -86,7 +86,7 @@ int unionfs_setxattr(struct dentry *dentry, const char *name, unionfs_lock_dentry(dentry); - if (!__unionfs_d_revalidate_chain(dentry, NULL)) { + if (!__unionfs_d_revalidate_chain(dentry, NULL, 0)) { err = -ESTALE; goto out; } @@ -113,7 +113,7 @@ int unionfs_removexattr(struct dentry *dentry, const char *name) unionfs_lock_dentry(dentry); - if (!__unionfs_d_revalidate_chain(dentry, NULL)) { + if (!__unionfs_d_revalidate_chain(dentry, NULL, 0)) { err = -ESTALE; goto out; } @@ -140,7 +140,7 @@ ssize_t unionfs_listxattr(struct dentry *dentry, char *list, size_t size) unionfs_lock_dentry(dentry); - if (!__unionfs_d_revalidate_chain(dentry, NULL)) { + if (!__unionfs_d_revalidate_chain(dentry, NULL, 0)) { err = -ESTALE; goto out; } -- 2.43.0