diff options
| author | Nathan Scott <nathans@sgi.com> | 2006-03-30 22:08:59 -0500 |
|---|---|---|
| committer | Nathan Scott <nathans@sgi.com> | 2006-03-30 22:08:59 -0500 |
| commit | 1b895840ce93fd2d150a86c800a3085eaab4eb9e (patch) | |
| tree | 2f1c664ca2f948ec8c47f2c66e03cb21f2b9a45c | |
| parent | 3bbcc8e3976f8bba2fd607c8850d7dfe7e332fda (diff) | |
[XFS] Provide XFS support for the splice syscall.
Signed-off-by: Nathan Scott <nathans@sgi.com>
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 113 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_linux.h | 1 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_lrw.c | 120 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_lrw.h | 11 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_vnode.h | 12 | ||||
| -rw-r--r-- | fs/xfs/xfs_vnodeops.c | 4 |
6 files changed, 199 insertions, 62 deletions
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 85997b1205f5..ae4c4754ed31 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
| @@ -69,7 +69,6 @@ __xfs_file_read( | |||
| 69 | return rval; | 69 | return rval; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | |||
| 73 | STATIC ssize_t | 72 | STATIC ssize_t |
| 74 | xfs_file_aio_read( | 73 | xfs_file_aio_read( |
| 75 | struct kiocb *iocb, | 74 | struct kiocb *iocb, |
| @@ -90,7 +89,6 @@ xfs_file_aio_read_invis( | |||
| 90 | return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); | 89 | return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); |
| 91 | } | 90 | } |
| 92 | 91 | ||
| 93 | |||
| 94 | STATIC inline ssize_t | 92 | STATIC inline ssize_t |
| 95 | __xfs_file_write( | 93 | __xfs_file_write( |
| 96 | struct kiocb *iocb, | 94 | struct kiocb *iocb, |
| @@ -113,7 +111,6 @@ __xfs_file_write( | |||
| 113 | return rval; | 111 | return rval; |
| 114 | } | 112 | } |
| 115 | 113 | ||
| 116 | |||
| 117 | STATIC ssize_t | 114 | STATIC ssize_t |
| 118 | xfs_file_aio_write( | 115 | xfs_file_aio_write( |
| 119 | struct kiocb *iocb, | 116 | struct kiocb *iocb, |
| @@ -134,7 +131,6 @@ xfs_file_aio_write_invis( | |||
| 134 | return __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); | 131 | return __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos); |
| 135 | } | 132 | } |
| 136 | 133 | ||
| 137 | |||
| 138 | STATIC inline ssize_t | 134 | STATIC inline ssize_t |
| 139 | __xfs_file_readv( | 135 | __xfs_file_readv( |
| 140 | struct file *file, | 136 | struct file *file, |
| @@ -179,7 +175,6 @@ xfs_file_readv_invis( | |||
| 179 | return __xfs_file_readv(file, iov, IO_INVIS, nr_segs, ppos); | 175 | return __xfs_file_readv(file, iov, IO_INVIS, nr_segs, ppos); |
| 180 | } | 176 | } |
| 181 | 177 | ||
| 182 | |||
| 183 | STATIC inline ssize_t | 178 | STATIC inline ssize_t |
| 184 | __xfs_file_writev( | 179 | __xfs_file_writev( |
| 185 | struct file *file, | 180 | struct file *file, |
| @@ -204,7 +199,6 @@ __xfs_file_writev( | |||
| 204 | return rval; | 199 | return rval; |
| 205 | } | 200 | } |
| 206 | 201 | ||
| 207 | |||
| 208 | STATIC ssize_t | 202 | STATIC ssize_t |
| 209 | xfs_file_writev( | 203 | xfs_file_writev( |
| 210 | struct file *file, | 204 | struct file *file, |
| @@ -228,7 +222,7 @@ xfs_file_writev_invis( | |||
| 228 | STATIC ssize_t | 222 | STATIC ssize_t |
| 229 | xfs_file_sendfile( | 223 | xfs_file_sendfile( |
| 230 | struct file *filp, | 224 | struct file *filp, |
| 231 | loff_t *ppos, | 225 | loff_t *pos, |
| 232 | size_t count, | 226 | size_t count, |
| 233 | read_actor_t actor, | 227 | read_actor_t actor, |
| 234 | void *target) | 228 | void *target) |
| @@ -236,10 +230,80 @@ xfs_file_sendfile( | |||
| 236 | vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); | 230 | vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); |
| 237 | ssize_t rval; | 231 | ssize_t rval; |
| 238 | 232 | ||
| 239 | VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, rval); | 233 | VOP_SENDFILE(vp, filp, pos, 0, count, actor, target, NULL, rval); |
| 240 | return rval; | 234 | return rval; |
| 241 | } | 235 | } |
| 242 | 236 | ||
| 237 | STATIC ssize_t | ||
| 238 | xfs_file_sendfile_invis( | ||
| 239 | struct file *filp, | ||
| 240 | loff_t *pos, | ||
| 241 | size_t count, | ||
| 242 | read_actor_t actor, | ||
| 243 | void *target) | ||
| 244 | { | ||
| 245 | vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); | ||
| 246 | ssize_t rval; | ||
| 247 | |||
| 248 | VOP_SENDFILE(vp, filp, pos, IO_INVIS, count, actor, target, NULL, rval); | ||
| 249 | return rval; | ||
| 250 | } | ||
| 251 | |||
| 252 | STATIC ssize_t | ||
| 253 | xfs_file_splice_read( | ||
| 254 | struct file *infilp, | ||
| 255 | struct inode *pipe, | ||
| 256 | size_t len, | ||
| 257 | unsigned int flags) | ||
| 258 | { | ||
| 259 | vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode); | ||
| 260 | ssize_t rval; | ||
| 261 | |||
| 262 | VOP_SPLICE_READ(vp, infilp, pipe, len, flags, 0, NULL, rval); | ||
| 263 | return rval; | ||
| 264 | } | ||
| 265 | |||
| 266 | STATIC ssize_t | ||
| 267 | xfs_file_splice_read_invis( | ||
| 268 | struct file *infilp, | ||
| 269 | struct inode *pipe, | ||
| 270 | size_t len, | ||
| 271 | unsigned int flags) | ||
| 272 | { | ||
| 273 | vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode); | ||
| 274 | ssize_t rval; | ||
| 275 | |||
| 276 | VOP_SPLICE_READ(vp, infilp, pipe, len, flags, IO_INVIS, NULL, rval); | ||
| 277 | return rval; | ||
| 278 | } | ||
| 279 | |||
| 280 | STATIC ssize_t | ||
| 281 | xfs_file_splice_write( | ||
| 282 | struct inode *pipe, | ||
| 283 | struct file *outfilp, | ||
| 284 | size_t len, | ||
| 285 | unsigned int flags) | ||
| 286 | { | ||
| 287 | vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode); | ||
| 288 | ssize_t rval; | ||
| 289 | |||
| 290 | VOP_SPLICE_WRITE(vp, pipe, outfilp, len, flags, 0, NULL, rval); | ||
| 291 | return rval; | ||
| 292 | } | ||
| 293 | |||
| 294 | STATIC ssize_t | ||
| 295 | xfs_file_splice_write_invis( | ||
| 296 | struct inode *pipe, | ||
| 297 | struct file *outfilp, | ||
| 298 | size_t len, | ||
| 299 | unsigned int flags) | ||
| 300 | { | ||
| 301 | vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode); | ||
| 302 | ssize_t rval; | ||
| 303 | |||
| 304 | VOP_SPLICE_WRITE(vp, pipe, outfilp, len, flags, IO_INVIS, NULL, rval); | ||
| 305 | return rval; | ||
| 306 | } | ||
| 243 | 307 | ||
| 244 | STATIC int | 308 | STATIC int |
| 245 | xfs_file_open( | 309 | xfs_file_open( |
| @@ -251,13 +315,10 @@ xfs_file_open( | |||
| 251 | 315 | ||
| 252 | if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) | 316 | if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) |
| 253 | return -EFBIG; | 317 | return -EFBIG; |
| 254 | |||
| 255 | ASSERT(vp); | ||
| 256 | VOP_OPEN(vp, NULL, error); | 318 | VOP_OPEN(vp, NULL, error); |
| 257 | return -error; | 319 | return -error; |
| 258 | } | 320 | } |
| 259 | 321 | ||
| 260 | |||
| 261 | STATIC int | 322 | STATIC int |
| 262 | xfs_file_release( | 323 | xfs_file_release( |
| 263 | struct inode *inode, | 324 | struct inode *inode, |
| @@ -271,7 +332,6 @@ xfs_file_release( | |||
| 271 | return -error; | 332 | return -error; |
| 272 | } | 333 | } |
| 273 | 334 | ||
| 274 | |||
| 275 | STATIC int | 335 | STATIC int |
| 276 | xfs_file_fsync( | 336 | xfs_file_fsync( |
| 277 | struct file *filp, | 337 | struct file *filp, |
| @@ -285,21 +345,11 @@ xfs_file_fsync( | |||
| 285 | 345 | ||
| 286 | if (datasync) | 346 | if (datasync) |
| 287 | flags |= FSYNC_DATA; | 347 | flags |= FSYNC_DATA; |
| 288 | |||
| 289 | ASSERT(vp); | ||
| 290 | VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error); | 348 | VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error); |
| 291 | return -error; | 349 | return -error; |
| 292 | } | 350 | } |
| 293 | 351 | ||
| 294 | /* | ||
| 295 | * xfs_file_readdir maps to VOP_READDIR(). | ||
| 296 | * We need to build a uio, cred, ... | ||
| 297 | */ | ||
| 298 | |||
| 299 | #define nextdp(dp) ((struct xfs_dirent *)((char *)(dp) + (dp)->d_reclen)) | ||
| 300 | |||
| 301 | #ifdef CONFIG_XFS_DMAPI | 352 | #ifdef CONFIG_XFS_DMAPI |
| 302 | |||
| 303 | STATIC struct page * | 353 | STATIC struct page * |
| 304 | xfs_vm_nopage( | 354 | xfs_vm_nopage( |
| 305 | struct vm_area_struct *area, | 355 | struct vm_area_struct *area, |
| @@ -319,10 +369,8 @@ xfs_vm_nopage( | |||
| 319 | 369 | ||
| 320 | return filemap_nopage(area, address, type); | 370 | return filemap_nopage(area, address, type); |
| 321 | } | 371 | } |
| 322 | |||
| 323 | #endif /* CONFIG_XFS_DMAPI */ | 372 | #endif /* CONFIG_XFS_DMAPI */ |
| 324 | 373 | ||
| 325 | |||
| 326 | STATIC int | 374 | STATIC int |
| 327 | xfs_file_readdir( | 375 | xfs_file_readdir( |
| 328 | struct file *filp, | 376 | struct file *filp, |
| @@ -330,7 +378,7 @@ xfs_file_readdir( | |||
| 330 | filldir_t filldir) | 378 | filldir_t filldir) |
| 331 | { | 379 | { |
| 332 | int error = 0; | 380 | int error = 0; |
| 333 | vnode_t *vp; | 381 | vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); |
| 334 | uio_t uio; | 382 | uio_t uio; |
| 335 | iovec_t iov; | 383 | iovec_t iov; |
| 336 | int eof = 0; | 384 | int eof = 0; |
| @@ -340,9 +388,6 @@ xfs_file_readdir( | |||
| 340 | xfs_off_t start_offset, curr_offset; | 388 | xfs_off_t start_offset, curr_offset; |
| 341 | xfs_dirent_t *dbp = NULL; | 389 | xfs_dirent_t *dbp = NULL; |
| 342 | 390 | ||
| 343 | vp = vn_from_inode(filp->f_dentry->d_inode); | ||
| 344 | ASSERT(vp); | ||
| 345 | |||
| 346 | /* Try fairly hard to get memory */ | 391 | /* Try fairly hard to get memory */ |
| 347 | do { | 392 | do { |
| 348 | if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL))) | 393 | if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL))) |
| @@ -387,7 +432,7 @@ xfs_file_readdir( | |||
| 387 | } | 432 | } |
| 388 | size -= dbp->d_reclen; | 433 | size -= dbp->d_reclen; |
| 389 | curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */; | 434 | curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */; |
| 390 | dbp = nextdp(dbp); | 435 | dbp = (xfs_dirent_t *)((char *)dbp + dbp->d_reclen); |
| 391 | } | 436 | } |
| 392 | } | 437 | } |
| 393 | done: | 438 | done: |
| @@ -402,7 +447,6 @@ done: | |||
| 402 | return -error; | 447 | return -error; |
| 403 | } | 448 | } |
| 404 | 449 | ||
| 405 | |||
| 406 | STATIC int | 450 | STATIC int |
| 407 | xfs_file_mmap( | 451 | xfs_file_mmap( |
| 408 | struct file *filp, | 452 | struct file *filp, |
| @@ -457,11 +501,10 @@ xfs_file_ioctl_invis( | |||
| 457 | unsigned int cmd, | 501 | unsigned int cmd, |
| 458 | unsigned long arg) | 502 | unsigned long arg) |
| 459 | { | 503 | { |
| 460 | int error; | ||
| 461 | struct inode *inode = filp->f_dentry->d_inode; | 504 | struct inode *inode = filp->f_dentry->d_inode; |
| 462 | vnode_t *vp = vn_from_inode(inode); | 505 | vnode_t *vp = vn_from_inode(inode); |
| 506 | int error; | ||
| 463 | 507 | ||
| 464 | ASSERT(vp); | ||
| 465 | VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error); | 508 | VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error); |
| 466 | VMODIFY(vp); | 509 | VMODIFY(vp); |
| 467 | 510 | ||
| @@ -537,6 +580,8 @@ const struct file_operations xfs_file_operations = { | |||
| 537 | .aio_read = xfs_file_aio_read, | 580 | .aio_read = xfs_file_aio_read, |
| 538 | .aio_write = xfs_file_aio_write, | 581 | .aio_write = xfs_file_aio_write, |
| 539 | .sendfile = xfs_file_sendfile, | 582 | .sendfile = xfs_file_sendfile, |
| 583 | .splice_read = xfs_file_splice_read, | ||
| 584 | .splice_write = xfs_file_splice_write, | ||
| 540 | .unlocked_ioctl = xfs_file_ioctl, | 585 | .unlocked_ioctl = xfs_file_ioctl, |
| 541 | #ifdef CONFIG_COMPAT | 586 | #ifdef CONFIG_COMPAT |
| 542 | .compat_ioctl = xfs_file_compat_ioctl, | 587 | .compat_ioctl = xfs_file_compat_ioctl, |
| @@ -558,7 +603,9 @@ const struct file_operations xfs_invis_file_operations = { | |||
| 558 | .writev = xfs_file_writev_invis, | 603 | .writev = xfs_file_writev_invis, |
| 559 | .aio_read = xfs_file_aio_read_invis, | 604 | .aio_read = xfs_file_aio_read_invis, |
| 560 | .aio_write = xfs_file_aio_write_invis, | 605 | .aio_write = xfs_file_aio_write_invis, |
| 561 | .sendfile = xfs_file_sendfile, | 606 | .sendfile = xfs_file_sendfile_invis, |
| 607 | .splice_read = xfs_file_splice_read_invis, | ||
| 608 | .splice_write = xfs_file_splice_write_invis, | ||
| 562 | .unlocked_ioctl = xfs_file_ioctl_invis, | 609 | .unlocked_ioctl = xfs_file_ioctl_invis, |
| 563 | #ifdef CONFIG_COMPAT | 610 | #ifdef CONFIG_COMPAT |
| 564 | .compat_ioctl = xfs_file_compat_invis_ioctl, | 611 | .compat_ioctl = xfs_file_compat_invis_ioctl, |
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 1fe09f2d6519..e9fe43d74768 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h | |||
| @@ -103,6 +103,7 @@ | |||
| 103 | */ | 103 | */ |
| 104 | #undef HAVE_REFCACHE /* reference cache not needed for NFS in 2.6 */ | 104 | #undef HAVE_REFCACHE /* reference cache not needed for NFS in 2.6 */ |
| 105 | #define HAVE_SENDFILE /* sendfile(2) exists in 2.6, but not in 2.4 */ | 105 | #define HAVE_SENDFILE /* sendfile(2) exists in 2.6, but not in 2.4 */ |
| 106 | #define HAVE_SPLICE /* a splice(2) exists in 2.6, but not in 2.4 */ | ||
| 106 | #ifdef CONFIG_SMP | 107 | #ifdef CONFIG_SMP |
| 107 | #define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ | 108 | #define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ |
| 108 | #else | 109 | #else |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 84ddf1893894..90cd314acbaa 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c | |||
| @@ -301,36 +301,23 @@ xfs_sendfile( | |||
| 301 | void *target, | 301 | void *target, |
| 302 | cred_t *credp) | 302 | cred_t *credp) |
| 303 | { | 303 | { |
| 304 | xfs_inode_t *ip = XFS_BHVTOI(bdp); | ||
| 305 | xfs_mount_t *mp = ip->i_mount; | ||
| 304 | ssize_t ret; | 306 | ssize_t ret; |
| 305 | xfs_fsize_t n; | ||
| 306 | xfs_inode_t *ip; | ||
| 307 | xfs_mount_t *mp; | ||
| 308 | vnode_t *vp; | ||
| 309 | |||
| 310 | ip = XFS_BHVTOI(bdp); | ||
| 311 | vp = BHV_TO_VNODE(bdp); | ||
| 312 | mp = ip->i_mount; | ||
| 313 | 307 | ||
| 314 | XFS_STATS_INC(xs_read_calls); | 308 | XFS_STATS_INC(xs_read_calls); |
| 315 | 309 | if (XFS_FORCED_SHUTDOWN(mp)) | |
| 316 | n = XFS_MAXIOFFSET(mp) - *offset; | ||
| 317 | if ((n <= 0) || (count == 0)) | ||
| 318 | return 0; | ||
| 319 | |||
| 320 | if (n < count) | ||
| 321 | count = n; | ||
| 322 | |||
| 323 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
| 324 | return -EIO; | 310 | return -EIO; |
| 325 | 311 | ||
| 326 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | 312 | xfs_ilock(ip, XFS_IOLOCK_SHARED); |
| 327 | 313 | ||
| 328 | if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) && | 314 | if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) && |
| 329 | (!(ioflags & IO_INVIS))) { | 315 | (!(ioflags & IO_INVIS))) { |
| 330 | vrwlock_t locktype = VRWLOCK_READ; | 316 | vrwlock_t locktype = VRWLOCK_READ; |
| 331 | int error; | 317 | int error; |
| 332 | 318 | ||
| 333 | error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), *offset, count, | 319 | error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), |
| 320 | *offset, count, | ||
| 334 | FILP_DELAY_FLAG(filp), &locktype); | 321 | FILP_DELAY_FLAG(filp), &locktype); |
| 335 | if (error) { | 322 | if (error) { |
| 336 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | 323 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); |
| @@ -340,12 +327,96 @@ xfs_sendfile( | |||
| 340 | xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore, | 327 | xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore, |
| 341 | (void *)(unsigned long)target, count, *offset, ioflags); | 328 | (void *)(unsigned long)target, count, *offset, ioflags); |
| 342 | ret = generic_file_sendfile(filp, offset, count, actor, target); | 329 | ret = generic_file_sendfile(filp, offset, count, actor, target); |
| 330 | if (ret > 0) | ||
| 331 | XFS_STATS_ADD(xs_read_bytes, ret); | ||
| 343 | 332 | ||
| 344 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | 333 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); |
| 334 | return ret; | ||
| 335 | } | ||
| 345 | 336 | ||
| 337 | ssize_t | ||
| 338 | xfs_splice_read( | ||
| 339 | bhv_desc_t *bdp, | ||
| 340 | struct file *infilp, | ||
| 341 | struct inode *pipe, | ||
| 342 | size_t count, | ||
| 343 | int flags, | ||
| 344 | int ioflags, | ||
| 345 | cred_t *credp) | ||
| 346 | { | ||
| 347 | xfs_inode_t *ip = XFS_BHVTOI(bdp); | ||
| 348 | xfs_mount_t *mp = ip->i_mount; | ||
| 349 | ssize_t ret; | ||
| 350 | |||
| 351 | XFS_STATS_INC(xs_read_calls); | ||
| 352 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
| 353 | return -EIO; | ||
| 354 | |||
| 355 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | ||
| 356 | |||
| 357 | if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) && | ||
| 358 | (!(ioflags & IO_INVIS))) { | ||
| 359 | vrwlock_t locktype = VRWLOCK_READ; | ||
| 360 | int error; | ||
| 361 | |||
| 362 | error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), | ||
| 363 | infilp->f_pos, count, | ||
| 364 | FILP_DELAY_FLAG(infilp), &locktype); | ||
| 365 | if (error) { | ||
| 366 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | ||
| 367 | return -error; | ||
| 368 | } | ||
| 369 | } | ||
| 370 | xfs_rw_enter_trace(XFS_SPLICE_READ_ENTER, &ip->i_iocore, | ||
| 371 | pipe, count, infilp->f_pos, ioflags); | ||
| 372 | ret = generic_file_splice_read(infilp, pipe, count, flags); | ||
| 346 | if (ret > 0) | 373 | if (ret > 0) |
| 347 | XFS_STATS_ADD(xs_read_bytes, ret); | 374 | XFS_STATS_ADD(xs_read_bytes, ret); |
| 348 | 375 | ||
| 376 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | ||
| 377 | return ret; | ||
| 378 | } | ||
| 379 | |||
| 380 | ssize_t | ||
| 381 | xfs_splice_write( | ||
| 382 | bhv_desc_t *bdp, | ||
| 383 | struct inode *pipe, | ||
| 384 | struct file *outfilp, | ||
| 385 | size_t count, | ||
| 386 | int flags, | ||
| 387 | int ioflags, | ||
| 388 | cred_t *credp) | ||
| 389 | { | ||
| 390 | xfs_inode_t *ip = XFS_BHVTOI(bdp); | ||
| 391 | xfs_mount_t *mp = ip->i_mount; | ||
| 392 | ssize_t ret; | ||
| 393 | |||
| 394 | XFS_STATS_INC(xs_write_calls); | ||
| 395 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
| 396 | return -EIO; | ||
| 397 | |||
| 398 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | ||
| 399 | |||
| 400 | if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) && | ||
| 401 | (!(ioflags & IO_INVIS))) { | ||
| 402 | vrwlock_t locktype = VRWLOCK_WRITE; | ||
| 403 | int error; | ||
| 404 | |||
| 405 | error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp), | ||
| 406 | outfilp->f_pos, count, | ||
| 407 | FILP_DELAY_FLAG(outfilp), &locktype); | ||
| 408 | if (error) { | ||
| 409 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
| 410 | return -error; | ||
| 411 | } | ||
| 412 | } | ||
| 413 | xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore, | ||
| 414 | pipe, count, outfilp->f_pos, ioflags); | ||
| 415 | ret = generic_file_splice_write(pipe, outfilp, count, flags); | ||
| 416 | if (ret > 0) | ||
| 417 | XFS_STATS_ADD(xs_write_bytes, ret); | ||
| 418 | |||
| 419 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
| 349 | return ret; | 420 | return ret; |
| 350 | } | 421 | } |
| 351 | 422 | ||
| @@ -363,7 +434,7 @@ xfs_zero_last_block( | |||
| 363 | xfs_fsize_t end_size) | 434 | xfs_fsize_t end_size) |
| 364 | { | 435 | { |
| 365 | xfs_fileoff_t last_fsb; | 436 | xfs_fileoff_t last_fsb; |
| 366 | xfs_mount_t *mp; | 437 | xfs_mount_t *mp = io->io_mount; |
| 367 | int nimaps; | 438 | int nimaps; |
| 368 | int zero_offset; | 439 | int zero_offset; |
| 369 | int zero_len; | 440 | int zero_len; |
| @@ -373,8 +444,6 @@ xfs_zero_last_block( | |||
| 373 | 444 | ||
| 374 | ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0); | 445 | ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0); |
| 375 | 446 | ||
| 376 | mp = io->io_mount; | ||
| 377 | |||
| 378 | zero_offset = XFS_B_FSB_OFFSET(mp, isize); | 447 | zero_offset = XFS_B_FSB_OFFSET(mp, isize); |
| 379 | if (zero_offset == 0) { | 448 | if (zero_offset == 0) { |
| 380 | /* | 449 | /* |
| @@ -405,10 +474,9 @@ xfs_zero_last_block( | |||
| 405 | * don't deadlock when the buffer cache calls back to us. | 474 | * don't deadlock when the buffer cache calls back to us. |
| 406 | */ | 475 | */ |
| 407 | XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD); | 476 | XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD); |
| 408 | loff = XFS_FSB_TO_B(mp, last_fsb); | ||
| 409 | 477 | ||
| 478 | loff = XFS_FSB_TO_B(mp, last_fsb); | ||
| 410 | zero_len = mp->m_sb.sb_blocksize - zero_offset; | 479 | zero_len = mp->m_sb.sb_blocksize - zero_offset; |
| 411 | |||
| 412 | error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size); | 480 | error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size); |
| 413 | 481 | ||
| 414 | XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); | 482 | XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); |
| @@ -441,7 +509,7 @@ xfs_zero_eof( | |||
| 441 | xfs_fileoff_t zero_count_fsb; | 509 | xfs_fileoff_t zero_count_fsb; |
| 442 | xfs_fileoff_t last_fsb; | 510 | xfs_fileoff_t last_fsb; |
| 443 | xfs_extlen_t buf_len_fsb; | 511 | xfs_extlen_t buf_len_fsb; |
| 444 | xfs_mount_t *mp; | 512 | xfs_mount_t *mp = io->io_mount; |
| 445 | int nimaps; | 513 | int nimaps; |
| 446 | int error = 0; | 514 | int error = 0; |
| 447 | xfs_bmbt_irec_t imap; | 515 | xfs_bmbt_irec_t imap; |
| @@ -450,8 +518,6 @@ xfs_zero_eof( | |||
| 450 | ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); | 518 | ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); |
| 451 | ASSERT(offset > isize); | 519 | ASSERT(offset > isize); |
| 452 | 520 | ||
| 453 | mp = io->io_mount; | ||
| 454 | |||
| 455 | /* | 521 | /* |
| 456 | * First handle zeroing the block on which isize resides. | 522 | * First handle zeroing the block on which isize resides. |
| 457 | * We only zero a part of that block so it is handled specially. | 523 | * We only zero a part of that block so it is handled specially. |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h index 38864a88d42d..eaa5659713fb 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.h +++ b/fs/xfs/linux-2.6/xfs_lrw.h | |||
| @@ -60,6 +60,8 @@ struct xfs_iomap; | |||
| 60 | #define XFS_IOMAP_ALLOC_ENTER 25 | 60 | #define XFS_IOMAP_ALLOC_ENTER 25 |
| 61 | #define XFS_IOMAP_ALLOC_MAP 26 | 61 | #define XFS_IOMAP_ALLOC_MAP 26 |
| 62 | #define XFS_IOMAP_UNWRITTEN 27 | 62 | #define XFS_IOMAP_UNWRITTEN 27 |
| 63 | #define XFS_SPLICE_READ_ENTER 28 | ||
| 64 | #define XFS_SPLICE_WRITE_ENTER 29 | ||
| 63 | extern void xfs_rw_enter_trace(int, struct xfs_iocore *, | 65 | extern void xfs_rw_enter_trace(int, struct xfs_iocore *, |
| 64 | void *, size_t, loff_t, int); | 66 | void *, size_t, loff_t, int); |
| 65 | extern void xfs_inval_cached_trace(struct xfs_iocore *, | 67 | extern void xfs_inval_cached_trace(struct xfs_iocore *, |
| @@ -78,6 +80,7 @@ extern int xfs_bmap(struct bhv_desc *, xfs_off_t, ssize_t, int, | |||
| 78 | struct xfs_iomap *, int *); | 80 | struct xfs_iomap *, int *); |
| 79 | extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *); | 81 | extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *); |
| 80 | extern int xfs_bdstrat_cb(struct xfs_buf *); | 82 | extern int xfs_bdstrat_cb(struct xfs_buf *); |
| 83 | extern int xfs_dev_is_read_only(struct xfs_mount *, char *); | ||
| 81 | 84 | ||
| 82 | extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t, | 85 | extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t, |
| 83 | xfs_fsize_t, xfs_fsize_t); | 86 | xfs_fsize_t, xfs_fsize_t); |
| @@ -90,7 +93,11 @@ extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *, | |||
| 90 | extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *, | 93 | extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *, |
| 91 | loff_t *, int, size_t, read_actor_t, | 94 | loff_t *, int, size_t, read_actor_t, |
| 92 | void *, struct cred *); | 95 | void *, struct cred *); |
| 93 | 96 | extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, | |
| 94 | extern int xfs_dev_is_read_only(struct xfs_mount *, char *); | 97 | struct inode *, size_t, int, int, |
| 98 | struct cred *); | ||
| 99 | extern ssize_t xfs_splice_write(struct bhv_desc *, struct inode *, | ||
| 100 | struct file *, size_t, int, int, | ||
| 101 | struct cred *); | ||
| 95 | 102 | ||
| 96 | #endif /* __XFS_LRW_H__ */ | 103 | #endif /* __XFS_LRW_H__ */ |
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 06f5845e9568..6f1c79a28f8b 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h | |||
| @@ -173,6 +173,12 @@ typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *, | |||
| 173 | typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *, | 173 | typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *, |
| 174 | loff_t *, int, size_t, read_actor_t, | 174 | loff_t *, int, size_t, read_actor_t, |
| 175 | void *, struct cred *); | 175 | void *, struct cred *); |
| 176 | typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, | ||
| 177 | struct inode *, size_t, int, int, | ||
| 178 | struct cred *); | ||
| 179 | typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct inode *, | ||
| 180 | struct file *, size_t, int, int, | ||
| 181 | struct cred *); | ||
| 176 | typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *, | 182 | typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *, |
| 177 | int, unsigned int, void __user *); | 183 | int, unsigned int, void __user *); |
| 178 | typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int, | 184 | typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int, |
| @@ -231,6 +237,8 @@ typedef struct vnodeops { | |||
| 231 | vop_read_t vop_read; | 237 | vop_read_t vop_read; |
| 232 | vop_write_t vop_write; | 238 | vop_write_t vop_write; |
| 233 | vop_sendfile_t vop_sendfile; | 239 | vop_sendfile_t vop_sendfile; |
| 240 | vop_splice_read_t vop_splice_read; | ||
| 241 | vop_splice_write_t vop_splice_write; | ||
| 234 | vop_ioctl_t vop_ioctl; | 242 | vop_ioctl_t vop_ioctl; |
| 235 | vop_getattr_t vop_getattr; | 243 | vop_getattr_t vop_getattr; |
| 236 | vop_setattr_t vop_setattr; | 244 | vop_setattr_t vop_setattr; |
| @@ -276,6 +284,10 @@ typedef struct vnodeops { | |||
| 276 | rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr) | 284 | rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr) |
| 277 | #define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv) \ | 285 | #define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv) \ |
| 278 | rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr) | 286 | rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr) |
| 287 | #define VOP_SPLICE_READ(vp,f,pipe,cnt,fl,iofl,cr,rv) \ | ||
| 288 | rv = _VOP_(vop_splice_read, vp)((vp)->v_fbhv,f,pipe,cnt,fl,iofl,cr) | ||
| 289 | #define VOP_SPLICE_WRITE(vp,f,pipe,cnt,fl,iofl,cr,rv) \ | ||
| 290 | rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,pipe,cnt,fl,iofl,cr) | ||
| 279 | #define VOP_BMAP(vp,of,sz,rw,b,n,rv) \ | 291 | #define VOP_BMAP(vp,of,sz,rw,b,n,rv) \ |
| 280 | rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n) | 292 | rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n) |
| 281 | #define VOP_OPEN(vp, cr, rv) \ | 293 | #define VOP_OPEN(vp, cr, rv) \ |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index de49601919c1..fa71b305ba5c 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
| @@ -4649,6 +4649,10 @@ vnodeops_t xfs_vnodeops = { | |||
| 4649 | #ifdef HAVE_SENDFILE | 4649 | #ifdef HAVE_SENDFILE |
| 4650 | .vop_sendfile = xfs_sendfile, | 4650 | .vop_sendfile = xfs_sendfile, |
| 4651 | #endif | 4651 | #endif |
| 4652 | #ifdef HAVE_SPLICE | ||
| 4653 | .vop_splice_read = xfs_splice_read, | ||
| 4654 | .vop_splice_write = xfs_splice_write, | ||
| 4655 | #endif | ||
| 4652 | .vop_write = xfs_write, | 4656 | .vop_write = xfs_write, |
| 4653 | .vop_ioctl = xfs_ioctl, | 4657 | .vop_ioctl = xfs_ioctl, |
| 4654 | .vop_getattr = xfs_getattr, | 4658 | .vop_getattr = xfs_getattr, |
