Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
new file mode 100644
index 0000000..747fd1e
--- /dev/null
+++ b/fs/bfs/file.c
@@ -0,0 +1,162 @@
+/*
+ *	fs/bfs/file.c
+ *	BFS file operations.
+ *	Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
+ */
+
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/smp_lock.h>
+#include "bfs.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define dprintf(x...)	printf(x)
+#else
+#define dprintf(x...)
+#endif
+
+struct file_operations bfs_file_operations = {
+	.llseek 	= generic_file_llseek,
+	.read		= generic_file_read,
+	.write		= generic_file_write,
+	.mmap		= generic_file_mmap,
+	.sendfile	= generic_file_sendfile,
+};
+
+static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb)
+{
+	struct buffer_head *bh, *new;
+
+	bh = sb_bread(sb, from);
+	if (!bh)
+		return -EIO;
+	new = sb_getblk(sb, to);
+	memcpy(new->b_data, bh->b_data, bh->b_size);
+	mark_buffer_dirty(new);
+	bforget(bh);
+	brelse(new);
+	return 0;
+}
+
+static int bfs_move_blocks(struct super_block *sb, unsigned long start, unsigned long end, 
+				unsigned long where)
+{
+	unsigned long i;
+
+	dprintf("%08lx-%08lx->%08lx\n", start, end, where);
+	for (i = start; i <= end; i++)
+		if(bfs_move_block(i, where + i, sb)) {
+			dprintf("failed to move block %08lx -> %08lx\n", i, where + i);
+			return -EIO;
+		}
+	return 0;
+}
+
+static int bfs_get_block(struct inode * inode, sector_t block, 
+	struct buffer_head * bh_result, int create)
+{
+	long phys;
+	int err;
+	struct super_block *sb = inode->i_sb;
+	struct bfs_sb_info *info = BFS_SB(sb);
+	struct bfs_inode_info *bi = BFS_I(inode);
+	struct buffer_head *sbh = info->si_sbh;
+
+	if (block < 0 || block > info->si_blocks)
+		return -EIO;
+
+	phys = bi->i_sblock + block;
+	if (!create) {
+		if (phys <= bi->i_eblock) {
+			dprintf("c=%d, b=%08lx, phys=%08lx (granted)\n", create, block, phys);
+			map_bh(bh_result, sb, phys);
+		}
+		return 0;
+	}
+
+	/* if the file is not empty and the requested block is within the range
+	   of blocks allocated for this file, we can grant it */
+	if (inode->i_size && phys <= bi->i_eblock) {
+		dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n", 
+				create, block, phys);
+		map_bh(bh_result, sb, phys);
+		return 0;
+	}
+
+	/* the rest has to be protected against itself */
+	lock_kernel();
+
+	/* if the last data block for this file is the last allocated block, we can
+	   extend the file trivially, without moving it anywhere */
+	if (bi->i_eblock == info->si_lf_eblk) {
+		dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n", 
+				create, block, phys);
+		map_bh(bh_result, sb, phys);
+		info->si_freeb -= phys - bi->i_eblock;
+		info->si_lf_eblk = bi->i_eblock = phys;
+		mark_inode_dirty(inode);
+		mark_buffer_dirty(sbh);
+		err = 0;
+		goto out;
+	}
+
+	/* Ok, we have to move this entire file to the next free block */
+	phys = info->si_lf_eblk + 1;
+	if (bi->i_sblock) { /* if data starts on block 0 then there is no data */
+		err = bfs_move_blocks(inode->i_sb, bi->i_sblock, 
+				bi->i_eblock, phys);
+		if (err) {
+			dprintf("failed to move ino=%08lx -> fs corruption\n", inode->i_ino);
+			goto out;
+		}
+	} else
+		err = 0;
+
+	dprintf("c=%d, b=%08lx, phys=%08lx (moved)\n", create, block, phys);
+	bi->i_sblock = phys;
+	phys += block;
+	info->si_lf_eblk = bi->i_eblock = phys;
+
+	/* this assumes nothing can write the inode back while we are here
+	 * and thus update inode->i_blocks! (XXX)*/
+	info->si_freeb -= bi->i_eblock - bi->i_sblock + 1 - inode->i_blocks;
+	mark_inode_dirty(inode);
+	mark_buffer_dirty(sbh);
+	map_bh(bh_result, sb, phys);
+out:
+	unlock_kernel();
+	return err;
+}
+
+static int bfs_writepage(struct page *page, struct writeback_control *wbc)
+{
+	return block_write_full_page(page, bfs_get_block, wbc);
+}
+
+static int bfs_readpage(struct file *file, struct page *page)
+{
+	return block_read_full_page(page, bfs_get_block);
+}
+
+static int bfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+{
+	return block_prepare_write(page, from, to, bfs_get_block);
+}
+
+static sector_t bfs_bmap(struct address_space *mapping, sector_t block)
+{
+	return generic_block_bmap(mapping, block, bfs_get_block);
+}
+
+struct address_space_operations bfs_aops = {
+	.readpage	= bfs_readpage,
+	.writepage	= bfs_writepage,
+	.sync_page	= block_sync_page,
+	.prepare_write	= bfs_prepare_write,
+	.commit_write	= generic_commit_write,
+	.bmap		= bfs_bmap,
+};
+
+struct inode_operations bfs_file_inops;