fs: remove duplicated iovec checking code v8
Subsystems (5)
PATCH 1/2 fs: remove duplicated iovec checking code v8
Where are several places where the same code used for iovec checks. This patch just move this code to separate helper function, and replace duplicated code with it. IMHO it is better because these are checks that we want for all filesystems/drivers that use vectored I/O.
--- fs/ntfs/file.c | 21 +++------------------ fs/read_write.c | 40 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/linux-2.6/xfs_lrw.c | 22 +++------------------- include/linux/fs.h | 3 +++ mm/filemap.c | 43 ++++++------------------------------------- 5 files changed, 55 insertions(+), 74 deletions(-)
fs/ntfs/file.c +3 -18
@@ -2129,28 +2129,13 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb,struct address_space *mapping = file->f_mapping;struct inode *inode = mapping->host;loff_t pos; -unsigned long seg;size_t count;/* after file limit checks */ ssize_t written, err; count =0 ; -for (seg =0 ; seg < nr_segs; seg++) { -const struct iovec *iv = &iov[seg]; -/* -* If any segment has a negative length, or the cumulative -* length ever wraps negative then return -EINVAL. -*/ - count += iv->iov_len; -if (unlikely ((ssize_t )(count|iv->iov_len) <0 )) -return -EINVAL ; -if (access_ok (VERIFY_READ , iv->iov_base, iv->iov_len)) -continue ; -if (!seg) -return -EFAULT ; - nr_segs = seg; - count -= iv->iov_len;/* This segment is no good */ -break ; - } + err =generic_iovec_checks (iov, &nr_segs, &count,VERIFY_READ ); +if (err) +return err; pos = *ppos;vfs_check_frozen (inode->i_sb,SB_FREEZE_WRITE );/* We can write back this queue in page reclaim. */
fs/read_write.c +40 -0
@@ -217,6 +217,46 @@ Einval:return -EINVAL ; } +/* +* Performs necessary iovec checks before doing a write +* @iov: io vector request +* @nr_segs: number of segments in the iovec +* @count: number of bytes to write +* @access_flags: type of access: %VERIFY_READ or %VERIFY_WRITE +* +* Adjust number of segments and amount of bytes to write (nr_segs should be +* properly initialized first). Returns appropriate error code that caller +* should return or zero in case that write should be allowed. +*/ +int generic_iovec_checks (const struct iovec *iov, +unsigned long *nr_segs,size_t *count, +unsigned long access_flags) +{ +unsigned long seg; +size_t cnt =0 ; +for (seg =0 ; seg < *nr_segs; seg++) { +const struct iovec *iv = &iov[seg]; + +/* +* If any segment has a negative length, or the cumulative +* length ever wraps negative then return -EINVAL. +*/ + cnt += iv->iov_len; +if (unlikely ((ssize_t )(cnt|iv->iov_len) <0 )) +return -EINVAL ; +if (access_ok (access_flags, iv->iov_base, iv->iov_len)) +continue ; +if (seg ==0 ) +return -EFAULT ; + *nr_segs = seg; + cnt -= iv->iov_len;/* This segment is no good */ +break ; + } + *count = cnt; +return 0 ; +} +EXPORT_SYMBOL (generic_iovec_checks); +static void wait_on_retry_sync_kiocb (struct kiocb *iocb) {set_current_state (TASK_UNINTERRUPTIBLE );
fs/xfs/linux-2.6/xfs_lrw.c +3 -19
@@ -639,7 +639,6 @@ xfs_write(xfs_fsize_t isize, new_size;xfs_iocore_t *io;bhv_vnode_t *vp; -unsigned long seg;int iolock;int eventsent =0 ;bhv_vrwlock_t locktype;
@@ -652,24 +651,9 @@ xfs_write( vp =BHV_TO_VNODE (bdp); xip =XFS_BHVTOI (bdp); -for (seg =0 ; seg < segs; seg++) { -const struct iovec *iv = &iovp[seg]; - -/* -* If any segment has a negative length, or the cumulative -* length ever wraps negative then return -EINVAL. -*/ - ocount += iv->iov_len; -if (unlikely ((ssize_t )(ocount|iv->iov_len) <0 )) -return -EINVAL ; -if (access_ok (VERIFY_READ , iv->iov_base, iv->iov_len)) -continue ; -if (seg ==0 ) -return -EFAULT ; - segs = seg; - ocount -= iv->iov_len;/* This segment is no good */ -break ; - } + error =generic_iovec_checks (iovp, &segs, &ocount,VERIFY_READ ); +if (error) +return error; count = ocount; pos = *offset;
include/linux/fs.h +3 -0
@@ -1771,6 +1771,9 @@ extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actorextern void do_generic_mapping_read (struct address_space *mapping,struct file_ra_state *,struct file *,loff_t *,read_descriptor_t *,read_actor_t ); +extern int generic_iovec_checks (const struct iovec *iov, +unsigned long *nr_segs,size_t *count, +unsigned long access_flags);/* fs/splice.c */ extern ssize_t generic_file_splice_read(struct file *, loff_t *,
mm/filemap.c +6 -37
60 lines not on this page · raw message
Signature · 9 lines
1.4.4.2 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
Quoted 5 lines · Dmitriy Monakhov
Where are several places where the same code used for iovec checks. This patch just move this code to separate helper function, and replace duplicated code with it. IMHO it is better because these are checks that we want for all filesystems/drivers that use vectored I/O.
Please move this into the common code path, so it's checked before entering the filesystem. This won't cover the calculating count until we have an iodesc/uio strcuture to pass it down, so feel free to add a tiny helper for that temporaily.