Whamcloud - gitweb
LU-5393 osd-ldiskfs: read i_size once to protect against race 07/13707/6
authorBruno Faccini <bruno.faccini@intel.com>
Tue, 10 Feb 2015 10:07:11 +0000 (11:07 +0100)
committerOleg Drokin <oleg.drokin@intel.com>
Tue, 3 Mar 2015 17:20:36 +0000 (17:20 +0000)
There have been several occurences of ASSERTION(local_nb[i].rc == 0)
failures in ost_brw_read(), where inode's i_size has changed due to
a racing write/growth beyond EOF. osd_read_prep() must protect
himself against this legal behavior by only reading i_size once.

Also removed m local variable declaration/usage apparently outdated.

Signed-off-by: Bruno Faccini <bruno.faccini@intel.com>
Change-Id: I5d931d5254b970e7031363f37114d0bad8b573fa
Reviewed-on: http://review.whamcloud.com/13707
Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com>
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/osd-ldiskfs/osd_io.c

index e2e08e3..45822ff 100644 (file)
@@ -1285,7 +1285,8 @@ static int osd_read_prep(const struct lu_env *env, struct dt_object *dt,
         struct osd_device *osd = osd_obj2dev(osd_dt_obj(dt));
         struct timeval start, end;
         unsigned long timediff;
         struct osd_device *osd = osd_obj2dev(osd_dt_obj(dt));
         struct timeval start, end;
         unsigned long timediff;
-       int rc = 0, i, m = 0, cache = 0, cache_hits = 0, cache_misses = 0;
+       int rc = 0, i, cache = 0, cache_hits = 0, cache_misses = 0;
+       loff_t isize;
 
         LASSERT(inode);
 
 
         LASSERT(inode);
 
@@ -1293,26 +1294,25 @@ static int osd_read_prep(const struct lu_env *env, struct dt_object *dt,
        if (unlikely(rc != 0))
                RETURN(rc);
 
        if (unlikely(rc != 0))
                RETURN(rc);
 
+       isize = i_size_read(inode);
+
        if (osd->od_read_cache)
                cache = 1;
        if (osd->od_read_cache)
                cache = 1;
-       if (i_size_read(inode) > osd->od_readcache_max_filesize)
+       if (isize > osd->od_readcache_max_filesize)
                cache = 0;
 
        do_gettimeofday(&start);
        for (i = 0; i < npages; i++) {
 
                cache = 0;
 
        do_gettimeofday(&start);
        for (i = 0; i < npages; i++) {
 
-               if (i_size_read(inode) <= lnb[i].lnb_file_offset)
+               if (isize <= lnb[i].lnb_file_offset)
                        /* If there's no more data, abort early.
                         * lnb->lnb_rc == 0, so it's easy to detect later. */
                        break;
 
                        /* If there's no more data, abort early.
                         * lnb->lnb_rc == 0, so it's easy to detect later. */
                        break;
 
-               if (i_size_read(inode) <
-                   lnb[i].lnb_file_offset + lnb[i].lnb_len - 1)
-                       lnb[i].lnb_rc = i_size_read(inode) -
-                               lnb[i].lnb_file_offset;
+               if (isize < lnb[i].lnb_file_offset + lnb[i].lnb_len - 1)
+                       lnb[i].lnb_rc = isize - lnb[i].lnb_file_offset;
                else
                        lnb[i].lnb_rc = lnb[i].lnb_len;
                else
                        lnb[i].lnb_rc = lnb[i].lnb_len;
-               m += lnb[i].lnb_len;
 
                if (PageUptodate(lnb[i].lnb_page)) {
                        cache_hits++;
 
                if (PageUptodate(lnb[i].lnb_page)) {
                        cache_hits++;