static int trd_make_request(request_queue_t *q, int rw, struct buffer_head *bh) { u_long start, len; char *b_addr; void *addr; u_long minor, page, ofs, len1; start = bh->b_rsector << 9; minor = MINOR(bh->b_rdev); len = bh->b_size; if (!trd_base[minor]) { int ret; printk(KERN_ERR DEVICE_NAME ": access to unopened device minor=%ld\n", minor); ret = trd_allocate(minor); if (ret != 0) return ret; } if (minor >= MAX_DEVS || !trd_base[minor]) { printk(KERN_ERR DEVICE_NAME ": bad minor %ld\n", minor); goto io_error; } if (start + bh->b_size > TRD_SIZE) { printk(KERN_ERR DEVICE_NAME ": bad access: block=%ld, count=%d\n", bh->b_rsector, bh->b_size); goto io_error; } if (rw == READA) rw = READ; if ((rw != READ) && (rw != WRITE)) { printk(KERN_ERR DEVICE_NAME ": bad command: %d\n", rw); goto io_error; } b_addr = bh_kmap(bh); while (len) { page = start >> PAGE_SHIFT; ofs = start & (PAGE_SIZE-1); addr = (void *) (((char *)(trd_base[minor][page])) + ofs); len1 = len; if (ofs + len1 > PAGE_SIZE) { len1 = PAGE_SIZE - ofs; } if (rw == READ) { memcpy(b_addr, (char *)addr, len1); } else { memcpy((char *)addr, b_addr, len1); } len -= len1; start += len1; b_addr += len1; } bh_kunmap(bh); bh->b_end_io(bh,1); return 0; io_error: buffer_IO_error(bh); return 0; }
static int rd_blkdev_pagecache_IO(int rw, struct buffer_head * sbh, int minor) { struct address_space * mapping; unsigned long index; int offset, size, err; err = -EIO; err = 0; mapping = rd_bdev[minor]->bd_inode->i_mapping; index = sbh->b_rsector >> (PAGE_CACHE_SHIFT - 9); offset = (sbh->b_rsector << 9) & ~PAGE_CACHE_MASK; size = sbh->b_size; do { int count; struct page ** hash; struct page * page; char * src, * dst; int unlock = 0; count = PAGE_CACHE_SIZE - offset; if (count > size) count = size; size -= count; hash = page_hash(mapping, index); page = __find_get_page(mapping, index, hash); if (!page) { page = grab_cache_page(mapping, index); err = -ENOMEM; if (!page) goto out; err = 0; if (!Page_Uptodate(page)) { memset(kmap(page), 0, PAGE_CACHE_SIZE); kunmap(page); SetPageUptodate(page); } unlock = 1; } index++; if (rw == READ) { src = kmap(page); src += offset; dst = bh_kmap(sbh); } else { dst = kmap(page); dst += offset; src = bh_kmap(sbh); } offset = 0; memcpy(dst, src, count); kunmap(page); bh_kunmap(sbh); if (rw == READ) { flush_dcache_page(page); } else { SetPageDirty(page); } if (unlock) UnlockPage(page); __free_page(page); } while (size); out: return err; }