From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx2.suse.de ([195.135.220.15]:44417 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759337AbcAKP5E (ORCPT ); Mon, 11 Jan 2016 10:57:04 -0500 Date: Mon, 11 Jan 2016 16:57:09 +0100 From: Jan Kara To: Eric Sandeen Cc: fsdevel , xfs@oss.sgi.com, Jan Kara Subject: Re: [PATCH 3/4] xfs: Factor xfs_seek_hole_data into helper Message-ID: <20160111155709.GI6262@quack.suse.cz> References: <568FEA2C.6080708@redhat.com> <568FEAD1.5040302@sandeen.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <568FEAD1.5040302@sandeen.net> Sender: linux-fsdevel-owner@vger.kernel.org List-ID: On Fri 08-01-16 10:58:57, Eric Sandeen wrote: > Factor xfs_seek_hole_data into an unlocked helper which takes > an xfs inode rather than a file for internal use. > > Also allow specification of "end" - the vfs lseek interface is > defined such that any offset past eof/i_size shall return -ENXIO, > but we will use this for quota code which does not maintain i_size, > and we want to be able to SEEK_DATA past i_size as well. So the > lseek path can send in i_size, and the quota code can determine > its own ending offset. This patch looks whitespace damaged making it difficult to read... Honza > Signed-off-by: Eric Sandeen > --- > fs/xfs/xfs_file.c | 82 ++++++++++++++++++++++++++++++++++++---------------- > fs/xfs/xfs_inode.h | 2 + > 2 files changed, 59 insertions(+), 25 deletions(-) > > diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c > index ebe9b82..5dc7113 100644 > --- a/fs/xfs/xfs_file.c > +++ b/fs/xfs/xfs_file.c > @@ -1337,31 +1337,31 @@ out: > return found; > } > > -STATIC loff_t > -xfs_seek_hole_data( > - struct file *file, > +/* > + * caller must lock inode with xfs_ilock_data_map_shared, > + * can we craft an appropriate ASSERT? > + * > + * end is because the VFS-level lseek interface is defined such that any > + * offset past i_size shall return -ENXIO, but we use this for quota code > + * which does not maintain i_size, and we want to SEEK_DATA past i_size. > + */ > +loff_t > +__xfs_seek_hole_data( > + struct inode *inode, > loff_t start, > + loff_t end, > int whence) > { > - struct inode *inode = file->f_mapping->host; > struct xfs_inode *ip = XFS_I(inode); > struct xfs_mount *mp = ip->i_mount; > loff_t uninitialized_var(offset); > - xfs_fsize_t isize; > xfs_fileoff_t fsbno; > - xfs_filblks_t end; > - uint lock; > + xfs_filblks_t lastbno; > int error; > > - if (XFS_FORCED_SHUTDOWN(mp)) > - return -EIO; > - > - lock = xfs_ilock_data_map_shared(ip); > - > - isize = i_size_read(inode); > - if (start >= isize) { > + if (start >= end) { > error = -ENXIO; > - goto out_unlock; > + goto out_error; > } > > /* > @@ -1369,22 +1369,22 @@ xfs_seek_hole_data( > * by fsbno to the end block of the file. > */ > fsbno = XFS_B_TO_FSBT(mp, start); > - end = XFS_B_TO_FSB(mp, isize); > + lastbno = XFS_B_TO_FSB(mp, end); > > for (;;) { > struct xfs_bmbt_irec map[2]; > int nmap = 2; > unsigned int i; > > - error = xfs_bmapi_read(ip, fsbno, end - fsbno, map, &nmap, > + error = xfs_bmapi_read(ip, fsbno, lastbno - fsbno, map, &nmap, > XFS_BMAPI_ENTIRE); > if (error) > - goto out_unlock; > + goto out_error; > > /* No extents at given offset, must be beyond EOF */ > if (nmap == 0) { > error = -ENXIO; > - goto out_unlock; > + goto out_error; > } > > for (i = 0; i < nmap; i++) { > @@ -1426,7 +1426,7 @@ xfs_seek_hole_data( > * hole at the end of any file). > */ > if (whence == SEEK_HOLE) { > - offset = isize; > + offset = end; > break; > } > /* > @@ -1434,7 +1434,7 @@ xfs_seek_hole_data( > */ > ASSERT(whence == SEEK_DATA); > error = -ENXIO; > - goto out_unlock; > + goto out_error; > } > > ASSERT(i > 1); > @@ -1445,14 +1445,14 @@ xfs_seek_hole_data( > */ > fsbno = map[i - 1].br_startoff + map[i - 1].br_blockcount; > start = XFS_FSB_TO_B(mp, fsbno); > - if (start >= isize) { > + if (start >= end) { > if (whence == SEEK_HOLE) { > - offset = isize; > + offset = end; > break; > } > ASSERT(whence == SEEK_DATA); > error = -ENXIO; > - goto out_unlock; > + goto out_error; > } > } > > @@ -1464,7 +1464,39 @@ out: > * situation in particular. > */ > if (whence == SEEK_HOLE) > - offset = min_t(loff_t, offset, isize); > + offset = min_t(loff_t, offset, end); > + > + return offset; > + > +out_error: > + return error; > +} > + > +STATIC loff_t > +xfs_seek_hole_data( > + struct file *file, > + loff_t start, > + int whence) > +{ > + struct inode *inode = file->f_mapping->host; > + struct xfs_inode *ip = XFS_I(inode); > + struct xfs_mount *mp = ip->i_mount; > + uint lock; > + loff_t offset, end; > + int error = 0; > + > + if (XFS_FORCED_SHUTDOWN(mp)) > + return -EIO; > + > + lock = xfs_ilock_data_map_shared(ip); > + > + end = i_size_read(inode); > + offset = __xfs_seek_hole_data(inode, start, end, whence); > + if (offset < 0) { > + error = offset; > + goto out_unlock; > + } > + > offset = vfs_setpos(file, offset, inode->i_sb->s_maxbytes); > > out_unlock: > diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h > index ca9e119..ed7e933 100644 > --- a/fs/xfs/xfs_inode.h > +++ b/fs/xfs/xfs_inode.h > @@ -437,6 +437,8 @@ int xfs_update_prealloc_flags(struct xfs_inode *ip, > int xfs_zero_eof(struct xfs_inode *ip, xfs_off_t offset, > xfs_fsize_t isize, bool *did_zeroing); > int xfs_iozero(struct xfs_inode *ip, loff_t pos, size_t count); > +loff_t __xfs_seek_hole_data(struct inode *inode, loff_t start, > + loff_t eof, int whence); > > > /* from xfs_iops.c */ > -- > 1.7.1 > > -- Jan Kara SUSE Labs, CR