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, |