From 6866bef40d06f7c2baac3a855b1917a8ca75456c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 16 Oct 2007 10:01:29 +0200 Subject: splice: fix double kunmap() in vmsplice copy path The out label should not include the unmap, the only way to jump there already has unmapped the source. 00002000 f7c21a00 00000000 00000000 c0489036 00018e32 00000002 00000000 00001000 Call Trace: [] pipe_to_user+0xca/0xd3 [] __splice_from_pipe+0x53/0x1bd [] ------------[ cut here ]------------ filemap_fault+0x221/0x380 [] pipe_to_user+0x0/0xd3 [] sys_vmsplice+0x3b7/0x422 [] kernel BUG at mm/highmem.c:206! handle_mm_fault+0x4d5/0x8eb [] kmap_atomic+0x1c/0x20 [] unmap_vmas+0x3d1/0x584 [] free_pgtables+0x90/0xa0 [] pgd_dtor+0x0/0x1 [] audit_syscall_exit+0x2aa/0x2c6 [] do_syscall_trace+0x124/0x169 [] syscall_call+0x7/0xb ======================= Code: 2d 00 d0 5b 00 25 00 00 e0 ff 29 invalid opcode: 0000 [#1] c2 89 d0 c1 e8 0c 8b 14 85 a0 6c 7c c0 4a 85 d2 89 14 85 a0 6c 7c c0 74 07 31 c9 4a 75 15 eb 04 <0f> 0b eb fe 31 c9 81 3d 78 38 6d c0 78 38 6d c0 0f 95 c1 b0 01 EIP: [] kunmap_high+0x51/0x8e SS:ESP 0068:f5960df0 SMP Modules linked in: netconsole autofs4 hidp nfs lockd nfs_acl rfcomm l2cap bluetooth sunrpc ipv6 ib_iser rdma_cm ib_cm iw_cmib_sa ib_mad ib_core ib_addr iscsi_tcp libiscsi scsi_transport_iscsi dm_mirror dm_multipath dm_mod video output sbs batteryac parport_pc lp parport sg i2c_piix4 i2c_core floppy cfi_probe gen_probe scb2_flash mtd chipreg tg3 e1000 button ide_cd serio_raw cdrom aic7xxx scsi_transport_spi sd_mod scsi_mod ext3 jbd ehci_hcd ohci_hcd uhci_hcd CPU: 3 EIP: 0060:[] Not tainted VLI EFLAGS: 00010246 (2.6.23 #1) EIP is at kunmap_high+0x51/0x8e Signed-off-by: Jens Axboe --- fs/splice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/splice.c b/fs/splice.c index e95a3622886..02c39ae719b 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -1390,10 +1390,10 @@ static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf, if (copy_to_user(sd->u.userptr, src + buf->offset, sd->len)) ret = -EFAULT; + buf->ops->unmap(pipe, buf, src); out: if (ret > 0) sd->u.userptr += ret; - buf->ops->unmap(pipe, buf, src); return ret; } -- cgit v1.2.3-18-g5258 From 2b94de552e07610dfa79fc49ea49d1cfa5cd9ce8 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 18 Jul 2007 13:14:03 +0200 Subject: bio: use memset() in bio_init() Use memset() to clear the bio, instead of doing each field manually. Signed-off-by: Jens Axboe --- fs/bio.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'fs') diff --git a/fs/bio.c b/fs/bio.c index 5f604f269df..ac987fc7acd 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -127,21 +127,9 @@ static void bio_fs_destructor(struct bio *bio) void bio_init(struct bio *bio) { - bio->bi_next = NULL; - bio->bi_bdev = NULL; + memset(bio, 0, sizeof(*bio)); bio->bi_flags = 1 << BIO_UPTODATE; - bio->bi_rw = 0; - bio->bi_vcnt = 0; - bio->bi_idx = 0; - bio->bi_phys_segments = 0; - bio->bi_hw_segments = 0; - bio->bi_hw_front_size = 0; - bio->bi_hw_back_size = 0; - bio->bi_size = 0; - bio->bi_max_vecs = 0; - bio->bi_end_io = NULL; atomic_set(&bio->bi_cnt, 1); - bio->bi_private = NULL; } /** -- cgit v1.2.3-18-g5258 From 992c5ddaf1b8b85d2252339c4c89adf7469c09ca Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 18 Jul 2007 13:18:08 +0200 Subject: bio: make freeing of ->bi_io_vec conditional in bio_free() The empty barrier patches do not carry data, so they have no iovec attached. Signed-off-by: Jens Axboe --- fs/bio.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/bio.c b/fs/bio.c index ac987fc7acd..d59ddbf7962 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -109,11 +109,14 @@ static inline struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned lon void bio_free(struct bio *bio, struct bio_set *bio_set) { - const int pool_idx = BIO_POOL_IDX(bio); + if (bio->bi_io_vec) { + const int pool_idx = BIO_POOL_IDX(bio); - BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS); + BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS); + + mempool_free(bio->bi_io_vec, bio_set->bvec_pools[pool_idx]); + } - mempool_free(bio->bi_io_vec, bio_set->bvec_pools[pool_idx]); mempool_free(bio, bio_set->bio_pool); } -- cgit v1.2.3-18-g5258