Whamcloud - gitweb
LU-8284 osd-ldiskfs: i_size updates from BRW should be atomic 16/20816/4
authorAndrew Perepechko <andrew.perepechko@seagate.com>
Wed, 15 Jun 2016 18:03:41 +0000 (21:03 +0300)
committerOleg Drokin <oleg.drokin@intel.com>
Mon, 11 Jul 2016 23:53:38 +0000 (23:53 +0000)
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 <andrew.perepechko@seagate.com>
Reviewed-by: Alexander Zarochentsev <alexander.zarochentsev@seagate.com>
Reviewed-by: Alexander Nikolaevich Boyko <alexander.boyko@seagate.com>
Seagate-bug-id: MRP-3528
Reviewed-on: http://review.whamcloud.com/20816
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Alexander Boyko <alexander.boyko@seagate.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/osd-ldiskfs/osd_io.c

index aaea2f0..bdbee56 100644 (file)
@@ -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);
        }