X-Spam-Checker-Version: SpamAssassin 3.4.0-r929098 (2010-03-30) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham version=3.4.0-r929098 Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by oss.sgi.com (8.14.3/8.14.3/SuSE Linux 0.8) with ESMTP id q0CDTkTK258060 for ; Thu, 12 Jan 2012 07:29:46 -0600 X-ASG-Debug-ID: 1326374984-005fe612a67737f0001-NocioJ Received: from acsinet15.oracle.com (acsinet15.oracle.com [141.146.126.227]) by cuda.sgi.com with ESMTP id 10nioxrsayJKCZsO; Thu, 12 Jan 2012 05:29:44 -0800 (PST) X-Barracuda-Envelope-From: jeff.liu@oracle.com X-Barracuda-Apparent-Source-IP: 141.146.126.227 Received: from ucsinet21.oracle.com (ucsinet21.oracle.com [156.151.31.93]) by acsinet15.oracle.com (Switch-3.4.4/Switch-3.4.4) with ESMTP id q0CDTe3w023860 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 12 Jan 2012 13:29:41 GMT Received: from acsmt358.oracle.com (acsmt358.oracle.com [141.146.40.158]) by ucsinet21.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id q0CDTdAu014206 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 12 Jan 2012 13:29:39 GMT Received: from abhmt114.oracle.com (abhmt114.oracle.com [141.146.116.66]) by acsmt358.oracle.com (8.12.11.20060308/8.12.11) with ESMTP id q0CDTcku018375; Thu, 12 Jan 2012 07:29:38 -0600 Received: from [10.191.45.24] (/10.191.45.24) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 12 Jan 2012 05:29:38 -0800 Message-ID: <4F0EE03D.8090402@oracle.com> Date: Thu, 12 Jan 2012 21:29:33 +0800 From: Jeff Liu Reply-To: jeff.liu@oracle.com Organization: Oracle User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.18) Gecko/20110617 Thunderbird/3.1.11 MIME-Version: 1.0 To: Mark Tinguely CC: Ben Myers , Christoph Hellwig , Chris Mason , xfs@oss.sgi.com Subject: Re: Introduce SEEK_DATA/SEEK_HOLE to XFS V5 References: <4F06F71A.2010301@oracle.com> <20120110171855.GX6390@sgi.com> <4F0D21E5.7010908@oracle.com> <4F0DFA11.7030305@sgi.com> X-ASG-Orig-Subj: Re: Introduce SEEK_DATA/SEEK_HOLE to XFS V5 In-Reply-To: <4F0DFA11.7030305@sgi.com> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Source-IP: ucsinet21.oracle.com [156.151.31.93] X-CT-RefId: str=0001.0A020207.4F0EE045.0090,ss=1,re=0.000,fgs=0 X-Barracuda-Connect: acsinet15.oracle.com[141.146.126.227] X-Barracuda-Start-Time: 1326374984 X-Barracuda-URL: http://cuda.sgi.com:80/cgi-mod/mark.cgi X-Virus-Scanned: ClamAV version 0.94.2, clamav-milter version 0.94.2 on oss.sgi.com X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=2.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.1 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.2.85724 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- X-Virus-Status: Clean Hi Mark, Thanks for your comments! On 01/12/2012 05:07 AM, Mark Tinguely wrote: > > xfs_bmapi_read() returns the br_state == XFS_EXT_NORM for a hole. Yes, this is key point I have missed before. > There are a couple places that a hole can trigger a data test. > BTW, I could not generate a large enough hole that xfs_bmapi_read() > would return as more than one hole entry, so I will ignore those > situations and just list the couple places that a hole may be match > a data rule: > > in xfs_seek_data(): > + /* > + * Landed in an unwritten extent, try to find out the data > + * buffer offset from page cache firstly. If nothing was > + * found, treat it as a hole, and skip to check the next > + * extent, something just like above. > + */ > + if (map[0].br_state == XFS_EXT_UNWRITTEN) { > + if (xfs_has_unwritten_buffer(inode, &map[0], > + PAGECACHE_TAG_DIRTY, > + &offset) || > + xfs_has_unwritten_buffer(inode, &map[0], > + PAGECACHE_TAG_WRITEBACK, > + &offset)) { > + offset = max_t(loff_t, seekoff, offset); > + break; > + } > + > + /* No data extent at the given offset */ > + if (nmap == 1) { > + error = ENXIO; > + break; > + } > + > + if (map[1].br_state == XFS_EXT_NORM || > ^^^ could be a hole and not data^^^ > > I think you need to add back the br_startblock test: > > + if ((map[1].br_state == XFS_EXT_NORM && > + map[1].br_startblock != HOLESTARTBLOCK) || Ok, I'll add !isnullstartblock() test for normal extents test. > > > in xfs_seek_hole(): > + /* > + * Landed in a delay allocated extent or a real data extent, > + * if the next extent is landed in a hole or in an unwritten > + * extent but without data committed in the page cache, return > + * its offset. If the next extent has dirty data in page cache, > + * but its offset starts past both the start block of the map > + * and the seek offset, it still be a hole. > + */ > + if (map[0].br_startblock == DELAYSTARTBLOCK || > + map[0].br_state == XFS_EXT_NORM) { > ^^^ could be a hole ^^^ > > and this only matters because this test is checked before the next test: > > + > + /* Landed in a hole, its fine to return */ > + if (map[0].br_startblock == HOLESTARTBLOCK) { > + offset = max_t(loff_t, seekoff, > + XFS_FSB_TO_B(mp, map[0].br_startoff)); > + break; > + } > > > > Switching the order of these two tests would return the immediate offset > starting a hole seek at the offset of a hole. looks this issue is caused by missing hole test for extents at XFS_EXT_NORM state. I'll fix them later. Thanks, -Jeff > > > None of these conditions will result in data corruption, only earlier > detection of a hole.