From 98f2f46d51a4d4bdb12df2cf7b4f2b2c4fbbd735 Mon Sep 17 00:00:00 2001 From: Andrew Perepechko Date: Wed, 15 Jun 2016 21:03:41 +0300 Subject: [PATCH] LU-8284 osd-ldiskfs: i_size updates from BRW should be atomic In osd_write_commit(), it is possible that somewhere between i_size_read() check and i_size_write() another write updates i_size to a larger value. In the end, we will have a lower i_size value than we should. Change-Id: I720a6cc1214e3e6b32df4f9e2c1017a47e7962f0 Signed-off-by: Andrew Perepechko Reviewed-by: Alexander Zarochentsev Reviewed-by: Alexander Nikolaevich Boyko Seagate-bug-id: MRP-3528 Reviewed-on: http://review.whamcloud.com/20816 Reviewed-by: Andreas Dilger Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Alexander Boyko Reviewed-by: Oleg Drokin --- lustre/osd-ldiskfs/osd_io.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/lustre/osd-ldiskfs/osd_io.c b/lustre/osd-ldiskfs/osd_io.c index aaea2f0..bdbee56 100644 --- a/lustre/osd-ldiskfs/osd_io.c +++ b/lustre/osd-ldiskfs/osd_io.c @@ -1274,16 +1274,20 @@ static int osd_write_commit(const struct lu_env *env, struct dt_object *dt, thandle->th_local = 1; } - if (likely(rc == 0)) { - if (isize > i_size_read(inode)) { - i_size_write(inode, isize); - LDISKFS_I(inode)->i_disksize = isize; + if (likely(rc == 0)) { + spin_lock(&inode->i_lock); + if (isize > i_size_read(inode)) { + i_size_write(inode, isize); + LDISKFS_I(inode)->i_disksize = isize; + spin_unlock(&inode->i_lock); ll_dirty_inode(inode, I_DIRTY_DATASYNC); - } + } else { + spin_unlock(&inode->i_lock); + } - rc = osd_do_bio(osd, inode, iobuf); - /* we don't do stats here as in read path because - * write is async: we'll do this in osd_put_bufs() */ + rc = osd_do_bio(osd, inode, iobuf); + /* we don't do stats here as in read path because + * write is async: we'll do this in osd_put_bufs() */ } else { osd_fini_iobuf(osd, iobuf); } -- 1.8.3.1