[XFS] Provide XFS support for the splice syscall.

Signed-off-by: Nathan Scott <nathans@sgi.com>

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