Maxim Patlasov <mpatla...@virtuozzo.com> writes: > Before the patch, the only way to pick up updated file size from server (in a > scenario when local inode was created earlier, then the file was updated > from another node) was in fuse_open_common(): > >> atomic_inc(&fi->num_openers); >> >> if (atomic_read(&fi->num_openers) == 1) { >> err = fuse_getattr_size(inode, file, &size); >> ... >> spin_lock(&fc->lock); >> i_size_write(inode, size); >> spin_unlock(&fc->lock); >> } > > This is correct, but someone may ask about i_size w/o open, e.g.: ls -l foo. > The patch ensures that every time the server reports us some file size, if no > open-s happened yet (num_openers=0), fuse stores that server size in local > inode->i_size. This resolves the following problem: > > # pstorage-mount -c test -l /var/log/f1.log /pcs1 > # pstorage-mount -c test -l /var/log/f2.log /pcs2 > > # date > /pcs1/foo; ls -l /pcs1/foo /pcs2/foo > -rwx------ 1 root root 29 Dec 14 16:31 /pcs1/foo > -rwx------ 1 root root 29 Dec 14 16:31 /pcs2/foo > > # date >> /pcs1/foo; ls -l /pcs1/foo /pcs2/foo > -rwx------ 1 root root 58 Dec 14 16:31 /pcs1/foo > -rwx------ 1 root root 29 Dec 14 16:31 /pcs2/foo > > https://jira.sw.ru/browse/PSBM-57047 > > Signed-off-by: Maxim Patlasov <mpatla...@virtuozzo.com> Ok. But IMHO fi->num_openers is redundant it protects special metadata, but thre are other cases where we may get client/server mdata out of sync.
> --- > fs/fuse/file.c | 12 +++++++++++- > fs/fuse/fuse_i.h | 3 +++ > fs/fuse/inode.c | 4 +++- > 3 files changed, 17 insertions(+), 2 deletions(-) > > diff --git a/fs/fuse/file.c b/fs/fuse/file.c > index 9cad8c5..62967d2 100644 > --- a/fs/fuse/file.c > +++ b/fs/fuse/file.c > @@ -296,12 +296,20 @@ int fuse_open_common(struct inode *inode, struct file > *file, bool isdir) > u64 size; > > mutex_lock(&inode->i_mutex); > + > + spin_lock(&fc->lock); > atomic_inc(&fi->num_openers); > > if (atomic_read(&fi->num_openers) == 1) { > + fi->i_size_unstable = 1; > + spin_unlock(&fc->lock); > err = fuse_getattr_size(inode, file, &size); > if (err) { > + spin_lock(&fc->lock); > atomic_dec(&fi->num_openers); > + fi->i_size_unstable = 0; > + spin_unlock(&fc->lock); > + > mutex_unlock(&inode->i_mutex); > fuse_release_common(file, FUSE_RELEASE); > return err; > @@ -309,8 +317,10 @@ int fuse_open_common(struct inode *inode, struct file > *file, bool isdir) > > spin_lock(&fc->lock); > i_size_write(inode, size); > + fi->i_size_unstable = 0; > + spin_unlock(&fc->lock); > + } else > spin_unlock(&fc->lock); > - } > > mutex_unlock(&inode->i_mutex); > } > diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h > index 1d24bf6..22eb9c9 100644 > --- a/fs/fuse/fuse_i.h > +++ b/fs/fuse/fuse_i.h > @@ -124,6 +124,9 @@ struct fuse_inode { > > /** Mostly to detect very first open */ > atomic_t num_openers; > + > + /** Even though num_openers>0, trust server i_size */ > + int i_size_unstable; > }; > > /** FUSE inode state bits */ > diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c > index 5ccecae..f606deb 100644 > --- a/fs/fuse/inode.c > +++ b/fs/fuse/inode.c > @@ -97,6 +97,7 @@ static struct inode *fuse_alloc_inode(struct super_block > *sb) > fi->writectr = 0; > fi->orig_ino = 0; > fi->state = 0; > + fi->i_size_unstable = 0; > INIT_LIST_HEAD(&fi->write_files); > INIT_LIST_HEAD(&fi->rw_files); > INIT_LIST_HEAD(&fi->queued_writes); > @@ -226,7 +227,8 @@ void fuse_change_attributes(struct inode *inode, struct > fuse_attr *attr, > * extend local i_size without keeping userspace server in sync. So, > * attr->size coming from server can be stale. We cannot trust it. > */ > - if (!is_wb || !S_ISREG(inode->i_mode)) > + if (!is_wb || !S_ISREG(inode->i_mode) || > + !atomic_read(&fi->num_openers) || fi->i_size_unstable) > i_size_write(inode, attr->size); > spin_unlock(&fc->lock); > _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel