From 3a6effe81fa0bd2fb9c6c5ecde665492536733e3 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Sat, 10 Mar 2007 03:57:25 -0500 Subject: [JFFS2] Remove superfluous source file fs/jffs2/comprtest.c Delete the obsolete source file fs/jffs2/comprtest.c. Signed-off-by: Robert P. J. Day Signed-off-by: David Woodhouse --- fs/jffs2/comprtest.c | 307 --------------------------------------------------- 1 file changed, 307 deletions(-) delete mode 100644 fs/jffs2/comprtest.c (limited to 'fs') diff --git a/fs/jffs2/comprtest.c b/fs/jffs2/comprtest.c deleted file mode 100644 index f0fb8be7740c..000000000000 --- a/fs/jffs2/comprtest.c +++ /dev/null @@ -1,307 +0,0 @@ -/* $Id: comprtest.c,v 1.6 2005/11/07 11:14:38 gleixner Exp $ */ - -#include -#include -#include -#include -#if 0 -#define TESTDATA_LEN 512 -static unsigned char testdata[TESTDATA_LEN] = { - 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x83, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00, - 0xb0, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x20, 0x00, 0x06, 0x00, 0x28, 0x00, - 0x1e, 0x00, 0x1b, 0x00, 0x06, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x80, 0x04, 0x08, - 0x34, 0x80, 0x04, 0x08, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xf4, 0x80, 0x04, 0x08, - 0xf4, 0x80, 0x04, 0x08, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x08, - 0x00, 0x80, 0x04, 0x08, 0x0d, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x10, 0x95, 0x04, 0x08, - 0x10, 0x95, 0x04, 0x08, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x58, 0x05, 0x00, 0x00, 0x58, 0x95, 0x04, 0x08, - 0x58, 0x95, 0x04, 0x08, 0xa0, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x08, 0x81, 0x04, 0x08, - 0x08, 0x81, 0x04, 0x08, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x6c, 0x64, 0x2d, 0x6c, 0x69, 0x6e, 0x75, - 0x78, 0x2e, 0x73, 0x6f, 0x2e, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x47, 0x4e, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, - 0x0c, 0x83, 0x04, 0x08, 0x81, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x1c, 0x83, 0x04, 0x08, 0xac, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, - 0x2c, 0x83, 0x04, 0x08, 0xdd, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, - 0x3c, 0x83, 0x04, 0x08, 0x2e, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, - 0x4c, 0x83, 0x04, 0x08, 0x7d, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, - 0x00, 0x85, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x67, - 0x6d, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x5f, 0x00, 0x6c, 0x69, 0x62, 0x63, - 0x2e, 0x73, 0x6f, 0x2e, 0x36, 0x00, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x00, 0x5f, 0x5f, 0x63}; -#else -#define TESTDATA_LEN 3481 -static unsigned char testdata[TESTDATA_LEN] = { - 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x22, 0x64, 0x62, 0x65, 0x6e, 0x63, 0x68, - 0x2e, 0x68, 0x22, 0x0a, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x4d, 0x41, 0x58, - 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x20, 0x31, 0x30, 0x30, 0x30, 0x0a, 0x0a, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x63, 0x20, 0x63, 0x68, 0x61, 0x72, 0x20, 0x62, 0x75, 0x66, 0x5b, 0x37, 0x30, 0x30, - 0x30, 0x30, 0x5d, 0x3b, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x20, - 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x7b, 0x0a, 0x09, 0x69, 0x6e, - 0x74, 0x20, 0x66, 0x64, 0x3b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, - 0x65, 0x3b, 0x0a, 0x7d, 0x20, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x4d, 0x41, 0x58, 0x5f, - 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5d, 0x3b, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, - 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, - 0x61, 0x6d, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, - 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x75, - 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x20, 0x21, 0x3d, 0x20, - 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, - 0x25, 0x64, 0x29, 0x20, 0x75, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x25, 0x73, 0x20, 0x66, 0x61, - 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, - 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, - 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x5f, 0x66, - 0x69, 0x6c, 0x65, 0x28, 0x69, 0x6e, 0x74, 0x20, 0x66, 0x64, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, - 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x73, 0x3b, 0x0a, - 0x09, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x28, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a, - 0x09, 0x09, 0x73, 0x20, 0x3d, 0x20, 0x4d, 0x49, 0x4e, 0x28, 0x73, 0x69, 0x7a, 0x65, 0x6f, 0x66, - 0x28, 0x62, 0x75, 0x66, 0x29, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x09, - 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x66, 0x64, 0x2c, 0x20, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x73, - 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x2d, 0x3d, 0x20, 0x73, 0x3b, 0x0a, - 0x09, 0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x6f, 0x70, - 0x65, 0x6e, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, - 0x69, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, - 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x66, 0x64, 0x2c, - 0x20, 0x69, 0x3b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, - 0x20, 0x4f, 0x5f, 0x52, 0x44, 0x57, 0x52, 0x7c, 0x4f, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x3b, - 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x20, 0x73, 0x74, - 0x3b, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x3b, 0x0a, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, - 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x73, 0x69, - 0x7a, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x7c, - 0x3d, 0x20, 0x4f, 0x5f, 0x54, 0x52, 0x55, 0x4e, 0x43, 0x3b, 0x0a, 0x0a, 0x09, 0x66, 0x64, 0x20, - 0x3d, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x66, 0x6c, - 0x61, 0x67, 0x73, 0x2c, 0x20, 0x30, 0x36, 0x30, 0x30, 0x29, 0x3b, 0x0a, 0x09, 0x69, 0x66, 0x20, - 0x28, 0x66, 0x64, 0x20, 0x3d, 0x3d, 0x20, 0x2d, 0x31, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, - 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x6f, 0x70, 0x65, 0x6e, - 0x20, 0x25, 0x73, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, - 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e, 0x22, - 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, - 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x68, - 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, - 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x66, 0x73, 0x74, 0x61, 0x74, 0x28, 0x66, 0x64, 0x2c, - 0x20, 0x26, 0x73, 0x74, 0x29, 0x3b, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x73, 0x69, 0x7a, 0x65, - 0x20, 0x3e, 0x20, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b, - 0x0a, 0x23, 0x69, 0x66, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, - 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, - 0x69, 0x6e, 0x67, 0x20, 0x25, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x25, 0x64, 0x20, 0x66, 0x72, 0x6f, - 0x6d, 0x20, 0x25, 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66, - 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x28, 0x69, 0x6e, 0x74, - 0x29, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x23, 0x65, - 0x6e, 0x64, 0x69, 0x66, 0x0a, 0x09, 0x09, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x5f, 0x66, 0x69, - 0x6c, 0x65, 0x28, 0x66, 0x64, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x74, - 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x20, 0x65, 0x6c, - 0x73, 0x65, 0x20, 0x69, 0x66, 0x20, 0x28, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x3c, 0x20, 0x73, 0x74, - 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, - 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x69, 0x6e, 0x67, - 0x20, 0x25, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x25, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x25, - 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x28, 0x69, 0x6e, - 0x74, 0x29, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, - 0x09, 0x66, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x28, 0x66, 0x64, 0x2c, 0x20, 0x73, - 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x69, - 0x3d, 0x30, 0x3b, 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x3b, 0x69, - 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x3d, 0x20, - 0x30, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66, - 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, - 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x66, 0x69, - 0x6c, 0x65, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x25, 0x73, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b, - 0x0a, 0x09, 0x09, 0x65, 0x78, 0x69, 0x74, 0x28, 0x31, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, - 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, - 0x20, 0x3d, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x3b, 0x0a, 0x09, 0x66, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x64, 0x3b, 0x0a, 0x09, - 0x69, 0x66, 0x20, 0x28, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2b, 0x2b, 0x20, 0x25, 0x20, 0x31, 0x30, - 0x30, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, - 0x74, 0x66, 0x28, 0x22, 0x2e, 0x22, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x76, - 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x69, 0x6e, 0x74, - 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x7a, - 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x0a, 0x7b, - 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x62, - 0x75, 0x66, 0x5b, 0x30, 0x5d, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x6d, 0x65, 0x6d, 0x73, - 0x65, 0x74, 0x28, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x6f, - 0x66, 0x28, 0x62, 0x75, 0x66, 0x29, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, - 0x69, 0x3d, 0x30, 0x3b, 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x3b, - 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x3d, - 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, - 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41, 0x58, - 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x29, 0x20, 0x7b, 0x0a, 0x23, 0x69, 0x66, 0x20, 0x31, 0x0a, - 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, - 0x6f, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x3a, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, - 0x25, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, - 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x25, 0x64, 0x20, 0x6f, 0x66, 0x73, 0x3d, 0x25, 0x64, 0x5c, 0x6e, - 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, - 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, - 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x3b, 0x0a, - 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b, - 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x6c, 0x73, 0x65, 0x65, 0x6b, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, - 0x20, 0x53, 0x45, 0x45, 0x4b, 0x5f, 0x53, 0x45, 0x54, 0x29, 0x3b, 0x0a, 0x09, 0x69, 0x66, 0x20, - 0x28, 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, - 0x2e, 0x66, 0x64, 0x2c, 0x20, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, - 0x21, 0x3d, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, - 0x6e, 0x74, 0x66, 0x28, 0x22, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, - 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x5c, 0x6e, - 0x22, 0x2c, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d, - 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x28, 0x69, - 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x73, - 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, - 0x0a, 0x7b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x3b, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, - 0x28, 0x69, 0x3d, 0x30, 0x3b, 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, - 0x3b, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, - 0x3d, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, - 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41, - 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, - 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x72, 0x65, 0x61, - 0x64, 0x3a, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x20, 0x77, 0x61, 0x73, - 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x25, - 0x64, 0x20, 0x6f, 0x66, 0x73, 0x3d, 0x25, 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x2c, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, - 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x6c, 0x73, 0x65, 0x65, 0x6b, 0x28, 0x66, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x2c, 0x20, 0x53, 0x45, 0x45, 0x4b, 0x5f, 0x53, 0x45, 0x54, 0x29, 0x3b, 0x0a, 0x09, - 0x72, 0x65, 0x61, 0x64, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, - 0x64, 0x2c, 0x20, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x7d, - 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28, - 0x69, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x69, - 0x6e, 0x74, 0x20, 0x69, 0x3b, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x69, 0x3d, 0x30, 0x3b, - 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x3b, 0x69, 0x2b, 0x2b, 0x29, - 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, - 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x68, 0x61, 0x6e, - 0x64, 0x6c, 0x65, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, - 0x69, 0x66, 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, - 0x45, 0x53, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, - 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x3a, 0x20, 0x68, - 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74, - 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, - 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28, 0x66, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x29, 0x3b, 0x0a, 0x09, 0x66, 0x74, 0x61, - 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x20, - 0x30, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x6d, 0x6b, - 0x64, 0x69, 0x72, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, - 0x0a, 0x7b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x66, 0x6e, 0x61, - 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x6d, 0x6b, 0x64, 0x69, 0x72, - 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x30, 0x37, 0x30, 0x30, 0x29, 0x20, 0x21, 0x3d, - 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x23, 0x69, 0x66, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x0a, - 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x6d, 0x6b, 0x64, 0x69, 0x72, 0x20, - 0x25, 0x73, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e, - 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6e, 0x61, - 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72, - 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x0a, 0x09, 0x7d, 0x0a, - 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x72, 0x6d, 0x64, 0x69, 0x72, - 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x0a, 0x7b, 0x0a, - 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, - 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x72, 0x6d, 0x64, 0x69, 0x72, 0x28, 0x66, 0x6e, - 0x61, 0x6d, 0x65, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, - 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x72, 0x6d, 0x64, 0x69, 0x72, 0x20, 0x25, 0x73, 0x20, - 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e, 0x22, 0x2c, 0x20, - 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, - 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, - 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, - 0x5f, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x6f, 0x6c, - 0x64, 0x2c, 0x20, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x6e, 0x65, 0x77, 0x29, 0x0a, 0x7b, 0x0a, - 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x6f, 0x6c, 0x64, 0x29, 0x3b, 0x0a, - 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x6e, 0x65, 0x77, 0x29, 0x3b, 0x0a, - 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x6f, 0x6c, 0x64, - 0x2c, 0x20, 0x6e, 0x65, 0x77, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, - 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, - 0x25, 0x73, 0x20, 0x25, 0x73, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73, - 0x29, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x6e, 0x65, 0x77, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d, - 0x0a, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x28, - 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, - 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x20, 0x73, 0x74, 0x61, 0x74, 0x20, 0x73, 0x74, 0x3b, 0x0a, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, - 0x70, 0x70, 0x65, 0x72, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69, - 0x66, 0x20, 0x28, 0x73, 0x74, 0x61, 0x74, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x26, - 0x73, 0x74, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, - 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x73, 0x74, - 0x61, 0x74, 0x3a, 0x20, 0x25, 0x73, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x25, 0x64, 0x20, 0x25, - 0x73, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d, - 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x53, 0x5f, 0x49, - 0x53, 0x44, 0x49, 0x52, 0x28, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x29, - 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, - 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x21, 0x3d, 0x20, 0x73, 0x69, - 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, - 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x3a, 0x20, 0x25, 0x73, - 0x20, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x25, 0x64, 0x20, 0x25, - 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d, - 0x65, 0x2c, 0x20, 0x28, 0x69, 0x6e, 0x74, 0x29, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, - 0x7a, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d, 0x0a, - 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x28, - 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, - 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x64, 0x6f, 0x5f, 0x6f, 0x70, 0x65, - 0x6e, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x35, 0x30, 0x30, 0x30, 0x2c, 0x20, 0x73, - 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x64, 0x6f, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28, - 0x35, 0x30, 0x30, 0x30, 0x29, 0x3b, 0x0a, 0x7d, 0x0a -}; -#endif -static unsigned char comprbuf[TESTDATA_LEN]; -static unsigned char decomprbuf[TESTDATA_LEN]; - -int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, - unsigned char *data_out, uint32_t cdatalen, uint32_t datalen); -unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, - uint32_t *datalen, uint32_t *cdatalen); - -int init_module(void ) { - unsigned char comprtype; - uint32_t c, d; - int ret; - - printk("Original data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - testdata[0],testdata[1],testdata[2],testdata[3], - testdata[4],testdata[5],testdata[6],testdata[7], - testdata[8],testdata[9],testdata[10],testdata[11], - testdata[12],testdata[13],testdata[14],testdata[15]); - d = TESTDATA_LEN; - c = TESTDATA_LEN; - comprtype = jffs2_compress(testdata, comprbuf, &d, &c); - - printk("jffs2_compress used compression type %d. Compressed size %d, uncompressed size %d\n", - comprtype, c, d); - printk("Compressed data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - comprbuf[0],comprbuf[1],comprbuf[2],comprbuf[3], - comprbuf[4],comprbuf[5],comprbuf[6],comprbuf[7], - comprbuf[8],comprbuf[9],comprbuf[10],comprbuf[11], - comprbuf[12],comprbuf[13],comprbuf[14],comprbuf[15]); - - ret = jffs2_decompress(comprtype, comprbuf, decomprbuf, c, d); - printk("jffs2_decompress returned %d\n", ret); - printk("Decompressed data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - decomprbuf[0],decomprbuf[1],decomprbuf[2],decomprbuf[3], - decomprbuf[4],decomprbuf[5],decomprbuf[6],decomprbuf[7], - decomprbuf[8],decomprbuf[9],decomprbuf[10],decomprbuf[11], - decomprbuf[12],decomprbuf[13],decomprbuf[14],decomprbuf[15]); - if (memcmp(decomprbuf, testdata, d)) - printk("Compression and decompression corrupted data\n"); - else - printk("Compression good for %d bytes\n", d); - return 1; -} -- cgit v1.2.2 From 8dc64fca75b631142f282047d7f6ae9e8af82543 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Mon, 26 Mar 2007 21:45:41 -0800 Subject: [JFFS2] Delete everything related to obsolete JFFS2_PROC option Delete everything related to the apparently non-existent kernel config option JFFS2_PROC. Signed-off-by: Robert P. J. Day Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- fs/jffs2/compr.c | 138 ------------------------------------------------------- fs/jffs2/compr.h | 10 ---- 2 files changed, 148 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c index 7001ba26c067..647cb15d5499 100644 --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c @@ -268,144 +268,6 @@ int jffs2_unregister_compressor(struct jffs2_compressor *comp) return 0; } -#ifdef CONFIG_JFFS2_PROC - -#define JFFS2_STAT_BUF_SIZE 16000 - -char *jffs2_list_compressors(void) -{ - struct jffs2_compressor *this; - char *buf, *act_buf; - - act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL); - list_for_each_entry(this, &jffs2_compressor_list, list) { - act_buf += sprintf(act_buf, "%10s priority:%d ", this->name, this->priority); - if ((this->disabled)||(!this->compress)) - act_buf += sprintf(act_buf,"disabled"); - else - act_buf += sprintf(act_buf,"enabled"); - act_buf += sprintf(act_buf,"\n"); - } - return buf; -} - -char *jffs2_stats(void) -{ - struct jffs2_compressor *this; - char *buf, *act_buf; - - act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL); - - act_buf += sprintf(act_buf,"JFFS2 compressor statistics:\n"); - act_buf += sprintf(act_buf,"%10s ","none"); - act_buf += sprintf(act_buf,"compr: %d blocks (%d) decompr: %d blocks\n", none_stat_compr_blocks, - none_stat_compr_size, none_stat_decompr_blocks); - spin_lock(&jffs2_compressor_list_lock); - list_for_each_entry(this, &jffs2_compressor_list, list) { - act_buf += sprintf(act_buf,"%10s ",this->name); - if ((this->disabled)||(!this->compress)) - act_buf += sprintf(act_buf,"- "); - else - act_buf += sprintf(act_buf,"+ "); - act_buf += sprintf(act_buf,"compr: %d blocks (%d/%d) decompr: %d blocks ", this->stat_compr_blocks, - this->stat_compr_new_size, this->stat_compr_orig_size, - this->stat_decompr_blocks); - act_buf += sprintf(act_buf,"\n"); - } - spin_unlock(&jffs2_compressor_list_lock); - - return buf; -} - -char *jffs2_get_compression_mode_name(void) -{ - switch (jffs2_compression_mode) { - case JFFS2_COMPR_MODE_NONE: - return "none"; - case JFFS2_COMPR_MODE_PRIORITY: - return "priority"; - case JFFS2_COMPR_MODE_SIZE: - return "size"; - } - return "unkown"; -} - -int jffs2_set_compression_mode_name(const char *name) -{ - if (!strcmp("none",name)) { - jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; - return 0; - } - if (!strcmp("priority",name)) { - jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY; - return 0; - } - if (!strcmp("size",name)) { - jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE; - return 0; - } - return 1; -} - -static int jffs2_compressor_Xable(const char *name, int disabled) -{ - struct jffs2_compressor *this; - spin_lock(&jffs2_compressor_list_lock); - list_for_each_entry(this, &jffs2_compressor_list, list) { - if (!strcmp(this->name, name)) { - this->disabled = disabled; - spin_unlock(&jffs2_compressor_list_lock); - return 0; - } - } - spin_unlock(&jffs2_compressor_list_lock); - printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name); - return 1; -} - -int jffs2_enable_compressor_name(const char *name) -{ - return jffs2_compressor_Xable(name, 0); -} - -int jffs2_disable_compressor_name(const char *name) -{ - return jffs2_compressor_Xable(name, 1); -} - -int jffs2_set_compressor_priority(const char *name, int priority) -{ - struct jffs2_compressor *this,*comp; - spin_lock(&jffs2_compressor_list_lock); - list_for_each_entry(this, &jffs2_compressor_list, list) { - if (!strcmp(this->name, name)) { - this->priority = priority; - comp = this; - goto reinsert; - } - } - spin_unlock(&jffs2_compressor_list_lock); - printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name); - return 1; -reinsert: - /* list is sorted in the order of priority, so if - we change it we have to reinsert it into the - good place */ - list_del(&comp->list); - list_for_each_entry(this, &jffs2_compressor_list, list) { - if (this->priority < comp->priority) { - list_add(&comp->list, this->list.prev); - spin_unlock(&jffs2_compressor_list_lock); - return 0; - } - } - list_add_tail(&comp->list, &jffs2_compressor_list); - spin_unlock(&jffs2_compressor_list_lock); - return 0; -} - -#endif - void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig) { if (orig != comprbuf) diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h index 509b8b1c0811..aee2de0ca69b 100644 --- a/fs/jffs2/compr.h +++ b/fs/jffs2/compr.h @@ -76,16 +76,6 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig); -#ifdef CONFIG_JFFS2_PROC -int jffs2_enable_compressor_name(const char *name); -int jffs2_disable_compressor_name(const char *name); -int jffs2_set_compression_mode_name(const char *mode_name); -char *jffs2_get_compression_mode_name(void); -int jffs2_set_compressor_priority(const char *mode_name, int priority); -char *jffs2_list_compressors(void); -char *jffs2_stats(void); -#endif - /* Compressor modules */ /* These functions will be called by jffs2_compressors_init/exit */ -- cgit v1.2.2 From 53043002ef6cc0369fd5c5fa0a257f290ba6a3a6 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 5 Apr 2007 11:09:01 +0200 Subject: [JFFS2] check node crc before doing anything else Check the node CRC on scan before doing anything else with the node. Signed-off-by: Thomas Gleixner Signed-off-by: David Woodhouse --- fs/jffs2/scan.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 7fb45bd4915c..a5103df5242e 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -952,8 +952,7 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) { struct jffs2_inode_cache *ic; - uint32_t ino = je32_to_cpu(ri->ino); - int err; + uint32_t crc, ino = je32_to_cpu(ri->ino); D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs)); @@ -966,21 +965,22 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc Which means that the _full_ amount of time to get to proper write mode with GC operational may actually be _longer_ than before. Sucks to be me. */ + /* Check the node CRC in any case. */ + crc = crc32(0, ri, sizeof(*ri)-8); + if (crc != je32_to_cpu(ri->node_crc)) { + printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on " + "node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", + ofs, je32_to_cpu(ri->node_crc), crc); + /* + * We believe totlen because the CRC on the node + * _header_ was OK, just the node itself failed. + */ + return jffs2_scan_dirty_space(c, jeb, + PAD(je32_to_cpu(ri->totlen))); + } + ic = jffs2_get_ino_cache(c, ino); if (!ic) { - /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the - first node we found for this inode. Do a CRC check to protect against the former - case */ - uint32_t crc = crc32(0, ri, sizeof(*ri)-8); - - if (crc != je32_to_cpu(ri->node_crc)) { - printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - ofs, je32_to_cpu(ri->node_crc), crc); - /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ - if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(ri->totlen))))) - return err; - return 0; - } ic = jffs2_scan_make_ino_cache(c, ino); if (!ic) return -ENOMEM; -- cgit v1.2.2 From b0afbbec4981417f79e05865a36e57abfc289002 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 21 Mar 2007 11:07:05 +0200 Subject: [JFFS2] fix deadlock on error path When the MTD driver returns write failure, the following deadlock occurs: We are in __jffs2_flush_wbuf(), we hold &c->wbuf_sem. Write failure. jffs2_wbuf_recover()->jffs2_reserve_space_gc()->jffs2_do_reserve_space() ->jffs2_erase_pending_blocks()->jffs2_flash_read() and it tries to lock &c->wbuf_sem again. Deadlock. Reported-by: Adrian Hunter Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- fs/jffs2/erase.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index ad0121088dde..6b1f7bee3653 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -333,7 +333,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl *bad_offset = ofs; - ret = jffs2_flash_read(c, ofs, readlen, &retlen, ebuf); + ret = c->mtd->read(c->mtd, ofs, readlen, &retlen, ebuf); if (ret) { printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret); goto fail; -- cgit v1.2.2 From 99c2594f0e13de1ca84f97efc3f9e7bc49f91e11 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 29 Mar 2007 11:00:47 +0300 Subject: [JFFS2] Prevent list corruption when handling write errors If a write error occurs, the affected block is placed on the bad_used_list. In the case that the write error occured when writing summary data the block was also being placed on the dirty_list, which caused list corruption and ultimately a soft lockup in jffs2_mark_node_obsolete. This fixes that. Signed-off-by: Adrian Hunter Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- fs/jffs2/nodemgmt.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'fs') diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index d88376992ed9..c8b50dea9e14 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -172,6 +172,11 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) { + if (c->nextblock == NULL) { + D1(printk(KERN_DEBUG "jffs2_close_nextblock: Erase block at 0x%08x has already been placed in a list\n", + jeb->offset)); + return; + } /* Check, if we have a dirty block now, or if it was dirty already */ if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) { c->dirty_size += jeb->wasted_size; -- cgit v1.2.2 From 7f762ab24ca2215b69a1395b5b58877f8282a089 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 4 Apr 2007 13:47:53 +0300 Subject: [JFFS2] Disable summary after wbuf recovery After a write error, any data in the write buffer must be relocated. This is handled by the jffs2_wbuf_recover function. This function does not fix up the erase block summary information that is collected for writing at the end of the block, which results in an incorrect summary (or BUG if the summary was found to be empty). As the summary is not essential (it is an optimisation), it may be disabled for the current erase block when this situation arises. This patch does that. Signed-off-by: Adrian Hunter Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- fs/jffs2/wbuf.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs') diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 4fac6dd53954..f9da0e755a3e 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -345,6 +345,9 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) return; } + /* The summary is not recovered, so it must be disabled for this erase block */ + jffs2_sum_disable_collecting(c->summary); + ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, nr_refile); if (ret) { printk(KERN_WARNING "Failed to allocate node refs for wbuf recovery. Data loss ensues.\n"); -- cgit v1.2.2 From 10731f83009e2556f98ffa5c7c2cbffe66dacfb3 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 4 Apr 2007 13:59:11 +0300 Subject: [JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes() In read inode we have an optimization which prevents one min. I/O unit (e.g. NAND page) to be read more then once. Namely, at the beginning we do not know which node type we read, so we read so we assume we read the directory entry, because it has the smallest node header. When we read it, we read up to the next min. I/O unit, just because if later we'll need to read more, we already have this data. If it turns out to be that the node is not directory entry, and we need more data, and we did not read it because it sits in the next min. I/O unit, we read the whole next (or several next) min. I/O unit(s). And if it happens to be that we read a data node, and we've read part of its data, we calculate partial CRC. So if later we need to check data CRC, we'll only read the rest of the data from further min. I/O units and continue CRC checking. This code was a bit messy and buggy. The bug was that it assumed relatively large min. I/O unit, so that the largest node header could overlap only one min. I/O unit boundary. This parch clean-ups the code a bit and fixes this bug. The patch was not tested on flash with small min. I/O unit, like NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so it at least does not break NAND. It was also tested with mtdram so it should not break NOR. Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- fs/jffs2/readinode.c | 98 ++++++++++++++++++---------------------------------- 1 file changed, 33 insertions(+), 65 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 717a48cf7df2..1298848336b8 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -421,49 +421,38 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re * negative error code on failure. */ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, - int right_size, int *rdlen, unsigned char *buf, unsigned char *bufstart) + int needed_len, int *rdlen, unsigned char *buf) { - int right_len, err, len; + int err, to_read = needed_len - *rdlen; size_t retlen; uint32_t offs; if (jffs2_is_writebuffered(c)) { - right_len = c->wbuf_pagesize - (bufstart - buf); - if (right_size + (int)(bufstart - buf) > c->wbuf_pagesize) - right_len += c->wbuf_pagesize; - } else - right_len = right_size; + int rem = to_read % c->wbuf_pagesize; - if (*rdlen == right_len) - return 0; + if (rem) + to_read += c->wbuf_pagesize - rem; + } /* We need to read more data */ offs = ref_offset(ref) + *rdlen; - if (jffs2_is_writebuffered(c)) { - bufstart = buf + c->wbuf_pagesize; - len = c->wbuf_pagesize; - } else { - bufstart = buf + *rdlen; - len = right_size - *rdlen; - } - dbg_readinode("read more %d bytes\n", len); + dbg_readinode("read more %d bytes\n", to_read); - err = jffs2_flash_read(c, offs, len, &retlen, bufstart); + err = jffs2_flash_read(c, offs, to_read, &retlen, buf + *rdlen); if (err) { JFFS2_ERROR("can not read %d bytes from 0x%08x, " - "error code: %d.\n", len, offs, err); + "error code: %d.\n", to_read, offs, err); return err; } - if (retlen < len) { + if (retlen < to_read) { JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", - offs, retlen, len); + offs, retlen, to_read); return -EIO; } - *rdlen = right_len; - + *rdlen += to_read; return 0; } @@ -486,27 +475,9 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf dbg_readinode("ino #%u\n", f->inocache->ino); - if (jffs2_is_writebuffered(c)) { - /* - * If we have the write buffer, we assume the minimal I/O unit - * is c->wbuf_pagesize. We implement some optimizations which in - * this case and we need a temporary buffer of size = - * 2*c->wbuf_pagesize bytes (see comments in read_dnode()). - * Basically, we want to read not only the node header, but the - * whole wbuf (NAND page in case of NAND) or 2, if the node - * header overlaps the border between the 2 wbufs. - */ - len = 2*c->wbuf_pagesize; - } else { - /* - * When there is no write buffer, the size of the temporary - * buffer is the size of the larges node header. - */ - len = sizeof(union jffs2_node_union); - } - /* FIXME: in case of NOR and available ->point() this * needs to be fixed. */ + len = sizeof(union jffs2_node_union) + c->wbuf_pagesize; buf = kmalloc(len, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -516,8 +487,6 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf if (!valid_ref && f->inocache->ino != 1) JFFS2_WARNING("Eep. No valid nodes for ino #%u.\n", f->inocache->ino); while (valid_ref) { - unsigned char *bufstart; - /* We can hold a pointer to a non-obsolete node without the spinlock, but _obsolete_ nodes may disappear at any time, if the block they're in gets erased. So if we mark 'ref' obsolete while we're @@ -533,32 +502,31 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf /* * At this point we don't know the type of the node we're going * to read, so we do not know the size of its header. In order - * to minimize the amount of flash IO we assume the node has - * size = JFFS2_MIN_NODE_HEADER. + * to minimize the amount of flash IO we assume the header is + * of size = JFFS2_MIN_NODE_HEADER. */ + len = JFFS2_MIN_NODE_HEADER; if (jffs2_is_writebuffered(c)) { + int end, rem; + /* - * We treat 'buf' as 2 adjacent wbufs. We want to - * adjust bufstart such as it points to the - * beginning of the node within this wbuf. + * We are about to read JFFS2_MIN_NODE_HEADER bytes, + * but this flash has some minimal I/O unit. It is + * possible that we'll need to read more soon, so read + * up to the next min. I/O unit, in order not to + * re-read the same min. I/O unit twice. */ - bufstart = buf + (ref_offset(ref) % c->wbuf_pagesize); - /* We will read either one wbuf or 2 wbufs. */ - len = c->wbuf_pagesize - (bufstart - buf); - if (JFFS2_MIN_NODE_HEADER + (int)(bufstart - buf) > c->wbuf_pagesize) { - /* The header spans the border of the first wbuf */ - len += c->wbuf_pagesize; - } - } else { - bufstart = buf; - len = JFFS2_MIN_NODE_HEADER; + end = ref_offset(ref) + len; + rem = end % c->wbuf_pagesize; + if (rem) + end += c->wbuf_pagesize - rem; + len = end - ref_offset(ref); } dbg_readinode("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref)); /* FIXME: point() */ - err = jffs2_flash_read(c, ref_offset(ref), len, - &retlen, bufstart); + err = jffs2_flash_read(c, ref_offset(ref), len, &retlen, buf); if (err) { JFFS2_ERROR("can not read %d bytes from 0x%08x, " "error code: %d.\n", len, ref_offset(ref), err); goto free_out; @@ -570,7 +538,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf goto free_out; } - node = (union jffs2_node_union *)bufstart; + node = (union jffs2_node_union *)buf; /* No need to mask in the valid bit; it shouldn't be invalid */ if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) { @@ -596,7 +564,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf case JFFS2_NODETYPE_DIRENT: if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) { - err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf, bufstart); + err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf); if (unlikely(err)) goto free_out; } @@ -616,7 +584,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf case JFFS2_NODETYPE_INODE: if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) { - err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf, bufstart); + err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf); if (unlikely(err)) goto free_out; } @@ -635,7 +603,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf default: if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node)) { - err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf, bufstart); + err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf); if (unlikely(err)) goto free_out; } -- cgit v1.2.2 From c2aecda79cd872679b9b11f9e59d797fb4c7d677 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Tue, 27 Mar 2007 13:32:09 +0200 Subject: [JFFS2] Speed up mount for directly-mapped NOR flash Remove excessive scanning of empty flash after a clean marker for users of the point/unpoint method. cfi_cmdset_0001 uses point/unpoint by default iff flash mapping is linear. The speedup is several orders of magnitude if FS is less than half full. Signed-off-by: Joakim Tjernlund Signed-off-by: David Woodhouse --- fs/jffs2/scan.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index a5103df5242e..7a46a436edfc 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -636,16 +636,17 @@ scan_more: if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) { uint32_t inbuf_ofs; - uint32_t empty_start; + uint32_t empty_start, scan_end; empty_start = ofs; ofs += 4; + scan_end = min_t(uint32_t, EMPTY_SCAN_SIZE(c->sector_size)/8, buf_len); D1(printk(KERN_DEBUG "Found empty flash at 0x%08x\n", ofs)); more_empty: inbuf_ofs = ofs - buf_ofs; - while (inbuf_ofs < buf_len) { - if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) { + while (inbuf_ofs < scan_end) { + if (unlikely(*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff)) { printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n", empty_start, ofs); if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start))) @@ -666,7 +667,11 @@ scan_more: D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size))); return BLK_STATE_CLEANMARKER; } - + if (!buf_size && (scan_end != buf_len)) {/* XIP/point case */ + scan_end = buf_len; + goto more_empty; + } + /* See how much more there is to read in this eraseblock... */ buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); if (!buf_len) { @@ -676,6 +681,8 @@ scan_more: empty_start)); break; } + /* point never reaches here */ + scan_end = buf_len; D1(printk(KERN_DEBUG "Reading another 0x%x at 0x%08x\n", buf_len, ofs)); err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); if (err) -- cgit v1.2.2 From a491486a2087ac3dfc00efb4f838c8d684afaf54 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Fri, 16 Mar 2007 16:15:45 +0100 Subject: [JFFS2] Obsolete dirent nodes immediately on unlink, where possible. Signed-off-by: Joakim Tjernlund Signed-off-by: David Woodhouse --- fs/jffs2/write.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 67176792e138..57a79a6ba3d9 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -507,8 +507,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t alloclen; int ret; - if (1 /* alternative branch needs testing */ || - !jffs2_can_mark_obsolete(c)) { + if (!jffs2_can_mark_obsolete(c)) { /* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */ rd = jffs2_alloc_raw_dirent(); -- cgit v1.2.2 From 566865a2a4791c9290155f651ee0c2c606db0b1d Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 23 Apr 2007 12:07:17 +0100 Subject: [JFFS2] Fix cross-endian build. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiling a LE-capable JFFS2 on PowerPC, wbuf.c fails to compile: fs/jffs2/wbuf.c:973: error: braced-group within expression allowed only inside a function fs/jffs2/wbuf.c:973: error: initializer element is not constant fs/jffs2/wbuf.c:973: error: (near initialization for ‘oob_cleanmarker.magic’) fs/jffs2/wbuf.c:974: error: braced-group within expression allowed only inside a function fs/jffs2/wbuf.c:974: error: initializer element is not constant fs/jffs2/wbuf.c:974: error: (near initialization for ‘oob_cleanmarker.nodetype’) fs/jffs2/wbuf.c:975: error: braced-group within expression allowed only inside a function fs/jffs2/wbuf.c:976: error: initializer element is not constant fs/jffs2/wbuf.c:976: error: (near initialization for ‘oob_cleanmarker.totlen’) Provide constant_cpu_to_je{16,32} functions, and use them for initialising the offending structure. Signed-off-by: David Woodhouse --- fs/jffs2/nodelist.h | 9 +++++++++ fs/jffs2/wbuf.c | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 4178b4b55948..382662cc61e7 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -40,6 +40,9 @@ #define cpu_to_je32(x) ((jint32_t){x}) #define cpu_to_jemode(x) ((jmode_t){os_to_jffs2_mode(x)}) +#define constant_cpu_to_je16(x) ((jint16_t){x}) +#define constant_cpu_to_je32(x) ((jint32_t){x}) + #define je16_to_cpu(x) ((x).v16) #define je32_to_cpu(x) ((x).v32) #define jemode_to_cpu(x) (jffs2_to_os_mode((x).m)) @@ -48,6 +51,9 @@ #define cpu_to_je32(x) ((jint32_t){cpu_to_be32(x)}) #define cpu_to_jemode(x) ((jmode_t){cpu_to_be32(os_to_jffs2_mode(x))}) +#define constant_cpu_to_je16(x) ((jint16_t){__constant_cpu_to_be16(x)}) +#define constant_cpu_to_je32(x) ((jint32_t){__constant_cpu_to_be32(x)}) + #define je16_to_cpu(x) (be16_to_cpu(x.v16)) #define je32_to_cpu(x) (be32_to_cpu(x.v32)) #define jemode_to_cpu(x) (be32_to_cpu(jffs2_to_os_mode((x).m))) @@ -56,6 +62,9 @@ #define cpu_to_je32(x) ((jint32_t){cpu_to_le32(x)}) #define cpu_to_jemode(x) ((jmode_t){cpu_to_le32(os_to_jffs2_mode(x))}) +#define constant_cpu_to_je16(x) ((jint16_t){__constant_cpu_to_le16(x)}) +#define constant_cpu_to_je32(x) ((jint32_t){__constant_cpu_to_le32(x)}) + #define je16_to_cpu(x) (le16_to_cpu(x.v16)) #define je32_to_cpu(x) (le32_to_cpu(x.v32)) #define jemode_to_cpu(x) (le32_to_cpu(jffs2_to_os_mode((x).m))) diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index f9da0e755a3e..f87f11af7086 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -970,9 +970,9 @@ exit: static const struct jffs2_unknown_node oob_cleanmarker = { - .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK), - .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), - .totlen = cpu_to_je32(8) + .magic = constant_cpu_to_je16(JFFS2_MAGIC_BITMASK), + .nodetype = constant_cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), + .totlen = constant_cpu_to_je32(8) }; /* -- cgit v1.2.2 From 44b998e1eb254edc87177819ee693690fac68b7f Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 23 Apr 2007 12:11:46 +0100 Subject: [JFFS2] Improve failure mode if inode checking leaves unchecked space. We should never find the unchecked size is non-zero after we've finished checking all inodes. If it happens, used to BUG(), leaving the alloc_sem held and deadlocking. Instead, just return -ENOSPC after complaining. The GC thread will die, but read-only operation should be able to continue and the file system should be unmountable. Signed-off-by: David Woodhouse --- fs/jffs2/gc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 3a3cf225981f..e92cf0f02529 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -144,7 +144,8 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) c->unchecked_size); jffs2_dbg_dump_block_lists_nolock(c); spin_unlock(&c->erase_completion_lock); - BUG(); + up(&c->alloc_sem); + return -ENOSPC; } spin_unlock(&c->erase_completion_lock); -- cgit v1.2.2 From df8e96f39103adf5a13332d784040a2c62667243 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 25 Apr 2007 03:23:42 +0100 Subject: [JFFS2] Improve read_inode memory usage, v2. We originally used to read every node and allocate a jffs2_tmp_dnode_info structure for each, before processing them in (reverse) version order and discarding the ones which are obsoleted by later nodes. With huge logfiles, this behaviour caused memory problems. For example, a file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO machine to run out of memory during the first stage of read_inode(). Instead of just inserting nodes into a tree in version order as we find them, we now put them into a tree in order of their offset within the file, which allows us to immediately discard nodes which are completely obsoleted. We don't use a full tree with 'fragments' pointing to the real data structure, as we do in the normal fragtree. We sort only on the start address, and add an 'overlapped' flag to the tmp_dnode_info to indicate that the node in question is (partially) overlapped by another. When the scan is complete, we start at the end of the file, adding each node to a real fragtree as before. Where the node is non-overlapped, we just add it (it doesn't matter that it's not the latest version; there is no overlap). When the node at the end of the tree _is_ overlapped, we sort it and all its overlapping nodes into version order and then add them to the fragtree in that order. This 'early discard' reduces the peak allocation of tmp_dnode_info structures from 1.8M to a mere 62872 (3.5%) in the degenerate case referenced above. This version of the patch also correctly rememembers the highest node version# seen for an inode when it's scanned. Signed-off-by: David Woodhouse --- fs/jffs2/nodelist.c | 460 -------------------------------- fs/jffs2/nodelist.h | 25 +- fs/jffs2/readinode.c | 732 +++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 618 insertions(+), 599 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 5a6b4d64206c..fecffbc63552 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -397,466 +397,6 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in return 0; } -/* - * Check the data CRC of the node. - * - * Returns: 0 if the data CRC is correct; - * 1 - if incorrect; - * error code if an error occured. - */ -static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) -{ - struct jffs2_raw_node_ref *ref = tn->fn->raw; - int err = 0, pointed = 0; - struct jffs2_eraseblock *jeb; - unsigned char *buffer; - uint32_t crc, ofs, len; - size_t retlen; - - BUG_ON(tn->csize == 0); - - if (!jffs2_is_writebuffered(c)) - goto adj_acc; - - /* Calculate how many bytes were already checked */ - ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); - len = ofs % c->wbuf_pagesize; - if (likely(len)) - len = c->wbuf_pagesize - len; - - if (len >= tn->csize) { - dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n", - ref_offset(ref), tn->csize, ofs); - goto adj_acc; - } - - ofs += len; - len = tn->csize - len; - - dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n", - ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len); - -#ifndef __ECOS - /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(), - * adding and jffs2_flash_read_end() interface. */ - if (c->mtd->point) { - err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer); - if (!err && retlen < tn->csize) { - JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize); - c->mtd->unpoint(c->mtd, buffer, ofs, len); - } else if (err) - JFFS2_WARNING("MTD point failed: error code %d.\n", err); - else - pointed = 1; /* succefully pointed to device */ - } -#endif - - if (!pointed) { - buffer = kmalloc(len, GFP_KERNEL); - if (unlikely(!buffer)) - return -ENOMEM; - - /* TODO: this is very frequent pattern, make it a separate - * routine */ - err = jffs2_flash_read(c, ofs, len, &retlen, buffer); - if (err) { - JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err); - goto free_out; - } - - if (retlen != len) { - JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len); - err = -EIO; - goto free_out; - } - } - - /* Continue calculating CRC */ - crc = crc32(tn->partial_crc, buffer, len); - if(!pointed) - kfree(buffer); -#ifndef __ECOS - else - c->mtd->unpoint(c->mtd, buffer, ofs, len); -#endif - - if (crc != tn->data_crc) { - JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n", - ofs, tn->data_crc, crc); - return 1; - } - -adj_acc: - jeb = &c->blocks[ref->flash_offset / c->sector_size]; - len = ref_totlen(c, jeb, ref); - - /* - * Mark the node as having been checked and fix the - * accounting accordingly. - */ - spin_lock(&c->erase_completion_lock); - jeb->used_size += len; - jeb->unchecked_size -= len; - c->used_size += len; - c->unchecked_size -= len; - spin_unlock(&c->erase_completion_lock); - - return 0; - -free_out: - if(!pointed) - kfree(buffer); -#ifndef __ECOS - else - c->mtd->unpoint(c->mtd, buffer, ofs, len); -#endif - return err; -} - -/* - * Helper function for jffs2_add_older_frag_to_fragtree(). - * - * Checks the node if we are in the checking stage. - */ -static int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn) -{ - int ret; - - BUG_ON(ref_obsolete(tn->fn->raw)); - - /* We only check the data CRC of unchecked nodes */ - if (ref_flags(tn->fn->raw) != REF_UNCHECKED) - return 0; - - dbg_fragtree2("check node %#04x-%#04x, phys offs %#08x.\n", - tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw)); - - ret = check_node_data(c, tn); - if (unlikely(ret < 0)) { - JFFS2_ERROR("check_node_data() returned error: %d.\n", - ret); - } else if (unlikely(ret > 0)) { - dbg_fragtree2("CRC error, mark it obsolete.\n"); - jffs2_mark_node_obsolete(c, tn->fn->raw); - } - - return ret; -} - -/* - * Helper function for jffs2_add_older_frag_to_fragtree(). - * - * Called when the new fragment that is being inserted - * splits a hole fragment. - */ -static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, - struct jffs2_node_frag *newfrag, struct jffs2_node_frag *hole) -{ - dbg_fragtree2("fragment %#04x-%#04x splits the hole %#04x-%#04x\n", - newfrag->ofs, newfrag->ofs + newfrag->size, hole->ofs, hole->ofs + hole->size); - - if (hole->ofs == newfrag->ofs) { - /* - * Well, the new fragment actually starts at the same offset as - * the hole. - */ - if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) { - /* - * We replace the overlapped left part of the hole by - * the new node. - */ - - dbg_fragtree2("insert fragment %#04x-%#04x and cut the left part of the hole\n", - newfrag->ofs, newfrag->ofs + newfrag->size); - rb_replace_node(&hole->rb, &newfrag->rb, root); - - hole->ofs += newfrag->size; - hole->size -= newfrag->size; - - /* - * We know that 'hole' should be the right hand - * fragment. - */ - jffs2_fragtree_insert(hole, newfrag); - rb_insert_color(&hole->rb, root); - } else { - /* - * Ah, the new fragment is of the same size as the hole. - * Relace the hole by it. - */ - dbg_fragtree2("insert fragment %#04x-%#04x and overwrite hole\n", - newfrag->ofs, newfrag->ofs + newfrag->size); - rb_replace_node(&hole->rb, &newfrag->rb, root); - jffs2_free_node_frag(hole); - } - } else { - /* The new fragment lefts some hole space at the left */ - - struct jffs2_node_frag * newfrag2 = NULL; - - if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) { - /* The new frag also lefts some space at the right */ - newfrag2 = new_fragment(NULL, newfrag->ofs + - newfrag->size, hole->ofs + hole->size - - newfrag->ofs - newfrag->size); - if (unlikely(!newfrag2)) { - jffs2_free_node_frag(newfrag); - return -ENOMEM; - } - } - - hole->size = newfrag->ofs - hole->ofs; - dbg_fragtree2("left the hole %#04x-%#04x at the left and inserd fragment %#04x-%#04x\n", - hole->ofs, hole->ofs + hole->size, newfrag->ofs, newfrag->ofs + newfrag->size); - - jffs2_fragtree_insert(newfrag, hole); - rb_insert_color(&newfrag->rb, root); - - if (newfrag2) { - dbg_fragtree2("left the hole %#04x-%#04x at the right\n", - newfrag2->ofs, newfrag2->ofs + newfrag2->size); - jffs2_fragtree_insert(newfrag2, newfrag); - rb_insert_color(&newfrag2->rb, root); - } - } - - return 0; -} - -/* - * This function is used when we build inode. It expects the nodes are passed - * in the decreasing version order. The whole point of this is to improve the - * inodes checking on NAND: we check the nodes' data CRC only when they are not - * obsoleted. Previously, add_frag_to_fragtree() function was used and - * nodes were passed to it in the increasing version ordes and CRCs of all - * nodes were checked. - * - * Note: tn->fn->size shouldn't be zero. - * - * Returns 0 if the node was inserted - * 1 if it wasn't inserted (since it is obsolete) - * < 0 an if error occured - */ -int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - struct jffs2_tmp_dnode_info *tn) -{ - struct jffs2_node_frag *this, *newfrag; - uint32_t lastend; - struct jffs2_full_dnode *fn = tn->fn; - struct rb_root *root = &f->fragtree; - uint32_t fn_size = fn->size, fn_ofs = fn->ofs; - int err, checked = 0; - int ref_flag; - - dbg_fragtree("insert fragment %#04x-%#04x, ver %u\n", fn_ofs, fn_ofs + fn_size, tn->version); - - /* Skip all the nodes which are completed before this one starts */ - this = jffs2_lookup_node_frag(root, fn_ofs); - if (this) - dbg_fragtree2("'this' found %#04x-%#04x (%s)\n", this->ofs, this->ofs + this->size, this->node ? "data" : "hole"); - - if (this) - lastend = this->ofs + this->size; - else - lastend = 0; - - /* Detect the preliminary type of node */ - if (fn->size >= PAGE_CACHE_SIZE) - ref_flag = REF_PRISTINE; - else - ref_flag = REF_NORMAL; - - /* See if we ran off the end of the root */ - if (lastend <= fn_ofs) { - /* We did */ - - /* - * We are going to insert the new node into the - * fragment tree, so check it. - */ - err = check_node(c, f, tn); - if (err != 0) - return err; - - fn->frags = 1; - - newfrag = new_fragment(fn, fn_ofs, fn_size); - if (unlikely(!newfrag)) - return -ENOMEM; - - err = no_overlapping_node(c, root, newfrag, this, lastend); - if (unlikely(err != 0)) { - jffs2_free_node_frag(newfrag); - return err; - } - - goto out_ok; - } - - fn->frags = 0; - - while (1) { - /* - * Here we have: - * fn_ofs < this->ofs + this->size && fn_ofs >= this->ofs. - * - * Remember, 'this' has higher version, any non-hole node - * which is already in the fragtree is newer then the newly - * inserted. - */ - if (!this->node) { - /* - * 'this' is the hole fragment, so at least the - * beginning of the new fragment is valid. - */ - - /* - * We are going to insert the new node into the - * fragment tree, so check it. - */ - if (!checked) { - err = check_node(c, f, tn); - if (unlikely(err != 0)) - return err; - checked = 1; - } - - if (this->ofs + this->size >= fn_ofs + fn_size) { - /* We split the hole on two parts */ - - fn->frags += 1; - newfrag = new_fragment(fn, fn_ofs, fn_size); - if (unlikely(!newfrag)) - return -ENOMEM; - - err = split_hole(c, root, newfrag, this); - if (unlikely(err)) - return err; - goto out_ok; - } - - /* - * The beginning of the new fragment is valid since it - * overlaps the hole node. - */ - - ref_flag = REF_NORMAL; - - fn->frags += 1; - newfrag = new_fragment(fn, fn_ofs, - this->ofs + this->size - fn_ofs); - if (unlikely(!newfrag)) - return -ENOMEM; - - if (fn_ofs == this->ofs) { - /* - * The new node starts at the same offset as - * the hole and supersieds the hole. - */ - dbg_fragtree2("add the new fragment instead of hole %#04x-%#04x, refcnt %d\n", - fn_ofs, fn_ofs + this->ofs + this->size - fn_ofs, fn->frags); - - rb_replace_node(&this->rb, &newfrag->rb, root); - jffs2_free_node_frag(this); - } else { - /* - * The hole becomes shorter as its right part - * is supersieded by the new fragment. - */ - dbg_fragtree2("reduce size of hole %#04x-%#04x to %#04x-%#04x\n", - this->ofs, this->ofs + this->size, this->ofs, this->ofs + this->size - newfrag->size); - - dbg_fragtree2("add new fragment %#04x-%#04x, refcnt %d\n", fn_ofs, - fn_ofs + this->ofs + this->size - fn_ofs, fn->frags); - - this->size -= newfrag->size; - jffs2_fragtree_insert(newfrag, this); - rb_insert_color(&newfrag->rb, root); - } - - fn_ofs += newfrag->size; - fn_size -= newfrag->size; - this = rb_entry(rb_next(&newfrag->rb), - struct jffs2_node_frag, rb); - - dbg_fragtree2("switch to the next 'this' fragment: %#04x-%#04x %s\n", - this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)"); - } - - /* - * 'This' node is not the hole so it obsoletes the new fragment - * either fully or partially. - */ - if (this->ofs + this->size >= fn_ofs + fn_size) { - /* The new node is obsolete, drop it */ - if (fn->frags == 0) { - dbg_fragtree2("%#04x-%#04x is obsolete, mark it obsolete\n", fn_ofs, fn_ofs + fn_size); - ref_flag = REF_OBSOLETE; - } - goto out_ok; - } else { - struct jffs2_node_frag *new_this; - - /* 'This' node obsoletes the beginning of the new node */ - dbg_fragtree2("the beginning %#04x-%#04x is obsolete\n", fn_ofs, this->ofs + this->size); - - ref_flag = REF_NORMAL; - - fn_size -= this->ofs + this->size - fn_ofs; - fn_ofs = this->ofs + this->size; - dbg_fragtree2("now considering %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size); - - new_this = rb_entry(rb_next(&this->rb), struct jffs2_node_frag, rb); - if (!new_this) { - /* - * There is no next fragment. Add the rest of - * the new node as the right-hand child. - */ - if (!checked) { - err = check_node(c, f, tn); - if (unlikely(err != 0)) - return err; - checked = 1; - } - - fn->frags += 1; - newfrag = new_fragment(fn, fn_ofs, fn_size); - if (unlikely(!newfrag)) - return -ENOMEM; - - dbg_fragtree2("there are no more fragments, insert %#04x-%#04x\n", - newfrag->ofs, newfrag->ofs + newfrag->size); - rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); - rb_insert_color(&newfrag->rb, root); - goto out_ok; - } else { - this = new_this; - dbg_fragtree2("switch to the next 'this' fragment: %#04x-%#04x %s\n", - this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)"); - } - } - } - -out_ok: - BUG_ON(fn->size < PAGE_CACHE_SIZE && ref_flag == REF_PRISTINE); - - if (ref_flag == REF_OBSOLETE) { - dbg_fragtree2("the node is obsolete now\n"); - /* jffs2_mark_node_obsolete() will adjust space accounting */ - jffs2_mark_node_obsolete(c, fn->raw); - return 1; - } - - dbg_fragtree2("the node is \"%s\" now\n", ref_flag == REF_NORMAL ? "REF_NORMAL" : "REF_PRISTINE"); - - /* Space accounting was adjusted at check_node_data() */ - spin_lock(&c->erase_completion_lock); - fn->raw->flash_offset = ref_offset(fn->raw) | ref_flag; - spin_unlock(&c->erase_completion_lock); - - return 0; -} - void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state) { spin_lock(&c->inocache_lock); diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 382662cc61e7..e5c8f2be8e22 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -225,7 +225,20 @@ struct jffs2_tmp_dnode_info uint32_t version; uint32_t data_crc; uint32_t partial_crc; - uint32_t csize; + uint16_t csize; + uint16_t overlapped; +}; + +/* Temporary data structure used during readinode. */ +struct jffs2_readinode_info +{ + struct rb_root tn_root; + struct jffs2_tmp_dnode_info *mdata_tn; + uint32_t highest_version; + uint32_t latest_mctime; + uint32_t mctime_ver; + struct jffs2_full_dirent *fds; + struct jffs2_raw_node_ref *latest_ref; }; struct jffs2_full_dirent @@ -328,6 +341,15 @@ static inline struct jffs2_node_frag *frag_last(struct rb_root *root) #define frag_right(frag) rb_entry((frag)->rb.rb_right, struct jffs2_node_frag, rb) #define frag_erase(frag, list) rb_erase(&frag->rb, list); +#define tn_next(tn) rb_entry(rb_next(&(tn)->rb), struct jffs2_tmp_dnode_info, rb) +#define tn_prev(tn) rb_entry(rb_prev(&(tn)->rb), struct jffs2_tmp_dnode_info, rb) +#define tn_parent(tn) rb_entry(rb_parent(&(tn)->rb), struct jffs2_tmp_dnode_info, rb) +#define tn_left(tn) rb_entry((tn)->rb.rb_left, struct jffs2_tmp_dnode_info, rb) +#define tn_right(tn) rb_entry((tn)->rb.rb_right, struct jffs2_tmp_dnode_info, rb) +#define tn_erase(tn, list) rb_erase(&tn->rb, list); +#define tn_last(list) rb_entry(rb_last(list), struct jffs2_tmp_dnode_info, rb) +#define tn_first(list) rb_entry(rb_first(list), struct jffs2_tmp_dnode_info, rb) + /* nodelist.c */ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list); void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state); @@ -343,7 +365,6 @@ struct rb_node *rb_prev(struct rb_node *); void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); -int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t ofs, uint32_t len, diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 1298848336b8..49d4b0a67c55 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -22,30 +22,510 @@ #include "nodelist.h" /* - * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in - * order of increasing version. + * Check the data CRC of the node. + * + * Returns: 0 if the data CRC is correct; + * 1 - if incorrect; + * error code if an error occured. */ -static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list) +static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) { - struct rb_node **p = &list->rb_node; - struct rb_node * parent = NULL; - struct jffs2_tmp_dnode_info *this; - - while (*p) { - parent = *p; - this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); - - /* There may actually be a collision here, but it doesn't - actually matter. As long as the two nodes with the same - version are together, it's all fine. */ - if (tn->version > this->version) - p = &(*p)->rb_left; + struct jffs2_raw_node_ref *ref = tn->fn->raw; + int err = 0, pointed = 0; + struct jffs2_eraseblock *jeb; + unsigned char *buffer; + uint32_t crc, ofs, len; + size_t retlen; + + BUG_ON(tn->csize == 0); + + if (!jffs2_is_writebuffered(c)) + goto adj_acc; + + /* Calculate how many bytes were already checked */ + ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); + len = ofs % c->wbuf_pagesize; + if (likely(len)) + len = c->wbuf_pagesize - len; + + if (len >= tn->csize) { + dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n", + ref_offset(ref), tn->csize, ofs); + goto adj_acc; + } + + ofs += len; + len = tn->csize - len; + + dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n", + ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len); + +#ifndef __ECOS + /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(), + * adding and jffs2_flash_read_end() interface. */ + if (c->mtd->point) { + err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer); + if (!err && retlen < tn->csize) { + JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize); + c->mtd->unpoint(c->mtd, buffer, ofs, len); + } else if (err) + JFFS2_WARNING("MTD point failed: error code %d.\n", err); else - p = &(*p)->rb_right; + pointed = 1; /* succefully pointed to device */ + } +#endif + + if (!pointed) { + buffer = kmalloc(len, GFP_KERNEL); + if (unlikely(!buffer)) + return -ENOMEM; + + /* TODO: this is very frequent pattern, make it a separate + * routine */ + err = jffs2_flash_read(c, ofs, len, &retlen, buffer); + if (err) { + JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err); + goto free_out; + } + + if (retlen != len) { + JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len); + err = -EIO; + goto free_out; + } + } + + /* Continue calculating CRC */ + crc = crc32(tn->partial_crc, buffer, len); + if(!pointed) + kfree(buffer); +#ifndef __ECOS + else + c->mtd->unpoint(c->mtd, buffer, ofs, len); +#endif + + if (crc != tn->data_crc) { + JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n", + ofs, tn->data_crc, crc); + return 1; } - rb_link_node(&tn->rb, parent, p); - rb_insert_color(&tn->rb, list); +adj_acc: + jeb = &c->blocks[ref->flash_offset / c->sector_size]; + len = ref_totlen(c, jeb, ref); + /* If it should be REF_NORMAL, it'll get marked as such when + we build the fragtree, shortly. No need to worry about GC + moving it while it's marked REF_PRISTINE -- GC won't happen + till we've finished checking every inode anyway. */ + ref->flash_offset |= REF_PRISTINE; + /* + * Mark the node as having been checked and fix the + * accounting accordingly. + */ + spin_lock(&c->erase_completion_lock); + jeb->used_size += len; + jeb->unchecked_size -= len; + c->used_size += len; + c->unchecked_size -= len; + jffs2_dbg_acct_paranoia_check_nolock(c, jeb); + spin_unlock(&c->erase_completion_lock); + + return 0; + +free_out: + if(!pointed) + kfree(buffer); +#ifndef __ECOS + else + c->mtd->unpoint(c->mtd, buffer, ofs, len); +#endif + return err; +} + +/* + * Helper function for jffs2_add_older_frag_to_fragtree(). + * + * Checks the node if we are in the checking stage. + */ +static int check_tn_node(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) +{ + int ret; + + BUG_ON(ref_obsolete(tn->fn->raw)); + + /* We only check the data CRC of unchecked nodes */ + if (ref_flags(tn->fn->raw) != REF_UNCHECKED) + return 0; + + dbg_readinode("check node %#04x-%#04x, phys offs %#08x\n", + tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw)); + + ret = check_node_data(c, tn); + if (unlikely(ret < 0)) { + JFFS2_ERROR("check_node_data() returned error: %d.\n", + ret); + } else if (unlikely(ret > 0)) { + dbg_readinode("CRC error, mark it obsolete.\n"); + jffs2_mark_node_obsolete(c, tn->fn->raw); + } + + return ret; +} + +static struct jffs2_tmp_dnode_info *jffs2_lookup_tn(struct rb_root *tn_root, uint32_t offset) +{ + struct rb_node *next; + struct jffs2_tmp_dnode_info *tn = NULL; + + dbg_readinode("root %p, offset %d\n", tn_root, offset); + + next = tn_root->rb_node; + + while (next) { + tn = rb_entry(next, struct jffs2_tmp_dnode_info, rb); + + if (tn->fn->ofs < offset) + next = tn->rb.rb_right; + else if (tn->fn->ofs >= offset) + next = tn->rb.rb_left; + else + break; + } + + return tn; +} + + +static void jffs2_kill_tn(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) +{ + jffs2_mark_node_obsolete(c, tn->fn->raw); + jffs2_free_full_dnode(tn->fn); + jffs2_free_tmp_dnode_info(tn); +} +/* + * This function is used when we read an inode. Data nodes arrive in + * arbitrary order -- they may be older or newer than the nodes which + * are already in the tree. Where overlaps occur, the older node can + * be discarded as long as the newer passes the CRC check. We don't + * bother to keep track of holes in this rbtree, and neither do we deal + * with frags -- we can have multiple entries starting at the same + * offset, and the one with the smallest length will come first in the + * ordering. + * + * Returns 0 if the node was inserted + * 1 if the node is obsolete (because we can't mark it so yet) + * < 0 an if error occurred + */ +static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, + struct jffs2_readinode_info *rii, + struct jffs2_tmp_dnode_info *tn) +{ + uint32_t fn_end = tn->fn->ofs + tn->fn->size; + struct jffs2_tmp_dnode_info *insert_point = NULL, *this; + + dbg_readinode("insert fragment %#04x-%#04x, ver %u\n", tn->fn->ofs, fn_end, tn->version); + + /* If a node has zero dsize, we only have to keep if it if it might be the + node with highest version -- i.e. the one which will end up as f->metadata. + Note that such nodes won't be REF_UNCHECKED since there are no data to + check anyway. */ + if (!tn->fn->size) { + if (rii->mdata_tn) { + /* We had a candidate mdata node already */ + dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version); + jffs2_kill_tn(c, rii->mdata_tn); + } + rii->mdata_tn = tn; + dbg_readinode("keep new mdata with ver %d\n", tn->version); + return 0; + } + + /* Find the earliest node which _may_ be relevant to this one */ + this = jffs2_lookup_tn(&rii->tn_root, tn->fn->ofs); + if (!this) { + /* First addition to empty tree. $DEITY how I love the easy cases */ + rb_link_node(&tn->rb, NULL, &rii->tn_root.rb_node); + rb_insert_color(&tn->rb, &rii->tn_root); + dbg_readinode("keep new frag\n"); + return 0; + } + + /* If we add a new node it'll be somewhere under here. */ + insert_point = this; + + /* If the node is coincident with another at a lower address, + back up until the other node is found. It may be relevant */ + while (tn->overlapped) + tn = tn_prev(tn); + + dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole"); + + while (this) { + if (this->fn->ofs > fn_end) + break; + dbg_readinode("Ponder this ver %d, 0x%x-0x%x\n", + this->version, this->fn->ofs, this->fn->size); + + if (this->version == tn->version) { + /* Version number collision means REF_PRISTINE GC. Accept either of them + as long as the CRC is correct. Check the one we have already... */ + if (!check_tn_node(c, this)) { + /* The one we already had was OK. Keep it and throw away the new one */ + dbg_readinode("Like old node. Throw away new\n"); + jffs2_kill_tn(c, tn); + return 0; + } else { + /* Who cares if the new one is good; keep it for now anyway. */ + rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); + /* Same overlapping from in front and behind */ + tn->overlapped = this->overlapped; + jffs2_kill_tn(c, this); + dbg_readinode("Like new node. Throw away old\n"); + return 0; + } + } + if (this->version < tn->version && + this->fn->ofs >= tn->fn->ofs && + this->fn->ofs + this->fn->size <= fn_end) { + /* New node entirely overlaps 'this' */ + if (check_tn_node(c, tn)) { + dbg_readinode("new node bad CRC\n"); + jffs2_kill_tn(c, tn); + return 0; + } + /* ... and is good. Kill 'this'... */ + rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); + tn->overlapped = this->overlapped; + jffs2_kill_tn(c, this); + /* ... and any subsequent nodes which are also overlapped */ + this = tn_next(tn); + while (this && this->fn->ofs + this->fn->size < fn_end) { + struct jffs2_tmp_dnode_info *next = tn_next(this); + if (this->version < tn->version) { + tn_erase(this, &rii->tn_root); + dbg_readinode("Kill overlapped ver %d, 0x%x-0x%x\n", + this->version, this->fn->ofs, + this->fn->ofs+this->fn->size); + jffs2_kill_tn(c, this); + } + this = next; + } + dbg_readinode("Done inserting new\n"); + return 0; + } + if (this->version > tn->version && + this->fn->ofs <= tn->fn->ofs && + this->fn->ofs+this->fn->size >= fn_end) { + /* New node entirely overlapped by 'this' */ + if (!check_tn_node(c, this)) { + dbg_readinode("Good CRC on old node. Kill new\n"); + jffs2_kill_tn(c, tn); + return 0; + } + /* ... but 'this' was bad. Replace it... */ + rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); + dbg_readinode("Bad CRC on old overlapping node. Kill it\n"); + jffs2_kill_tn(c, this); + return 0; + } + /* We want to be inserted under the last node which is + either at a lower offset _or_ has a smaller range */ + if (this->fn->ofs < tn->fn->ofs || + (this->fn->ofs == tn->fn->ofs && + this->fn->size <= tn->fn->size)) + insert_point = this; + + this = tn_next(this); + } + dbg_readinode("insert_point %p, ver %d, 0x%x-0x%x, ov %d\n", + insert_point, insert_point->version, insert_point->fn->ofs, + insert_point->fn->ofs+insert_point->fn->size, + insert_point->overlapped); + /* We neither completely obsoleted nor were completely + obsoleted by an earlier node. Insert under insert_point */ + { + struct rb_node *parent = &insert_point->rb; + struct rb_node **link = &parent; + + while (*link) { + parent = *link; + insert_point = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); + if (tn->fn->ofs > insert_point->fn->ofs) + link = &insert_point->rb.rb_right; + else if (tn->fn->ofs < insert_point->fn->ofs || + tn->fn->size < insert_point->fn->size) + link = &insert_point->rb.rb_left; + else + link = &insert_point->rb.rb_right; + } + rb_link_node(&tn->rb, &insert_point->rb, link); + rb_insert_color(&tn->rb, &rii->tn_root); + } + /* If there's anything behind that overlaps us, note it */ + this = tn_prev(tn); + if (this) { + while (1) { + if (this->fn->ofs + this->fn->size > tn->fn->ofs) { + dbg_readinode("Node is overlapped by %p (v %d, 0x%x-0x%x)\n", + this, this->version, this->fn->ofs, + this->fn->ofs+this->fn->size); + tn->overlapped = 1; + break; + } + if (!this->overlapped) + break; + this = tn_prev(this); + } + } + + /* If the new node overlaps anything ahead, note it */ + this = tn_next(tn); + while (this && this->fn->ofs < fn_end) { + this->overlapped = 1; + dbg_readinode("Node ver %d, 0x%x-0x%x is overlapped\n", + this->version, this->fn->ofs, + this->fn->ofs+this->fn->size); + this = tn_next(this); + } + return 0; +} + +/* Trivial function to remove the last node in the tree. Which by definition + has no right-hand -- so can be removed just by making its only child (if + any) take its place under its parent. */ +static void eat_last(struct rb_root *root, struct rb_node *node) +{ + struct rb_node *parent = rb_parent(node); + struct rb_node **link; + + /* LAST! */ + BUG_ON(node->rb_right); + + if (!parent) + link = &root->rb_node; + else if (node == parent->rb_left) + link = &parent->rb_left; + else + link = &parent->rb_right; + + *link = node->rb_left; + /* Colour doesn't matter now. Only the parent pointer. */ + if (node->rb_left) + node->rb_left->rb_parent_color = node->rb_parent_color; +} + +/* We put this in reverse order, so we can just use eat_last */ +static void ver_insert(struct rb_root *ver_root, struct jffs2_tmp_dnode_info *tn) +{ + struct rb_node **link = &ver_root->rb_node; + struct rb_node *parent = NULL; + struct jffs2_tmp_dnode_info *this_tn; + + while (*link) { + parent = *link; + this_tn = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); + + if (tn->version > this_tn->version) + link = &parent->rb_left; + else + link = &parent->rb_right; + } + dbg_readinode("Link new node at %p (root is %p)\n", link, ver_root); + rb_link_node(&tn->rb, parent, link); + rb_insert_color(&tn->rb, ver_root); +} + +/* Build final, normal fragtree from tn tree. It doesn't matter which order + we add nodes to the real fragtree, as long as they don't overlap. And + having thrown away the majority of overlapped nodes as we went, there + really shouldn't be many sets of nodes which do overlap. If we start at + the end, we can use the overlap markers -- we can just eat nodes which + aren't overlapped, and when we encounter nodes which _do_ overlap we + sort them all into a temporary tree in version order before replaying them. */ +static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c, + struct jffs2_inode_info *f, + struct jffs2_readinode_info *rii) +{ + struct jffs2_tmp_dnode_info *pen, *last, *this; + struct rb_root ver_root = RB_ROOT; + uint32_t high_ver = 0; + + if (rii->mdata_tn) { + dbg_readinode("potential mdata is ver %d at %p\n", rii->mdata_tn->version, rii->mdata_tn); + high_ver = rii->mdata_tn->version; + rii->latest_ref = rii->mdata_tn->fn->raw; + } +#ifdef JFFS2_DBG_READINODE_MESSAGES + this = tn_last(&rii->tn_root); + while (this) { + dbg_readinode("tn %p ver %d range 0x%x-0x%x ov %d\n", this, this->version, this->fn->ofs, + this->fn->ofs+this->fn->size, this->overlapped); + this = tn_prev(this); + } +#endif + pen = tn_last(&rii->tn_root); + while ((last = pen)) { + pen = tn_prev(last); + + eat_last(&rii->tn_root, &last->rb); + ver_insert(&ver_root, last); + + if (unlikely(last->overlapped)) + continue; + + /* Now we have a bunch of nodes in reverse version + order, in the tree at ver_root. Most of the time, + there'll actually be only one node in the 'tree', + in fact. */ + this = tn_last(&ver_root); + + while (this) { + struct jffs2_tmp_dnode_info *vers_next; + int ret; + vers_next = tn_prev(this); + eat_last(&ver_root, &this->rb); + if (check_tn_node(c, this)) { + dbg_readinode("node ver %x, 0x%x-0x%x failed CRC\n", + this->version, this->fn->ofs, + this->fn->ofs+this->fn->size); + jffs2_kill_tn(c, this); + } else { + if (this->version > high_ver) { + /* Note that this is different from the other + highest_version, because this one is only + counting _valid_ nodes which could give the + latest inode metadata */ + high_ver = this->version; + rii->latest_ref = this->fn->raw; + } + dbg_readinode("Add %p (v %x, 0x%x-0x%x, ov %d) to fragtree\n", + this, this->version, this->fn->ofs, + this->fn->ofs+this->fn->size, this->overlapped); + + ret = jffs2_add_full_dnode_to_inode(c, f, this->fn); + if (ret) { + /* Free the nodes in vers_root; let the caller + deal with the rest */ + JFFS2_ERROR("Add node to tree failed %d\n", ret); + while (1) { + vers_next = tn_prev(this); + if (check_tn_node(c, this)) + jffs2_mark_node_obsolete(c, this->fn->raw); + jffs2_free_full_dnode(this->fn); + jffs2_free_tmp_dnode_info(this); + this = vers_next; + if (!this) + break; + eat_last(&ver_root, &vers_next->rb); + } + return ret; + } + jffs2_free_tmp_dnode_info(this); + } + this = vers_next; + } + } + return 0; } static void jffs2_free_tmp_dnode_info_list(struct rb_root *list) @@ -112,8 +592,8 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r * negative error code on failure. */ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, - struct jffs2_raw_dirent *rd, size_t read, struct jffs2_full_dirent **fdp, - uint32_t *latest_mctime, uint32_t *mctime_ver) + struct jffs2_raw_dirent *rd, size_t read, + struct jffs2_readinode_info *rii) { struct jffs2_full_dirent *fd; uint32_t crc; @@ -125,7 +605,8 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r if (unlikely(crc != je32_to_cpu(rd->node_crc))) { JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n", ref_offset(ref), je32_to_cpu(rd->node_crc), crc); - return 1; + jffs2_mark_node_obsolete(c, ref); + return 0; } /* If we've never checked the CRCs on this node, check them now */ @@ -137,7 +618,8 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); - return 1; + jffs2_mark_node_obsolete(c, ref); + return 0; } jeb = &c->blocks[ref->flash_offset / c->sector_size]; @@ -161,10 +643,13 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r fd->ino = je32_to_cpu(rd->ino); fd->type = rd->type; + if (fd->version > rii->highest_version) + rii->highest_version = fd->version; + /* Pick out the mctime of the latest dirent */ - if(fd->version > *mctime_ver && je32_to_cpu(rd->mctime)) { - *mctime_ver = fd->version; - *latest_mctime = je32_to_cpu(rd->mctime); + if(fd->version > rii->mctime_ver && je32_to_cpu(rd->mctime)) { + rii->mctime_ver = fd->version; + rii->latest_mctime = je32_to_cpu(rd->mctime); } /* @@ -201,7 +686,7 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r * Wheee. We now have a complete jffs2_full_dirent structure, with * the name in it and everything. Link it into the list */ - jffs2_add_fd_to_list(c, fd, fdp); + jffs2_add_fd_to_list(c, fd, &rii->fds); return 0; } @@ -210,13 +695,13 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r * Helper function for jffs2_get_inode_nodes(). * It is called every time an inode node is found. * - * Returns: 0 on succes; + * Returns: 0 on success; * 1 if the node should be marked obsolete; * negative error code on failure. */ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, - struct jffs2_raw_inode *rd, struct rb_root *tnp, int rdlen, - uint32_t *latest_mctime, uint32_t *mctime_ver) + struct jffs2_raw_inode *rd, int rdlen, + struct jffs2_readinode_info *rii) { struct jffs2_tmp_dnode_info *tn; uint32_t len, csize; @@ -230,7 +715,8 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref if (unlikely(crc != je32_to_cpu(rd->node_crc))) { JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n", ref_offset(ref), je32_to_cpu(rd->node_crc), crc); - return 1; + jffs2_mark_node_obsolete(c, ref); + return 0; } tn = jffs2_alloc_tmp_dnode_info(); @@ -342,6 +828,10 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref tn->data_crc = je32_to_cpu(rd->data_crc); tn->csize = csize; tn->fn->raw = ref; + tn->overlapped = 0; + + if (tn->version > rii->highest_version) + rii->highest_version = tn->version; /* There was a bug where we wrote hole nodes out with csize/dsize swapped. Deal with it */ @@ -353,13 +843,25 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize); - jffs2_add_tn_to_tree(tn, tnp); + ret = jffs2_add_tn_to_tree(c, rii, tn); + if (ret) { + jffs2_free_full_dnode(tn->fn); + free_out: + jffs2_free_tmp_dnode_info(tn); + return ret; + } +#ifdef JFFS2_DBG_READINODE_MESSAGES + dbg_readinode("After adding ver %d:\n", tn->version); + tn = tn_first(&rii->tn_root); + while (tn) { + dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n", + tn, tn->version, tn->fn->ofs, + tn->fn->ofs+tn->fn->size, tn->overlapped); + tn = tn_next(tn); + } +#endif return 0; - -free_out: - jffs2_free_tmp_dnode_info(tn); - return ret; } /* @@ -379,7 +881,8 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n", je16_to_cpu(un->magic), je16_to_cpu(un->nodetype), je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc)); - return 1; + jffs2_mark_node_obsolete(c, ref); + return 0; } un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); @@ -407,7 +910,8 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re case JFFS2_FEATURE_RWCOMPAT_DELETE: JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", je16_to_cpu(un->nodetype), ref_offset(ref)); - return 1; + jffs2_mark_node_obsolete(c, ref); + return 0; } return 0; @@ -457,21 +961,20 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, } /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated - with this ino, returning the former in order of version */ + with this ino. Perform a preliminary ordering on data nodes, throwing away + those which are completely obsoleted by newer ones. The naïve approach we + use to take of just returning them _all_ in version order will cause us to + run out of memory in certain degenerate cases. */ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - struct rb_root *tnp, struct jffs2_full_dirent **fdp, - uint32_t *highest_version, uint32_t *latest_mctime, - uint32_t *mctime_ver) + struct jffs2_readinode_info *rii) { struct jffs2_raw_node_ref *ref, *valid_ref; - struct rb_root ret_tn = RB_ROOT; - struct jffs2_full_dirent *ret_fd = NULL; unsigned char *buf = NULL; union jffs2_node_union *node; size_t retlen; int len, err; - *mctime_ver = 0; + rii->mctime_ver = 0; dbg_readinode("ino #%u\n", f->inocache->ino); @@ -569,16 +1072,10 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf goto free_out; } - err = read_direntry(c, ref, &node->d, retlen, &ret_fd, latest_mctime, mctime_ver); - if (err == 1) { - jffs2_mark_node_obsolete(c, ref); - break; - } else if (unlikely(err)) + err = read_direntry(c, ref, &node->d, retlen, rii); + if (unlikely(err)) goto free_out; - if (je32_to_cpu(node->d.version) > *highest_version) - *highest_version = je32_to_cpu(node->d.version); - break; case JFFS2_NODETYPE_INODE: @@ -589,16 +1086,10 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf goto free_out; } - err = read_dnode(c, ref, &node->i, &ret_tn, len, latest_mctime, mctime_ver); - if (err == 1) { - jffs2_mark_node_obsolete(c, ref); - break; - } else if (unlikely(err)) + err = read_dnode(c, ref, &node->i, len, rii); + if (unlikely(err)) goto free_out; - if (je32_to_cpu(node->i.version) > *highest_version) - *highest_version = je32_to_cpu(node->i.version); - break; default: @@ -621,17 +1112,19 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf } spin_unlock(&c->erase_completion_lock); - *tnp = ret_tn; - *fdp = ret_fd; kfree(buf); + f->highest_version = rii->highest_version; + dbg_readinode("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n", - f->inocache->ino, *highest_version, *latest_mctime, *mctime_ver); + f->inocache->ino, rii->highest_version, rii->latest_mctime, + rii->mctime_ver); return 0; free_out: - jffs2_free_tmp_dnode_info_list(&ret_tn); - jffs2_free_full_dirent_list(ret_fd); + jffs2_free_tmp_dnode_info_list(&rii->tn_root); + jffs2_free_full_dirent_list(rii->fds); + rii->fds = NULL; kfree(buf); return err; } @@ -640,20 +1133,17 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *latest_node) { - struct jffs2_tmp_dnode_info *tn; - struct rb_root tn_list; - struct rb_node *rb, *repl_rb; - struct jffs2_full_dirent *fd_list; - struct jffs2_full_dnode *fn, *first_fn = NULL; + struct jffs2_readinode_info rii; uint32_t crc; - uint32_t latest_mctime, mctime_ver; size_t retlen; int ret; dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink); + memset(&rii, 0, sizeof(rii)); + /* Grab all nodes relevant to this ino */ - ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); + ret = jffs2_get_inode_nodes(c, f, &rii); if (ret) { JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret); @@ -661,74 +1151,42 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); return ret; } - f->dents = fd_list; - - rb = rb_first(&tn_list); - while (rb) { - cond_resched(); - tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb); - fn = tn->fn; - ret = 1; - dbg_readinode("consider node ver %u, phys offset " - "%#08x(%d), range %u-%u.\n", tn->version, - ref_offset(fn->raw), ref_flags(fn->raw), - fn->ofs, fn->ofs + fn->size); - - if (fn->size) { - ret = jffs2_add_older_frag_to_fragtree(c, f, tn); - /* TODO: the error code isn't checked, check it */ - jffs2_dbg_fragtree_paranoia_check_nolock(f); - BUG_ON(ret < 0); - if (!first_fn && ret == 0) - first_fn = fn; - } else if (!first_fn) { - first_fn = fn; - f->metadata = fn; - ret = 0; /* Prevent freeing the metadata update node */ - } else - jffs2_mark_node_obsolete(c, fn->raw); - - BUG_ON(rb->rb_left); - if (rb_parent(rb) && rb_parent(rb)->rb_left == rb) { - /* We were then left-hand child of our parent. We need - * to move our own right-hand child into our place. */ - repl_rb = rb->rb_right; - if (repl_rb) - rb_set_parent(repl_rb, rb_parent(rb)); - } else - repl_rb = NULL; - - rb = rb_next(rb); - - /* Remove the spent tn from the tree; don't bother rebalancing - * but put our right-hand child in our own place. */ - if (rb_parent(&tn->rb)) { - if (rb_parent(&tn->rb)->rb_left == &tn->rb) - rb_parent(&tn->rb)->rb_left = repl_rb; - else if (rb_parent(&tn->rb)->rb_right == &tn->rb) - rb_parent(&tn->rb)->rb_right = repl_rb; - else BUG(); - } else if (tn->rb.rb_right) - rb_set_parent(tn->rb.rb_right, NULL); + ret = jffs2_build_inode_fragtree(c, f, &rii); + if (ret) { + JFFS2_ERROR("Failed to build final fragtree for inode #%u: error %d\n", + f->inocache->ino, ret); + if (f->inocache->state == INO_STATE_READING) + jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); + jffs2_free_tmp_dnode_info_list(&rii.tn_root); + /* FIXME: We could at least crc-check them all */ + if (rii.mdata_tn) { + jffs2_free_full_dnode(rii.mdata_tn->fn); + jffs2_free_tmp_dnode_info(rii.mdata_tn); + rii.mdata_tn = NULL; + } + return ret; + } - jffs2_free_tmp_dnode_info(tn); - if (ret) { - dbg_readinode("delete dnode %u-%u.\n", - fn->ofs, fn->ofs + fn->size); - jffs2_free_full_dnode(fn); + if (rii.mdata_tn) { + if (rii.mdata_tn->fn->raw == rii.latest_ref) { + f->metadata = rii.mdata_tn->fn; + jffs2_free_tmp_dnode_info(rii.mdata_tn); + } else { + jffs2_kill_tn(c, rii.mdata_tn); } + rii.mdata_tn = NULL; } - jffs2_dbg_fragtree_paranoia_check_nolock(f); - BUG_ON(first_fn && ref_obsolete(first_fn->raw)); + f->dents = rii.fds; + + jffs2_dbg_fragtree_paranoia_check_nolock(f); - fn = first_fn; - if (unlikely(!first_fn)) { + if (unlikely(!rii.latest_ref)) { /* No data nodes for this inode. */ if (f->inocache->ino != 1) { JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino); - if (!fd_list) { + if (!rii.fds) { if (f->inocache->state == INO_STATE_READING) jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); return -EIO; @@ -746,7 +1204,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, return 0; } - ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node); + ret = jffs2_flash_read(c, ref_offset(rii.latest_ref), sizeof(*latest_node), &retlen, (void *)latest_node); if (ret || retlen != sizeof(*latest_node)) { JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n", ret, retlen, sizeof(*latest_node)); @@ -759,7 +1217,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, crc = crc32(0, latest_node, sizeof(*latest_node)-8); if (crc != je32_to_cpu(latest_node->node_crc)) { JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n", - f->inocache->ino, ref_offset(fn->raw)); + f->inocache->ino, ref_offset(rii.latest_ref)); up(&f->sem); jffs2_do_clear_inode(c, f); return -EIO; @@ -767,10 +1225,10 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, switch(jemode_to_cpu(latest_node->mode) & S_IFMT) { case S_IFDIR: - if (mctime_ver > je32_to_cpu(latest_node->version)) { + if (rii.mctime_ver > je32_to_cpu(latest_node->version)) { /* The times in the latest_node are actually older than mctime in the latest dirent. Cheat. */ - latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime); + latest_node->ctime = latest_node->mtime = cpu_to_je32(rii.latest_mctime); } break; @@ -800,7 +1258,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, return -ENOMEM; } - ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node), + ret = jffs2_flash_read(c, ref_offset(rii.latest_ref) + sizeof(*latest_node), je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); if (ret || retlen != je32_to_cpu(latest_node->csize)) { -- cgit v1.2.2 From 0dec4c8bc6ed62a65b61594aa754e21270423796 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Sat, 10 Mar 2007 17:08:44 +0100 Subject: [JFFS2] Better fix for all-zero node headers No need to check for all-zero header since the header cannot be zero due to other checks. Replace the all-zero header check in readinode.c with a check for the magic word. Signed-off-by: Joakim Tjernlund Signed-off-by: David Woodhouse --- fs/jffs2/readinode.c | 8 ++++---- fs/jffs2/scan.c | 12 +----------- 2 files changed, 5 insertions(+), 15 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 49d4b0a67c55..b09fa23abe53 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -1054,10 +1054,10 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf jffs2_mark_node_obsolete(c, ref); goto cont; } - /* Due to poor choice of crc32 seed, an all-zero node will have a correct CRC */ - if (!je32_to_cpu(node->u.hdr_crc) && !je16_to_cpu(node->u.nodetype) && - !je16_to_cpu(node->u.magic) && !je32_to_cpu(node->u.totlen)) { - JFFS2_NOTICE("All zero node header at %#08x.\n", ref_offset(ref)); + if (je16_to_cpu(node->u.magic) != JFFS2_MAGIC_BITMASK) { + /* Not a JFFS2 node, whinge and move on */ + JFFS2_NOTICE("Wrong magic bitmask 0x%04x in node header at %#08x.\n", + je16_to_cpu(node->u.magic), ref_offset(ref)); jffs2_mark_node_obsolete(c, ref); goto cont; } diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 7a46a436edfc..858e3ed8e23d 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -741,18 +741,8 @@ scan_more: ofs += 4; continue; } - /* Due to poor choice of crc32 seed, an all-zero node will have a correct CRC */ - if (!je32_to_cpu(node->hdr_crc) && !je16_to_cpu(node->nodetype) && - !je16_to_cpu(node->magic) && !je32_to_cpu(node->totlen)) { - noisy_printk(&noise, "jffs2_scan_eraseblock(): All zero node header at 0x%08x.\n", ofs); - if ((err = jffs2_scan_dirty_space(c, jeb, 4))) - return err; - ofs += 4; - continue; - } - if (ofs + je32_to_cpu(node->totlen) > - jeb->offset + c->sector_size) { + if (ofs + je32_to_cpu(node->totlen) > jeb->offset + c->sector_size) { /* Eep. Node goes over the end of the erase block. */ printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n", ofs, je32_to_cpu(node->totlen)); -- cgit v1.2.2 From c00c310eac04a28d2143368ae988716792ed53ce Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 25 Apr 2007 14:16:47 +0100 Subject: [JFFS2] Tidy up licensing/copyright boilerplate. In particular, remove the bit in the LICENCE file about contacting Red Hat for alternative arrangements. Their errant IS department broke that arrangement a long time ago -- the policy of collecting copyright assignments from contributors came to an end when the plug was pulled on the servers hosting the project, without notice or reason. We do still dual-license it for use with eCos, with the GPL+exception licence approved by the FSF as being GPL-compatible. It's just that nobody has the right to license it differently. Signed-off-by: David Woodhouse --- fs/jffs2/LICENCE | 7 +---- fs/jffs2/Makefile | 1 - fs/jffs2/README.Locking | 1 - fs/jffs2/TODO | 3 -- fs/jffs2/acl.c | 3 +- fs/jffs2/acl.h | 3 +- fs/jffs2/background.c | 4 +-- fs/jffs2/build.c | 4 +-- fs/jffs2/compr.c | 6 ++-- fs/jffs2/compr.h | 7 ++--- fs/jffs2/compr_rtime.c | 3 +- fs/jffs2/compr_rubin.c | 82 +++++++++++++++++++++++++++++++++++++++++++++--- fs/jffs2/compr_rubin.h | 21 ------------- fs/jffs2/compr_zlib.c | 4 +-- fs/jffs2/debug.c | 5 ++- fs/jffs2/debug.h | 5 ++- fs/jffs2/dir.c | 4 +-- fs/jffs2/erase.c | 4 +-- fs/jffs2/file.c | 4 +-- fs/jffs2/fs.c | 4 +-- fs/jffs2/gc.c | 4 +-- fs/jffs2/ioctl.c | 4 +-- fs/jffs2/jffs2_fs_i.h | 11 ++++++- fs/jffs2/jffs2_fs_sb.h | 11 ++++++- fs/jffs2/malloc.c | 4 +-- fs/jffs2/nodelist.c | 4 +-- fs/jffs2/nodelist.h | 4 +-- fs/jffs2/nodemgmt.c | 4 +-- fs/jffs2/os-linux.h | 4 +-- fs/jffs2/pushpull.h | 72 ------------------------------------------ fs/jffs2/read.c | 4 +-- fs/jffs2/readinode.c | 4 +-- fs/jffs2/scan.c | 5 ++- fs/jffs2/security.c | 3 +- fs/jffs2/summary.c | 12 +++---- fs/jffs2/summary.h | 10 +++--- fs/jffs2/super.c | 6 ++-- fs/jffs2/symlink.c | 5 +-- fs/jffs2/wbuf.c | 6 ++-- fs/jffs2/write.c | 4 +-- fs/jffs2/writev.c | 4 +-- fs/jffs2/xattr.c | 3 +- fs/jffs2/xattr.h | 3 +- fs/jffs2/xattr_trusted.c | 3 +- fs/jffs2/xattr_user.c | 3 +- 45 files changed, 155 insertions(+), 217 deletions(-) delete mode 100644 fs/jffs2/compr_rubin.h delete mode 100644 fs/jffs2/pushpull.h (limited to 'fs') diff --git a/fs/jffs2/LICENCE b/fs/jffs2/LICENCE index cd81d83e4ad2..562885908135 100644 --- a/fs/jffs2/LICENCE +++ b/fs/jffs2/LICENCE @@ -1,7 +1,7 @@ The files in this directory and elsewhere which refer to this LICENCE file are part of JFFS2, the Journalling Flash File System v2. - Copyright (C) 2001, 2002 Red Hat, Inc. + Copyright © 2001-2007 Red Hat, Inc. and others JFFS2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -28,8 +28,3 @@ of the GNU General Public License. This exception does not invalidate any other reasons why a work based on this file might be covered by the GNU General Public License. -For information on obtaining alternative licences for JFFS2, see -http://sources.redhat.com/jffs2/jffs2-licence.html - - - $Id: LICENCE,v 1.1 2002/05/20 14:56:37 dwmw2 Exp $ diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile index 7f28ee0bd132..c32b241e3d91 100644 --- a/fs/jffs2/Makefile +++ b/fs/jffs2/Makefile @@ -1,7 +1,6 @@ # # Makefile for the Linux Journalling Flash File System v2 (JFFS2) # -# $Id: Makefile.common,v 1.11 2005/09/07 08:34:53 havasi Exp $ # obj-$(CONFIG_JFFS2_FS) += jffs2.o diff --git a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking index c8f0bd64e53e..d14d5a4dc5ac 100644 --- a/fs/jffs2/README.Locking +++ b/fs/jffs2/README.Locking @@ -1,4 +1,3 @@ - $Id: README.Locking,v 1.12 2005/04/13 13:22:35 dwmw2 Exp $ JFFS2 LOCKING DOCUMENTATION --------------------------- diff --git a/fs/jffs2/TODO b/fs/jffs2/TODO index d0e23b26fa50..5d3ea4070f01 100644 --- a/fs/jffs2/TODO +++ b/fs/jffs2/TODO @@ -1,4 +1,3 @@ -$Id: TODO,v 1.18 2005/09/22 11:24:56 dedekind Exp $ - support asynchronous operation -- add a per-fs 'reserved_space' count, let each outstanding write reserve the _maximum_ amount of physical @@ -30,8 +29,6 @@ $Id: TODO,v 1.18 2005/09/22 11:24:56 dedekind Exp $ the full dirent, we only need to go to the flash in lookup() when we think we've got a match, and in readdir(). - Doubly-linked next_in_ino list to allow us to free obsoleted raw_node_refs immediately? - - Remove totlen from jffs2_raw_node_ref? Need to have totlen passed into - jffs2_mark_node_obsolete(). Can all callers work it out? - Remove size from jffs2_raw_node_frag. dedekind: diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index 73f0d60f73a5..a46101ee867a 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c @@ -1,13 +1,14 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2006 NEC Corporation + * Copyright © 2006 NEC Corporation * * Created by KaiGai Kohei * * For licensing information, see the file 'LICENCE' in this directory. * */ + #include #include #include diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h index fa327dbd3171..c84378cee82a 100644 --- a/fs/jffs2/acl.h +++ b/fs/jffs2/acl.h @@ -1,13 +1,14 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2006 NEC Corporation + * Copyright © 2006 NEC Corporation * * Created by KaiGai Kohei * * For licensing information, see the file 'LICENCE' in this directory. * */ + struct jffs2_acl_entry { jint16_t e_tag; jint16_t e_perm; diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index 888f236e5494..0c82dfcfd246 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: background.c,v 1.54 2005/05/20 21:37:12 gleixner Exp $ - * */ #include diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index 07119c42a861..0ca2fff2617f 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.85 2005/11/07 11:14:38 gleixner Exp $ - * */ #include diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c index 647cb15d5499..485d065de41f 100644 --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c @@ -1,16 +1,14 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * Created by Arjan van de Ven * - * Copyright (C) 2004 Ferenc Havasi , + * Copyright © 2004 Ferenc Havasi , * University of Szeged, Hungary * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr.c,v 1.46 2005/11/07 11:14:38 gleixner Exp $ - * */ #include "compr.h" diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h index aee2de0ca69b..68cc7010dbdf 100644 --- a/fs/jffs2/compr.h +++ b/fs/jffs2/compr.h @@ -1,13 +1,10 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2004 Ferenc Havasi , + * Copyright © 2004 Ferenc Havasi , * University of Szeged, Hungary * - * For licensing information, see the file 'LICENCE' in the - * jffs2 directory. - * - * $Id: compr.h,v 1.9 2005/11/07 11:14:38 gleixner Exp $ + * For licensing information, see the file 'LICENCE' in this directory. * */ diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c index 2eb1b7428d16..0d0bfd2e4e0d 100644 --- a/fs/jffs2/compr_rtime.c +++ b/fs/jffs2/compr_rtime.c @@ -1,13 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by Arjan van de Ven * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr_rtime.c,v 1.14 2004/06/23 16:34:40 havasi Exp $ * * * Very simple lz77-ish encoder. diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c index e792e675d624..1f3a4410523b 100644 --- a/fs/jffs2/compr_rubin.c +++ b/fs/jffs2/compr_rubin.c @@ -1,23 +1,95 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001, 2002 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by Arjan van de Ven * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr_rubin.c,v 1.20 2004/06/23 16:34:40 havasi Exp $ - * */ #include #include #include -#include "compr_rubin.h" -#include "histo_mips.h" +#include #include "compr.h" + +#define RUBIN_REG_SIZE 16 +#define UPPER_BIT_RUBIN (((long) 1)<<(RUBIN_REG_SIZE-1)) +#define LOWER_BITS_RUBIN ((((long) 1)<<(RUBIN_REG_SIZE-1))-1) + + +struct rubin_state { + unsigned long p; + unsigned long q; + unsigned long rec_q; + long bit_number; + struct pushpull pp; + int bit_divider; + int bits[8]; +}; + +#define BIT_DIVIDER_MIPS 1043 +static int bits_mips[8] = { 277,249,290,267,229,341,212,241}; /* mips32 */ + +#include + +struct pushpull { + unsigned char *buf; + unsigned int buflen; + unsigned int ofs; + unsigned int reserve; +}; + + +static inline void init_pushpull(struct pushpull *pp, char *buf, unsigned buflen, unsigned ofs, unsigned reserve) +{ + pp->buf = buf; + pp->buflen = buflen; + pp->ofs = ofs; + pp->reserve = reserve; +} + +static inline int pushbit(struct pushpull *pp, int bit, int use_reserved) +{ + if (pp->ofs >= pp->buflen - (use_reserved?0:pp->reserve)) { + return -ENOSPC; + } + + if (bit) { + pp->buf[pp->ofs >> 3] |= (1<<(7-(pp->ofs &7))); + } + else { + pp->buf[pp->ofs >> 3] &= ~(1<<(7-(pp->ofs &7))); + } + pp->ofs++; + + return 0; +} + +static inline int pushedbits(struct pushpull *pp) +{ + return pp->ofs; +} + +static inline int pullbit(struct pushpull *pp) +{ + int bit; + + bit = (pp->buf[pp->ofs >> 3] >> (7-(pp->ofs & 7))) & 1; + + pp->ofs++; + return bit; +} + +static inline int pulledbits(struct pushpull *pp) +{ + return pp->ofs; +} + + static void init_rubin(struct rubin_state *rs, int div, int *bits) { int c; diff --git a/fs/jffs2/compr_rubin.h b/fs/jffs2/compr_rubin.h deleted file mode 100644 index bf1a93451621..000000000000 --- a/fs/jffs2/compr_rubin.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Rubin encoder/decoder header */ -/* work started at : aug 3, 1994 */ -/* last modification : aug 15, 1994 */ -/* $Id: compr_rubin.h,v 1.7 2005/11/07 11:14:38 gleixner Exp $ */ - -#include "pushpull.h" - -#define RUBIN_REG_SIZE 16 -#define UPPER_BIT_RUBIN (((long) 1)<<(RUBIN_REG_SIZE-1)) -#define LOWER_BITS_RUBIN ((((long) 1)<<(RUBIN_REG_SIZE-1))-1) - - -struct rubin_state { - unsigned long p; - unsigned long q; - unsigned long rec_q; - long bit_number; - struct pushpull pp; - int bit_divider; - int bits[8]; -}; diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c index 0c1fc6e20b43..2b87fccc1557 100644 --- a/fs/jffs2/compr_zlib.c +++ b/fs/jffs2/compr_zlib.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr_zlib.c,v 1.32 2005/11/07 11:14:38 gleixner Exp $ - * */ #if !defined(__KERNEL__) && !defined(__ECOS) diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c index 4189e4a36050..3a32c64ed497 100644 --- a/fs/jffs2/debug.c +++ b/fs/jffs2/debug.c @@ -1,15 +1,14 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.c,v 1.12 2005/11/07 11:14:39 gleixner Exp $ - * */ + #include #include #include diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index f89c85d5a3f8..2a49f2c51a9f 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -1,15 +1,14 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.21 2005/11/07 11:14:39 gleixner Exp $ - * */ + #ifndef _JFFS2_DEBUG_H_ #define _JFFS2_DEBUG_H_ diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 9fa2e27f0641..c1dfca310dd6 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: dir.c,v 1.90 2005/11/07 11:14:39 gleixner Exp $ - * */ #include diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index 6b1f7bee3653..66e7c2f1e644 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: erase.c,v 1.85 2005/09/20 14:53:15 dedekind Exp $ - * */ #include diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index e82eeaf7590d..99871279a1ed 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: file.c,v 1.104 2005/10/18 23:29:35 tpoynor Exp $ - * */ #include diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index abb90c0c09cc..23029f42ae8c 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.66 2005/09/27 13:17:29 dedekind Exp $ - * */ #include diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index e92cf0f02529..2d99e06ab223 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: gc.c,v 1.155 2005/11/07 11:14:39 gleixner Exp $ - * */ #include diff --git a/fs/jffs2/ioctl.c b/fs/jffs2/ioctl.c index 69099835de1c..f4d525b0ea53 100644 --- a/fs/jffs2/ioctl.c +++ b/fs/jffs2/ioctl.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: ioctl.c,v 1.10 2005/11/07 11:14:40 gleixner Exp $ - * */ #include diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h index 3a566077ac95..0b78fdc9773b 100644 --- a/fs/jffs2/jffs2_fs_i.h +++ b/fs/jffs2/jffs2_fs_i.h @@ -1,4 +1,13 @@ -/* $Id: jffs2_fs_i.h,v 1.19 2005/11/07 11:14:52 gleixner Exp $ */ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright © 2001-2007 Red Hat, Inc. + * + * Created by David Woodhouse + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ #ifndef _JFFS2_FS_I #define _JFFS2_FS_I diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index ea88f69af130..b13298a824ed 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h @@ -1,4 +1,13 @@ -/* $Id: jffs2_fs_sb.h,v 1.54 2005/09/21 13:37:34 dedekind Exp $ */ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright © 2001-2007 Red Hat, Inc. + * + * Created by David Woodhouse + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ #ifndef _JFFS2_FS_SB #define _JFFS2_FS_SB diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index 83f9881ec4cc..35c1a5e30ba1 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: malloc.c,v 1.31 2005/11/07 11:14:40 gleixner Exp $ - * */ #include diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index fecffbc63552..ac2a4c422e32 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.115 2005/11/07 11:14:40 gleixner Exp $ - * */ #include diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index e5c8f2be8e22..cb34cac5d0f8 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.140 2005/09/07 08:34:54 havasi Exp $ - * */ #ifndef __JFFS2_NODELIST_H__ diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index c8b50dea9e14..dbc908ad622b 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodemgmt.c,v 1.127 2005/09/20 15:49:12 dedekind Exp $ - * */ #include diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index e07a0edcdb4f..2379c7e88735 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2002-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: os-linux.h,v 1.64 2005/09/30 13:59:13 dedekind Exp $ - * */ #ifndef __JFFS2_OS_LINUX_H__ diff --git a/fs/jffs2/pushpull.h b/fs/jffs2/pushpull.h deleted file mode 100644 index c0c2a9158dff..000000000000 --- a/fs/jffs2/pushpull.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * JFFS2 -- Journalling Flash File System, Version 2. - * - * Copyright (C) 2001, 2002 Red Hat, Inc. - * - * Created by David Woodhouse - * - * For licensing information, see the file 'LICENCE' in this directory. - * - * $Id: pushpull.h,v 1.10 2004/11/16 20:36:11 dwmw2 Exp $ - * - */ - -#ifndef __PUSHPULL_H__ -#define __PUSHPULL_H__ - -#include - -struct pushpull { - unsigned char *buf; - unsigned int buflen; - unsigned int ofs; - unsigned int reserve; -}; - - -static inline void init_pushpull(struct pushpull *pp, char *buf, unsigned buflen, unsigned ofs, unsigned reserve) -{ - pp->buf = buf; - pp->buflen = buflen; - pp->ofs = ofs; - pp->reserve = reserve; -} - -static inline int pushbit(struct pushpull *pp, int bit, int use_reserved) -{ - if (pp->ofs >= pp->buflen - (use_reserved?0:pp->reserve)) { - return -ENOSPC; - } - - if (bit) { - pp->buf[pp->ofs >> 3] |= (1<<(7-(pp->ofs &7))); - } - else { - pp->buf[pp->ofs >> 3] &= ~(1<<(7-(pp->ofs &7))); - } - pp->ofs++; - - return 0; -} - -static inline int pushedbits(struct pushpull *pp) -{ - return pp->ofs; -} - -static inline int pullbit(struct pushpull *pp) -{ - int bit; - - bit = (pp->buf[pp->ofs >> 3] >> (7-(pp->ofs & 7))) & 1; - - pp->ofs++; - return bit; -} - -static inline int pulledbits(struct pushpull *pp) -{ - return pp->ofs; -} - -#endif /* __PUSHPULL_H__ */ diff --git a/fs/jffs2/read.c b/fs/jffs2/read.c index f3b86da833ba..cfe05c1966a5 100644 --- a/fs/jffs2/read.c +++ b/fs/jffs2/read.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: read.c,v 1.42 2005/11/07 11:14:41 gleixner Exp $ - * */ #include diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index b09fa23abe53..a42ffba2ed17 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.143 2005/11/07 11:14:41 gleixner Exp $ - * */ #include diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 858e3ed8e23d..2a1c976c7924 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -1,15 +1,14 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: scan.c,v 1.125 2005/09/30 13:59:13 dedekind Exp $ - * */ + #include #include #include diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c index 52a9894a6364..bc9f6ba10823 100644 --- a/fs/jffs2/security.c +++ b/fs/jffs2/security.c @@ -1,13 +1,14 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2006 NEC Corporation + * Copyright © 2006 NEC Corporation * * Created by KaiGai Kohei * * For licensing information, see the file 'LICENCE' in this directory. * */ + #include #include #include diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 30f888414ce7..d828b296392a 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -1,16 +1,14 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2004 Ferenc Havasi , - * Zoltan Sogor , - * Patrik Kluba , - * University of Szeged, Hungary - * 2006 KaiGai Kohei + * Copyright © 2004 Ferenc Havasi , + * Zoltan Sogor , + * Patrik Kluba , + * University of Szeged, Hungary + * 2006 KaiGai Kohei * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: summary.c,v 1.4 2005/09/26 11:37:21 havasi Exp $ - * */ #include diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h index 6bf1f6aa4552..0c6669e21390 100644 --- a/fs/jffs2/summary.h +++ b/fs/jffs2/summary.h @@ -1,15 +1,13 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2004 Ferenc Havasi , - * Zoltan Sogor , - * Patrik Kluba , - * University of Szeged, Hungary + * Copyright © 2004 Ferenc Havasi , + * Zoltan Sogor , + * Patrik Kluba , + * University of Szeged, Hungary * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: summary.h,v 1.2 2005/09/26 11:37:21 havasi Exp $ - * */ #ifndef JFFS2_SUMMARY_H diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index cc7e8e71ad46..e51164a8a8d4 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: super.c,v 1.110 2005/11/07 11:14:42 gleixner Exp $ - * */ #include @@ -347,7 +345,7 @@ static int __init init_jffs2_fs(void) #ifdef CONFIG_JFFS2_SUMMARY " (SUMMARY) " #endif - " (C) 2001-2006 Red Hat, Inc.\n"); + " © 2001-2006 Red Hat, Inc.\n"); jffs2_inode_cachep = kmem_cache_create("jffs2_i", sizeof(struct jffs2_inode_info), diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index 7e4882c8a7ed..b7339c3b6ad9 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c @@ -1,17 +1,14 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001, 2002 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: symlink.c,v 1.19 2005/11/07 11:14:42 gleixner Exp $ - * */ - #include #include #include diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index f87f11af7086..dafcd4102401 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -1,16 +1,14 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. - * Copyright (C) 2004 Thomas Gleixner + * Copyright © 2001-2007 Red Hat, Inc. + * Copyright © 2004 Thomas Gleixner * * Created by David Woodhouse * Modified debugged and enhanced by Thomas Gleixner * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: wbuf.c,v 1.100 2005/09/30 13:59:13 dedekind Exp $ - * */ #include diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 57a79a6ba3d9..c9fe0ab3a329 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001-2003 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: write.c,v 1.97 2005/11/07 11:14:42 gleixner Exp $ - * */ #include diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c index c638ae1008de..b9276b11bac6 100644 --- a/fs/jffs2/writev.c +++ b/fs/jffs2/writev.c @@ -1,14 +1,12 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001, 2002 Red Hat, Inc. + * Copyright © 2001-2007 Red Hat, Inc. * * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: writev.c,v 1.8 2005/09/09 15:11:58 havasi Exp $ - * */ #include diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 4bb3f1897330..78fc08893a6c 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -1,13 +1,14 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2006 NEC Corporation + * Copyright © 2006 NEC Corporation * * Created by KaiGai Kohei * * For licensing information, see the file 'LICENCE' in this directory. * */ + #include #include #include diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h index 06a5c69dcf8b..3b0ff2925937 100644 --- a/fs/jffs2/xattr.h +++ b/fs/jffs2/xattr.h @@ -1,13 +1,14 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2006 NEC Corporation + * Copyright © 2006 NEC Corporation * * Created by KaiGai Kohei * * For licensing information, see the file 'LICENCE' in this directory. * */ + #ifndef _JFFS2_FS_XATTR_H_ #define _JFFS2_FS_XATTR_H_ diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c index ed046e19dbfa..8ec5765ef348 100644 --- a/fs/jffs2/xattr_trusted.c +++ b/fs/jffs2/xattr_trusted.c @@ -1,13 +1,14 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2006 NEC Corporation + * Copyright © 2006 NEC Corporation * * Created by KaiGai Kohei * * For licensing information, see the file 'LICENCE' in this directory. * */ + #include #include #include diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c index 2f8e9aa01ea0..40942bc516bb 100644 --- a/fs/jffs2/xattr_user.c +++ b/fs/jffs2/xattr_user.c @@ -1,13 +1,14 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2006 NEC Corporation + * Copyright © 2006 NEC Corporation * * Created by KaiGai Kohei * * For licensing information, see the file 'LICENCE' in this directory. * */ + #include #include #include -- cgit v1.2.2 From 61c4b23770d1b0cef7c06a23378ab544eb0c64b4 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 25 Apr 2007 17:04:23 +0100 Subject: [JFFS2] Handle inodes with only a single metadata node with non-zero isize This should never happen unless there's corruption on the medium and the actual data nodes go missing. But the failure mode (an oops when we assume the fragtree isn't empty and go looking for its last node) isn't useful. Signed-off-by: David Woodhouse --- fs/jffs2/nodelist.c | 18 ++++++++++++------ fs/jffs2/nodelist.h | 2 +- fs/jffs2/readinode.c | 9 +++++++-- 3 files changed, 20 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index ac2a4c422e32..4bf86088b3ae 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -52,7 +52,7 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new *prev = new; } -void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) +uint32_t jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) { struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); @@ -74,18 +74,24 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint } if (size == 0) - return; + return 0; - /* - * If the last fragment starts at the RAM page boundary, it is - * REF_PRISTINE irrespective of its size. - */ frag = frag_last(list); + + /* Sanity check for truncation to longer than we started with... */ + if (!frag) + return 0; + if (frag->ofs + frag->size < size) + return frag->ofs + frag->size; + + /* If the last fragment starts at the RAM page boundary, it is + * REF_PRISTINE irrespective of its size. */ if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) { dbg_fragtree2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", frag->ofs, frag->ofs + frag->size); frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE; } + return size; } static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index cb34cac5d0f8..25126a062cae 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -362,7 +362,7 @@ struct rb_node *rb_next(struct rb_node *); struct rb_node *rb_prev(struct rb_node *); void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); -void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); +uint32_t jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t ofs, uint32_t len, diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index a42ffba2ed17..6aff38930b50 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -1132,7 +1132,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, struct jffs2_raw_inode *latest_node) { struct jffs2_readinode_info rii; - uint32_t crc; + uint32_t crc, new_size; size_t retlen; int ret; @@ -1233,7 +1233,12 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, case S_IFREG: /* If it was a regular file, truncate it to the latest node's isize */ - jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); + new_size = jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); + if (new_size != je32_to_cpu(latest_node->isize)) { + JFFS2_WARNING("Truncating ino #%u to %d bytes failed because it only had %d bytes to start with!\n", + f->inocache->ino, je32_to_cpu(latest_node->isize), new_size); + latest_node->isize = cpu_to_je32(new_size); + } break; case S_IFLNK: -- cgit v1.2.2 From f6449f4ece2bf283500bda73edcbea82f2cb3a1b Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 26 Apr 2007 07:27:04 +0100 Subject: [JFFS2] Fix compr_rubin.c build after include file elimination. It seems to be silly season lately. (Oops, test builds are more useful if the file in question is actually configured on. dwmw2). Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- fs/jffs2/compr_rubin.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c index 1f3a4410523b..ea0431e047d5 100644 --- a/fs/jffs2/compr_rubin.c +++ b/fs/jffs2/compr_rubin.c @@ -21,16 +21,6 @@ #define LOWER_BITS_RUBIN ((((long) 1)<<(RUBIN_REG_SIZE-1))-1) -struct rubin_state { - unsigned long p; - unsigned long q; - unsigned long rec_q; - long bit_number; - struct pushpull pp; - int bit_divider; - int bits[8]; -}; - #define BIT_DIVIDER_MIPS 1043 static int bits_mips[8] = { 277,249,290,267,229,341,212,241}; /* mips32 */ @@ -43,6 +33,15 @@ struct pushpull { unsigned int reserve; }; +struct rubin_state { + unsigned long p; + unsigned long q; + unsigned long rec_q; + long bit_number; + struct pushpull pp; + int bit_divider; + int bits[8]; +}; static inline void init_pushpull(struct pushpull *pp, char *buf, unsigned buflen, unsigned ofs, unsigned reserve) { -- cgit v1.2.2