@@ -89,32 +89,19 @@ static int ovl_change_flags(struct file *file, unsigned int flags)
8989 return 0 ;
9090}
9191
92- static int ovl_real_fdget_meta (const struct file * file , struct fd * real ,
93- bool allow_meta )
92+ static int ovl_real_fdget_path (const struct file * file , struct fd * real ,
93+ struct path * realpath )
9494{
95- struct dentry * dentry = file_dentry (file );
9695 struct file * realfile = file -> private_data ;
97- struct path realpath ;
98- int err ;
9996
10097 real -> word = (unsigned long )realfile ;
10198
102- if (allow_meta ) {
103- ovl_path_real (dentry , & realpath );
104- } else {
105- /* lazy lookup and verify of lowerdata */
106- err = ovl_verify_lowerdata (dentry );
107- if (err )
108- return err ;
109-
110- ovl_path_realdata (dentry , & realpath );
111- }
112- if (!realpath .dentry )
99+ if (WARN_ON_ONCE (!realpath -> dentry ))
113100 return - EIO ;
114101
115102 /* Has it been copied up since we'd opened it? */
116- if (unlikely (file_inode (realfile ) != d_inode (realpath . dentry ))) {
117- struct file * f = ovl_open_realfile (file , & realpath );
103+ if (unlikely (file_inode (realfile ) != d_inode (realpath -> dentry ))) {
104+ struct file * f = ovl_open_realfile (file , realpath );
118105 if (IS_ERR (f ))
119106 return PTR_ERR (f );
120107 real -> word = (unsigned long )f | FDPUT_FPUT ;
@@ -130,15 +117,26 @@ static int ovl_real_fdget_meta(const struct file *file, struct fd *real,
130117
131118static int ovl_real_fdget (const struct file * file , struct fd * real )
132119{
133- if (d_is_dir (file_dentry (file ))) {
120+ struct dentry * dentry = file_dentry (file );
121+ struct path realpath ;
122+ int err ;
123+
124+ if (d_is_dir (dentry )) {
134125 struct file * f = ovl_dir_real_file (file , false);
135126 if (IS_ERR (f ))
136127 return PTR_ERR (f );
137128 real -> word = (unsigned long )f ;
138129 return 0 ;
139130 }
140131
141- return ovl_real_fdget_meta (file , real , false);
132+ /* lazy lookup and verify of lowerdata */
133+ err = ovl_verify_lowerdata (dentry );
134+ if (err )
135+ return err ;
136+
137+ ovl_path_realdata (dentry , & realpath );
138+
139+ return ovl_real_fdget_path (file , real , & realpath );
142140}
143141
144142static int ovl_open (struct inode * inode , struct file * file )
@@ -396,6 +394,9 @@ static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out,
396394
397395static int ovl_fsync (struct file * file , loff_t start , loff_t end , int datasync )
398396{
397+ struct dentry * dentry = file_dentry (file );
398+ enum ovl_path_type type ;
399+ struct path upperpath ;
399400 struct fd real ;
400401 const struct cred * old_cred ;
401402 int ret ;
@@ -404,16 +405,19 @@ static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync)
404405 if (ret <= 0 )
405406 return ret ;
406407
407- ret = ovl_real_fdget_meta (file , & real , !datasync );
408+ /* Don't sync lower file for fear of receiving EROFS error */
409+ type = ovl_path_type (dentry );
410+ if (!OVL_TYPE_UPPER (type ) || (datasync && OVL_TYPE_MERGE (type )))
411+ return 0 ;
412+
413+ ovl_path_upper (dentry , & upperpath );
414+ ret = ovl_real_fdget_path (file , & real , & upperpath );
408415 if (ret )
409416 return ret ;
410417
411- /* Don't sync lower file for fear of receiving EROFS error */
412- if (file_inode (fd_file (real )) == ovl_inode_upper (file_inode (file ))) {
413- old_cred = ovl_override_creds (file_inode (file )-> i_sb );
414- ret = vfs_fsync_range (fd_file (real ), start , end , datasync );
415- ovl_revert_creds (old_cred );
416- }
418+ old_cred = ovl_override_creds (file_inode (file )-> i_sb );
419+ ret = vfs_fsync_range (fd_file (real ), start , end , datasync );
420+ ovl_revert_creds (old_cred );
417421
418422 fdput (real );
419423
0 commit comments