> +int sio_pool_init(void) > +{ > + if (!sio_pool) > + sio_pool = mempool_create_kmalloc_pool( > + SWAP_CLUSTER_MAX, sizeof(struct swap_iocb)); I can't see anything serializing access here, so we'll need a lock or cmpxchg dance. > + if (sio_pool) > + return 0; > + else > + return -ENOMEM; Nit: This would flow much nicer as: if (!sio_pool) return -ENOMEM; return 0; > int swap_readpage(struct page *page, bool synchronous) > { > struct bio *bio; > @@ -378,13 +412,25 @@ int swap_readpage(struct page *page, bool synchronous) > } > > if (data_race(sis->flags & SWP_FS_OPS)) { > - //struct file *swap_file = sis->swap_file; > - //struct address_space *mapping = swap_file->f_mapping; This should not be left by the previous patch. In fact I suspect the part of the previous patch that adds ->swap_rw should probably be folded into this patch. > + struct file *swap_file = sis->swap_file; > + struct address_space *mapping = swap_file->f_mapping; > + struct iov_iter from; > + struct swap_iocb *sio; > + loff_t pos = page_file_offset(page); > + > + sio = mempool_alloc(sio_pool, GFP_KERNEL); > + init_sync_kiocb(&sio->iocb, swap_file); > + sio->iocb.ki_pos = pos; > + sio->iocb.ki_complete = sio_read_complete; > + sio->bvec.bv_page = page; > + sio->bvec.bv_len = PAGE_SIZE; > + sio->bvec.bv_offset = 0; > + > + iov_iter_bvec(&from, READ, &sio->bvec, 1, PAGE_SIZE); > + ret = mapping->a_ops->swap_rw(&sio->iocb, &from); > + if (ret != -EIOCBQUEUED) > + sio_read_complete(&sio->iocb, ret); > > goto out; I'd be tempted to split the SWP_FS_OPS into a helper to keep the code tidy.