예제 #1
0
파일: trd.c 프로젝트: tridge/junkcode
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;
}
예제 #2
0
파일: rd.c 프로젝트: nhanh0/hah
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;
}