linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC/PATCH 4/5] loop: add execute in place support
@ 2005-05-11 14:30 Carsten Otte
  0 siblings, 0 replies; only message in thread
From: Carsten Otte @ 2005-05-11 14:30 UTC (permalink / raw)
  To: cotte; +Cc: linux-kernel, linux-fsdevel, schwidefsky, akpm

[RFC/PATCH 4/5] loop: add execute in place support
The old loop driver in 2.6.11. used the readpage/writepage aops to
transfer data. Now loop can also use read/write and direct_IO on the
file if readpage/writepage are not available. Unlike the old 2.6.11.
version, today's loop driver does work with files that do not have
readpage/writepage. Threrefore, this patch is optional.
This patch adds one more transport method to loop that uses the new
address space operation get_xip_page if available.

Signed-off-by: Carsten Otte <cotte@de.ibm.com>
---
diff -ruN linux-2.6-git/drivers/block/loop.c linux-2.6-git-xip/drivers/block/loop.c
--- linux-2.6-git/drivers/block/loop.c	2005-05-10 14:55:05.000000000 +0200
+++ linux-2.6-git-xip/drivers/block/loop.c	2005-05-10 16:21:49.803071544 +0200
@@ -275,6 +275,83 @@
 	goto out;
 }

+
+static int
+do_lo_send_xip(struct loop_device *lo, struct bio_vec *bvec, int bsize, loff_t pos,
+		struct page* ignored)
+{
+	struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */
+	struct address_space *mapping = file->f_mapping;
+	struct address_space_operations *aops = mapping->a_ops;
+	struct page *page;
+	pgoff_t index;
+	unsigned size, offset, bv_offs;
+	int len;
+	int ret = 0;
+
+	down(&mapping->host->i_sem);
+	index = pos >> PAGE_CACHE_SHIFT;
+	offset = pos & ((pgoff_t)PAGE_CACHE_SIZE - 1);
+	bv_offs = bvec->bv_offset;
+	len = bvec->bv_len;
+	while (len > 0) {
+		sector_t IV;
+		int transfer_result;
+
+		IV = ((sector_t)index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9);
+
+		size = PAGE_CACHE_SIZE - offset;
+		if (size > len)
+			size = len;
+
+		page = aops->get_xip_page(mapping,
+			index*(PAGE_SIZE/512), 0);
+		if (!page)
+			goto fail;
+		if (unlikely(IS_ERR(page))) {
+			if (PTR_ERR(page) == -ENODATA) {
+				/* sparse */
+				page = virt_to_page(empty_zero_page);
+			} else
+				goto fail;
+		} else
+			BUG_ON(!PageUptodate(page));
+
+		transfer_result = lo_do_transfer(lo, WRITE, page, offset,
+						 bvec->bv_page, bv_offs,
+						 size, IV);
+		if (transfer_result) {
+			char *kaddr;
+
+			/*
+			 * The transfer failed, but we still write the data to
+			 * keep prepare/commit calls balanced.
+			 */
+			printk(KERN_ERR "loop: transfer error block %llu\n",
+			       (unsigned long long)index);
+			kaddr = kmap_atomic(page, KM_USER0);
+			memset(kaddr + offset, 0, size);
+			kunmap_atomic(kaddr, KM_USER0);
+		}
+		flush_dcache_page(page);
+		if (transfer_result)
+			goto fail;
+		bv_offs += size;
+		len -= size;
+		offset = 0;
+		index++;
+		pos += size;
+	}
+	up(&mapping->host->i_sem);
+out:
+	return ret;
+
+fail:
+	up(&mapping->host->i_sem);
+	ret = -1;
+	goto out;
+}
+
 /**
  * __do_lo_send_write - helper for writing data to a loop device
  *
@@ -356,8 +433,11 @@
 	struct page *page = NULL;
 	int i, ret = 0;

-	do_lo_send = do_lo_send_aops;
-	if (!(lo->lo_flags & LO_FLAGS_USE_AOPS)) {
+	if (lo->lo_flags & LO_FLAGS_USE_AOPS)
+		do_lo_send = do_lo_send_aops;
+	else if (lo->lo_flags & LO_FLAGS_USE_XIP)
+		do_lo_send = do_lo_send_xip;
+	else {
 		do_lo_send = do_lo_send_direct_write;
 		if (lo->transfer != transfer_none) {
 			page = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
@@ -787,11 +867,13 @@
 		 */
 		if (!file->f_op->sendfile)
 			goto out_putf;
-		if (aops->prepare_write && aops->commit_write)
+		if (aops->get_xip_page)
+			lo_flags |= LO_FLAGS_USE_XIP;
+		else if (aops->prepare_write && aops->commit_write)
 			lo_flags |= LO_FLAGS_USE_AOPS;
-		if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
+		if (!(lo_flags & (LO_FLAGS_USE_AOPS | LO_FLAGS_USE_XIP))
+		    && !file->f_op->write)
 			lo_flags |= LO_FLAGS_READ_ONLY;
-
 		lo_blocksize = inode->i_blksize;
 		error = 0;
 	} else {
diff -ruN linux-2.6-git/include/linux/loop.h linux-2.6-git-xip/include/linux/loop.h
--- linux-2.6-git/include/linux/loop.h	2005-05-10 14:55:23.000000000 +0200
+++ linux-2.6-git-xip/include/linux/loop.h	2005-05-10 16:21:31.816805872 +0200
@@ -74,6 +74,7 @@
 enum {
 	LO_FLAGS_READ_ONLY	= 1,
 	LO_FLAGS_USE_AOPS	= 2,
+	LO_FLAGS_USE_XIP        = 4,
 };

 #include <asm/posix_types.h>	/* for __kernel_old_dev_t */



^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-05-11 14:30 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-05-11 14:30 [RFC/PATCH 4/5] loop: add execute in place support Carsten Otte

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).