> Very well, I will try to explain with code: > > int ovl_inode_is_open_for_write(struct inode *inode) > { > struct inode *upper_inode = ovl_inode_upper(inode); > > return upper_inode && inode_is_open_for_write(upper_inode); > } > > void ovl_maybe_mark_inode_dirty(struct inode *inode) > { > struct inode *upper_inode = ovl_inode_upper(inode); > > if (upper_inode && upper_inode->i_state & I_DIRTY_ALL) > mark_inode_dirty(inode); > } > > int ovl_open(struct inode *inode, struct file *file) > { > ... > if (ovl_inode_is_open_for_write(file_inode(file))) > ovl_add_inode_to_suspect_list(inode); > > file->private_data = realfile; > > return 0; > } > > int ovl_release(struct inode *inode, struct file *file) > { > struct inode *inode = file_inode(file); > > if (ovl_inode_is_open_for_write(inode)) { Darn! that should have been (!ovl_inode_is_open_for_write(inode)) and it should be done after fput() and grabbing inode reference with ihold() before fput(). > ovl_maybe_mark_inode_dirty(inode); > ovl_remove_inode_from_suspect_list(inode); > } > > fput(file->private_data); > > return 0; > } > > int ovl_drop_inode(struct inode *inode) > { > struct inode *upper_inode = ovl_inode_upper(inode); > > if (!upper_inode) > return 1; > if (upper_inode->i_state & I_DIRTY_ALL) > return 0; > > return !inode_is_open_for_write(upper_inode); > } > > static int ovl_sync_fs(struct super_block *sb, int wait) > { > struct ovl_fs *ofs = sb->s_fs_info; > struct super_block *upper_sb; > int ret; > > if (!ovl_upper_mnt(ofs)) > return 0; > > /* > * Not called for sync(2) call or an emergency sync (SB_I_SKIP_SYNC). > * All the super blocks will be iterated, including upper_sb. > * > * If this is a syncfs(2) call, then we do need to call > * sync_filesystem() on upper_sb, but enough if we do it when being > * called with wait == 1. > */ > if (!wait) { > /* mark inodes on the suspect list dirty if thier > upper inode is dirty */ > ovl_mark_suspect_list_inodes_dirty(); > return 0; > } > ... > > > The races are avoided because inode is added/removed from suspect > list while overlay inode has a reference (from file) and because upper inode > cannot be dirtied by overlayfs when overlay inode is not on the suspect list. > > Unless I am missing something. > > Thanks, > Amir.