linux-ext4.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Michal Novotny <minovotn@redhat.com>
To: linux-ext4@vger.kernel.org
Subject: [PATCH] extend e2fsprogs functionality to add EXT2_FLAG_DIRECT option
Date: Fri, 08 Jan 2010 10:36:50 +0100	[thread overview]
Message-ID: <4B46FCB2.1090308@redhat.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 911 bytes --]

This patch extends functionality of e{2|4}fsprogs to add 
EXT2_FLAG_DIRECT flag to be passed to ext2fs_open2() function. This 
internally calls open() function with O_DIRECT and handles the memory 
alignment for both read and write operations.
In some cases direct access to devices is necessary and that was the 
main reason for this patch to be done.

The main reason why this was done is that pygrub (used by xen 
virtualization user-space package, it's a python version of grub for 
paravirtualized guests) sometimes uses outdated version of grub.conf 
file. Modifications to xen package were *not* enough because e2fsprogs 
doesn't open the files directly. That's why I added EXT2_FLAG_DIRECT 
support to make read/write operations work directly when passed. It's 
been tested with pygrub like mentioned above for read operation and it's 
working fine.

Signed-off-by: Michal Novotny <minovotn@redhat.com>

[-- Attachment #2: mig-e4fsprogs-direct-read-write.patch --]
[-- Type: text/x-patch, Size: 5618 bytes --]

Author: Michal Novotny <minovotn@redhat.com>
Date:   Wed Dec 23 11:25:40 2009 +0200

    extend e{2|4}fsprogs functionality to add EXT2_FLAG_DIRECT option
    
    This patch extends functionality of e{2|4}fsprogs to add EXT2_FLAG_DIRECT
    flag to be passed to ext2fs_open2() function. This internally calls open()
    function with O_DIRECT and handles the memory alignment for both read and
    write operations.
    In some cases direct access to devices is necessary and that was the main
    reason for this patch to be done.
    
    Signed-off-by: Michal Novotny <minovotn@redhat.com>

diff -up e2fsprogs-1.41.9/lib/ext2fs/ext2fs.h.opendirect e2fsprogs-1.41.9/lib/ext2fs/ext2fs.h
--- e2fsprogs-1.41.9/lib/ext2fs/ext2fs.h.opendirect	2009-12-23 10:04:05.000000000 +0100
+++ e2fsprogs-1.41.9/lib/ext2fs/ext2fs.h	2009-12-23 10:04:05.000000000 +0100
@@ -172,6 +172,7 @@ typedef struct ext2_file *ext2_file_t;
 #define EXT2_FLAG_EXCLUSIVE		0x4000
 #define EXT2_FLAG_SOFTSUPP_FEATURES	0x8000
 #define EXT2_FLAG_NOFREE_ON_ERROR	0x10000
+#define EXT2_FLAG_DIRECT		0x20000
 
 /*
  * Special flag in the ext2 inode i_flag field that means that this is
diff -up e2fsprogs-1.41.9/lib/ext2fs/ext2_io.h.opendirect e2fsprogs-1.41.9/lib/ext2fs/ext2_io.h
--- e2fsprogs-1.41.9/lib/ext2fs/ext2_io.h.opendirect	2009-08-23 04:44:35.000000000 +0200
+++ e2fsprogs-1.41.9/lib/ext2fs/ext2_io.h	2009-12-23 10:04:05.000000000 +0100
@@ -29,6 +29,7 @@ typedef struct struct_io_channel *io_cha
 typedef struct struct_io_stats *io_stats;
 
 #define CHANNEL_FLAGS_WRITETHROUGH	0x01
+#define CHANNEL_FLAGS_DIRECT		0x02
 
 struct struct_io_channel {
 	errcode_t	magic;
@@ -88,6 +89,7 @@ struct struct_io_manager {
 
 #define IO_FLAG_RW		0x0001
 #define IO_FLAG_EXCLUSIVE	0x0002
+#define IO_FLAG_DIRECT		0x0004
 
 /*
  * Convenience functions....
diff -up e2fsprogs-1.41.9/lib/ext2fs/openfs.c.opendirect e2fsprogs-1.41.9/lib/ext2fs/openfs.c
--- e2fsprogs-1.41.9/lib/ext2fs/openfs.c.opendirect	2009-08-23 04:44:35.000000000 +0200
+++ e2fsprogs-1.41.9/lib/ext2fs/openfs.c	2009-12-23 10:04:05.000000000 +0100
@@ -121,6 +121,8 @@ errcode_t ext2fs_open2(const char *name,
 		io_flags |= IO_FLAG_RW;
 	if (flags & EXT2_FLAG_EXCLUSIVE)
 		io_flags |= IO_FLAG_EXCLUSIVE;
+	if (flags & EXT2_FLAG_DIRECT)
+		io_flags |= IO_FLAG_DIRECT;
 	retval = manager->open(fs->device_name, io_flags, &fs->io);
 	if (retval)
 		goto cleanup;
@@ -296,6 +298,7 @@ errcode_t ext2fs_open2(const char *name,
        }
 	fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
 					  EXT2_DESC_PER_BLOCK(fs->super));
+
 	retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
 				&fs->group_desc);
 	if (retval)
diff -up e2fsprogs-1.41.9/lib/ext2fs/unix_io.c.opendirect e2fsprogs-1.41.9/lib/ext2fs/unix_io.c
--- e2fsprogs-1.41.9/lib/ext2fs/unix_io.c.opendirect	2009-08-13 03:39:57.000000000 +0200
+++ e2fsprogs-1.41.9/lib/ext2fs/unix_io.c	2009-12-23 10:16:26.000000000 +0100
@@ -17,6 +17,7 @@
 
 #define _LARGEFILE_SOURCE
 #define _LARGEFILE64_SOURCE
+#define _GNU_SOURCE
 
 #include <stdio.h>
 #include <string.h>
@@ -163,15 +164,37 @@ static errcode_t raw_read_blk(io_channel
 	ssize_t		size;
 	ext2_loff_t	location;
 	int		actual = 0;
+	int		memret;
+	void		*aligned_buffer;
+	long		pagesize;
 
 	size = (count < 0) ? -count : count * channel->block_size;
+
 	data->io_stats.bytes_read += size;
 	location = ((ext2_loff_t) block * channel->block_size) + data->offset;
 	if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
 		retval = errno ? errno : EXT2_ET_LLSEEK_FAILED;
 		goto error_out;
 	}
-	actual = read(data->dev, buf, size);
+
+	if (channel->flags & CHANNEL_FLAGS_DIRECT) {
+		pagesize = sysconf(_SC_PAGE_SIZE);
+		if (pagesize < 0)
+			goto error_out;
+
+		memret = posix_memalign(&aligned_buffer, pagesize, size);
+		if (memret != 0) {
+			errno = memret;
+			goto error_out;
+		}
+		actual = read(data->dev, aligned_buffer, size);
+		if (actual > 0)
+			memcpy(buf, aligned_buffer, size);
+		free(aligned_buffer);
+	}
+	else
+		actual = read(data->dev, buf, size);
+
 	if (actual != size) {
 		if (actual < 0)
 			actual = 0;
@@ -252,6 +275,9 @@ static errcode_t raw_write_blk(io_channe
 	ext2_loff_t	location;
 	int		actual = 0;
 	errcode_t	retval;
+        int		memret;
+        void		*aligned_buffer;
+        long		pagesize;
 
 	if (count == 1)
 		size = channel->block_size;
@@ -269,7 +295,23 @@ static errcode_t raw_write_blk(io_channe
 		goto error_out;
 	}
 
-	actual = write(data->dev, buf, size);
+	if (channel->flags & CHANNEL_FLAGS_DIRECT) {
+		pagesize = sysconf(_SC_PAGE_SIZE);
+		if (pagesize < 0)
+			goto error_out;
+
+		memret = posix_memalign(&aligned_buffer, pagesize, size);
+		if (memret != 0) {
+			errno = memret;
+			goto error_out;
+		}
+		memcpy(aligned_buffer, buf, size);
+		actual = write(data->dev, aligned_buffer, size);
+		free(aligned_buffer);
+	}
+	else
+		actual = write(data->dev, buf, size);
+
 	if (actual != size) {
 		retval = EXT2_ET_SHORT_WRITE;
 		goto error_out;
@@ -443,6 +485,9 @@ static errcode_t unix_open(const char *n
 	io->write_error = 0;
 	io->refcount = 1;
 
+	if (flags & IO_FLAG_DIRECT)
+		io->flags = CHANNEL_FLAGS_DIRECT;
+
 	memset(data, 0, sizeof(struct unix_private_data));
 	data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL;
 	data->io_stats.num_fields = 2;
@@ -453,6 +498,8 @@ static errcode_t unix_open(const char *n
 	open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY;
 	if (flags & IO_FLAG_EXCLUSIVE)
 		open_flags |= O_EXCL;
+        if (flags & IO_FLAG_DIRECT)
+                open_flags |= O_DIRECT;
 #ifdef HAVE_OPEN64
 	data->dev = open64(io->name, open_flags);
 #else

             reply	other threads:[~2010-01-08  9:37 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-01-08  9:36 Michal Novotny [this message]
2010-01-11 20:06 ` [PATCH] extend e2fsprogs functionality to add EXT2_FLAG_DIRECT option Ric Wheeler
2010-01-12 10:54   ` Michal Novotny
2010-01-12 11:59     ` Ric Wheeler
2010-01-12 12:15       ` Michal Novotny
2010-01-12 12:23         ` Christoph Hellwig
2010-01-12 12:30           ` Michal Novotny
2010-01-12 12:46             ` Christoph Hellwig
2010-01-12 13:01               ` Michal Novotny
2010-01-12 13:04                 ` Ric Wheeler
2010-01-12 13:12                   ` Michal Novotny
2010-01-12 13:23                     ` Michal Novotny
2010-01-12 13:29                       ` Ric Wheeler
2010-01-12 13:33                         ` Michal Novotny
2010-01-12 14:33                           ` Chris Lee
2010-01-12 14:37                             ` Michal Novotny
2010-01-12 16:38                 ` Christoph Hellwig
2010-01-12 16:43                   ` Michal Novotny
2010-01-12 16:47                     ` Christoph Hellwig
2010-01-12 16:51                       ` Michal Novotny
2010-01-12 16:50                     ` Ric Wheeler
2010-01-12 16:53                       ` Michal Novotny
2010-01-12 16:56                         ` Eric Sandeen
2010-01-12 16:59                           ` Ric Wheeler
2010-01-12 17:00                             ` Michal Novotny
2010-01-14 13:46                               ` Michal Novotny
2010-01-12 12:47             ` Andreas Dilger
2010-01-12 13:04               ` Michal Novotny
2010-01-12 15:16           ` Eric Sandeen
2010-01-12 15:46             ` Michal Novotny
2010-01-12 20:01               ` Ric Wheeler

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4B46FCB2.1090308@redhat.com \
    --to=minovotn@redhat.com \
    --cc=linux-ext4@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).