linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andrew Morton <akpm@linux-foundation.org>
To: "Jörn Engel" <joern@lazybastard.org>
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-mtd@lists.infradead.org,
	Albert Cahalan <acahalan@gmail.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Jan Engelhardt <jengelh@linux01.gwdg.de>,
	Evgeniy Polyakov <johnpol@2ka.mipt.ru>,
	Pekka Enberg <penberg@cs.helsinki.fi>, Greg KH <greg@kroah.com>,
	Ingo Oeser <ioe-lkml@rameria.de>
Subject: Re: [PATCH] LogFS take three
Date: Tue, 15 May 2007 13:37:59 -0700	[thread overview]
Message-ID: <20070515133759.9ee434a2.akpm@linux-foundation.org> (raw)
In-Reply-To: <20070515151919.GA32510@lazybastard.org>

On Tue, 15 May 2007 17:19:20 +0200
J__rn Engel <joern@lazybastard.org> wrote:

> Add LogFS, a scalable flash filesystem.
>
> ...
>
>  
> +config LOGFS
> +	tristate "Log Filesystem (EXPERIMENTAL)"
> +	depends on EXPERIMENTAL
> +	select ZLIB_INFLATE
> +	select ZLIB_DEFLATE
> +	help
> +	  Flash filesystem aimed to scale efficiently to large devices.
> +	  In comparison to JFFS2 it offers significantly faster mount
> +	  times and potentially less RAM usage, although the latter has
> +	  not been measured yet.
> +
> +	  In its current state it is still very experimental and should
> +	  not be used for other than testing purposes.
> +
> +	  If unsure, say N.
> +
> +config LOGFS_FSCK
> +	bool "Run LogFS fsck at mount time"
> +	depends on LOGFS
> +	help
> +	  Run a full filesystem check on every mount.  If any errors are
> +	  found, mounting the filesystem will fail.  This is a debug option
> +	  for developers.
> +
> +	  If unsure, say N.
> +

No dependency on MTD,

> @@ -0,0 +1,373 @@
> +/*
> + * fs/logfs/logfs.h
> + *
> + * As should be obvious for Linux kernel code, license is GPLv2
> + *
> + * Copyright (c) 2005-2007 Joern Engel
> + *
> + * Private header for logfs.
> + */
> +#ifndef fs_logfs_logfs_h
> +#define fs_logfs_logfs_h
> +
> +#define __CHECK_ENDIAN__
> +
> +
> +#include <linux/crc32.h>
> +#include <linux/fs.h>
> +#include <linux/kallsyms.h>
> +#include <linux/kernel.h>
> +#include <linux/logfs.h>
> +#include <linux/pagemap.h>
> +#include <linux/statfs.h>
> +#include <linux/mtd/mtd.h>

But it includes an MTD header file.

Can this code be tested by people who don't have MTD hardware?  We used to
ahve a fake-mtd-on-a-blockdev thing, whcih was in a state of some
disrepair.  Maybe it got repaired.  Or removed.  I can't immediately locate
it...

It's strange and a bit regrettable that an fs would have dependency on MTD,
really.

> +
> +/**
> + * struct logfs_area - area management information
> + *
> + * @a_sb:			the superblock this area belongs to
> + * @a_is_open:			1 if the area is currently open, else 0
> + * @a_segno:			segment number of area
> + * @a_used_objects:		number of used objects (XXX: should get removed)
> + * @a_used_bytes:		number of used bytes
> + * @a_ops:			area operations (either journal or ostore)
> + * @a_wbuf:			write buffer
> + * @a_erase_count:		erase count
> + * @a_level:			GC level
> + */

ooh, documentation.  Quick, merge it!

> +/* memtree.c */
> +void btree_init(struct btree_head *head);
> +void *btree_lookup(struct btree_head *head, long val);
> +int btree_insert(struct btree_head *head, long val, void *ptr);
> +int btree_remove(struct btree_head *head, long val);

These names are too generic.  If we later add a btree library: blam.

> +
> +/* readwrite.c */
> +int logfs_inode_read(struct inode *inode, void *buf, size_t n, loff_t _pos);
> +int logfs_inode_write(struct inode *inode, const void *buf, size_t n,
> +		loff_t pos);

It's a bit rude stealing the logfs* namespace, but I guess you got there
first ;)

> +int logfs_readpage_nolock(struct page *page);
> +int logfs_write_buf(struct inode *inode, pgoff_t index, void *buf);
> +int logfs_delete(struct inode *inode, pgoff_t index);
> +int logfs_rewrite_block(struct inode *inode, pgoff_t index, u64 ofs, int level);
> +int logfs_is_valid_block(struct super_block *sb, u64 ofs, u64 ino, u64 pos);
> +void logfs_truncate(struct inode *inode);
> +u64 logfs_seek_data(struct inode *inode, u64 pos);
> +
> +int logfs_init_rw(struct logfs_super *super);
> +void logfs_cleanup_rw(struct logfs_super *super);
> +
> +/* segment.c */
> +int logfs_erase_segment(struct super_block *sb, u32 ofs);
> +int wbuf_read(struct super_block *sb, u64 ofs, size_t len, void *buf);
> +int logfs_segment_read(struct super_block *sb, void *buf, u64 ofs);
> +s64 logfs_segment_write(struct inode *inode, void *buf, u64 pos, int level,
> +		int alloc);
> +int logfs_segment_delete(struct inode *inode, u64 ofs, u64 pos, int level);
> +void logfs_set_blocks(struct inode *inode, u64 no);
> +void __logfs_set_blocks(struct inode *inode);
> +/* area handling */
> +int logfs_init_areas(struct super_block *sb);
> +void logfs_cleanup_areas(struct logfs_super *super);
> +int logfs_open_area(struct logfs_area *area);
> +void logfs_close_area(struct logfs_area *area);
> +
> +/* super.c */
> +int mtdread(struct super_block *sb, loff_t ofs, size_t len, void *buf);
> +int mtdwrite(struct super_block *sb, loff_t ofs, size_t len, void *buf);
> +int mtderase(struct super_block *sb, loff_t ofs, size_t len);
> +void logfs_crash_dump(struct super_block *sb);
> +int all_ff(void *buf, size_t len);
> +int logfs_statfs(struct dentry *dentry, struct kstatfs *stats);

Have you checked that all of this needs global scope?

> +
> +/* progs/fsck.c */
> +#ifdef CONFIG_LOGFS_FSCK
> +int logfs_fsck(struct super_block *sb);
> +#else
> +#define logfs_fsck(sb) ({ 0; })

static inline int logfs_fsck(struct super_block *sb)
{
	return 0;
}

is better: nicer to look at, has typechecking.

> +#endif

> +
> +/* progs/mkfs.c */
> +int logfs_mkfs(struct super_block *sb, struct logfs_disk_super *ds);
> +
> +
> +#define LOGFS_BUG(sb) do {		\
> +	struct super_block *__sb = sb;	\
> +	logfs_crash_dump(__sb);		\
> +	BUG();				\
> +} while(0)
> +
> +#define LOGFS_BUG_ON(condition, sb) \
> +	do { if (unlikely((condition)!=0)) LOGFS_BUG((sb)); } while(0)
> +
> +
> +static inline struct logfs_super *LOGFS_SUPER(struct super_block *sb)
> +{
> +	return sb->s_fs_info;
> +}
> +
> +static inline struct logfs_inode *LOGFS_INODE(struct inode *inode)
> +{
> +	return container_of(inode, struct logfs_inode, vfs_inode);
> +}

Do these need to be uppercase?

> +
> +static inline __be32 logfs_crc32(void *data, size_t len, size_t skip)
> +{
> +	return cpu_to_be32(crc32(~0, data+skip, len-skip));
> +}
> +
> +
> +static inline u8 logfs_type(struct inode *inode)
> +{
> +	return (inode->i_mode >> 12) & 15;
> +}
> +
> +
> +static inline pgoff_t logfs_index(u64 pos)
> +{
> +	return pos / LOGFS_BLOCKSIZE;
> +}

If the compiler goofs up here we'll end up trying to do a 64/32 divide and
it won't link on 32-bit machines.  It would be safer to do

	return pos >> LOGFS_BLOCKSHIFT;


> --- /dev/null	2007-04-18 05:32:26.652341749 +0200
> +++ linux-2.6.21logfs/fs/logfs/compr.c	2007-05-10 19:07:24.000000000 +0200
> @@ -0,0 +1,107 @@
> +/*
> + * fs/logfs/compr.c	- compression routines
> + *
> + * As should be obvious for Linux kernel code, license is GPLv2
> + *
> + * Copyright (c) 2005-2007 Joern Engel
> + */
> +#include "logfs.h"
> +#include <linux/vmalloc.h>
> +#include <linux/zlib.h>
> +
> +#define COMPR_LEVEL 3
> +
> +static DEFINE_MUTEX(compr_mutex);
> +static struct z_stream_s stream;
> +
> +
>
> ...
>
> +
> +int logfs_uncompress(void *in, void *out, size_t inlen, size_t outlen)
> +{
> +	int err, ret;
> +
> +	ret = -EIO;
> +	mutex_lock(&compr_mutex);

A per-superblock lock and stream would be nicer.

> +	err = zlib_inflateInit(&stream);
> +	if (err != Z_OK)
> +		goto error;
> +
> +	stream.next_in = in;
> +	stream.avail_in = inlen;
> +	stream.total_in = 0;
> +	stream.next_out = out;
> +	stream.avail_out = outlen;
> +	stream.total_out = 0;
> +
> +	err = zlib_inflate(&stream, Z_FINISH);
> +	if (err != Z_STREAM_END)
> +		goto error;
> +
> +	err = zlib_inflateEnd(&stream);
> +	if (err != Z_OK)
> +		goto error;
> +
> +	ret = 0;
> +error:
> +	mutex_unlock(&compr_mutex);
> +	return ret;
> +}
>
> ...
>
> --- /dev/null	2007-04-18 05:32:26.652341749 +0200
> +++ linux-2.6.21logfs/fs/logfs/dir.c	2007-05-10 19:57:46.000000000 +0200
> @@ -0,0 +1,725 @@
> +}
> +
> +
> +static inline loff_t file_end(struct inode *inode)
> +{
> +	return (i_size_read(inode) + inode->i_sb->s_blocksize - 1)
> +		>> inode->i_sb->s_blocksize_bits;
> +}
> +static void logfs_set_name(struct logfs_disk_dentry *dd, struct qstr *name)
> +{

The code has a strange mix of two-blank-lines-between-functions and
no-blank-lines-between-functions.  One blank line is usual.


> +	BUG_ON(name->len > LOGFS_MAX_NAMELEN);
> +	dd->namelen = cpu_to_be16(name->len);
> +	memcpy(dd->name, name->name, name->len);
> +}
> +static int logfs_write_dir(struct inode *dir, struct dentry *dentry,
> +		struct inode *inode)
> +{
> +	struct logfs_disk_dentry dd;
> +	int err;
> +
> +	memset(&dd, 0, sizeof(dd));
> +	dd.ino = cpu_to_be64(inode->i_ino);
> +	dd.type = logfs_type(inode);
> +	logfs_set_name(&dd, &dentry->d_name);
> +
> +	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
> +	/*
> +	 * FIXME: the file size should actually get aligned when writing,
> +	 * not when reading.
> +	 */
> +	err = write_dir(dir, &dd, file_end(dir));
> +	if (err)
> +		return err;
> +	d_instantiate(dentry, inode);
> +	return 0;
> +}
> +
> +
>
> ...
>
> +
> +	if (dest) {
> +		/* symlink */
> +		ret = logfs_inode_write(inode, dest, destlen, 0);
> +	} else {
> +		/* creat/mkdir/mknod */
> +		ret = __logfs_write_inode(inode);
> +	}
> +	super->s_victim_ino = 0;
> +	if (ret) {
> +		if (!dest)
> +			li->li_flags |= LOGFS_IF_STILLBORN;
> +		/* FIXME: truncate symlink */
> +		inode->i_nlink--;
> +		iput(inode);
> +		goto out;
> +	}
> +
> +	if (inode->i_mode & S_IFDIR)
> +		dir->i_nlink++;

You have helper functions for i_nlink++, which remember to do
mark_inode_dirty()?

> +	ret = logfs_write_dir(dir, dentry, inode);
> +
> +	if (ret) {
> +		if (inode->i_mode & S_IFDIR)
> +			dir->i_nlink--;
> +		logfs_remove_inode(inode);
> +		iput(inode);
> +	}
> +out:
> +	mutex_unlock(&super->s_victim_mutex);
> +	return ret;
> +}
> +
>
> ...
>
> +
> +static struct inode_operations logfs_symlink_iops = {
> +	.readlink	= generic_readlink,
> +	.follow_link	= page_follow_link_light,
> +};

Should be const.

> +static int logfs_permission(struct inode *inode, int mask, struct nameidata *nd)
> +{
> +	return generic_permission(inode, mask, NULL);
> +}

Does this need to exist?

> +
> +struct inode_operations logfs_dir_iops = {
> +	.create		= logfs_create,
> +	.link		= logfs_link,
> +	.lookup		= logfs_lookup,
> +	.mkdir		= logfs_mkdir,
> +	.mknod		= logfs_mknod,
> +	.rename		= logfs_rename,
> +	.rmdir		= logfs_rmdir,
> +	.permission	= logfs_permission,
> +	.symlink	= logfs_symlink,
> +	.unlink		= logfs_unlink,
> +};

const

> +struct file_operations logfs_dir_fops = {
> +	.readdir	= logfs_readdir,
> +	.read		= generic_read_dir,
> +};

const

> --- /dev/null	2007-04-18 05:32:26.652341749 +0200
> +++ linux-2.6.21logfs/fs/logfs/file.c	2007-05-10 19:46:21.000000000 +0200
> @@ -0,0 +1,81 @@
> +/*
> + * fs/logfs/file.c	- prepare_write, commit_write and friends
> + *
> + * As should be obvious for Linux kernel code, license is GPLv2
> + *
> + * Copyright (c) 2005-2007 Joern Engel
> + */
> +#include "logfs.h"
> +
> +
> +static int logfs_prepare_write(struct file *file, struct page *page,
> +		unsigned start, unsigned end)
> +{
> +	if (PageUptodate(page))
> +		return 0;
> +
> +	if ((start == 0) && (end == PAGE_CACHE_SIZE))
> +		return 0;
> +
> +	return logfs_readpage_nolock(page);
> +}
> +
> +
> +static int logfs_commit_write(struct file *file, struct page *page,
> +		unsigned start, unsigned end)
> +{
> +	struct inode *inode = page->mapping->host;
> +	pgoff_t index = page->index;
> +	void *buf;
> +	int ret;
> +
> +	BUG_ON(PAGE_CACHE_SIZE != inode->i_sb->s_blocksize);

This check can be done once, at mount time.

> +	BUG_ON(page->index > I3_BLOCKS);
> +
> +	if (start == end)
> +		return 0; /* FIXME: do we need to update inode? */
> +
> +	if (i_size_read(inode) < (index << PAGE_CACHE_SHIFT) + end) {
> +		i_size_write(inode, (index << PAGE_CACHE_SHIFT) + end);
> +		mark_inode_dirty(inode);
> +	}
> +
> +	buf = kmap(page);
> +	ret = logfs_write_buf(inode, index, buf);
> +	kunmap(page);

kmap() is lame.  The preferred approach would be to pass the page* down to
the lower layers and to use kmap_atomic() at the lowest possible point.

> +	return ret;
> +}
> +
> +
> +static int logfs_readpage(struct file *file, struct page *page)
> +{
> +	int ret;
> +
> +	ret = logfs_readpage_nolock(page);
> +	unlock_page(page);
> +	return ret;
> +}
> +
> +
> +struct inode_operations logfs_reg_iops = {
> +	.truncate	= logfs_truncate,
> +};

const

> +
> +struct file_operations logfs_reg_fops = {
> +	.aio_read	= generic_file_aio_read,
> +	.aio_write	= generic_file_aio_write,
> +	.llseek		= generic_file_llseek,
> +	.mmap		= generic_file_readonly_mmap,
> +	.open		= generic_file_open,
> +	.read		= do_sync_read,
> +	.write		= do_sync_write,
> +};

const

> +
> +struct address_space_operations logfs_reg_aops = {
> +	.commit_write	= logfs_commit_write,
> +	.prepare_write	= logfs_prepare_write,
> +	.readpage	= logfs_readpage,
> +	.set_page_dirty	= __set_page_dirty_nobuffers,
> +};

const

> +/*
> + * cookie is set to 1 if we hand out a cached inode, 0 otherwise.
> + * this allows logfs_iput to do the right thing later
> + */
> +struct inode *logfs_iget(struct super_block *sb, ino_t ino, int *cookie)
> +{
> +	struct logfs_super *super = LOGFS_SUPER(sb);
> +	struct logfs_inode *li;
> +
> +	if (ino == LOGFS_INO_MASTER)
> +		return super->s_master_inode;
> +
> +	spin_lock(&inode_lock);
> +	list_for_each_entry(li, &super->s_freeing_list, li_freeing_list)
> +		if (li->vfs_inode.i_ino == ino) {
> +			spin_unlock(&inode_lock);
> +			*cookie = 1;
> +			return &li->vfs_inode;
> +		}
> +	spin_unlock(&inode_lock);
> +
> +	*cookie = 0;
> +	return __logfs_iget(sb, ino);
> +}

A filesystem playing with inode_lock: not good.  What's going on here?

As a minimum, the reasons for this should be clearly spelled out in code
comments, because this sticks out like a sore thumb.

> +
> +	li = kmem_cache_alloc(logfs_inode_cache, GFP_KERNEL);
> +	if (!li)
> +		return NULL;
> +	logfs_init_inode(&li->vfs_inode);
> +	return &li->vfs_inode;
> +}
> +
> +
> +struct inode *logfs_new_meta_inode(struct super_block *sb, u64 ino)
> +{
> +	struct inode *inode;
> +
> +	inode = logfs_alloc_inode(sb);
> +	if (!inode)
> +		return ERR_PTR(-ENOMEM);
> +
> +	logfs_init_inode(inode);
> +	inode->i_mode = 0;
> +	inode->i_ino = ino;
> +	inode->i_sb = sb;
> +
> +	/* This is a blatant copy of alloc_inode code.  We'd need alloc_inode
> +	 * to be nonstatic, alas. */
> +	{
> +		static const struct address_space_operations empty_aops;
> +		struct address_space * const mapping = &inode->i_data;
> +
> +		mapping->a_ops = &empty_aops;
> +		mapping->host = inode;
> +		mapping->flags = 0;
> +		mapping_set_gfp_mask(mapping, GFP_HIGHUSER);
> +		mapping->assoc_mapping = NULL;
> +		mapping->backing_dev_info = &default_backing_dev_info;
> +		inode->i_mapping = mapping;
> +	}
> +
> +	return inode;
> +}

This function would benefit from some comments.  What's it doing, and why
is it special?  I mean, new_inode() calls alloc_inode() anyway, so you're
unable to use new_inode().  The reader wonders why.


> +
> +/*
> + * We depend on the kernel to hand us proper time here.  If it has more
> + * nanoseconds than fit in a second, something's fishy.  Either the currently
> + * running kernel is confused or we read a wrong value.  The latter could be
> + * because whoever wrote the value messed up or we have undetected data
> + * corruption.
> + * Whatever the case, give a warning.
> + */
> +static struct timespec be64_to_timespec(__be64 betime)
> +{
> +	u64 time = be64_to_cpu(betime);
> +	struct timespec tsp;
> +
> +	tsp.tv_sec = time >> 32;
> +	tsp.tv_nsec = time & 0xffffffff;
> +	WARN_ON(tsp.tv_nsec > 999999999);
> +	return tsp;
> +}

Could use ns_to_timespec(be64_to_cpu(betime)) here.

Should use >= NSEC_PER_SEC here.

> +
> +static __be64 timespec_to_be64(struct timespec tsp)
> +{
> +	u64 time = ((u64)tsp.tv_sec << 32) + (tsp.tv_nsec & 0xffffffff);
> +
> +	WARN_ON(tsp.tv_nsec > 999999999);
> +	return cpu_to_be64(time);
> +}

Dittos.

> +/* called with inode_lock held */
> +static void logfs_drop_inode(struct inode *inode)
> +{
> +	struct logfs_super *super = LOGFS_SUPER(inode->i_sb);
> +	struct logfs_inode *li = LOGFS_INODE(inode);
> +
> +	list_move(&li->li_freeing_list, &super->s_freeing_list);
> +	generic_drop_inode(inode);
> +}
> +
> +
> +static u64 logfs_get_ino(struct super_block *sb)
> +{
> +	struct logfs_super *super = LOGFS_SUPER(sb);
> +	u64 ino;
> +
> +	/*
> +	 * FIXME: ino allocation should work in two modes:
> +	 * o nonsparse - ifile is mostly occupied, just append
> +	 * o sparse - ifile has lots of holes, fill them up
> +	 *
> +	 * SEEK_HOLE would obviously help a lot here.
> +	 */
> +	spin_lock(&super->s_ino_lock);
> +	ino = super->s_last_ino;
> +	super->s_last_ino++;
> +	spin_unlock(&super->s_ino_lock);
> +	return ino;
> +}

Could use atomic64_add_return() here.

> +
> +struct inode *logfs_new_inode(struct inode *dir, int mode)
> +{
> +	struct super_block *sb = dir->i_sb;
> +	struct inode *inode;
> +
> +	inode = new_inode(sb);
> +	if (!inode)
> +		return ERR_PTR(-ENOMEM);
> +
> +	logfs_init_inode(inode);
> +
> +	inode->i_mode = mode;
> +	inode->i_ino = logfs_get_ino(sb);
> +
> +	insert_inode_hash(inode);
> +
> +	return inode;
> +}
> +
> +
> +static void logfs_init_once(void *_li, struct kmem_cache *cachep,
> +		unsigned long flags)
> +{
> +	struct logfs_inode *li = _li;
> +	int i;
> +
> +	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
> +			SLAB_CTOR_CONSTRUCTOR) {

This won't compile in mainline (SLAB_CTOR_VERIFY has gone)

And it won't compile in -mm (SLAB_CTOR_CONSTRUCTOR has gone).

Just remove the test altogether.

> +		li->li_flags = 0;
> +		li->li_used_bytes = 0;
> +		for (i=0; i<LOGFS_EMBEDDED_FIELDS; i++)
> +			li->li_data[i] = 0;
> +		inode_init_once(&li->vfs_inode);
> +	}
> +
> +}
> +
> +
> +struct super_operations logfs_super_operations = {
> +	.alloc_inode	= logfs_alloc_inode,
> +	.delete_inode	= logfs_delete_inode,
> +	.destroy_inode	= logfs_destroy_inode,
> +	.drop_inode	= logfs_drop_inode,
> +	.read_inode	= logfs_read_inode,
> +	.write_inode	= logfs_write_inode,
> +	.statfs		= logfs_statfs,
> +};

const

> +
> +int logfs_init_inode_cache(void)
> +{
> +	logfs_inode_cache = kmem_cache_create("logfs_inode_cache",
> +			sizeof(struct logfs_inode), 0, SLAB_RECLAIM_ACCOUNT,
> +			logfs_init_once, NULL);

Use KMEM_CACHE() helper

> +	if (!logfs_inode_cache)
> +		return -ENOMEM;
> +	return 0;
> +}
> +
> +
> +void logfs_destroy_inode_cache(void)
> +{
> +	kmem_cache_destroy(logfs_inode_cache);
> +}

<attention span ran out, sorry>

  parent reply	other threads:[~2007-05-15 20:37 UTC|newest]

Thread overview: 87+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-05-15 15:19 [PATCH] LogFS take three Jörn Engel
2007-05-15 15:21 ` Review status (Re: [PATCH] LogFS take three) Jörn Engel
2007-05-17 16:03   ` Evgeniy Polyakov
2007-05-17 17:10     ` Jörn Engel
2007-05-20 17:30       ` Evgeniy Polyakov
2007-05-23 12:58         ` Jörn Engel
2007-05-23 15:07           ` Evgeniy Polyakov
2007-05-23 15:14             ` Jörn Engel
2007-05-23 15:53               ` Evgeniy Polyakov
2007-05-15 18:37 ` [PATCH] LogFS take three Sam Ravnborg
2007-05-15 19:10   ` Jörn Engel
2007-05-15 19:07 ` John Stoffel
2007-05-15 19:19   ` Jörn Engel
2007-05-16  4:54     ` David Woodhouse
2007-05-16 11:09       ` Jörn Engel
2007-05-16 11:34         ` Jamie Lokier
2007-05-16 11:38           ` Artem Bityutskiy
2007-05-16 12:25             ` Jamie Lokier
2007-05-16 12:49               ` Jörn Engel
2007-05-16 11:50           ` Jörn Engel
2007-05-16 12:06             ` CaT
2007-05-17 17:07               ` Jan Engelhardt
2007-05-16 12:29             ` Evgeniy Polyakov
2007-05-16 12:55               ` Jörn Engel
2007-05-17 17:08                 ` Jan Engelhardt
2007-05-16 13:41             ` John Stoffel
2007-05-16 13:53               ` Jörn Engel
2007-05-16 14:04                 ` David Woodhouse
2007-05-16 14:13                   ` Artem Bityutskiy
2007-05-16 14:17                   ` Kevin Bowling
2007-05-17  9:12                     ` Pavel Machek
2007-05-17  9:52                       ` David Woodhouse
2007-05-19 15:00                     ` Bill Davidsen
2007-05-16 14:29                 ` CaT
2007-05-17 17:14                 ` Jan Engelhardt
2007-05-19 14:45                 ` David Weinehall
2007-05-19 16:17                   ` Jamie Lokier
2007-05-19 16:27                     ` Evgeniy Polyakov
2007-05-17 16:59         ` Jan Engelhardt
2007-05-17 11:39     ` Arnd Bergmann
2007-05-15 20:37 ` Andrew Morton [this message]
2007-05-16  0:06   ` Jörn Engel
2007-05-16  2:11     ` Jörn Engel
2007-05-16  5:22     ` Willy Tarreau
2007-05-16 11:23       ` Jörn Engel
2007-05-17 17:26     ` Jan Engelhardt
2007-05-17 17:45       ` Evgeniy Polyakov
2007-05-18  1:00         ` Kyle Moffett
2007-05-18  6:16           ` Jan Engelhardt
2007-05-16 12:07   ` David Woodhouse
2007-05-16 15:34     ` Andrew Morton
2007-05-16 15:49       ` David Woodhouse
2007-05-16 16:41         ` Jörn Engel
     [not found]           ` <7fe698080705162312t4e7ed90byd10ef8e664027b17@mail.gmail.com>
2007-05-17  6:25             ` David Woodhouse
2007-05-17  8:20               ` Dongjun Shin
2007-05-17  8:43                 ` David Woodhouse
2007-05-17 12:05                   ` Jörn Engel
2007-05-17 20:18                 ` Pavel Machek
2007-05-18  0:01                   ` Dongjun Shin
2007-05-18  6:17                     ` Jan Engelhardt
2007-05-18  6:47                       ` David Woodhouse
2007-05-19 15:18                 ` Bill Davidsen
2007-05-19  6:15   ` Rob Landley
2007-05-19  9:24     ` Jan Engelhardt
2007-05-19 17:26       ` Rob Landley
2007-05-15 23:26 ` Albert Cahalan
2007-05-16  0:09   ` Jörn Engel
2007-05-16 11:18   ` Jamie Lokier
2007-05-16 12:08     ` Pekka Enberg
2007-05-16 12:58       ` Jörn Engel
2007-05-16  2:37 ` Roland Dreier
2007-05-16 11:35   ` Jörn Engel
2007-05-16 10:21 ` Pekka J Enberg
2007-05-16 12:26   ` Jörn Engel
2007-05-16 12:36     ` Pekka Enberg
2007-05-16 12:38       ` Pekka Enberg
2007-05-16 13:20       ` Jörn Engel
2007-05-17 20:58         ` Pekka Enberg
2007-05-17 21:36           ` Arnd Bergmann
2007-05-17 21:50             ` Jörn Engel
2007-05-16 19:17 ` Pavel Machek
2007-05-16 19:23   ` Jörn Engel
2007-05-17 15:08 ` Arnd Bergmann
2007-05-17 20:21   ` Jörn Engel
2007-05-17 21:00     ` Arnd Bergmann
2007-05-17 21:30       ` Jörn Engel
2007-05-17 22:01     ` Jamie Lokier

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=20070515133759.9ee434a2.akpm@linux-foundation.org \
    --to=akpm@linux-foundation.org \
    --cc=acahalan@gmail.com \
    --cc=greg@kroah.com \
    --cc=ioe-lkml@rameria.de \
    --cc=jengelh@linux01.gwdg.de \
    --cc=joern@lazybastard.org \
    --cc=johnpol@2ka.mipt.ru \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=penberg@cs.helsinki.fi \
    --cc=tglx@linutronix.de \
    /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).