diff options
Diffstat (limited to 'patches')
| -rw-r--r-- | patches/DIFFS.TXT | 260 | ||||
| -rw-r--r-- | patches/cvf-uvfat.diff-2.0.33 | 110 | ||||
| -rw-r--r-- | patches/cvf.c | 147 | ||||
| -rw-r--r-- | patches/cvf.c-2.1.128 | 147 | ||||
| -rw-r--r-- | patches/cvf.c.README | 70 | ||||
| -rw-r--r-- | patches/cvf.diff-2.0.33 | 1056 | ||||
| -rw-r--r-- | patches/cvf.diff-2.0.33+fat32-0.2.8 | 1074 | ||||
| -rw-r--r-- | patches/cvf.diff-2.0.34 | 1074 | ||||
| -rw-r--r-- | patches/fat-truncate-bugfix.diff | 13 | ||||
| -rw-r--r-- | patches/fat_cvf.txt | 210 | ||||
| -rw-r--r-- | patches/fat_cvf.txt-2.1.128 | 210 | ||||
| -rw-r--r-- | patches/in-kernel-2.0.35.diff | 62 | ||||
| -rw-r--r-- | patches/linux-2.2.13-dmsdos.patch-1 | 16 | ||||
| -rw-r--r-- | patches/linux-2.3.30-pre6-dmsdos.patch-1 | 284 | ||||
| -rw-r--r-- | patches/magic | 16 | ||||
| -rw-r--r-- | patches/msdos-rmdir-bugfix.diff | 19 | ||||
| -rw-r--r-- | patches/vfat-brelse-bugfix.diff | 15 |
17 files changed, 4783 insertions, 0 deletions
diff --git a/patches/DIFFS.TXT b/patches/DIFFS.TXT new file mode 100644 index 0000000..6ad1e6f --- /dev/null +++ b/patches/DIFFS.TXT @@ -0,0 +1,260 @@ + +The list of CVF-FAT diffs is actually some lines below. + +Some notes about applying patches +--------------------------------- + +This section is for people not familiar with kernel patches. Feel free to +skip it if you are an experienced patch hacker :) + +Well, as always be careful with diffs. Nobody knows whether they always +apply correctly. Praise yourself lucky if you see errors on the screen - +then at least you know that the patch failed. :) + +However, I've seen patches applying without errors, but changing code at +the wrong place, even creating syntactically correct but senseless +and not well working code. (For example, this happens for a small part of +the patches if you use the plain 2.0.33 diff here for a fat32 patched +2.0.33 kernel or a 2.1.76 kernel. Argh. It's almost impossible to find +and repair such an error if you haven't written the code yourself.) + +From the patch manual: + + Patch usually produces the correct results, even when it + has to do a lot of guessing. However, the results are + guaranteed to be correct only when the patch is applied to + exactly the same version of the file that the patch was + generated from. + +So do at least the usual security steps. It's best to get a fresh kernel +from the net (*not* upgrading by patches). But sometimes you need patches. +Ensure: + + A. Before applying a patch: + + 1. Copy your complete kernel sources to another place, and operate + only on this test copy, e.g. + + cp -a /usr/src/linux-x.y.z /usr/src/linux-x.y.z-test + cd /usr/src/linux-x.y.z-test + + 2. Remove all patch related files in the kernel sources, e.g. + + find . -name "*.orig" -exec rm {} \; + find . -name "*.rej" -exec rm {} \; + + B. Apply the patches you need. Order is important. + + 1. Look at the first lines of the diff. There's very likely a complete + path in the filenames. If it begins with "linux..." you need the + option -p1, if it begins with "/usr/src/linux..." you need -p4 or + -p0 (you'll see). If the option is wrong or the number behind -p is + wrong, patch will display a prompt like "file to patch?" and wait + for your answer, which should be CTRL-C in that case :-). Okay: + + patch -p1 < your-favorite-diff + + 2. After applying each patch, watch for reject files, e.g. + + find . -name "*.rej" -print + + If there are any, then the patch failed. You must repair it manually + now or you can give up completely. If you dare to repair it, take + a look at the *.rej files and try to find out what should have been + changed in the sources but couldn't be changed for some reasons. + + Just note, you *cannot* continue if any "*.rej" file is present and + the problem is not fixed manually. You will have messed up kernel + sources that won't work or won't even compile. + + 3. After applying the patch and eventually fixing problems manually + remove all patch related files in the kernel sources, e.g. + + find . -name "*.orig" -exec rm {} \; + find . -name "*.rej" -exec rm {} \; + + 4. Then apply the next patch (if you need), and so on. + + C. Recompile the kernel from scratch. Don't install it yet. Watch for + errors and warnings that were not present before: + + make mrproper (this is not always needed, but if problems arise + without it, try again starting here) + make config (this is also not always needed) + make dep + make clean + make zImage + make modules + + Okay, if everything succeeded, you might want to give it a try. + It's best to use a boot disk for the first test ('make zdisk'), but + if your configuration is highly modular this won't be enough, + so you might not have another choice than doing 'make zlilo' and + 'make modules_install'. + + Be sure to have a rescue boot and root floppy (a simple boot disk is + not always sufficient). I know most people are lazy and ignore this + until "it" happens. I've been lazy too :-) Also be sure to have + your old kernel and your old modules handy (if you only operated on + your test copy of the kernel, as I recommended above, you have them + still somewhere in the original source tree). + + +Good luck and happy hacking. :) + + +---------------------------------------------------------------------------- + +List of CVF-FAT related diffs +----------------------------- + +cvf.diff-2.0.33 + + This is a diff was generated against a cyrix-patched 2.0.33 kernel (I need + cyrix support, so don't ask me to leave it out). This shouldn't matter as + the cyrix patches don't affect filesystem code. So just don't wonder why + the paths in that patch include the name 'cyrix-patched'. Of course, the + diff does not contain the cyrix patches itself :) + + This diff has been tested thoroughly and found to work with a plain 2.0.33 + kernel. + + If you are using the uvfat patches, uvfat will not work correctly on CVFs + (it cannot since some wrappers must be patched in). You must additionally + apply the cvf-uvfat.diff-2.0.33 patch. + + This patch does not work for fat32 support. Try the next one instead :) + This patch also fails for Linux 2.0.34 and newer. Try the next one in this + case. + +cvf.diff-2.0.33+fat32-0.2.8 +cvf.diff-2.0.34 (link to same file) + + This diff was generated against a cyrix-patched and fat32-patched 2.0.33 + kernel. It works also with a 2.0.33 kernel that is only fat32-patched. + The fat32 version used is 0.2.8. + + Please don't misunderstand. This diff does *not* include fat32 support + itself. It only works against a kernel that has already been patched for + fat32 support. + + This patch has also been tested against the new 2.0.34, 2.0.35 and 2.0.36 + kernels and found to work without problems :) + +cvf-uvfat.diff-2.0.33 + + This diff changes the uvfat filesystem so it works properly on CVFs. + Changes are minimal. This diff does not contain the uvfat patches itself. + + What uvfat is? Look: + uvfat : umsdos == vfat : msdos + Search the net for more information. There's a uvfat homepage: + http://lab1.psy.univie.ac.at/~michael/uvfat.html + + This diff must be applied *after* the uvfat patch and *after* the + cvf.diff-2.0.33 patch (or cvf.diff-2.0.33+fat32-0.2.8 - depending on what + you need). Note that the uvfat patches caused a reject file when I tried + (fs/Makefile.rej), so be sure to check. The problem was because there was + autofs added in Linux 2.0.31, and plain uvfat is against kernel 2.0.28. + Just add the text uvfat to the list in Makefile, and it works. As far as + I know, there's no uvfat update for newer (2.1.xx with xx>80) kernels. + + Okay, step by step, this is what I have done, and it worked for me: + + 1. Get linux 2.0.33 sources and unpack. + 2. Patch in linux-2.0.28-uvfat-0.1.diff. + 3. Repair the rejected file fs/Makefile. + 4. Patch in cvf.diff-2.0.33. + 5. Patch in this patch. + +kerneld-autoload.diff + + This diff has been removed because it is obsolete. Use the updated cvf.c + files instead (see file cvf.c.README). + +in-kernel-2.0.35.diff + + This diff can be used to compile dmsdos as a fix part of the kernel. + It hangs dmsdos into some of the kernel initialization files. If you want + to compile dmsdos as a fix part of the kernel, apply this patch, then + create a directory linux/fs/dmsdos, copy the dmsdos sources from src into + that directory, replace the Makefile with 'Makefile.kernel', and create a + link 'dmsdos-config.h' pointing to the generic kernel config include file + 'linux/include/linux/config.h' If you want a working help subsystem just + append the dmsdos Configure.help file to that one in the kernel. All of + that should be done automatically by the script 'in-kernel.sh' so just take + a look at it for details :) The script additionally avoids copying + unnecessary files. + + NOTE: This patch may not work for kernels other than 2.0.35. But changes + are small and easy to understand. I expect that patching the fs/Makefile + fails just in the same way as it fails for the UVFAT patches :) Fix that + by manually adding the word 'dmsdos' to the subdirectory list in that + file. + +msdos-rmdir-bugfix.diff + + This is indeed an excerpt from Alan Cox' pre-2.0.36 patches. It fixes + the msdos rmdir bug that can cause filesystem corruption in a msdos + filesystem (and therefore also in a compressed msdos filesystem). + Affected kernels are 2.0.34 and 2.0.35 and all earlier kernels that have + been patched for FAT32 support version 0.2.8. The bug is fixed in 2.0.36. + + The diff just adds two missing braces to the msdos fs source code ... + + I do not know whether 2.1.xx kernels are affected too. Maybe you take a + look at what where the diff adds the two missing braces and verify that + they are there in your kernel sources :) + + In 2.2.x kernels this bug is not present. + +fat-truncate-bugfix.diff + + There's a design flaw somewhere in the kernel or in the FAT driver (I + really cannot say where) that can write to a disk though the device is + mounted read-only. It is triggered at least by damaged directory entries + on a FAT partition. Such damaged directory entries are a rare condition, + but the dmsdos driver may leave them around when finding another problem + and setting the filesystem to read-only mode. This bug can destroy any + FAT based filesystem that has damaged directory entries. + + The bug is at least present in kernels up to 2.0.36 from the 2.0 series + and in all kernels in the 2.1 series. Also it is in 2.2.x up to 2.2.2. For + newer kernels I don't know. As always with bugfixes: take a look at the + diff and the kernel sources ... :) + + This bug has not yet been fixed in official kernels (kernel 2.2.2). + +vfat-brelse-bugfix.diff + + There is a serious bug in the vfat driver (calls to brelse instead of + fat_brelse) that makes the system corrupt internal filesystem buffer + lists. (The bug bypasses the CVF-FAT interface and also causes problems + with filesystems that use a non-512 byte sector size [very rare condition + today].) It has only been reported to affect 2.2.x kernels, but late 2.1.x + kernels may have this bug too. Check the source code. As of kernel 2.2.2, + it has not yet been fixed in official kernels. + + The bug is not present in 2.0.x kernels. + +linux-2.2.13-dmsdos.patch-1 + + Simple fix to fat_add_cluster1 to return non-NULL pointer to + first buffer-head of newly allocated cluster. + +linux-2.3.30-pre6-dmsdos.patch-1 + + Many changes needed to enable basic DMSDOS functionality + without MMAP support for 2.3.30-pre6 + It contains + - simple fix to fat_extend_dir to return non-NULL + pointer to first buffer-head of newly allocated cluster + - fixes to fat read super - cvf_format must be set before + cvf_mount is called. + - cvf struct type fixes + + +-------------------------------------------------------------------------- + +Well, are there other useful extensions for the fat based filesystems +that should be checked whether they work with CVF-FAT ? Just let me know. diff --git a/patches/cvf-uvfat.diff-2.0.33 b/patches/cvf-uvfat.diff-2.0.33 new file mode 100644 index 0000000..e778111 --- /dev/null +++ b/patches/cvf-uvfat.diff-2.0.33 @@ -0,0 +1,110 @@ +diff -u -r -N linux-2.0.33-cyrix-patched-uvfat/fs/uvfat/emd.c linux-2.0.33-cyrix-patched-uvfat-test/fs/uvfat/emd.c +--- linux-2.0.33-cyrix-patched-uvfat/fs/uvfat/emd.c Sun Jan 4 15:01:56 1998 ++++ linux-2.0.33-cyrix-patched-uvfat-test/fs/uvfat/emd.c Sun Jan 4 15:15:23 1998 +@@ -34,6 +34,7 @@ + int ret; + int old_fs = get_fs(); + set_fs (KERNEL_DS); ++ MSDOS_I(inode)->i_binary=2; + ret = fat_file_read(inode,filp,buf,count); + set_fs (old_fs); + return ret; +@@ -50,6 +51,7 @@ + int ret; + int old_fs = get_fs(); + set_fs (KERNEL_DS); ++ MSDOS_I(inode)->i_binary=2; + ret = fat_file_write(inode,filp,buf,count); + set_fs (old_fs); + return ret; +diff -u -r -N linux-2.0.33-cyrix-patched-uvfat/fs/uvfat/file.c linux-2.0.33-cyrix-patched-uvfat-test/fs/uvfat/file.c +--- linux-2.0.33-cyrix-patched-uvfat/fs/uvfat/file.c Sun Jan 4 15:01:56 1998 ++++ linux-2.0.33-cyrix-patched-uvfat-test/fs/uvfat/file.c Sun Jan 4 15:18:16 1998 +@@ -131,3 +131,38 @@ + NULL, /* smap */ + }; + ++/* For other with larger and unaligned file system with readpage */ ++struct file_operations uvfat_file_operations_readpage = { ++ NULL, /* lseek - default */ ++ UVFAT_file_read, /* read */ ++ UVFAT_file_write, /* write */ ++ NULL, /* readdir - bad */ ++ NULL, /* select - default */ ++ NULL, /* ioctl - default */ ++ generic_file_mmap, /* mmap */ ++ NULL, /* no special open is needed */ ++ NULL, /* release */ ++ file_fsync /* fsync */ ++}; ++ ++struct inode_operations uvfat_file_inode_operations_readpage = { ++ &uvfat_file_operations_readpage, /* default file operations */ ++ NULL, /* create */ ++ NULL, /* lookup */ ++ NULL, /* link */ ++ NULL, /* unlink */ ++ NULL, /* symlink */ ++ NULL, /* mkdir */ ++ NULL, /* rmdir */ ++ NULL, /* mknod */ ++ NULL, /* rename */ ++ NULL, /* readlink */ ++ NULL, /* follow_link */ ++ fat_readpage, /* readpage */ ++ NULL, /* writepage */ ++ NULL, /* bmap */ ++ UVFAT_truncate,/* truncate */ ++ NULL, /* permission */ ++ NULL, /* smap */ ++}; ++ +diff -u -r -N linux-2.0.33-cyrix-patched-uvfat/fs/uvfat/inode.c linux-2.0.33-cyrix-patched-uvfat-test/fs/uvfat/inode.c +--- linux-2.0.33-cyrix-patched-uvfat/fs/uvfat/inode.c Sun Jan 4 15:01:56 1998 ++++ linux-2.0.33-cyrix-patched-uvfat-test/fs/uvfat/inode.c Sun Jan 4 15:22:33 1998 +@@ -165,11 +165,20 @@ + if (!uvfat_isinit(inode)){ + inode->u.uvfat_i.i_emd_dir = 0; + if (S_ISREG(inode->i_mode)){ ++ if (MSDOS_SB(inode->i_sb)->cvf_format){ ++ if (MSDOS_SB(inode->i_sb)->cvf_format->flags ++ &CVF_USE_READPAGE){ ++ inode->i_op = &uvfat_file_inode_operations_readpage; ++ }else{ ++ inode->i_op = &uvfat_file_inode_operations_no_bmap; ++ } ++ }else{ + if (inode->i_op->bmap != NULL){ + inode->i_op = &uvfat_file_inode_operations; + }else{ + inode->i_op = &uvfat_file_inode_operations_no_bmap; + } ++ } + }else if (S_ISDIR(inode->i_mode)){ + if (dir != NULL){ + uvfat_setup_dir_inode(inode); +diff -u -r -N linux-2.0.33-cyrix-patched-uvfat/fs/uvfat/ioctl.c linux-2.0.33-cyrix-patched-uvfat-test/fs/uvfat/ioctl.c +--- linux-2.0.33-cyrix-patched-uvfat/fs/uvfat/ioctl.c Sun Jan 4 15:01:56 1998 ++++ linux-2.0.33-cyrix-patched-uvfat-test/fs/uvfat/ioctl.c Sun Jan 4 15:24:41 1998 +@@ -62,6 +62,21 @@ + { + int ret = -EPERM; + int err; ++ ++ /* forward non-uvfat ioctls - this hopefully doesn't cause conflicts */ ++ if(cmd!=UVFAT_GETVERSION ++ &&cmd!=UVFAT_READDIR_DOS ++ &&cmd!=UVFAT_READDIR_EMD ++ &&cmd!=UVFAT_INIT_EMD ++ &&cmd!=UVFAT_CREAT_EMD ++ &&cmd!=UVFAT_RENAME_DOS ++ &&cmd!=UVFAT_UNLINK_EMD ++ &&cmd!=UVFAT_UNLINK_DOS ++ &&cmd!=UVFAT_RMDIR_DOS ++ &&cmd!=UVFAT_STAT_DOS ++ &&cmd!=UVFAT_DOS_SETUP) ++ return fat_dir_ioctl(dir,filp,cmd,data); ++ + /* #Specification: ioctl / acces + Only root (effective id) is allowed to do IOCTL on directory + in UVFAT. EPERM is returned for other user. diff --git a/patches/cvf.c b/patches/cvf.c new file mode 100644 index 0000000..62c85c8 --- /dev/null +++ b/patches/cvf.c @@ -0,0 +1,147 @@ +/* + * CVF extensions for fat-based filesystems + * + * written 1997,1998 by Frank Gockel <[email protected]> + * + * please do not remove the next line, dmsdos needs it for verifying patches + * CVF-FAT-VERSION-ID: 1.1.0 + * + */ + +#include<linux/sched.h> +#include<linux/fs.h> +#include<linux/msdos_fs.h> +#include<linux/msdos_fs_sb.h> +#include<linux/string.h> +#include<linux/fat_cvf.h> +#include<linux/config.h> +#ifdef CONFIG_KERNELD +#include<linux/kerneld.h> +#endif + +#define MAX_CVF_FORMATS 3 + +struct cvf_format *cvf_formats[MAX_CVF_FORMATS]={NULL,NULL,NULL}; +int cvf_format_use_count[MAX_CVF_FORMATS]={0,0,0}; + +int register_cvf_format(struct cvf_format*cvf_format) +{ int i,j; + + for(i=0;i<MAX_CVF_FORMATS;++i) + { if(cvf_formats[i]==NULL) + { /* free slot found, now check version */ + for(j=0;j<MAX_CVF_FORMATS;++j) + { if(cvf_formats[j]) + { if(cvf_formats[j]->cvf_version==cvf_format->cvf_version) + { printk("register_cvf_format: version %d already registered\n", + cvf_format->cvf_version); + return -1; + } + } + } + cvf_formats[i]=cvf_format; + cvf_format_use_count[i]=0; + printk("CVF format %s (version id %d) successfully registered.\n", + cvf_format->cvf_version_text,cvf_format->cvf_version); + return 0; + } + } + + printk("register_cvf_format: too many formats\n"); + return -1; +} + +int unregister_cvf_format(struct cvf_format*cvf_format) +{ int i; + + for(i=0;i<MAX_CVF_FORMATS;++i) + { if(cvf_formats[i]) + { if(cvf_formats[i]->cvf_version==cvf_format->cvf_version) + { if(cvf_format_use_count[i]) + { printk("unregister_cvf_format: format %d in use, cannot remove!\n", + cvf_formats[i]->cvf_version); + return -1; + } + + printk("CVF format %s (version id %d) successfully unregistered.\n", + cvf_formats[i]->cvf_version_text,cvf_formats[i]->cvf_version); + cvf_formats[i]=NULL; + return 0; + } + } + } + + printk("unregister_cvf_format: format %d is not registered\n", + cvf_format->cvf_version); + return -1; +} + +void dec_cvf_format_use_count_by_version(int version) +{ int i; + + for(i=0;i<MAX_CVF_FORMATS;++i) + { if(cvf_formats[i]) + { if(cvf_formats[i]->cvf_version==version) + { --cvf_format_use_count[i]; + if(cvf_format_use_count[i]<0) + { cvf_format_use_count[i]=0; + printk(KERN_EMERG "FAT FS/CVF: This is a bug in cvf_version_use_count\n"); + } + return; + } + } + } + + printk("dec_cvf_format_use_count_by_version: version %d not found ???\n", + version); +} + +int detect_cvf(struct super_block*sb,char*force) +{ int i; + int found=0; + int found_i=-1; + + if(force) + if(strcmp(force,"autoload")==0) + { +#ifdef CONFIG_KERNELD + request_module("cvf_autoload"); + force=NULL; +#else + printk("cannot autoload CVF modules: kerneld support is not compiled into kernel\n"); + return -1; +#endif + } + +#ifdef CONFIG_KERNELD + if(force) + if(*force) + request_module(force); +#endif + + if(force) + { if(*force) + { for(i=0;i<MAX_CVF_FORMATS;++i) + { if(cvf_formats[i]) + { if(!strcmp(cvf_formats[i]->cvf_version_text,force)) + return i; + } + } + printk("CVF format %s unknown (module not loaded?)\n",force); + return -1; + } + } + + for(i=0;i<MAX_CVF_FORMATS;++i) + { if(cvf_formats[i]) + { if(cvf_formats[i]->detect_cvf(sb)) + { ++found; + found_i=i; + } + } + } + + if(found==1)return found_i; + if(found>1)printk("CVF detection ambiguous, please use cvf_format=xxx option\n"); + return -1; +} diff --git a/patches/cvf.c-2.1.128 b/patches/cvf.c-2.1.128 new file mode 100644 index 0000000..9dd70f8 --- /dev/null +++ b/patches/cvf.c-2.1.128 @@ -0,0 +1,147 @@ +/* + * CVF extensions for fat-based filesystems + * + * written 1997,1998 by Frank Gockel <[email protected]> + * + * please do not remove the next line, dmsdos needs it for verifying patches + * CVF-FAT-VERSION-ID: 1.2.0 + * + */ + +#include<linux/sched.h> +#include<linux/fs.h> +#include<linux/msdos_fs.h> +#include<linux/msdos_fs_sb.h> +#include<linux/string.h> +#include<linux/fat_cvf.h> +#include<linux/config.h> +#ifdef CONFIG_KMOD +#include<linux/kmod.h> +#endif + +#define MAX_CVF_FORMATS 3 + +struct cvf_format *cvf_formats[MAX_CVF_FORMATS]={NULL,NULL,NULL}; +int cvf_format_use_count[MAX_CVF_FORMATS]={0,0,0}; + +int register_cvf_format(struct cvf_format*cvf_format) +{ int i,j; + + for(i=0;i<MAX_CVF_FORMATS;++i) + { if(cvf_formats[i]==NULL) + { /* free slot found, now check version */ + for(j=0;j<MAX_CVF_FORMATS;++j) + { if(cvf_formats[j]) + { if(cvf_formats[j]->cvf_version==cvf_format->cvf_version) + { printk("register_cvf_format: version %d already registered\n", + cvf_format->cvf_version); + return -1; + } + } + } + cvf_formats[i]=cvf_format; + cvf_format_use_count[i]=0; + printk("CVF format %s (version id %d) successfully registered.\n", + cvf_format->cvf_version_text,cvf_format->cvf_version); + return 0; + } + } + + printk("register_cvf_format: too many formats\n"); + return -1; +} + +int unregister_cvf_format(struct cvf_format*cvf_format) +{ int i; + + for(i=0;i<MAX_CVF_FORMATS;++i) + { if(cvf_formats[i]) + { if(cvf_formats[i]->cvf_version==cvf_format->cvf_version) + { if(cvf_format_use_count[i]) + { printk("unregister_cvf_format: format %d in use, cannot remove!\n", + cvf_formats[i]->cvf_version); + return -1; + } + + printk("CVF format %s (version id %d) successfully unregistered.\n", + cvf_formats[i]->cvf_version_text,cvf_formats[i]->cvf_version); + cvf_formats[i]=NULL; + return 0; + } + } + } + + printk("unregister_cvf_format: format %d is not registered\n", + cvf_format->cvf_version); + return -1; +} + +void dec_cvf_format_use_count_by_version(int version) +{ int i; + + for(i=0;i<MAX_CVF_FORMATS;++i) + { if(cvf_formats[i]) + { if(cvf_formats[i]->cvf_version==version) + { --cvf_format_use_count[i]; + if(cvf_format_use_count[i]<0) + { cvf_format_use_count[i]=0; + printk(KERN_EMERG "FAT FS/CVF: This is a bug in cvf_version_use_count\n"); + } + return; + } + } + } + + printk("dec_cvf_format_use_count_by_version: version %d not found ???\n", + version); +} + +int detect_cvf(struct super_block*sb,char*force) +{ int i; + int found=0; + int found_i=-1; + + if(force) + if(strcmp(force,"autoload")==0) + { +#ifdef CONFIG_KMOD + request_module("cvf_autoload"); + force=NULL; +#else + printk("cannot autoload CVF modules: kmod support is not compiled into kernel\n"); + return -1; +#endif + } + +#ifdef CONFIG_KMOD + if(force) + if(*force) + request_module(force); +#endif + + if(force) + { if(*force) + { for(i=0;i<MAX_CVF_FORMATS;++i) + { if(cvf_formats[i]) + { if(!strcmp(cvf_formats[i]->cvf_version_text,force)) + return i; + } + } + printk("CVF format %s unknown (module not loaded?)\n",force); + return -1; + } + } + + for(i=0;i<MAX_CVF_FORMATS;++i) + { if(cvf_formats[i]) + { if(cvf_formats[i]->detect_cvf(sb)) + { ++found; + found_i=i; + } + } + } + + if(found==1)return found_i; + if(found>1)printk("CVF detection ambiguous, please use cvf_format=xxx option\n"); + return -1; +} diff --git a/patches/cvf.c.README b/patches/cvf.c.README new file mode 100644 index 0000000..9d5561c --- /dev/null +++ b/patches/cvf.c.README @@ -0,0 +1,70 @@ + +Update to CVF-FAT 1.1.0 or 1.2.0 +-------------------------------- + +Today's kernels (currently means in time of Linux 2.2.2) use still CVF-FAT +interface version 1.0.0. That is a bit outdated (and known to have one minor +bug and some missing features). + +Latest versions are: + * CVF-FAT version 1.1.0 for 2.0.xx kernels + * CVF-FAT version 1.2.0 for kernels 2.1.128 or newer (also 2.2.x) + (The break between those two is somewhere between 2.1.94 and 2.1.128, + exactly it should be when kerneld was replaced by kmod, but I have never + verified that. Better use 2.0 or 2.2 kernels. :) ) + +Files: + + cvf.c: CVF-FAT 1.1.0. For kernels that support kerneld. + fat_cvf.txt: Documentation for CVF-FAT 1.1.0 (in file cvf.c). + + cvf.c-2.1.128: CVF-FAT 1.2.0. For newer kernels that support kmod + instead of kerneld (including 2.2.x kernels). + fat_cvf.txt-2.1.128: Documentation for CVF-FAT 1.2.0 (in file + cvf.c-2.1.128). + +These files _replace_ the respective files in the kernel sources: + + linux/fs/fat/cvf.c + linux/fs/Documentation/filesystems/fat_cvf.txt + +The only difference between CVF-FAT 1.1.0 and 1.2.0 is that 1.2.0 has +been rewritten for kmod support which replaces kerneld in latest 2.1.xx +kernels (and also 2.2.x kernels). +*** Be sure to use the right file for your kernel! You must check the + kernel source or kernel documentation in order to find out whether + your kernel supports kerneld or kmod. At least, I know that all 2.0.xx + kernels support kerneld. Also, I checked that 2.1.128 uses kmod. Newer + kernels also should support kmod. That's all I know. You're on your + own here to find that out. A kernel that supports kmod should have a + file linux/Documentation/kmod.txt or similar, but I'm not 100% sure :) + +Who should update +----------------- + +If you are using CVF-FAT 1.0.0 or older you may want to update. Watch for a +version number in file linux/fs/fat/cvf.c. There should be a line somewhere +at the beginning of the file that reads "CVF-FAT-VERSION-ID: x.y.z" where +"x.y.z" is the version number. If this line is missing you are using version +1.0.0 or older. + +Why update +---------- + +It fixes a bug that lets the mount command silently succeed if there is a +special kind of error. This bug sometimes caused the plain FAT driver to +mount a CVF in case of error with CVF-FAT support, which is surely not a +good idea :) + +Now 'mount' fails with an error message in that case. + +Also the kerneld/kmod-autoload feature is now permanently in that file so you +do not have to apply it as a seperate patch. For latest 2.1.xx kernels, +where kerneld has been replaced by kmod, the kerneld-autoload support has +been rewritten to use kmod instead. + +How to update +------------- + +You can simply replace the old files with the new ones as listed above. +Then recompile your modules (or your kernel if fat support is not modular). diff --git a/patches/cvf.diff-2.0.33 b/patches/cvf.diff-2.0.33 new file mode 100644 index 0000000..84b3154 --- /dev/null +++ b/patches/cvf.diff-2.0.33 @@ -0,0 +1,1056 @@ +diff -u -r -N linux-2.0.33-cyrix-patched/Documentation/filesystems/fat_cvf.txt linux-2.0.33-cyrix-patched-test/Documentation/filesystems/fat_cvf.txt +--- linux-2.0.33-cyrix-patched/Documentation/filesystems/fat_cvf.txt Thu Jan 1 01:00:00 1970 ++++ linux-2.0.33-cyrix-patched-test/Documentation/filesystems/fat_cvf.txt Wed Nov 18 20:40:50 1998 +@@ -0,0 +1,210 @@ ++This is the main documentation for the CVF-FAT filesystem extension. 18Nov1998 ++ ++ ++Table of Contents: ++ ++1. The idea of CVF-FAT ++2. Restrictions ++3. Mount options ++4. Description of the CVF-FAT interface ++5. CVF Modules ++ ++------------------------------------------------------------------------------ ++ ++ ++1. The idea of CVF-FAT ++------------------------------------------------------------------------------ ++ ++CVF-FAT is a FAT filesystem extension that provides a generic interface for ++Compressed Volume Files in FAT partitions. Popular CVF software, for ++example, are Microsoft's Doublespace/Drivespace and Stac's Stacker. ++Using the CVF-FAT interface, it is possible to load a module that handles ++all the low-level disk access that has to do with on-the-fly compression ++and decompression. Any other part of FAT filesystem access is still handled ++by the FAT, MSDOS or VFAT or even UMSDOS driver. ++ ++CVF access works by redirecting certain low-level routines from the FAT ++driver to a loadable, CVF-format specific module. This module must fake ++a normal FAT filesystem to the FAT driver while doing all the extra stuff ++like compression and decompression silently. ++ ++ ++2. Restrictions ++------------------------------------------------------------------------------ ++ ++- BMAP problems ++ ++ CVF filesystems cannot do bmap. It's impossible in principle. Thus ++ all actions that require bmap do not work (swapping, writable mmapping). ++ Read-only mmapping works because the FAT driver has a hack for this ++ situation :) Well, writable mmapping should now work using the readpage ++ interface function which has been hacked into the FAT driver just for ++ CVF-FAT :) ++ ++- attention, DOSEmu users ++ ++ You may have to unmount all CVF partitions before running DOSEmu depending ++ on your configuration. If DOSEmu is configured to use wholedisk or ++ partition access (this is often the case to let DOSEmu access ++ compressed partitions) there's a risk of destroying your compressed ++ partitions or crashing your system because of confused drivers. ++ ++ Note that it is always safe to redirect the compressed partitions with ++ lredir or emufs.sys. Refer to the DOSEmu documentation for details. ++ ++ ++3. Mount options ++------------------------------------------------------------------------------ ++ ++The CVF-FAT extension currently adds the following options to the FAT ++driver's standard options: ++ ++ cvf_format=xxx ++ Forces the driver to use the CVF module "xxx" instead of auto-detection. ++ Without this option, the CVF-FAT interface asks all currently loaded ++ CVF modules whether they recognize the CVF. Therefore, this option is ++ only necessary if the CVF format is not recognized correctly ++ because of bugs or incompatibilities in the CVF modules. (It skips ++ the detect_cvf call.) "xxx" may be the text "none" (without the quotes) ++ to inhibit using any of the loaded CVF modules, just in case a CVF ++ module insists on mounting plain FAT filesystems by misunderstanding. ++ "xxx" may also be the text "autoload", which has a special meaning for ++ kerneld, but does not skip auto-detection. ++ ++ If the kernel supports kerneld, the cvf_format=xxx option also controls ++ on-demand CVF module loading. Without this option, nothing is loaded ++ on demand. With cvf_format=xxx, a module "xxx" is requested automatically ++ before mounting the compressed filesystem (unless "xxx" is "none"). In ++ case there is a difference between the CVF format name and the module ++ name, setup aliases in your kerneld configuration. If the string "xxx" ++ is "autoload", a non-existent module "cvf_autoload" is requested which ++ can be used together with a special kerneld configuration (alias and ++ pre-install statements) in order to load more than one CVF module, let ++ them detect automatically which kind of CVF is to be mounted, and only ++ keep the "right" module in memory. For examples please refer to the ++ dmsdos documentation (ftp and http addresses see below). ++ ++ cvf_options=yyy ++ Option string passed to the CVF module. I.e. only the "yyy" is passed ++ (without the quotes). The documentation for each CVF module should ++ explain it since it is interpreted only by the CVF module. Note that ++ the string must not contain a comma (",") - this would lead to ++ misinterpretation by the FAT driver, which would recognize the text ++ after a comma as a FAT driver option and might get confused or print ++ strange error messages. The documentation for the CVF module should ++ offer a different separation symbol, for example the dot "." or the ++ plus sign "+", which is only valid inside the string "yyy". ++ ++ ++4. Description of the CVF-FAT interface ++------------------------------------------------------------------------------ ++ ++Assuming you want to write your own CVF module, you need to write a lot of ++interface functions. Most of them are covered in the kernel documentation ++you can find on the net, and thus won't be described here. They have been ++marked with "[...]" :-) Take a look at include/linux/fat_cvf.h. ++ ++struct cvf_format ++{ int cvf_version; ++ char* cvf_version_text; ++ unsigned long int flags; ++ int (*detect_cvf) (struct super_block*sb); ++ int (*mount_cvf) (struct super_block*sb,char*options); ++ int (*unmount_cvf) (struct super_block*sb); ++ [...] ++ void (*cvf_zero_cluster) (struct inode*inode,int clusternr); ++} ++ ++This structure defines the capabilities of a CVF module. It must be filled ++out completely by a CVF module. Consider it as a kind of form that is used ++to introduce the module to the FAT/CVF-FAT driver. ++ ++It contains... ++ - cvf_version: ++ A version id which must be unique. Choose one. ++ - cvf_version_text: ++ A human readable version string that should be one short word ++ describing the CVF format the module implements. This text is used ++ for the cvf_format option. This name must also be unique. ++ - flags: ++ Bit coded flags, currently only used for a readpage/mmap hack that ++ provides both mmap and readpage functionality. If CVF_USE_READPAGE ++ is set, mmap is set to generic_file_mmap and readpage is caught ++ and redirected to the cvf_readpage function. If it is not set, ++ readpage is set to generic_readpage and mmap is caught and redirected ++ to cvf_mmap. (If you want writable mmap use the readpage interface.) ++ - detect_cvf: ++ A function that is called to decide whether the filesystem is a CVF of ++ the type the module supports. The detect_cvf function must return 0 ++ for "NO, I DON'T KNOW THIS GARBAGE" or anything >0 for "YES, THIS IS ++ THE KIND OF CVF I SUPPORT". The function must maintain the module ++ usage counters for safety, i.e. do MOD_INC_USE_COUNT at the beginning ++ and MOD_DEC_USE_COUNT at the end. The function *must not* assume that ++ successful recongition would lead to a call of the mount_cvf function ++ later. ++ - mount_cvf: ++ A function that sets up some values or initializes something additional ++ to what has to be done when a CVF is mounted. This is called at the ++ end of fat_read_super and must return 0 on success. Definitely, this ++ function must increment the module usage counter by MOD_INC_USE_COUNT. ++ This mount_cvf function is also responsible for interpreting a CVF ++ module specific option string (the "yyy" from the FAT mount option ++ "cvf_options=yyy") which cannot contain a comma (use for example the ++ dot "." as option separator symbol). ++ - unmount_cvf: ++ A function that is called when the filesystem is unmounted. Most likely ++ it only frees up some memory and calls MOD_DEC_USE_COUNT. The return ++ value might be ignored (it currently is ignored). ++ - [...]: ++ All other interface functions are "caught" FAT driver functions, i.e. ++ are executed by the FAT driver *instead* of the original FAT driver ++ functions. NULL means use the original FAT driver functions instead. ++ If you really want "no action", write a function that does nothing and ++ hang it in instead. ++ - cvf_zero_cluster: ++ The cvf_zero_cluster function is called when the fat driver wants to ++ zero out a (new) cluster. This is important for directories (mkdir). ++ If it is NULL, the FAT driver defaults to overwriting the whole ++ cluster with zeros. Note that clusternr is absolute, not relative ++ to the provided inode. ++ ++Notes: ++ 1. The cvf_bmap function should be ignored. It really should never ++ get called from somewhere. I recommend redirecting it to a panic ++ or fatal error message so bugs show up immediately. ++ 2. The cvf_writepage function is ignored. This is because the fat ++ driver doesn't support it. This might change in future. I recommend ++ setting it to NULL (i.e use default). ++ ++int register_cvf_format(struct cvf_format*cvf_format); ++ If you have just set up a variable containing the above structure, ++ call this function to introduce your CVF format to the FAT/CVF-FAT ++ driver. This is usually done in init_module. Be sure to check the ++ return value. Zero means success, everything else causes a kernel ++ message printed in the syslog describing the error that occurred. ++ Typical errors are: ++ - a module with the same version id is already registered or ++ - too many CVF formats. Hack fs/fat/cvf.c if you need more. ++ ++int unregister_cvf_format(struct cvf_format*cvf_format); ++ This is usually called in cleanup_module. Return value =0 means ++ success. An error only occurs if you try to unregister a CVF format ++ that has not been previously registered. The code uses the version id ++ to distinguish the modules, so be sure to keep it unique. ++ ++5. CVF Modules ++------------------------------------------------------------------------------ ++ ++Refer to the dmsdos module (the successor of the dmsdos filesystem) for a ++sample implementation. It can currently be found at ++ ++ ftp://fb9nt.uni-duisburg.de/pub/linux/dmsdos/dmsdos-x.y.z.tgz ++ ftp://sunsite.unc.edu/pub/Linux/system/Filesystems/dosfs/dmsdos-x.y.z.tgz ++ ftp://ftp.uni-stuttgart.de/pub/systems/linux/local/system/dmsdos-x.y.z.tgz ++ ++(where x.y.z is to be replaced with the actual version number). Full ++documentation about dmsdos is included in the dmsdos package, but can also ++be found at ++ ++ http://fb9nt.uni-duisburg.de/mitarbeiter/gockel/software/dmsdos/index.html ++ http://www.yk.rim.or.jp/~takafumi/dmsdos/index.html (in Japanese). +diff -u -r -N linux-2.0.33-cyrix-patched/fs/fat/Makefile linux-2.0.33-cyrix-patched-test/fs/fat/Makefile +--- linux-2.0.33-cyrix-patched/fs/fat/Makefile Wed Feb 7 08:39:27 1996 ++++ linux-2.0.33-cyrix-patched-test/fs/fat/Makefile Sat Dec 27 21:34:20 1997 +@@ -8,7 +8,7 @@ + # Note 2! The CFLAGS definitions are now in the main makefile... + + O_TARGET := fat.o +-O_OBJS := buffer.o cache.o dir.o file.o inode.o misc.o mmap.o tables.o ++O_OBJS := buffer.o cache.o dir.o file.o inode.o misc.o mmap.o tables.o cvf.o + OX_OBJS := fatfs_syms.o + M_OBJS := $(O_TARGET) + +diff -u -r -N linux-2.0.33-cyrix-patched/fs/fat/buffer.c linux-2.0.33-cyrix-patched-test/fs/fat/buffer.c +--- linux-2.0.33-cyrix-patched/fs/fat/buffer.c Fri May 10 06:54:52 1996 ++++ linux-2.0.33-cyrix-patched-test/fs/fat/buffer.c Sat Dec 27 21:46:10 1997 +@@ -9,6 +9,7 @@ + #include <linux/string.h> + #include <linux/fs.h> + #include <linux/msdos_fs.h> ++#include <linux/fat_cvf.h> + + struct buffer_head *fat_bread ( + struct super_block *sb, +@@ -16,6 +17,10 @@ + { + struct buffer_head *ret = NULL; + ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_bread) ++ return MSDOS_SB(sb)->cvf_format->cvf_bread(sb,block); ++ + /* Note that the blocksize is 512 or 1024, but the first read + is always of size 1024. Doing readahead may be counterproductive + or just plain wrong. */ +@@ -73,6 +78,11 @@ + int block) + { + struct buffer_head *ret = NULL; ++ ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_getblk) ++ return MSDOS_SB(sb)->cvf_format->cvf_getblk(sb,block); ++ + if (sb->s_blocksize == 512){ + ret = getblk (sb->s_dev,block,512); + }else{ +@@ -92,6 +102,10 @@ + struct buffer_head *bh) + { + if (bh != NULL){ ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_brelse) ++ return MSDOS_SB(sb)->cvf_format->cvf_brelse(sb,bh); ++ + if (sb->s_blocksize == 512){ + brelse (bh); + }else{ +@@ -109,6 +123,12 @@ + struct buffer_head *bh, + int dirty_val) + { ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty) ++ { MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty(sb,bh,dirty_val); ++ return; ++ } ++ + if (sb->s_blocksize != 512){ + bh = bh->b_next; + } +@@ -120,6 +140,12 @@ + struct buffer_head *bh, + int val) + { ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_set_uptodate) ++ { MSDOS_SB(sb)->cvf_format->cvf_set_uptodate(sb,bh,val); ++ return; ++ } ++ + if (sb->s_blocksize != 512){ + bh = bh->b_next; + } +@@ -129,6 +155,10 @@ + struct super_block *sb, + struct buffer_head *bh) + { ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_is_uptodate) ++ return MSDOS_SB(sb)->cvf_format->cvf_is_uptodate(sb,bh); ++ + if (sb->s_blocksize != 512){ + bh = bh->b_next; + } +@@ -141,6 +171,12 @@ + int nbreq, + struct buffer_head *bh[32]) + { ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block) ++ { MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block(sb,opr,nbreq,bh); ++ return; ++ } ++ + if (sb->s_blocksize == 512){ + ll_rw_block(opr,nbreq,bh); + }else{ +diff -u -r -N linux-2.0.33-cyrix-patched/fs/fat/cache.c linux-2.0.33-cyrix-patched-test/fs/fat/cache.c +--- linux-2.0.33-cyrix-patched/fs/fat/cache.c Fri May 10 06:54:52 1996 ++++ linux-2.0.33-cyrix-patched-test/fs/fat/cache.c Sun Dec 28 12:16:08 1997 +@@ -9,6 +9,7 @@ + #include <linux/errno.h> + #include <linux/string.h> + #include <linux/stat.h> ++#include <linux/fat_cvf.h> + + #include "msbuffer.h" + +@@ -24,6 +25,10 @@ + unsigned char *p_first,*p_last; + int first,last,next,copy,b; + ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->fat_access) ++ return MSDOS_SB(sb)->cvf_format->fat_access(sb,nr,new_value); ++ + if ((unsigned) (nr-2) >= MSDOS_SB(sb)->clusters) + return 0; + if (MSDOS_SB(sb)->fat_bits == 16) { +@@ -246,6 +251,10 @@ + int cluster,offset; + + sb = MSDOS_SB(inode->i_sb); ++ if(sb->cvf_format) ++ if(sb->cvf_format->cvf_smap) ++ return sb->cvf_format->cvf_smap(inode,sector); ++ + if (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) && + !MSDOS_I(inode)->i_start)) { + if (sector >= sb->dir_entries >> MSDOS_DPS_BITS) return 0; +diff -u -r -N linux-2.0.33-cyrix-patched/fs/fat/cvf.c linux-2.0.33-cyrix-patched-test/fs/fat/cvf.c +--- linux-2.0.33-cyrix-patched/fs/fat/cvf.c Thu Jan 1 01:00:00 1970 ++++ linux-2.0.33-cyrix-patched-test/fs/fat/cvf.c Tue Nov 17 20:10:41 1998 +@@ -0,0 +1,147 @@ ++/* ++ * CVF extensions for fat-based filesystems ++ * ++ * written 1997,1998 by Frank Gockel <[email protected]> ++ * ++ * please do not remove the next line, dmsdos needs it for verifying patches ++ * CVF-FAT-VERSION-ID: 1.1.0 ++ * ++ */ ++ ++#include<linux/sched.h> ++#include<linux/fs.h> ++#include<linux/msdos_fs.h> ++#include<linux/msdos_fs_sb.h> ++#include<linux/string.h> ++#include<linux/fat_cvf.h> ++#include<linux/config.h> ++#ifdef CONFIG_KERNELD ++#include<linux/kerneld.h> ++#endif ++ ++#define MAX_CVF_FORMATS 3 ++ ++struct cvf_format *cvf_formats[MAX_CVF_FORMATS]={NULL,NULL,NULL}; ++int cvf_format_use_count[MAX_CVF_FORMATS]={0,0,0}; ++ ++int register_cvf_format(struct cvf_format*cvf_format) ++{ int i,j; ++ ++ for(i=0;i<MAX_CVF_FORMATS;++i) ++ { if(cvf_formats[i]==NULL) ++ { /* free slot found, now check version */ ++ for(j=0;j<MAX_CVF_FORMATS;++j) ++ { if(cvf_formats[j]) ++ { if(cvf_formats[j]->cvf_version==cvf_format->cvf_version) ++ { printk("register_cvf_format: version %d already registered\n", ++ cvf_format->cvf_version); ++ return -1; ++ } ++ } ++ } ++ cvf_formats[i]=cvf_format; ++ cvf_format_use_count[i]=0; ++ printk("CVF format %s (version id %d) successfully registered.\n", ++ cvf_format->cvf_version_text,cvf_format->cvf_version); ++ return 0; ++ } ++ } ++ ++ printk("register_cvf_format: too many formats\n"); ++ return -1; ++} ++ ++int unregister_cvf_format(struct cvf_format*cvf_format) ++{ int i; ++ ++ for(i=0;i<MAX_CVF_FORMATS;++i) ++ { if(cvf_formats[i]) ++ { if(cvf_formats[i]->cvf_version==cvf_format->cvf_version) ++ { if(cvf_format_use_count[i]) ++ { printk("unregister_cvf_format: format %d in use, cannot remove!\n", ++ cvf_formats[i]->cvf_version); ++ return -1; ++ } ++ ++ printk("CVF format %s (version id %d) successfully unregistered.\n", ++ cvf_formats[i]->cvf_version_text,cvf_formats[i]->cvf_version); ++ cvf_formats[i]=NULL; ++ return 0; ++ } ++ } ++ } ++ ++ printk("unregister_cvf_format: format %d is not registered\n", ++ cvf_format->cvf_version); ++ return -1; ++} ++ ++void dec_cvf_format_use_count_by_version(int version) ++{ int i; ++ ++ for(i=0;i<MAX_CVF_FORMATS;++i) ++ { if(cvf_formats[i]) ++ { if(cvf_formats[i]->cvf_version==version) ++ { --cvf_format_use_count[i]; ++ if(cvf_format_use_count[i]<0) ++ { cvf_format_use_count[i]=0; ++ printk(KERN_EMERG "FAT FS/CVF: This is a bug in cvf_version_use_count\n"); ++ } ++ return; ++ } ++ } ++ } ++ ++ printk("dec_cvf_format_use_count_by_version: version %d not found ???\n", ++ version); ++} ++ ++int detect_cvf(struct super_block*sb,char*force) ++{ int i; ++ int found=0; ++ int found_i=-1; ++ ++ if(force) ++ if(strcmp(force,"autoload")==0) ++ { ++#ifdef CONFIG_KERNELD ++ request_module("cvf_autoload"); ++ force=NULL; ++#else ++ printk("cannot autoload CVF modules: kerneld support is not compiled into kernel\n"); ++ return -1; ++#endif ++ } ++ ++#ifdef CONFIG_KERNELD ++ if(force) ++ if(*force) ++ request_module(force); ++#endif ++ ++ if(force) ++ { if(*force) ++ { for(i=0;i<MAX_CVF_FORMATS;++i) ++ { if(cvf_formats[i]) ++ { if(!strcmp(cvf_formats[i]->cvf_version_text,force)) ++ return i; ++ } ++ } ++ printk("CVF format %s unknown (module not loaded?)\n",force); ++ return -1; ++ } ++ } ++ ++ for(i=0;i<MAX_CVF_FORMATS;++i) ++ { if(cvf_formats[i]) ++ { if(cvf_formats[i]->detect_cvf(sb)) ++ { ++found; ++ found_i=i; ++ } ++ } ++ } ++ ++ if(found==1)return found_i; ++ if(found>1)printk("CVF detection ambiguous, please use cvf_format=xxx option\n"); ++ return -1; ++} +diff -u -r -N linux-2.0.33-cyrix-patched/fs/fat/dir.c linux-2.0.33-cyrix-patched-test/fs/fat/dir.c +--- linux-2.0.33-cyrix-patched/fs/fat/dir.c Fri May 10 06:54:52 1996 ++++ linux-2.0.33-cyrix-patched-test/fs/fat/dir.c Sat Jan 3 12:41:00 1998 +@@ -382,6 +382,7 @@ + unsigned int cmd, unsigned long arg) + { + int err; ++ + /* + * We want to provide an interface for Samba to be able + * to get the short filename for a given long filename. +@@ -408,6 +409,11 @@ + vfat_ioctl_fill, NULL, 1, 0, 1); + } + default: ++ /* forward ioctl to CVF extension */ ++ if(MSDOS_SB(inode->i_sb)->cvf_format ++ &&MSDOS_SB(inode->i_sb)->cvf_format->cvf_dir_ioctl) ++ return MSDOS_SB(inode->i_sb)->cvf_format-> ++ cvf_dir_ioctl(inode,filp,cmd,arg); + return -EINVAL; + } + +diff -u -r -N linux-2.0.33-cyrix-patched/fs/fat/fatfs_syms.c linux-2.0.33-cyrix-patched-test/fs/fat/fatfs_syms.c +--- linux-2.0.33-cyrix-patched/fs/fat/fatfs_syms.c Tue Mar 5 12:03:26 1996 ++++ linux-2.0.33-cyrix-patched-test/fs/fat/fatfs_syms.c Sat Jan 3 10:41:33 1998 +@@ -8,6 +8,7 @@ + + #include <linux/mm.h> + #include <linux/msdos_fs.h> ++#include <linux/fat_cvf.h> + + #include "msbuffer.h" + #include "tables.h" +@@ -48,6 +49,13 @@ + X(fat_uni2code), + X(fat_unlock_creation), + X(fat_write_inode), ++ X(register_cvf_format), ++ X(unregister_cvf_format), ++ X(get_cluster), ++ X(lock_fat), ++ X(unlock_fat), ++ X(fat_readpage), ++ X(fat_dir_ioctl), + #include <linux/symtab_end.h> + }; + +diff -u -r -N linux-2.0.33-cyrix-patched/fs/fat/file.c linux-2.0.33-cyrix-patched-test/fs/fat/file.c +--- linux-2.0.33-cyrix-patched/fs/fat/file.c Fri May 10 06:54:52 1996 ++++ linux-2.0.33-cyrix-patched-test/fs/fat/file.c Fri Jan 2 20:24:15 1998 +@@ -15,6 +15,7 @@ + #include <linux/stat.h> + #include <linux/string.h> + #include <linux/pagemap.h> ++#include <linux/fat_cvf.h> + + #include <asm/segment.h> + #include <asm/system.h> +@@ -109,6 +110,40 @@ + NULL /* smap */ + }; + ++static struct file_operations fat_file_operations_readpage = { ++ NULL, /* lseek - default */ ++ fat_file_read, /* read */ ++ fat_file_write, /* write */ ++ NULL, /* readdir - bad */ ++ NULL, /* select - default */ ++ NULL, /* ioctl - default */ ++ generic_file_mmap, /* mmap */ ++ NULL, /* no special open is needed */ ++ NULL, /* release */ ++ file_fsync /* fsync */ ++}; ++ ++struct inode_operations fat_file_inode_operations_readpage = { ++ &fat_file_operations_readpage, /* default file operations */ ++ NULL, /* create */ ++ NULL, /* lookup */ ++ NULL, /* link */ ++ NULL, /* unlink */ ++ NULL, /* symlink */ ++ NULL, /* mkdir */ ++ NULL, /* rmdir */ ++ NULL, /* mknod */ ++ NULL, /* rename */ ++ NULL, /* readlink */ ++ NULL, /* follow_link */ ++ fat_readpage, /* readpage */ ++ NULL, /* writepage */ ++ NULL, /* bmap */ ++ fat_truncate, /* truncate */ ++ NULL, /* permission */ ++ NULL /* smap */ ++}; ++ + #define MSDOS_PREFETCH 32 + struct fat_pre { + int file_sector;/* Next sector to read in the prefetch table */ +@@ -170,6 +205,10 @@ + printk("fat_file_read: inode = NULL\n"); + return -EINVAL; + } ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_file_read) ++ return MSDOS_SB(sb)->cvf_format->cvf_file_read(inode,filp,buf,count); ++ + /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */ + if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) { + printk("fat_file_read: mode = %07o\n",inode->i_mode); +@@ -287,6 +326,10 @@ + printk("fat_file_write: inode = NULL\n"); + return -EINVAL; + } ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_file_write) ++ return MSDOS_SB(sb)->cvf_format->cvf_file_write(inode,filp,buf,count); ++ + /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */ + if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) { + printk("fat_file_write: mode = %07o\n",inode->i_mode); +diff -u -r -N linux-2.0.33-cyrix-patched/fs/fat/inode.c linux-2.0.33-cyrix-patched-test/fs/fat/inode.c +--- linux-2.0.33-cyrix-patched/fs/fat/inode.c Sat Nov 30 11:27:38 1996 ++++ linux-2.0.33-cyrix-patched-test/fs/fat/inode.c Sat Jan 3 10:46:27 1998 +@@ -18,6 +18,8 @@ + #include <linux/fs.h> + #include <linux/stat.h> + #include <linux/locks.h> ++#include <linux/fat_cvf.h> ++#include <linux/malloc.h> + + #include "msbuffer.h" + #include "tables.h" +@@ -75,6 +77,10 @@ + + void fat_put_super(struct super_block *sb) + { ++ if(MSDOS_SB(sb)->cvf_format) ++ { dec_cvf_format_use_count_by_version(MSDOS_SB(sb)->cvf_format->cvf_version); ++ MSDOS_SB(sb)->cvf_format->unmount_cvf(sb); ++ } + fat_cache_inval_dev(sb->s_dev); + set_blocksize (sb->s_dev,BLOCK_SIZE); + lock_super(sb); +@@ -86,7 +92,8 @@ + + + static int parse_options(char *options,int *fat, int *blksize, int *debug, +- struct fat_mount_options *opts) ++ struct fat_mount_options *opts, ++ char* cvf_format, char*cvf_options) + { + char *this_char,*value; + +@@ -181,6 +188,17 @@ + return 0; + opts->sys_immutable = 1; + } ++ else if (!strcmp(this_char,"cvf_format")) { ++ if (!value) ++ return 0; ++ strncpy(cvf_format,value,20); ++ } ++ else if (!strcmp(this_char,"cvf_options")) { ++ if (!value) ++ return 0; ++ strncpy(cvf_options,value,100); ++ } ++ + } + return 1; + } +@@ -196,6 +214,14 @@ + int debug,error,fat; + int blksize = 512; + struct fat_mount_options opts; ++ int i; ++ char cvf_format[21]; ++ char cvf_options[101]; ++ ++ cvf_format[0]='\0'; ++ cvf_options[0]='\0'; ++ MSDOS_SB(sb)->cvf_format=NULL; ++ MSDOS_SB(sb)->private_data=NULL; + + MOD_INC_USE_COUNT; + if (hardsect_size[MAJOR(sb->s_dev)] != NULL){ +@@ -204,7 +230,7 @@ + printk ("MSDOS: Hardware sector size is %d\n",blksize); + } + } +- if (!parse_options((char *) data, &fat, &blksize, &debug, &opts) ++ if (!parse_options((char *) data, &fat, &blksize, &debug, &opts, cvf_format, cvf_options) + || (blksize != 512 && blksize != 1024)) { + sb->s_dev = 0; + MOD_DEC_USE_COUNT; +@@ -286,6 +312,9 @@ + /* because clusters (DOS) are often aligned */ + /* on odd sectors. */ + sb->s_blocksize_bits = blksize == 512 ? 9 : 10; ++ if(!strcmp(cvf_format,"none"))i=-1; ++ else i=detect_cvf(sb,cvf_format); ++ if(i>=0)error=cvf_formats[i]->mount_cvf(sb,cvf_options); + if (error || debug) { + /* The MSDOS_CAN_BMAP is obsolete, but left just to remember */ + printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c," +@@ -302,13 +331,15 @@ + (unsigned long)b->total_sect,logical_sector_size); + printk ("Transaction block size = %d\n",blksize); + } +- if (MSDOS_SB(sb)->clusters+2 > fat_clusters) ++ if(i<0) if (MSDOS_SB(sb)->clusters+2 > fat_clusters) + MSDOS_SB(sb)->clusters = fat_clusters-2; + if (error) { + if (!silent) + printk("VFS: Can't find a valid MSDOS filesystem on dev " + "%s.\n", kdevname(sb->s_dev)); + sb->s_dev = 0; ++ if(MSDOS_SB(sb)->private_data)kfree(MSDOS_SB(sb)->private_data); ++ MSDOS_SB(sb)->private_data=NULL; + MOD_DEC_USE_COUNT; + return NULL; + } +@@ -321,10 +352,16 @@ + memcpy(&(MSDOS_SB(sb)->options), &opts, sizeof(struct fat_mount_options)); + if (!(sb->s_mounted = iget(sb,MSDOS_ROOT_INO))) { + sb->s_dev = 0; ++ if(MSDOS_SB(sb)->private_data)kfree(MSDOS_SB(sb)->private_data); ++ MSDOS_SB(sb)->private_data=NULL; + printk("get root inode failed\n"); + MOD_DEC_USE_COUNT; + return NULL; + } ++ if(i>=0) ++ { MSDOS_SB(sb)->cvf_format=cvf_formats[i]; ++ ++cvf_format_use_count[i]; ++ } + return sb; + } + +@@ -333,7 +370,13 @@ + { + int free,nr; + struct statfs tmp; +- ++ ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_statfs) ++ { MSDOS_SB(sb)->cvf_format->cvf_statfs(sb,buf,bufsiz); ++ return; ++ } ++ + lock_fat(sb); + if (MSDOS_SB(sb)->free_clusters != -1) + free = MSDOS_SB(sb)->free_clusters; +@@ -362,6 +405,10 @@ + int cluster,offset; + + sb = MSDOS_SB(inode->i_sb); ++ if(sb->cvf_format) ++ if(sb->cvf_format->cvf_bmap) ++ return sb->cvf_format->cvf_bmap(inode,block); ++ + if (inode->i_ino == MSDOS_ROOT_INO) { + return sb->dir_start + block; + } +@@ -451,7 +498,12 @@ + !is_exec(raw_entry->ext))) + ? S_IRUGO|S_IWUGO : S_IRWXUGO) + & ~MSDOS_SB(sb)->options.fs_umask) | S_IFREG; +- inode->i_op = (sb->s_blocksize == 1024) ++ if(MSDOS_SB(sb)->cvf_format) ++ inode->i_op = (MSDOS_SB(sb)->cvf_format->flags&CVF_USE_READPAGE) ++ ? &fat_file_inode_operations_readpage ++ : &fat_file_inode_operations_1024; ++ else ++ inode->i_op = (sb->s_blocksize == 1024) + ? &fat_file_inode_operations_1024 + : &fat_file_inode_operations; + MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start); +diff -u -r -N linux-2.0.33-cyrix-patched/fs/fat/misc.c linux-2.0.33-cyrix-patched-test/fs/fat/misc.c +--- linux-2.0.33-cyrix-patched/fs/fat/misc.c Fri May 10 06:54:52 1996 ++++ linux-2.0.33-cyrix-patched-test/fs/fat/misc.c Fri Jan 2 22:35:54 1998 +@@ -186,6 +186,10 @@ + #endif + sector = MSDOS_SB(sb)->data_start+(nr-2)*cluster_size; + last_sector = sector + cluster_size; ++ if(MSDOS_SB(sb)->cvf_format&& ++ MSDOS_SB(sb)->cvf_format->zero_out_cluster) ++ MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode,nr); ++ else + for ( ; sector < last_sector; sector++) { + #ifdef DEBUG + printk("zeroing sector %d\n",sector); +diff -u -r -N linux-2.0.33-cyrix-patched/fs/fat/mmap.c linux-2.0.33-cyrix-patched-test/fs/fat/mmap.c +--- linux-2.0.33-cyrix-patched/fs/fat/mmap.c Fri Feb 9 06:47:16 1996 ++++ linux-2.0.33-cyrix-patched-test/fs/fat/mmap.c Fri Jan 2 20:15:29 1998 +@@ -93,6 +93,9 @@ + */ + int fat_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma) + { ++ if(MSDOS_SB(inode->i_sb)->cvf_format) ++ if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_mmap) ++ return MSDOS_SB(inode->i_sb)->cvf_format->cvf_mmap(inode,file,vma); + if (vma->vm_flags & VM_SHARED) /* only PAGE_COW or read-only supported now */ + return -EINVAL; + if (vma->vm_offset & (inode->i_sb->s_blocksize - 1)) +@@ -110,4 +113,12 @@ + return 0; + } + ++int fat_readpage(struct inode * inode, struct page * page) ++{ ++ if(MSDOS_SB(inode->i_sb)->cvf_format) ++ if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage) ++ return MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage(inode,page); + ++ printk("fat_readpage called with no handler (shouldn't happen)\n"); ++ return -1; ++} +diff -u -r -N linux-2.0.33-cyrix-patched/fs/umsdos/emd.c linux-2.0.33-cyrix-patched-test/fs/umsdos/emd.c +--- linux-2.0.33-cyrix-patched/fs/umsdos/emd.c Wed Feb 7 08:39:29 1996 ++++ linux-2.0.33-cyrix-patched-test/fs/umsdos/emd.c Sat Jan 3 19:13:43 1998 +@@ -32,6 +32,7 @@ + int ret; + int old_fs = get_fs(); + set_fs (KERNEL_DS); ++ MSDOS_I(inode)->i_binary=2; + ret = fat_file_read(inode,filp,buf,count); + set_fs (old_fs); + return ret; +@@ -48,6 +49,7 @@ + int ret; + int old_fs = get_fs(); + set_fs (KERNEL_DS); ++ MSDOS_I(inode)->i_binary=2; + ret = fat_file_write(inode,filp,buf,count); + set_fs (old_fs); + return ret; +diff -u -r -N linux-2.0.33-cyrix-patched/fs/umsdos/file.c linux-2.0.33-cyrix-patched-test/fs/umsdos/file.c +--- linux-2.0.33-cyrix-patched/fs/umsdos/file.c Tue Feb 20 09:28:13 1996 ++++ linux-2.0.33-cyrix-patched-test/fs/umsdos/file.c Fri Jan 2 23:50:57 1998 +@@ -129,3 +129,38 @@ + NULL, /* smap */ + }; + ++/* For other with larger and unaligned file system with readpage */ ++struct file_operations umsdos_file_operations_readpage = { ++ NULL, /* lseek - default */ ++ UMSDOS_file_read, /* read */ ++ UMSDOS_file_write, /* write */ ++ NULL, /* readdir - bad */ ++ NULL, /* select - default */ ++ NULL, /* ioctl - default */ ++ generic_file_mmap, /* mmap */ ++ NULL, /* no special open is needed */ ++ NULL, /* release */ ++ file_fsync /* fsync */ ++}; ++ ++struct inode_operations umsdos_file_inode_operations_readpage = { ++ &umsdos_file_operations_readpage, /* default file operations */ ++ NULL, /* create */ ++ NULL, /* lookup */ ++ NULL, /* link */ ++ NULL, /* unlink */ ++ NULL, /* symlink */ ++ NULL, /* mkdir */ ++ NULL, /* rmdir */ ++ NULL, /* mknod */ ++ NULL, /* rename */ ++ NULL, /* readlink */ ++ NULL, /* follow_link */ ++ fat_readpage, /* readpage */ ++ NULL, /* writepage */ ++ NULL, /* bmap */ ++ UMSDOS_truncate,/* truncate */ ++ NULL, /* permission */ ++ NULL, /* smap */ ++}; ++ +diff -u -r -N linux-2.0.33-cyrix-patched/fs/umsdos/inode.c linux-2.0.33-cyrix-patched-test/fs/umsdos/inode.c +--- linux-2.0.33-cyrix-patched/fs/umsdos/inode.c Sat Nov 30 11:21:22 1996 ++++ linux-2.0.33-cyrix-patched-test/fs/umsdos/inode.c Fri Jan 2 23:55:34 1998 +@@ -149,11 +149,20 @@ + if (!umsdos_isinit(inode)){ + inode->u.umsdos_i.i_emd_dir = 0; + if (S_ISREG(inode->i_mode)){ ++ if (MSDOS_SB(inode->i_sb)->cvf_format){ ++ if (MSDOS_SB(inode->i_sb)->cvf_format->flags ++ &CVF_USE_READPAGE){ ++ inode->i_op = &umsdos_file_inode_operations_readpage; ++ }else{ ++ inode->i_op = &umsdos_file_inode_operations_no_bmap; ++ } ++ } else { + if (inode->i_op->bmap != NULL){ + inode->i_op = &umsdos_file_inode_operations; + }else{ + inode->i_op = &umsdos_file_inode_operations_no_bmap; + } ++ } + }else if (S_ISDIR(inode->i_mode)){ + if (dir != NULL){ + umsdos_setup_dir_inode(inode); +diff -u -r -N linux-2.0.33-cyrix-patched/fs/umsdos/ioctl.c linux-2.0.33-cyrix-patched-test/fs/umsdos/ioctl.c +--- linux-2.0.33-cyrix-patched/fs/umsdos/ioctl.c Wed Jul 3 15:39:48 1996 ++++ linux-2.0.33-cyrix-patched-test/fs/umsdos/ioctl.c Sat Jan 3 13:01:52 1998 +@@ -60,6 +60,21 @@ + { + int ret = -EPERM; + int err; ++ ++ /* forward non-umsdos ioctls - this hopefully doesn't cause conflicts */ ++ if(cmd!=UMSDOS_GETVERSION ++ &&cmd!=UMSDOS_READDIR_DOS ++ &&cmd!=UMSDOS_READDIR_EMD ++ &&cmd!=UMSDOS_INIT_EMD ++ &&cmd!=UMSDOS_CREAT_EMD ++ &&cmd!=UMSDOS_RENAME_DOS ++ &&cmd!=UMSDOS_UNLINK_EMD ++ &&cmd!=UMSDOS_UNLINK_DOS ++ &&cmd!=UMSDOS_RMDIR_DOS ++ &&cmd!=UMSDOS_STAT_DOS ++ &&cmd!=UMSDOS_DOS_SETUP) ++ return fat_dir_ioctl(dir,filp,cmd,data); ++ + /* #Specification: ioctl / acces + Only root (effective id) is allowed to do IOCTL on directory + in UMSDOS. EPERM is returned for other user. +diff -u -r -N linux-2.0.33-cyrix-patched/include/linux/fat_cvf.h linux-2.0.33-cyrix-patched-test/include/linux/fat_cvf.h +--- linux-2.0.33-cyrix-patched/include/linux/fat_cvf.h Thu Jan 1 01:00:00 1970 ++++ linux-2.0.33-cyrix-patched-test/include/linux/fat_cvf.h Sat Jan 3 12:42:28 1998 +@@ -0,0 +1,55 @@ ++#ifndef _FAT_CVF ++#define _FAT_CVF ++ ++#define CVF_USE_READPAGE 0x0001 ++ ++struct cvf_format ++{ int cvf_version; ++ char* cvf_version_text; ++ unsigned long flags; ++ int (*detect_cvf) (struct super_block*sb); ++ int (*mount_cvf) (struct super_block*sb,char*options); ++ int (*unmount_cvf) (struct super_block*sb); ++ struct buffer_head* (*cvf_bread) (struct super_block*sb,int block); ++ struct buffer_head* (*cvf_getblk) (struct super_block*sb,int block); ++ void (*cvf_brelse) (struct super_block *sb,struct buffer_head *bh); ++ void (*cvf_mark_buffer_dirty) (struct super_block *sb, ++ struct buffer_head *bh, ++ int dirty_val); ++ void (*cvf_set_uptodate) (struct super_block *sb, ++ struct buffer_head *bh, ++ int val); ++ int (*cvf_is_uptodate) (struct super_block *sb,struct buffer_head *bh); ++ void (*cvf_ll_rw_block) (struct super_block *sb, ++ int opr, ++ int nbreq, ++ struct buffer_head *bh[32]); ++ int (*fat_access) (struct super_block *sb,int nr,int new_value); ++ void (*cvf_statfs) (struct super_block *sb,struct statfs *buf, int bufsiz); ++ int (*cvf_bmap) (struct inode *inode,int block); ++ int (*cvf_smap) (struct inode *inode,int sector); ++ int (*cvf_file_read) ( struct inode *inode, ++ struct file *filp, ++ char *buf, ++ int count); ++ int (*cvf_file_write) ( struct inode *inode, ++ struct file *filp, ++ const char *buf, ++ int count); ++ int (*cvf_mmap) (struct inode*, struct file *, struct vm_area_struct *); ++ int (*cvf_readpage) (struct inode *, struct page *); ++ int (*cvf_writepage) (struct inode *, struct page *); ++ int (*cvf_dir_ioctl) (struct inode * inode, struct file * filp, ++ unsigned int cmd, unsigned long arg); ++ void (*zero_out_cluster) (struct inode*, int clusternr); ++}; ++ ++int register_cvf_format(struct cvf_format*cvf_format); ++int unregister_cvf_format(struct cvf_format*cvf_format); ++void dec_cvf_format_use_count_by_version(int version); ++int detect_cvf(struct super_block*sb,char*force); ++ ++extern struct cvf_format *cvf_formats[]; ++extern int cvf_format_use_count[]; ++ ++#endif +diff -u -r -N linux-2.0.33-cyrix-patched/include/linux/msdos_fs.h linux-2.0.33-cyrix-patched-test/include/linux/msdos_fs.h +--- linux-2.0.33-cyrix-patched/include/linux/msdos_fs.h Tue Dec 23 22:50:14 1997 ++++ linux-2.0.33-cyrix-patched-test/include/linux/msdos_fs.h Sat Jan 3 13:03:16 1998 +@@ -221,12 +221,14 @@ + /* file.c */ + extern struct inode_operations fat_file_inode_operations; + extern struct inode_operations fat_file_inode_operations_1024; ++extern struct inode_operations fat_file_inode_operations_readpage; + extern int fat_file_read(struct inode *, struct file *, char *, int); + extern int fat_file_write(struct inode *, struct file *, const char *, int); + extern void fat_truncate(struct inode *inode); + + /* mmap.c */ + extern int fat_mmap(struct inode *, struct file *, struct vm_area_struct *); ++extern int fat_readpage(struct inode *, struct page *); + + + /* vfat.c */ +diff -u -r -N linux-2.0.33-cyrix-patched/include/linux/msdos_fs_sb.h linux-2.0.33-cyrix-patched-test/include/linux/msdos_fs_sb.h +--- linux-2.0.33-cyrix-patched/include/linux/msdos_fs_sb.h Mon Mar 11 10:25:58 1996 ++++ linux-2.0.33-cyrix-patched-test/include/linux/msdos_fs_sb.h Sat Jan 3 13:02:03 1998 +@@ -1,5 +1,6 @@ + #ifndef _MSDOS_FS_SB + #define _MSDOS_FS_SB ++#include<linux/fat_cvf.h> + + /* + * MS-DOS file system in-core superblock data +@@ -34,6 +35,8 @@ + int prev_free; /* previously returned free cluster number */ + int free_clusters; /* -1 if undefined */ + struct fat_mount_options options; ++ struct cvf_format* cvf_format; ++ void* private_data; + }; + + #endif +diff -u -r -N linux-2.0.33-cyrix-patched/include/linux/umsdos_fs.h linux-2.0.33-cyrix-patched-test/include/linux/umsdos_fs.h +--- linux-2.0.33-cyrix-patched/include/linux/umsdos_fs.h Tue Dec 23 22:50:14 1997 ++++ linux-2.0.33-cyrix-patched-test/include/linux/umsdos_fs.h Sat Jan 3 13:04:02 1998 +@@ -135,6 +135,7 @@ + extern struct file_operations umsdos_file_operations; + extern struct inode_operations umsdos_file_inode_operations; + extern struct inode_operations umsdos_file_inode_operations_no_bmap; ++extern struct inode_operations umsdos_file_inode_operations_readpage; + extern struct inode_operations umsdos_symlink_inode_operations; + extern int init_umsdos_fs(void); + +diff -u -r -N linux-2.0.33-cyrix-patched/kernel/ksyms.c linux-2.0.33-cyrix-patched-test/kernel/ksyms.c +--- linux-2.0.33-cyrix-patched/kernel/ksyms.c Sat Nov 22 18:26:32 1997 ++++ linux-2.0.33-cyrix-patched-test/kernel/ksyms.c Sat Jan 3 14:03:39 1998 +@@ -123,6 +123,9 @@ + X(do_mmap), + X(do_munmap), + X(exit_mm), ++ X(exit_sighand), ++ X(exit_fs), ++ X(exit_files), + + /* internal kernel memory management */ + X(__get_free_pages), diff --git a/patches/cvf.diff-2.0.33+fat32-0.2.8 b/patches/cvf.diff-2.0.33+fat32-0.2.8 new file mode 100644 index 0000000..4963301 --- /dev/null +++ b/patches/cvf.diff-2.0.33+fat32-0.2.8 @@ -0,0 +1,1074 @@ +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/Documentation/filesystems/fat_cvf.txt linux-2.0.33-cyrix-patched-fat32-test/Documentation/filesystems/fat_cvf.txt +--- linux-2.0.33-cyrix-patched-fat32/Documentation/filesystems/fat_cvf.txt Thu Jan 1 01:00:00 1970 ++++ linux-2.0.33-cyrix-patched-fat32-test/Documentation/filesystems/fat_cvf.txt Wed Nov 18 20:40:50 1998 +@@ -0,0 +1,210 @@ ++This is the main documentation for the CVF-FAT filesystem extension. 18Nov1998 ++ ++ ++Table of Contents: ++ ++1. The idea of CVF-FAT ++2. Restrictions ++3. Mount options ++4. Description of the CVF-FAT interface ++5. CVF Modules ++ ++------------------------------------------------------------------------------ ++ ++ ++1. The idea of CVF-FAT ++------------------------------------------------------------------------------ ++ ++CVF-FAT is a FAT filesystem extension that provides a generic interface for ++Compressed Volume Files in FAT partitions. Popular CVF software, for ++example, are Microsoft's Doublespace/Drivespace and Stac's Stacker. ++Using the CVF-FAT interface, it is possible to load a module that handles ++all the low-level disk access that has to do with on-the-fly compression ++and decompression. Any other part of FAT filesystem access is still handled ++by the FAT, MSDOS or VFAT or even UMSDOS driver. ++ ++CVF access works by redirecting certain low-level routines from the FAT ++driver to a loadable, CVF-format specific module. This module must fake ++a normal FAT filesystem to the FAT driver while doing all the extra stuff ++like compression and decompression silently. ++ ++ ++2. Restrictions ++------------------------------------------------------------------------------ ++ ++- BMAP problems ++ ++ CVF filesystems cannot do bmap. It's impossible in principle. Thus ++ all actions that require bmap do not work (swapping, writable mmapping). ++ Read-only mmapping works because the FAT driver has a hack for this ++ situation :) Well, writable mmapping should now work using the readpage ++ interface function which has been hacked into the FAT driver just for ++ CVF-FAT :) ++ ++- attention, DOSEmu users ++ ++ You may have to unmount all CVF partitions before running DOSEmu depending ++ on your configuration. If DOSEmu is configured to use wholedisk or ++ partition access (this is often the case to let DOSEmu access ++ compressed partitions) there's a risk of destroying your compressed ++ partitions or crashing your system because of confused drivers. ++ ++ Note that it is always safe to redirect the compressed partitions with ++ lredir or emufs.sys. Refer to the DOSEmu documentation for details. ++ ++ ++3. Mount options ++------------------------------------------------------------------------------ ++ ++The CVF-FAT extension currently adds the following options to the FAT ++driver's standard options: ++ ++ cvf_format=xxx ++ Forces the driver to use the CVF module "xxx" instead of auto-detection. ++ Without this option, the CVF-FAT interface asks all currently loaded ++ CVF modules whether they recognize the CVF. Therefore, this option is ++ only necessary if the CVF format is not recognized correctly ++ because of bugs or incompatibilities in the CVF modules. (It skips ++ the detect_cvf call.) "xxx" may be the text "none" (without the quotes) ++ to inhibit using any of the loaded CVF modules, just in case a CVF ++ module insists on mounting plain FAT filesystems by misunderstanding. ++ "xxx" may also be the text "autoload", which has a special meaning for ++ kerneld, but does not skip auto-detection. ++ ++ If the kernel supports kerneld, the cvf_format=xxx option also controls ++ on-demand CVF module loading. Without this option, nothing is loaded ++ on demand. With cvf_format=xxx, a module "xxx" is requested automatically ++ before mounting the compressed filesystem (unless "xxx" is "none"). In ++ case there is a difference between the CVF format name and the module ++ name, setup aliases in your kerneld configuration. If the string "xxx" ++ is "autoload", a non-existent module "cvf_autoload" is requested which ++ can be used together with a special kerneld configuration (alias and ++ pre-install statements) in order to load more than one CVF module, let ++ them detect automatically which kind of CVF is to be mounted, and only ++ keep the "right" module in memory. For examples please refer to the ++ dmsdos documentation (ftp and http addresses see below). ++ ++ cvf_options=yyy ++ Option string passed to the CVF module. I.e. only the "yyy" is passed ++ (without the quotes). The documentation for each CVF module should ++ explain it since it is interpreted only by the CVF module. Note that ++ the string must not contain a comma (",") - this would lead to ++ misinterpretation by the FAT driver, which would recognize the text ++ after a comma as a FAT driver option and might get confused or print ++ strange error messages. The documentation for the CVF module should ++ offer a different separation symbol, for example the dot "." or the ++ plus sign "+", which is only valid inside the string "yyy". ++ ++ ++4. Description of the CVF-FAT interface ++------------------------------------------------------------------------------ ++ ++Assuming you want to write your own CVF module, you need to write a lot of ++interface functions. Most of them are covered in the kernel documentation ++you can find on the net, and thus won't be described here. They have been ++marked with "[...]" :-) Take a look at include/linux/fat_cvf.h. ++ ++struct cvf_format ++{ int cvf_version; ++ char* cvf_version_text; ++ unsigned long int flags; ++ int (*detect_cvf) (struct super_block*sb); ++ int (*mount_cvf) (struct super_block*sb,char*options); ++ int (*unmount_cvf) (struct super_block*sb); ++ [...] ++ void (*cvf_zero_cluster) (struct inode*inode,int clusternr); ++} ++ ++This structure defines the capabilities of a CVF module. It must be filled ++out completely by a CVF module. Consider it as a kind of form that is used ++to introduce the module to the FAT/CVF-FAT driver. ++ ++It contains... ++ - cvf_version: ++ A version id which must be unique. Choose one. ++ - cvf_version_text: ++ A human readable version string that should be one short word ++ describing the CVF format the module implements. This text is used ++ for the cvf_format option. This name must also be unique. ++ - flags: ++ Bit coded flags, currently only used for a readpage/mmap hack that ++ provides both mmap and readpage functionality. If CVF_USE_READPAGE ++ is set, mmap is set to generic_file_mmap and readpage is caught ++ and redirected to the cvf_readpage function. If it is not set, ++ readpage is set to generic_readpage and mmap is caught and redirected ++ to cvf_mmap. (If you want writable mmap use the readpage interface.) ++ - detect_cvf: ++ A function that is called to decide whether the filesystem is a CVF of ++ the type the module supports. The detect_cvf function must return 0 ++ for "NO, I DON'T KNOW THIS GARBAGE" or anything >0 for "YES, THIS IS ++ THE KIND OF CVF I SUPPORT". The function must maintain the module ++ usage counters for safety, i.e. do MOD_INC_USE_COUNT at the beginning ++ and MOD_DEC_USE_COUNT at the end. The function *must not* assume that ++ successful recongition would lead to a call of the mount_cvf function ++ later. ++ - mount_cvf: ++ A function that sets up some values or initializes something additional ++ to what has to be done when a CVF is mounted. This is called at the ++ end of fat_read_super and must return 0 on success. Definitely, this ++ function must increment the module usage counter by MOD_INC_USE_COUNT. ++ This mount_cvf function is also responsible for interpreting a CVF ++ module specific option string (the "yyy" from the FAT mount option ++ "cvf_options=yyy") which cannot contain a comma (use for example the ++ dot "." as option separator symbol). ++ - unmount_cvf: ++ A function that is called when the filesystem is unmounted. Most likely ++ it only frees up some memory and calls MOD_DEC_USE_COUNT. The return ++ value might be ignored (it currently is ignored). ++ - [...]: ++ All other interface functions are "caught" FAT driver functions, i.e. ++ are executed by the FAT driver *instead* of the original FAT driver ++ functions. NULL means use the original FAT driver functions instead. ++ If you really want "no action", write a function that does nothing and ++ hang it in instead. ++ - cvf_zero_cluster: ++ The cvf_zero_cluster function is called when the fat driver wants to ++ zero out a (new) cluster. This is important for directories (mkdir). ++ If it is NULL, the FAT driver defaults to overwriting the whole ++ cluster with zeros. Note that clusternr is absolute, not relative ++ to the provided inode. ++ ++Notes: ++ 1. The cvf_bmap function should be ignored. It really should never ++ get called from somewhere. I recommend redirecting it to a panic ++ or fatal error message so bugs show up immediately. ++ 2. The cvf_writepage function is ignored. This is because the fat ++ driver doesn't support it. This might change in future. I recommend ++ setting it to NULL (i.e use default). ++ ++int register_cvf_format(struct cvf_format*cvf_format); ++ If you have just set up a variable containing the above structure, ++ call this function to introduce your CVF format to the FAT/CVF-FAT ++ driver. This is usually done in init_module. Be sure to check the ++ return value. Zero means success, everything else causes a kernel ++ message printed in the syslog describing the error that occurred. ++ Typical errors are: ++ - a module with the same version id is already registered or ++ - too many CVF formats. Hack fs/fat/cvf.c if you need more. ++ ++int unregister_cvf_format(struct cvf_format*cvf_format); ++ This is usually called in cleanup_module. Return value =0 means ++ success. An error only occurs if you try to unregister a CVF format ++ that has not been previously registered. The code uses the version id ++ to distinguish the modules, so be sure to keep it unique. ++ ++5. CVF Modules ++------------------------------------------------------------------------------ ++ ++Refer to the dmsdos module (the successor of the dmsdos filesystem) for a ++sample implementation. It can currently be found at ++ ++ ftp://fb9nt.uni-duisburg.de/pub/linux/dmsdos/dmsdos-x.y.z.tgz ++ ftp://sunsite.unc.edu/pub/Linux/system/Filesystems/dosfs/dmsdos-x.y.z.tgz ++ ftp://ftp.uni-stuttgart.de/pub/systems/linux/local/system/dmsdos-x.y.z.tgz ++ ++(where x.y.z is to be replaced with the actual version number). Full ++documentation about dmsdos is included in the dmsdos package, but can also ++be found at ++ ++ http://fb9nt.uni-duisburg.de/mitarbeiter/gockel/software/dmsdos/index.html ++ http://www.yk.rim.or.jp/~takafumi/dmsdos/index.html (in Japanese). +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/Makefile linux-2.0.33-cyrix-patched-fat32-test/fs/fat/Makefile +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/Makefile Wed Feb 7 08:39:27 1996 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/Makefile Sun Jan 4 11:59:56 1998 +@@ -8,7 +8,7 @@ + # Note 2! The CFLAGS definitions are now in the main makefile... + + O_TARGET := fat.o +-O_OBJS := buffer.o cache.o dir.o file.o inode.o misc.o mmap.o tables.o ++O_OBJS := buffer.o cache.o dir.o file.o inode.o misc.o mmap.o tables.o cvf.o + OX_OBJS := fatfs_syms.o + M_OBJS := $(O_TARGET) + +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/buffer.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/buffer.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/buffer.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/buffer.c Sun Jan 4 12:07:19 1998 +@@ -9,6 +9,7 @@ + #include <linux/string.h> + #include <linux/fs.h> + #include <linux/msdos_fs.h> ++#include <linux/fat_cvf.h> + + #if 0 + # define PRINTK(x) printk x +@@ -26,6 +27,11 @@ + /* Note that the blocksize is 512 or 1024, but the first read + is always of size 1024. Doing readahead may be counterproductive + or just plain wrong. */ ++ ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_bread) ++ return MSDOS_SB(sb)->cvf_format->cvf_bread(sb,block); ++ + if (sb->s_blocksize == 512) { + ret = bread (sb->s_dev,block,512); + } else { +@@ -81,6 +87,11 @@ + { + struct buffer_head *ret = NULL; + PRINTK(("fat_getblk: block=0x%x\n", block)); ++ ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_getblk) ++ return MSDOS_SB(sb)->cvf_format->cvf_getblk(sb,block); ++ + if (sb->s_blocksize == 512){ + ret = getblk (sb->s_dev,block,512); + }else{ +@@ -100,6 +111,10 @@ + struct buffer_head *bh) + { + if (bh != NULL){ ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_brelse) ++ return MSDOS_SB(sb)->cvf_format->cvf_brelse(sb,bh); ++ + if (sb->s_blocksize == 512){ + brelse (bh); + }else{ +@@ -117,6 +132,12 @@ + struct buffer_head *bh, + int dirty_val) + { ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty) ++ { MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty(sb,bh,dirty_val); ++ return; ++ } ++ + if (sb->s_blocksize != 512){ + bh = bh->b_next; + } +@@ -128,6 +149,12 @@ + struct buffer_head *bh, + int val) + { ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_set_uptodate) ++ { MSDOS_SB(sb)->cvf_format->cvf_set_uptodate(sb,bh,val); ++ return; ++ } ++ + if (sb->s_blocksize != 512){ + bh = bh->b_next; + } +@@ -137,6 +164,10 @@ + struct super_block *sb, + struct buffer_head *bh) + { ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_is_uptodate) ++ return MSDOS_SB(sb)->cvf_format->cvf_is_uptodate(sb,bh); ++ + if (sb->s_blocksize != 512){ + bh = bh->b_next; + } +@@ -149,6 +180,12 @@ + int nbreq, + struct buffer_head *bh[32]) + { ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block) ++ { MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block(sb,opr,nbreq,bh); ++ return; ++ } ++ + if (sb->s_blocksize == 512){ + ll_rw_block(opr,nbreq,bh); + }else{ +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/cache.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/cache.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/cache.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/cache.c Sun Jan 4 12:08:48 1998 +@@ -9,6 +9,7 @@ + #include <linux/errno.h> + #include <linux/string.h> + #include <linux/stat.h> ++#include <linux/fat_cvf.h> + + #include "msbuffer.h" + +@@ -29,6 +30,10 @@ + unsigned char *p_first,*p_last; + int copy,first,last,next,b; + ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->fat_access) ++ return MSDOS_SB(sb)->cvf_format->fat_access(sb,nr,new_value); ++ + if ((unsigned) (nr-2) >= MSDOS_SB(sb)->clusters) + return 0; + if (MSDOS_SB(sb)->fat_bits == 32) { +@@ -261,6 +266,10 @@ + int cluster,offset; + + sb = MSDOS_SB(inode->i_sb); ++ if(sb->cvf_format) ++ if(sb->cvf_format->cvf_smap) ++ return sb->cvf_format->cvf_smap(inode,sector); ++ + if ((sb->fat_bits != 32) && + (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) && + !MSDOS_I(inode)->i_start))) { +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/cvf.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/cvf.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/cvf.c Thu Jan 1 01:00:00 1970 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/cvf.c Tue Nov 17 20:10:41 1998 +@@ -0,0 +1,147 @@ ++/* ++ * CVF extensions for fat-based filesystems ++ * ++ * written 1997,1998 by Frank Gockel <[email protected]> ++ * ++ * please do not remove the next line, dmsdos needs it for verifying patches ++ * CVF-FAT-VERSION-ID: 1.1.0 ++ * ++ */ ++ ++#include<linux/sched.h> ++#include<linux/fs.h> ++#include<linux/msdos_fs.h> ++#include<linux/msdos_fs_sb.h> ++#include<linux/string.h> ++#include<linux/fat_cvf.h> ++#include<linux/config.h> ++#ifdef CONFIG_KERNELD ++#include<linux/kerneld.h> ++#endif ++ ++#define MAX_CVF_FORMATS 3 ++ ++struct cvf_format *cvf_formats[MAX_CVF_FORMATS]={NULL,NULL,NULL}; ++int cvf_format_use_count[MAX_CVF_FORMATS]={0,0,0}; ++ ++int register_cvf_format(struct cvf_format*cvf_format) ++{ int i,j; ++ ++ for(i=0;i<MAX_CVF_FORMATS;++i) ++ { if(cvf_formats[i]==NULL) ++ { /* free slot found, now check version */ ++ for(j=0;j<MAX_CVF_FORMATS;++j) ++ { if(cvf_formats[j]) ++ { if(cvf_formats[j]->cvf_version==cvf_format->cvf_version) ++ { printk("register_cvf_format: version %d already registered\n", ++ cvf_format->cvf_version); ++ return -1; ++ } ++ } ++ } ++ cvf_formats[i]=cvf_format; ++ cvf_format_use_count[i]=0; ++ printk("CVF format %s (version id %d) successfully registered.\n", ++ cvf_format->cvf_version_text,cvf_format->cvf_version); ++ return 0; ++ } ++ } ++ ++ printk("register_cvf_format: too many formats\n"); ++ return -1; ++} ++ ++int unregister_cvf_format(struct cvf_format*cvf_format) ++{ int i; ++ ++ for(i=0;i<MAX_CVF_FORMATS;++i) ++ { if(cvf_formats[i]) ++ { if(cvf_formats[i]->cvf_version==cvf_format->cvf_version) ++ { if(cvf_format_use_count[i]) ++ { printk("unregister_cvf_format: format %d in use, cannot remove!\n", ++ cvf_formats[i]->cvf_version); ++ return -1; ++ } ++ ++ printk("CVF format %s (version id %d) successfully unregistered.\n", ++ cvf_formats[i]->cvf_version_text,cvf_formats[i]->cvf_version); ++ cvf_formats[i]=NULL; ++ return 0; ++ } ++ } ++ } ++ ++ printk("unregister_cvf_format: format %d is not registered\n", ++ cvf_format->cvf_version); ++ return -1; ++} ++ ++void dec_cvf_format_use_count_by_version(int version) ++{ int i; ++ ++ for(i=0;i<MAX_CVF_FORMATS;++i) ++ { if(cvf_formats[i]) ++ { if(cvf_formats[i]->cvf_version==version) ++ { --cvf_format_use_count[i]; ++ if(cvf_format_use_count[i]<0) ++ { cvf_format_use_count[i]=0; ++ printk(KERN_EMERG "FAT FS/CVF: This is a bug in cvf_version_use_count\n"); ++ } ++ return; ++ } ++ } ++ } ++ ++ printk("dec_cvf_format_use_count_by_version: version %d not found ???\n", ++ version); ++} ++ ++int detect_cvf(struct super_block*sb,char*force) ++{ int i; ++ int found=0; ++ int found_i=-1; ++ ++ if(force) ++ if(strcmp(force,"autoload")==0) ++ { ++#ifdef CONFIG_KERNELD ++ request_module("cvf_autoload"); ++ force=NULL; ++#else ++ printk("cannot autoload CVF modules: kerneld support is not compiled into kernel\n"); ++ return -1; ++#endif ++ } ++ ++#ifdef CONFIG_KERNELD ++ if(force) ++ if(*force) ++ request_module(force); ++#endif ++ ++ if(force) ++ { if(*force) ++ { for(i=0;i<MAX_CVF_FORMATS;++i) ++ { if(cvf_formats[i]) ++ { if(!strcmp(cvf_formats[i]->cvf_version_text,force)) ++ return i; ++ } ++ } ++ printk("CVF format %s unknown (module not loaded?)\n",force); ++ return -1; ++ } ++ } ++ ++ for(i=0;i<MAX_CVF_FORMATS;++i) ++ { if(cvf_formats[i]) ++ { if(cvf_formats[i]->detect_cvf(sb)) ++ { ++found; ++ found_i=i; ++ } ++ } ++ } ++ ++ if(found==1)return found_i; ++ if(found>1)printk("CVF detection ambiguous, please use cvf_format=xxx option\n"); ++ return -1; ++} +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/dir.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/dir.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/dir.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/dir.c Sun Jan 4 11:59:56 1998 +@@ -425,6 +425,7 @@ + unsigned int cmd, unsigned long arg) + { + int err; ++ + /* + * We want to provide an interface for Samba to be able + * to get the short filename for a given long filename. +@@ -451,6 +452,11 @@ + vfat_ioctl_fill, NULL, 1, 0, 1); + } + default: ++ /* forward ioctl to CVF extension */ ++ if(MSDOS_SB(inode->i_sb)->cvf_format ++ &&MSDOS_SB(inode->i_sb)->cvf_format->cvf_dir_ioctl) ++ return MSDOS_SB(inode->i_sb)->cvf_format-> ++ cvf_dir_ioctl(inode,filp,cmd,arg); + return -EINVAL; + } + +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/fatfs_syms.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/fatfs_syms.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/fatfs_syms.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/fatfs_syms.c Sun Jan 4 12:11:10 1998 +@@ -11,6 +11,7 @@ + + #include <linux/mm.h> + #include <linux/msdos_fs.h> ++#include <linux/fat_cvf.h> + + #include "msbuffer.h" + +@@ -53,6 +54,13 @@ + X(fat_uni2esc) X_PUNCT + X(fat_unlock_creation) X_PUNCT + X(fat_write_inode) X_PUNCT ++X(register_cvf_format) X_PUNCT ++X(unregister_cvf_format) X_PUNCT ++X(get_cluster) X_PUNCT ++X(lock_fat) X_PUNCT ++X(unlock_fat) X_PUNCT ++X(fat_readpage) X_PUNCT ++X(fat_dir_ioctl) X_PUNCT + #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0) + #include <linux/symtab_end.h> + }; +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/file.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/file.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/file.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/file.c Sun Jan 4 11:59:56 1998 +@@ -17,6 +17,7 @@ + #include <linux/stat.h> + #include <linux/string.h> + #include <linux/pagemap.h> ++#include <linux/fat_cvf.h> + + #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,0) + #include <asm/uaccess.h> +@@ -121,6 +122,40 @@ + NULL /* smap */ + }; + ++static struct file_operations fat_file_operations_readpage = { ++ NULL, /* lseek - default */ ++ fat_file_read, /* read */ ++ fat_file_write, /* write */ ++ NULL, /* readdir - bad */ ++ NULL, /* select - default */ ++ NULL, /* ioctl - default */ ++ generic_file_mmap, /* mmap */ ++ NULL, /* no special open is needed */ ++ NULL, /* release */ ++ file_fsync /* fsync */ ++}; ++ ++struct inode_operations fat_file_inode_operations_readpage = { ++ &fat_file_operations_readpage, /* default file operations */ ++ NULL, /* create */ ++ NULL, /* lookup */ ++ NULL, /* link */ ++ NULL, /* unlink */ ++ NULL, /* symlink */ ++ NULL, /* mkdir */ ++ NULL, /* rmdir */ ++ NULL, /* mknod */ ++ NULL, /* rename */ ++ NULL, /* readlink */ ++ NULL, /* follow_link */ ++ fat_readpage, /* readpage */ ++ NULL, /* writepage */ ++ NULL, /* bmap */ ++ fat_truncate, /* truncate */ ++ NULL, /* permission */ ++ NULL /* smap */ ++}; ++ + #define MSDOS_PREFETCH 32 + struct fat_pre { + int file_sector;/* Next sector to read in the prefetch table */ +@@ -183,6 +218,10 @@ + printk("fat_file_read: inode = NULL\n"); + return -EINVAL; + } ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_file_read) ++ return MSDOS_SB(sb)->cvf_format->cvf_file_read(inode,filp,buf,count); ++ + /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */ + if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) { + printk("fat_file_read: mode = %07o\n",inode->i_mode); +@@ -305,6 +344,10 @@ + printk("fat_file_write: inode = NULL\n"); + return -EINVAL; + } ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_file_write) ++ return MSDOS_SB(sb)->cvf_format->cvf_file_write(inode,filp,buf,count); ++ + /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */ + if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) { + printk("fat_file_write: mode = %07o\n",inode->i_mode); +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/inode.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/inode.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/inode.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/inode.c Sun Jan 4 12:31:18 1998 +@@ -22,6 +22,7 @@ + #include <linux/stat.h> + #include <linux/locks.h> + #include <linux/malloc.h> ++#include <linux/fat_cvf.h> + + #include "msbuffer.h" + +@@ -88,6 +89,10 @@ + + void fat_put_super(struct super_block *sb) + { ++ if(MSDOS_SB(sb)->cvf_format) ++ { dec_cvf_format_use_count_by_version(MSDOS_SB(sb)->cvf_format->cvf_version); ++ MSDOS_SB(sb)->cvf_format->unmount_cvf(sb); ++ } + if (MSDOS_SB(sb)->fat_bits == 32) { + fat_clusters_flush(sb); + } +@@ -113,7 +118,8 @@ + + + static int parse_options(char *options,int *fat, int *blksize, int *debug, +- struct fat_mount_options *opts) ++ struct fat_mount_options *opts, ++ char* cvf_format, char*cvf_options) + { + char *this_char,*value,save,*savep; + char *p; +@@ -239,6 +245,16 @@ + ret = 0; + } + } ++ else if (!strcmp(this_char,"cvf_format")) { ++ if (!value) ++ return 0; ++ strncpy(cvf_format,value,20); ++ } ++ else if (!strcmp(this_char,"cvf_options")) { ++ if (!value) ++ return 0; ++ strncpy(cvf_options,value,100); ++ } + + if (this_char != options) *(this_char-1) = ','; + if (value) *savep = save; +@@ -261,6 +277,14 @@ + struct fat_mount_options opts; + char buf[50]; + char *p; ++ int i; ++ char cvf_format[21]; ++ char cvf_options[101]; ++ ++ cvf_format[0]='\0'; ++ cvf_options[0]='\0'; ++ MSDOS_SB(sb)->cvf_format=NULL; ++ MSDOS_SB(sb)->private_data=NULL; + + MOD_INC_USE_COUNT; + if (hardsect_size[MAJOR(sb->s_dev)] != NULL){ +@@ -270,7 +294,8 @@ + } + } + opts.isvfat = MSDOS_SB(sb)->options.isvfat; +- if (!parse_options((char *) data, &fat, &blksize, &debug, &opts) ++ if (!parse_options((char *) data, &fat, &blksize, &debug, &opts, ++ cvf_format, cvf_options) + || (blksize != 512 && blksize != 1024)) { + sb->s_dev = 0; + MOD_DEC_USE_COUNT; +@@ -375,6 +400,9 @@ + /* because clusters (DOS) are often aligned */ + /* on odd sectors. */ + sb->s_blocksize_bits = blksize == 512 ? 9 : 10; ++ if(!strcmp(cvf_format,"none"))i=-1; ++ else i=detect_cvf(sb,cvf_format); ++ if(i>=0)error=cvf_formats[i]->mount_cvf(sb,cvf_options); + if (error || debug) { + /* The MSDOS_CAN_BMAP is obsolete, but left just to remember */ + printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c," +@@ -392,13 +420,15 @@ + MSDOS_SB(sb)->root_cluster,MSDOS_SB(sb)->free_clusters); + printk ("Transaction block size = %d\n",blksize); + } +- if (MSDOS_SB(sb)->clusters+2 > fat_clusters) ++ if(i<0) if (MSDOS_SB(sb)->clusters+2 > fat_clusters) + MSDOS_SB(sb)->clusters = fat_clusters-2; + if (error) { + if (!silent) + printk("VFS: Can't find a valid MSDOS filesystem on dev " + "%s.\n", kdevname(sb->s_dev)); + sb->s_dev = 0; ++ if(MSDOS_SB(sb)->private_data)kfree(MSDOS_SB(sb)->private_data); ++ MSDOS_SB(sb)->private_data=NULL; + MOD_DEC_USE_COUNT; + return NULL; + } +@@ -419,6 +449,8 @@ + MSDOS_SB(sb)->nls_disk = load_nls_default(); + } else { + sb->s_dev = 0; ++ if(MSDOS_SB(sb)->private_data)kfree(MSDOS_SB(sb)->private_data); ++ MSDOS_SB(sb)->private_data=NULL; + MOD_DEC_USE_COUNT; + return NULL; + } +@@ -433,6 +465,8 @@ + kfree(opts.iocharset); + unload_nls(MSDOS_SB(sb)->nls_disk); + sb->s_dev = 0; ++ if(MSDOS_SB(sb)->private_data)kfree(MSDOS_SB(sb)->private_data); ++ MSDOS_SB(sb)->private_data=NULL; + MOD_DEC_USE_COUNT; + return NULL; + } else { +@@ -447,9 +481,16 @@ + unload_nls(MSDOS_SB(sb)->nls_disk); + if (MSDOS_SB(sb)->nls_io) unload_nls(MSDOS_SB(sb)->nls_io); + if (opts.iocharset) kfree(opts.iocharset); ++ if(MSDOS_SB(sb)->private_data)kfree(MSDOS_SB(sb)->private_data); ++ MSDOS_SB(sb)->private_data=NULL; + MOD_DEC_USE_COUNT; + return NULL; + } ++ ++ if(i>=0) ++ { MSDOS_SB(sb)->cvf_format=cvf_formats[i]; ++ ++cvf_format_use_count[i]; ++ } + + return sb; + } +@@ -459,7 +500,13 @@ + { + int free,nr; + struct statfs tmp; +- ++ ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_statfs) ++ { MSDOS_SB(sb)->cvf_format->cvf_statfs(sb,buf,bufsiz); ++ return; ++ } ++ + lock_fat(sb); + if (MSDOS_SB(sb)->free_clusters != -1) + free = MSDOS_SB(sb)->free_clusters; +@@ -488,6 +535,10 @@ + int cluster,offset; + + sb = MSDOS_SB(inode->i_sb); ++ if(sb->cvf_format) ++ if(sb->cvf_format->cvf_bmap) ++ return sb->cvf_format->cvf_bmap(inode,block); ++ + if ((inode->i_ino == MSDOS_ROOT_INO) && (sb->fat_bits != 32)) { + return sb->dir_start + block; + } +@@ -600,7 +651,12 @@ + !is_exec(raw_entry->ext))) + ? S_IRUGO|S_IWUGO : S_IRWXUGO) + & ~MSDOS_SB(sb)->options.fs_umask) | S_IFREG; +- inode->i_op = (sb->s_blocksize == 1024) ++ if(MSDOS_SB(sb)->cvf_format) ++ inode->i_op = (MSDOS_SB(sb)->cvf_format->flags&CVF_USE_READPAGE) ++ ? &fat_file_inode_operations_readpage ++ : &fat_file_inode_operations_1024; ++ else ++ inode->i_op = (sb->s_blocksize == 1024) + ? &fat_file_inode_operations_1024 + : &fat_file_inode_operations; + MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start); +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/misc.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/misc.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/misc.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/misc.c Sun Jan 4 11:59:56 1998 +@@ -225,6 +225,10 @@ + #endif + sector = MSDOS_SB(sb)->data_start+(nr-2)*cluster_size; + last_sector = sector + cluster_size; ++ if(MSDOS_SB(sb)->cvf_format&& ++ MSDOS_SB(sb)->cvf_format->zero_out_cluster) ++ MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode,nr); ++ else + for ( ; sector < last_sector; sector++) { + #ifdef DEBUG + printk("zeroing sector %d\n",sector); +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/mmap.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/mmap.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/mmap.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/mmap.c Sun Jan 4 11:59:56 1998 +@@ -100,6 +100,9 @@ + */ + int fat_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma) + { ++ if(MSDOS_SB(inode->i_sb)->cvf_format) ++ if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_mmap) ++ return MSDOS_SB(inode->i_sb)->cvf_format->cvf_mmap(inode,file,vma); + if (vma->vm_flags & VM_SHARED) /* only PAGE_COW or read-only supported now */ + return -EINVAL; + if (vma->vm_offset & (inode->i_sb->s_blocksize - 1)) +@@ -117,4 +120,12 @@ + return 0; + } + ++int fat_readpage(struct inode * inode, struct page * page) ++{ ++ if(MSDOS_SB(inode->i_sb)->cvf_format) ++ if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage) ++ return MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage(inode,page); + ++ printk("fat_readpage called with no handler (shouldn't happen)\n"); ++ return -1; ++} +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/umsdos/emd.c linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/emd.c +--- linux-2.0.33-cyrix-patched-fat32/fs/umsdos/emd.c Wed Feb 7 08:39:29 1996 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/emd.c Sun Jan 4 11:59:56 1998 +@@ -32,6 +32,7 @@ + int ret; + int old_fs = get_fs(); + set_fs (KERNEL_DS); ++ MSDOS_I(inode)->i_binary=2; + ret = fat_file_read(inode,filp,buf,count); + set_fs (old_fs); + return ret; +@@ -48,6 +49,7 @@ + int ret; + int old_fs = get_fs(); + set_fs (KERNEL_DS); ++ MSDOS_I(inode)->i_binary=2; + ret = fat_file_write(inode,filp,buf,count); + set_fs (old_fs); + return ret; +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/umsdos/file.c linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/file.c +--- linux-2.0.33-cyrix-patched-fat32/fs/umsdos/file.c Tue Feb 20 09:28:13 1996 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/file.c Sun Jan 4 11:59:56 1998 +@@ -129,3 +129,38 @@ + NULL, /* smap */ + }; + ++/* For other with larger and unaligned file system with readpage */ ++struct file_operations umsdos_file_operations_readpage = { ++ NULL, /* lseek - default */ ++ UMSDOS_file_read, /* read */ ++ UMSDOS_file_write, /* write */ ++ NULL, /* readdir - bad */ ++ NULL, /* select - default */ ++ NULL, /* ioctl - default */ ++ generic_file_mmap, /* mmap */ ++ NULL, /* no special open is needed */ ++ NULL, /* release */ ++ file_fsync /* fsync */ ++}; ++ ++struct inode_operations umsdos_file_inode_operations_readpage = { ++ &umsdos_file_operations_readpage, /* default file operations */ ++ NULL, /* create */ ++ NULL, /* lookup */ ++ NULL, /* link */ ++ NULL, /* unlink */ ++ NULL, /* symlink */ ++ NULL, /* mkdir */ ++ NULL, /* rmdir */ ++ NULL, /* mknod */ ++ NULL, /* rename */ ++ NULL, /* readlink */ ++ NULL, /* follow_link */ ++ fat_readpage, /* readpage */ ++ NULL, /* writepage */ ++ NULL, /* bmap */ ++ UMSDOS_truncate,/* truncate */ ++ NULL, /* permission */ ++ NULL, /* smap */ ++}; ++ +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/umsdos/inode.c linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/inode.c +--- linux-2.0.33-cyrix-patched-fat32/fs/umsdos/inode.c Sat Nov 30 11:21:22 1996 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/inode.c Sun Jan 4 11:59:56 1998 +@@ -149,11 +149,20 @@ + if (!umsdos_isinit(inode)){ + inode->u.umsdos_i.i_emd_dir = 0; + if (S_ISREG(inode->i_mode)){ ++ if (MSDOS_SB(inode->i_sb)->cvf_format){ ++ if (MSDOS_SB(inode->i_sb)->cvf_format->flags ++ &CVF_USE_READPAGE){ ++ inode->i_op = &umsdos_file_inode_operations_readpage; ++ }else{ ++ inode->i_op = &umsdos_file_inode_operations_no_bmap; ++ } ++ } else { + if (inode->i_op->bmap != NULL){ + inode->i_op = &umsdos_file_inode_operations; + }else{ + inode->i_op = &umsdos_file_inode_operations_no_bmap; + } ++ } + }else if (S_ISDIR(inode->i_mode)){ + if (dir != NULL){ + umsdos_setup_dir_inode(inode); +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/umsdos/ioctl.c linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/ioctl.c +--- linux-2.0.33-cyrix-patched-fat32/fs/umsdos/ioctl.c Wed Jul 3 15:39:48 1996 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/ioctl.c Sun Jan 4 11:59:56 1998 +@@ -60,6 +60,21 @@ + { + int ret = -EPERM; + int err; ++ ++ /* forward non-umsdos ioctls - this hopefully doesn't cause conflicts */ ++ if(cmd!=UMSDOS_GETVERSION ++ &&cmd!=UMSDOS_READDIR_DOS ++ &&cmd!=UMSDOS_READDIR_EMD ++ &&cmd!=UMSDOS_INIT_EMD ++ &&cmd!=UMSDOS_CREAT_EMD ++ &&cmd!=UMSDOS_RENAME_DOS ++ &&cmd!=UMSDOS_UNLINK_EMD ++ &&cmd!=UMSDOS_UNLINK_DOS ++ &&cmd!=UMSDOS_RMDIR_DOS ++ &&cmd!=UMSDOS_STAT_DOS ++ &&cmd!=UMSDOS_DOS_SETUP) ++ return fat_dir_ioctl(dir,filp,cmd,data); ++ + /* #Specification: ioctl / acces + Only root (effective id) is allowed to do IOCTL on directory + in UMSDOS. EPERM is returned for other user. +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/include/linux/fat_cvf.h linux-2.0.33-cyrix-patched-fat32-test/include/linux/fat_cvf.h +--- linux-2.0.33-cyrix-patched-fat32/include/linux/fat_cvf.h Thu Jan 1 01:00:00 1970 ++++ linux-2.0.33-cyrix-patched-fat32-test/include/linux/fat_cvf.h Sun Jan 4 11:59:56 1998 +@@ -0,0 +1,55 @@ ++#ifndef _FAT_CVF ++#define _FAT_CVF ++ ++#define CVF_USE_READPAGE 0x0001 ++ ++struct cvf_format ++{ int cvf_version; ++ char* cvf_version_text; ++ unsigned long flags; ++ int (*detect_cvf) (struct super_block*sb); ++ int (*mount_cvf) (struct super_block*sb,char*options); ++ int (*unmount_cvf) (struct super_block*sb); ++ struct buffer_head* (*cvf_bread) (struct super_block*sb,int block); ++ struct buffer_head* (*cvf_getblk) (struct super_block*sb,int block); ++ void (*cvf_brelse) (struct super_block *sb,struct buffer_head *bh); ++ void (*cvf_mark_buffer_dirty) (struct super_block *sb, ++ struct buffer_head *bh, ++ int dirty_val); ++ void (*cvf_set_uptodate) (struct super_block *sb, ++ struct buffer_head *bh, ++ int val); ++ int (*cvf_is_uptodate) (struct super_block *sb,struct buffer_head *bh); ++ void (*cvf_ll_rw_block) (struct super_block *sb, ++ int opr, ++ int nbreq, ++ struct buffer_head *bh[32]); ++ int (*fat_access) (struct super_block *sb,int nr,int new_value); ++ void (*cvf_statfs) (struct super_block *sb,struct statfs *buf, int bufsiz); ++ int (*cvf_bmap) (struct inode *inode,int block); ++ int (*cvf_smap) (struct inode *inode,int sector); ++ int (*cvf_file_read) ( struct inode *inode, ++ struct file *filp, ++ char *buf, ++ int count); ++ int (*cvf_file_write) ( struct inode *inode, ++ struct file *filp, ++ const char *buf, ++ int count); ++ int (*cvf_mmap) (struct inode*, struct file *, struct vm_area_struct *); ++ int (*cvf_readpage) (struct inode *, struct page *); ++ int (*cvf_writepage) (struct inode *, struct page *); ++ int (*cvf_dir_ioctl) (struct inode * inode, struct file * filp, ++ unsigned int cmd, unsigned long arg); ++ void (*zero_out_cluster) (struct inode*, int clusternr); ++}; ++ ++int register_cvf_format(struct cvf_format*cvf_format); ++int unregister_cvf_format(struct cvf_format*cvf_format); ++void dec_cvf_format_use_count_by_version(int version); ++int detect_cvf(struct super_block*sb,char*force); ++ ++extern struct cvf_format *cvf_formats[]; ++extern int cvf_format_use_count[]; ++ ++#endif +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/include/linux/msdos_fs.h linux-2.0.33-cyrix-patched-fat32-test/include/linux/msdos_fs.h +--- linux-2.0.33-cyrix-patched-fat32/include/linux/msdos_fs.h Sun Jan 4 11:55:33 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/include/linux/msdos_fs.h Sun Jan 4 12:40:48 1998 +@@ -246,12 +246,14 @@ + /* file.c */ + extern struct inode_operations fat_file_inode_operations; + extern struct inode_operations fat_file_inode_operations_1024; ++extern struct inode_operations fat_file_inode_operations_readpage; + extern int fat_file_read(struct inode *, struct file *, char *, int); + extern int fat_file_write(struct inode *, struct file *, const char *, int); + extern void fat_truncate(struct inode *inode); + + /* mmap.c */ + extern int fat_mmap(struct inode *, struct file *, struct vm_area_struct *); ++extern int fat_readpage(struct inode *, struct page *); + + + /* vfat.c */ +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/include/linux/msdos_fs_sb.h linux-2.0.33-cyrix-patched-fat32-test/include/linux/msdos_fs_sb.h +--- linux-2.0.33-cyrix-patched-fat32/include/linux/msdos_fs_sb.h Sun Jan 4 11:55:33 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/include/linux/msdos_fs_sb.h Sun Jan 4 12:02:05 1998 +@@ -1,5 +1,6 @@ + #ifndef _MSDOS_FS_SB + #define _MSDOS_FS_SB ++#include<linux/fat_cvf.h> + + /* + * MS-DOS file system in-core superblock data +@@ -46,6 +47,8 @@ + struct fat_mount_options options; + struct nls_table *nls_disk; /* Codepage used on disk */ + struct nls_table *nls_io; /* Charset used for input and display */ ++ struct cvf_format* cvf_format; ++ void* private_data; + }; + + #endif +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/include/linux/umsdos_fs.h linux-2.0.33-cyrix-patched-fat32-test/include/linux/umsdos_fs.h +--- linux-2.0.33-cyrix-patched-fat32/include/linux/umsdos_fs.h Tue Dec 23 22:50:14 1997 ++++ linux-2.0.33-cyrix-patched-fat32-test/include/linux/umsdos_fs.h Sun Jan 4 12:40:48 1998 +@@ -135,6 +135,7 @@ + extern struct file_operations umsdos_file_operations; + extern struct inode_operations umsdos_file_inode_operations; + extern struct inode_operations umsdos_file_inode_operations_no_bmap; ++extern struct inode_operations umsdos_file_inode_operations_readpage; + extern struct inode_operations umsdos_symlink_inode_operations; + extern int init_umsdos_fs(void); + +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/kernel/ksyms.c linux-2.0.33-cyrix-patched-fat32-test/kernel/ksyms.c +--- linux-2.0.33-cyrix-patched-fat32/kernel/ksyms.c Sun Jan 4 11:55:33 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/kernel/ksyms.c Sun Jan 4 11:59:56 1998 +@@ -124,6 +124,9 @@ + X(do_mmap), + X(do_munmap), + X(exit_mm), ++ X(exit_sighand), ++ X(exit_fs), ++ X(exit_files), + + /* internal kernel memory management */ + X(__get_free_pages), diff --git a/patches/cvf.diff-2.0.34 b/patches/cvf.diff-2.0.34 new file mode 100644 index 0000000..4963301 --- /dev/null +++ b/patches/cvf.diff-2.0.34 @@ -0,0 +1,1074 @@ +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/Documentation/filesystems/fat_cvf.txt linux-2.0.33-cyrix-patched-fat32-test/Documentation/filesystems/fat_cvf.txt +--- linux-2.0.33-cyrix-patched-fat32/Documentation/filesystems/fat_cvf.txt Thu Jan 1 01:00:00 1970 ++++ linux-2.0.33-cyrix-patched-fat32-test/Documentation/filesystems/fat_cvf.txt Wed Nov 18 20:40:50 1998 +@@ -0,0 +1,210 @@ ++This is the main documentation for the CVF-FAT filesystem extension. 18Nov1998 ++ ++ ++Table of Contents: ++ ++1. The idea of CVF-FAT ++2. Restrictions ++3. Mount options ++4. Description of the CVF-FAT interface ++5. CVF Modules ++ ++------------------------------------------------------------------------------ ++ ++ ++1. The idea of CVF-FAT ++------------------------------------------------------------------------------ ++ ++CVF-FAT is a FAT filesystem extension that provides a generic interface for ++Compressed Volume Files in FAT partitions. Popular CVF software, for ++example, are Microsoft's Doublespace/Drivespace and Stac's Stacker. ++Using the CVF-FAT interface, it is possible to load a module that handles ++all the low-level disk access that has to do with on-the-fly compression ++and decompression. Any other part of FAT filesystem access is still handled ++by the FAT, MSDOS or VFAT or even UMSDOS driver. ++ ++CVF access works by redirecting certain low-level routines from the FAT ++driver to a loadable, CVF-format specific module. This module must fake ++a normal FAT filesystem to the FAT driver while doing all the extra stuff ++like compression and decompression silently. ++ ++ ++2. Restrictions ++------------------------------------------------------------------------------ ++ ++- BMAP problems ++ ++ CVF filesystems cannot do bmap. It's impossible in principle. Thus ++ all actions that require bmap do not work (swapping, writable mmapping). ++ Read-only mmapping works because the FAT driver has a hack for this ++ situation :) Well, writable mmapping should now work using the readpage ++ interface function which has been hacked into the FAT driver just for ++ CVF-FAT :) ++ ++- attention, DOSEmu users ++ ++ You may have to unmount all CVF partitions before running DOSEmu depending ++ on your configuration. If DOSEmu is configured to use wholedisk or ++ partition access (this is often the case to let DOSEmu access ++ compressed partitions) there's a risk of destroying your compressed ++ partitions or crashing your system because of confused drivers. ++ ++ Note that it is always safe to redirect the compressed partitions with ++ lredir or emufs.sys. Refer to the DOSEmu documentation for details. ++ ++ ++3. Mount options ++------------------------------------------------------------------------------ ++ ++The CVF-FAT extension currently adds the following options to the FAT ++driver's standard options: ++ ++ cvf_format=xxx ++ Forces the driver to use the CVF module "xxx" instead of auto-detection. ++ Without this option, the CVF-FAT interface asks all currently loaded ++ CVF modules whether they recognize the CVF. Therefore, this option is ++ only necessary if the CVF format is not recognized correctly ++ because of bugs or incompatibilities in the CVF modules. (It skips ++ the detect_cvf call.) "xxx" may be the text "none" (without the quotes) ++ to inhibit using any of the loaded CVF modules, just in case a CVF ++ module insists on mounting plain FAT filesystems by misunderstanding. ++ "xxx" may also be the text "autoload", which has a special meaning for ++ kerneld, but does not skip auto-detection. ++ ++ If the kernel supports kerneld, the cvf_format=xxx option also controls ++ on-demand CVF module loading. Without this option, nothing is loaded ++ on demand. With cvf_format=xxx, a module "xxx" is requested automatically ++ before mounting the compressed filesystem (unless "xxx" is "none"). In ++ case there is a difference between the CVF format name and the module ++ name, setup aliases in your kerneld configuration. If the string "xxx" ++ is "autoload", a non-existent module "cvf_autoload" is requested which ++ can be used together with a special kerneld configuration (alias and ++ pre-install statements) in order to load more than one CVF module, let ++ them detect automatically which kind of CVF is to be mounted, and only ++ keep the "right" module in memory. For examples please refer to the ++ dmsdos documentation (ftp and http addresses see below). ++ ++ cvf_options=yyy ++ Option string passed to the CVF module. I.e. only the "yyy" is passed ++ (without the quotes). The documentation for each CVF module should ++ explain it since it is interpreted only by the CVF module. Note that ++ the string must not contain a comma (",") - this would lead to ++ misinterpretation by the FAT driver, which would recognize the text ++ after a comma as a FAT driver option and might get confused or print ++ strange error messages. The documentation for the CVF module should ++ offer a different separation symbol, for example the dot "." or the ++ plus sign "+", which is only valid inside the string "yyy". ++ ++ ++4. Description of the CVF-FAT interface ++------------------------------------------------------------------------------ ++ ++Assuming you want to write your own CVF module, you need to write a lot of ++interface functions. Most of them are covered in the kernel documentation ++you can find on the net, and thus won't be described here. They have been ++marked with "[...]" :-) Take a look at include/linux/fat_cvf.h. ++ ++struct cvf_format ++{ int cvf_version; ++ char* cvf_version_text; ++ unsigned long int flags; ++ int (*detect_cvf) (struct super_block*sb); ++ int (*mount_cvf) (struct super_block*sb,char*options); ++ int (*unmount_cvf) (struct super_block*sb); ++ [...] ++ void (*cvf_zero_cluster) (struct inode*inode,int clusternr); ++} ++ ++This structure defines the capabilities of a CVF module. It must be filled ++out completely by a CVF module. Consider it as a kind of form that is used ++to introduce the module to the FAT/CVF-FAT driver. ++ ++It contains... ++ - cvf_version: ++ A version id which must be unique. Choose one. ++ - cvf_version_text: ++ A human readable version string that should be one short word ++ describing the CVF format the module implements. This text is used ++ for the cvf_format option. This name must also be unique. ++ - flags: ++ Bit coded flags, currently only used for a readpage/mmap hack that ++ provides both mmap and readpage functionality. If CVF_USE_READPAGE ++ is set, mmap is set to generic_file_mmap and readpage is caught ++ and redirected to the cvf_readpage function. If it is not set, ++ readpage is set to generic_readpage and mmap is caught and redirected ++ to cvf_mmap. (If you want writable mmap use the readpage interface.) ++ - detect_cvf: ++ A function that is called to decide whether the filesystem is a CVF of ++ the type the module supports. The detect_cvf function must return 0 ++ for "NO, I DON'T KNOW THIS GARBAGE" or anything >0 for "YES, THIS IS ++ THE KIND OF CVF I SUPPORT". The function must maintain the module ++ usage counters for safety, i.e. do MOD_INC_USE_COUNT at the beginning ++ and MOD_DEC_USE_COUNT at the end. The function *must not* assume that ++ successful recongition would lead to a call of the mount_cvf function ++ later. ++ - mount_cvf: ++ A function that sets up some values or initializes something additional ++ to what has to be done when a CVF is mounted. This is called at the ++ end of fat_read_super and must return 0 on success. Definitely, this ++ function must increment the module usage counter by MOD_INC_USE_COUNT. ++ This mount_cvf function is also responsible for interpreting a CVF ++ module specific option string (the "yyy" from the FAT mount option ++ "cvf_options=yyy") which cannot contain a comma (use for example the ++ dot "." as option separator symbol). ++ - unmount_cvf: ++ A function that is called when the filesystem is unmounted. Most likely ++ it only frees up some memory and calls MOD_DEC_USE_COUNT. The return ++ value might be ignored (it currently is ignored). ++ - [...]: ++ All other interface functions are "caught" FAT driver functions, i.e. ++ are executed by the FAT driver *instead* of the original FAT driver ++ functions. NULL means use the original FAT driver functions instead. ++ If you really want "no action", write a function that does nothing and ++ hang it in instead. ++ - cvf_zero_cluster: ++ The cvf_zero_cluster function is called when the fat driver wants to ++ zero out a (new) cluster. This is important for directories (mkdir). ++ If it is NULL, the FAT driver defaults to overwriting the whole ++ cluster with zeros. Note that clusternr is absolute, not relative ++ to the provided inode. ++ ++Notes: ++ 1. The cvf_bmap function should be ignored. It really should never ++ get called from somewhere. I recommend redirecting it to a panic ++ or fatal error message so bugs show up immediately. ++ 2. The cvf_writepage function is ignored. This is because the fat ++ driver doesn't support it. This might change in future. I recommend ++ setting it to NULL (i.e use default). ++ ++int register_cvf_format(struct cvf_format*cvf_format); ++ If you have just set up a variable containing the above structure, ++ call this function to introduce your CVF format to the FAT/CVF-FAT ++ driver. This is usually done in init_module. Be sure to check the ++ return value. Zero means success, everything else causes a kernel ++ message printed in the syslog describing the error that occurred. ++ Typical errors are: ++ - a module with the same version id is already registered or ++ - too many CVF formats. Hack fs/fat/cvf.c if you need more. ++ ++int unregister_cvf_format(struct cvf_format*cvf_format); ++ This is usually called in cleanup_module. Return value =0 means ++ success. An error only occurs if you try to unregister a CVF format ++ that has not been previously registered. The code uses the version id ++ to distinguish the modules, so be sure to keep it unique. ++ ++5. CVF Modules ++------------------------------------------------------------------------------ ++ ++Refer to the dmsdos module (the successor of the dmsdos filesystem) for a ++sample implementation. It can currently be found at ++ ++ ftp://fb9nt.uni-duisburg.de/pub/linux/dmsdos/dmsdos-x.y.z.tgz ++ ftp://sunsite.unc.edu/pub/Linux/system/Filesystems/dosfs/dmsdos-x.y.z.tgz ++ ftp://ftp.uni-stuttgart.de/pub/systems/linux/local/system/dmsdos-x.y.z.tgz ++ ++(where x.y.z is to be replaced with the actual version number). Full ++documentation about dmsdos is included in the dmsdos package, but can also ++be found at ++ ++ http://fb9nt.uni-duisburg.de/mitarbeiter/gockel/software/dmsdos/index.html ++ http://www.yk.rim.or.jp/~takafumi/dmsdos/index.html (in Japanese). +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/Makefile linux-2.0.33-cyrix-patched-fat32-test/fs/fat/Makefile +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/Makefile Wed Feb 7 08:39:27 1996 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/Makefile Sun Jan 4 11:59:56 1998 +@@ -8,7 +8,7 @@ + # Note 2! The CFLAGS definitions are now in the main makefile... + + O_TARGET := fat.o +-O_OBJS := buffer.o cache.o dir.o file.o inode.o misc.o mmap.o tables.o ++O_OBJS := buffer.o cache.o dir.o file.o inode.o misc.o mmap.o tables.o cvf.o + OX_OBJS := fatfs_syms.o + M_OBJS := $(O_TARGET) + +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/buffer.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/buffer.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/buffer.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/buffer.c Sun Jan 4 12:07:19 1998 +@@ -9,6 +9,7 @@ + #include <linux/string.h> + #include <linux/fs.h> + #include <linux/msdos_fs.h> ++#include <linux/fat_cvf.h> + + #if 0 + # define PRINTK(x) printk x +@@ -26,6 +27,11 @@ + /* Note that the blocksize is 512 or 1024, but the first read + is always of size 1024. Doing readahead may be counterproductive + or just plain wrong. */ ++ ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_bread) ++ return MSDOS_SB(sb)->cvf_format->cvf_bread(sb,block); ++ + if (sb->s_blocksize == 512) { + ret = bread (sb->s_dev,block,512); + } else { +@@ -81,6 +87,11 @@ + { + struct buffer_head *ret = NULL; + PRINTK(("fat_getblk: block=0x%x\n", block)); ++ ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_getblk) ++ return MSDOS_SB(sb)->cvf_format->cvf_getblk(sb,block); ++ + if (sb->s_blocksize == 512){ + ret = getblk (sb->s_dev,block,512); + }else{ +@@ -100,6 +111,10 @@ + struct buffer_head *bh) + { + if (bh != NULL){ ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_brelse) ++ return MSDOS_SB(sb)->cvf_format->cvf_brelse(sb,bh); ++ + if (sb->s_blocksize == 512){ + brelse (bh); + }else{ +@@ -117,6 +132,12 @@ + struct buffer_head *bh, + int dirty_val) + { ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty) ++ { MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty(sb,bh,dirty_val); ++ return; ++ } ++ + if (sb->s_blocksize != 512){ + bh = bh->b_next; + } +@@ -128,6 +149,12 @@ + struct buffer_head *bh, + int val) + { ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_set_uptodate) ++ { MSDOS_SB(sb)->cvf_format->cvf_set_uptodate(sb,bh,val); ++ return; ++ } ++ + if (sb->s_blocksize != 512){ + bh = bh->b_next; + } +@@ -137,6 +164,10 @@ + struct super_block *sb, + struct buffer_head *bh) + { ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_is_uptodate) ++ return MSDOS_SB(sb)->cvf_format->cvf_is_uptodate(sb,bh); ++ + if (sb->s_blocksize != 512){ + bh = bh->b_next; + } +@@ -149,6 +180,12 @@ + int nbreq, + struct buffer_head *bh[32]) + { ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block) ++ { MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block(sb,opr,nbreq,bh); ++ return; ++ } ++ + if (sb->s_blocksize == 512){ + ll_rw_block(opr,nbreq,bh); + }else{ +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/cache.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/cache.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/cache.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/cache.c Sun Jan 4 12:08:48 1998 +@@ -9,6 +9,7 @@ + #include <linux/errno.h> + #include <linux/string.h> + #include <linux/stat.h> ++#include <linux/fat_cvf.h> + + #include "msbuffer.h" + +@@ -29,6 +30,10 @@ + unsigned char *p_first,*p_last; + int copy,first,last,next,b; + ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->fat_access) ++ return MSDOS_SB(sb)->cvf_format->fat_access(sb,nr,new_value); ++ + if ((unsigned) (nr-2) >= MSDOS_SB(sb)->clusters) + return 0; + if (MSDOS_SB(sb)->fat_bits == 32) { +@@ -261,6 +266,10 @@ + int cluster,offset; + + sb = MSDOS_SB(inode->i_sb); ++ if(sb->cvf_format) ++ if(sb->cvf_format->cvf_smap) ++ return sb->cvf_format->cvf_smap(inode,sector); ++ + if ((sb->fat_bits != 32) && + (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) && + !MSDOS_I(inode)->i_start))) { +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/cvf.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/cvf.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/cvf.c Thu Jan 1 01:00:00 1970 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/cvf.c Tue Nov 17 20:10:41 1998 +@@ -0,0 +1,147 @@ ++/* ++ * CVF extensions for fat-based filesystems ++ * ++ * written 1997,1998 by Frank Gockel <[email protected]> ++ * ++ * please do not remove the next line, dmsdos needs it for verifying patches ++ * CVF-FAT-VERSION-ID: 1.1.0 ++ * ++ */ ++ ++#include<linux/sched.h> ++#include<linux/fs.h> ++#include<linux/msdos_fs.h> ++#include<linux/msdos_fs_sb.h> ++#include<linux/string.h> ++#include<linux/fat_cvf.h> ++#include<linux/config.h> ++#ifdef CONFIG_KERNELD ++#include<linux/kerneld.h> ++#endif ++ ++#define MAX_CVF_FORMATS 3 ++ ++struct cvf_format *cvf_formats[MAX_CVF_FORMATS]={NULL,NULL,NULL}; ++int cvf_format_use_count[MAX_CVF_FORMATS]={0,0,0}; ++ ++int register_cvf_format(struct cvf_format*cvf_format) ++{ int i,j; ++ ++ for(i=0;i<MAX_CVF_FORMATS;++i) ++ { if(cvf_formats[i]==NULL) ++ { /* free slot found, now check version */ ++ for(j=0;j<MAX_CVF_FORMATS;++j) ++ { if(cvf_formats[j]) ++ { if(cvf_formats[j]->cvf_version==cvf_format->cvf_version) ++ { printk("register_cvf_format: version %d already registered\n", ++ cvf_format->cvf_version); ++ return -1; ++ } ++ } ++ } ++ cvf_formats[i]=cvf_format; ++ cvf_format_use_count[i]=0; ++ printk("CVF format %s (version id %d) successfully registered.\n", ++ cvf_format->cvf_version_text,cvf_format->cvf_version); ++ return 0; ++ } ++ } ++ ++ printk("register_cvf_format: too many formats\n"); ++ return -1; ++} ++ ++int unregister_cvf_format(struct cvf_format*cvf_format) ++{ int i; ++ ++ for(i=0;i<MAX_CVF_FORMATS;++i) ++ { if(cvf_formats[i]) ++ { if(cvf_formats[i]->cvf_version==cvf_format->cvf_version) ++ { if(cvf_format_use_count[i]) ++ { printk("unregister_cvf_format: format %d in use, cannot remove!\n", ++ cvf_formats[i]->cvf_version); ++ return -1; ++ } ++ ++ printk("CVF format %s (version id %d) successfully unregistered.\n", ++ cvf_formats[i]->cvf_version_text,cvf_formats[i]->cvf_version); ++ cvf_formats[i]=NULL; ++ return 0; ++ } ++ } ++ } ++ ++ printk("unregister_cvf_format: format %d is not registered\n", ++ cvf_format->cvf_version); ++ return -1; ++} ++ ++void dec_cvf_format_use_count_by_version(int version) ++{ int i; ++ ++ for(i=0;i<MAX_CVF_FORMATS;++i) ++ { if(cvf_formats[i]) ++ { if(cvf_formats[i]->cvf_version==version) ++ { --cvf_format_use_count[i]; ++ if(cvf_format_use_count[i]<0) ++ { cvf_format_use_count[i]=0; ++ printk(KERN_EMERG "FAT FS/CVF: This is a bug in cvf_version_use_count\n"); ++ } ++ return; ++ } ++ } ++ } ++ ++ printk("dec_cvf_format_use_count_by_version: version %d not found ???\n", ++ version); ++} ++ ++int detect_cvf(struct super_block*sb,char*force) ++{ int i; ++ int found=0; ++ int found_i=-1; ++ ++ if(force) ++ if(strcmp(force,"autoload")==0) ++ { ++#ifdef CONFIG_KERNELD ++ request_module("cvf_autoload"); ++ force=NULL; ++#else ++ printk("cannot autoload CVF modules: kerneld support is not compiled into kernel\n"); ++ return -1; ++#endif ++ } ++ ++#ifdef CONFIG_KERNELD ++ if(force) ++ if(*force) ++ request_module(force); ++#endif ++ ++ if(force) ++ { if(*force) ++ { for(i=0;i<MAX_CVF_FORMATS;++i) ++ { if(cvf_formats[i]) ++ { if(!strcmp(cvf_formats[i]->cvf_version_text,force)) ++ return i; ++ } ++ } ++ printk("CVF format %s unknown (module not loaded?)\n",force); ++ return -1; ++ } ++ } ++ ++ for(i=0;i<MAX_CVF_FORMATS;++i) ++ { if(cvf_formats[i]) ++ { if(cvf_formats[i]->detect_cvf(sb)) ++ { ++found; ++ found_i=i; ++ } ++ } ++ } ++ ++ if(found==1)return found_i; ++ if(found>1)printk("CVF detection ambiguous, please use cvf_format=xxx option\n"); ++ return -1; ++} +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/dir.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/dir.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/dir.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/dir.c Sun Jan 4 11:59:56 1998 +@@ -425,6 +425,7 @@ + unsigned int cmd, unsigned long arg) + { + int err; ++ + /* + * We want to provide an interface for Samba to be able + * to get the short filename for a given long filename. +@@ -451,6 +452,11 @@ + vfat_ioctl_fill, NULL, 1, 0, 1); + } + default: ++ /* forward ioctl to CVF extension */ ++ if(MSDOS_SB(inode->i_sb)->cvf_format ++ &&MSDOS_SB(inode->i_sb)->cvf_format->cvf_dir_ioctl) ++ return MSDOS_SB(inode->i_sb)->cvf_format-> ++ cvf_dir_ioctl(inode,filp,cmd,arg); + return -EINVAL; + } + +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/fatfs_syms.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/fatfs_syms.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/fatfs_syms.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/fatfs_syms.c Sun Jan 4 12:11:10 1998 +@@ -11,6 +11,7 @@ + + #include <linux/mm.h> + #include <linux/msdos_fs.h> ++#include <linux/fat_cvf.h> + + #include "msbuffer.h" + +@@ -53,6 +54,13 @@ + X(fat_uni2esc) X_PUNCT + X(fat_unlock_creation) X_PUNCT + X(fat_write_inode) X_PUNCT ++X(register_cvf_format) X_PUNCT ++X(unregister_cvf_format) X_PUNCT ++X(get_cluster) X_PUNCT ++X(lock_fat) X_PUNCT ++X(unlock_fat) X_PUNCT ++X(fat_readpage) X_PUNCT ++X(fat_dir_ioctl) X_PUNCT + #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0) + #include <linux/symtab_end.h> + }; +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/file.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/file.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/file.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/file.c Sun Jan 4 11:59:56 1998 +@@ -17,6 +17,7 @@ + #include <linux/stat.h> + #include <linux/string.h> + #include <linux/pagemap.h> ++#include <linux/fat_cvf.h> + + #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,0) + #include <asm/uaccess.h> +@@ -121,6 +122,40 @@ + NULL /* smap */ + }; + ++static struct file_operations fat_file_operations_readpage = { ++ NULL, /* lseek - default */ ++ fat_file_read, /* read */ ++ fat_file_write, /* write */ ++ NULL, /* readdir - bad */ ++ NULL, /* select - default */ ++ NULL, /* ioctl - default */ ++ generic_file_mmap, /* mmap */ ++ NULL, /* no special open is needed */ ++ NULL, /* release */ ++ file_fsync /* fsync */ ++}; ++ ++struct inode_operations fat_file_inode_operations_readpage = { ++ &fat_file_operations_readpage, /* default file operations */ ++ NULL, /* create */ ++ NULL, /* lookup */ ++ NULL, /* link */ ++ NULL, /* unlink */ ++ NULL, /* symlink */ ++ NULL, /* mkdir */ ++ NULL, /* rmdir */ ++ NULL, /* mknod */ ++ NULL, /* rename */ ++ NULL, /* readlink */ ++ NULL, /* follow_link */ ++ fat_readpage, /* readpage */ ++ NULL, /* writepage */ ++ NULL, /* bmap */ ++ fat_truncate, /* truncate */ ++ NULL, /* permission */ ++ NULL /* smap */ ++}; ++ + #define MSDOS_PREFETCH 32 + struct fat_pre { + int file_sector;/* Next sector to read in the prefetch table */ +@@ -183,6 +218,10 @@ + printk("fat_file_read: inode = NULL\n"); + return -EINVAL; + } ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_file_read) ++ return MSDOS_SB(sb)->cvf_format->cvf_file_read(inode,filp,buf,count); ++ + /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */ + if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) { + printk("fat_file_read: mode = %07o\n",inode->i_mode); +@@ -305,6 +344,10 @@ + printk("fat_file_write: inode = NULL\n"); + return -EINVAL; + } ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_file_write) ++ return MSDOS_SB(sb)->cvf_format->cvf_file_write(inode,filp,buf,count); ++ + /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */ + if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) { + printk("fat_file_write: mode = %07o\n",inode->i_mode); +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/inode.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/inode.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/inode.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/inode.c Sun Jan 4 12:31:18 1998 +@@ -22,6 +22,7 @@ + #include <linux/stat.h> + #include <linux/locks.h> + #include <linux/malloc.h> ++#include <linux/fat_cvf.h> + + #include "msbuffer.h" + +@@ -88,6 +89,10 @@ + + void fat_put_super(struct super_block *sb) + { ++ if(MSDOS_SB(sb)->cvf_format) ++ { dec_cvf_format_use_count_by_version(MSDOS_SB(sb)->cvf_format->cvf_version); ++ MSDOS_SB(sb)->cvf_format->unmount_cvf(sb); ++ } + if (MSDOS_SB(sb)->fat_bits == 32) { + fat_clusters_flush(sb); + } +@@ -113,7 +118,8 @@ + + + static int parse_options(char *options,int *fat, int *blksize, int *debug, +- struct fat_mount_options *opts) ++ struct fat_mount_options *opts, ++ char* cvf_format, char*cvf_options) + { + char *this_char,*value,save,*savep; + char *p; +@@ -239,6 +245,16 @@ + ret = 0; + } + } ++ else if (!strcmp(this_char,"cvf_format")) { ++ if (!value) ++ return 0; ++ strncpy(cvf_format,value,20); ++ } ++ else if (!strcmp(this_char,"cvf_options")) { ++ if (!value) ++ return 0; ++ strncpy(cvf_options,value,100); ++ } + + if (this_char != options) *(this_char-1) = ','; + if (value) *savep = save; +@@ -261,6 +277,14 @@ + struct fat_mount_options opts; + char buf[50]; + char *p; ++ int i; ++ char cvf_format[21]; ++ char cvf_options[101]; ++ ++ cvf_format[0]='\0'; ++ cvf_options[0]='\0'; ++ MSDOS_SB(sb)->cvf_format=NULL; ++ MSDOS_SB(sb)->private_data=NULL; + + MOD_INC_USE_COUNT; + if (hardsect_size[MAJOR(sb->s_dev)] != NULL){ +@@ -270,7 +294,8 @@ + } + } + opts.isvfat = MSDOS_SB(sb)->options.isvfat; +- if (!parse_options((char *) data, &fat, &blksize, &debug, &opts) ++ if (!parse_options((char *) data, &fat, &blksize, &debug, &opts, ++ cvf_format, cvf_options) + || (blksize != 512 && blksize != 1024)) { + sb->s_dev = 0; + MOD_DEC_USE_COUNT; +@@ -375,6 +400,9 @@ + /* because clusters (DOS) are often aligned */ + /* on odd sectors. */ + sb->s_blocksize_bits = blksize == 512 ? 9 : 10; ++ if(!strcmp(cvf_format,"none"))i=-1; ++ else i=detect_cvf(sb,cvf_format); ++ if(i>=0)error=cvf_formats[i]->mount_cvf(sb,cvf_options); + if (error || debug) { + /* The MSDOS_CAN_BMAP is obsolete, but left just to remember */ + printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c," +@@ -392,13 +420,15 @@ + MSDOS_SB(sb)->root_cluster,MSDOS_SB(sb)->free_clusters); + printk ("Transaction block size = %d\n",blksize); + } +- if (MSDOS_SB(sb)->clusters+2 > fat_clusters) ++ if(i<0) if (MSDOS_SB(sb)->clusters+2 > fat_clusters) + MSDOS_SB(sb)->clusters = fat_clusters-2; + if (error) { + if (!silent) + printk("VFS: Can't find a valid MSDOS filesystem on dev " + "%s.\n", kdevname(sb->s_dev)); + sb->s_dev = 0; ++ if(MSDOS_SB(sb)->private_data)kfree(MSDOS_SB(sb)->private_data); ++ MSDOS_SB(sb)->private_data=NULL; + MOD_DEC_USE_COUNT; + return NULL; + } +@@ -419,6 +449,8 @@ + MSDOS_SB(sb)->nls_disk = load_nls_default(); + } else { + sb->s_dev = 0; ++ if(MSDOS_SB(sb)->private_data)kfree(MSDOS_SB(sb)->private_data); ++ MSDOS_SB(sb)->private_data=NULL; + MOD_DEC_USE_COUNT; + return NULL; + } +@@ -433,6 +465,8 @@ + kfree(opts.iocharset); + unload_nls(MSDOS_SB(sb)->nls_disk); + sb->s_dev = 0; ++ if(MSDOS_SB(sb)->private_data)kfree(MSDOS_SB(sb)->private_data); ++ MSDOS_SB(sb)->private_data=NULL; + MOD_DEC_USE_COUNT; + return NULL; + } else { +@@ -447,9 +481,16 @@ + unload_nls(MSDOS_SB(sb)->nls_disk); + if (MSDOS_SB(sb)->nls_io) unload_nls(MSDOS_SB(sb)->nls_io); + if (opts.iocharset) kfree(opts.iocharset); ++ if(MSDOS_SB(sb)->private_data)kfree(MSDOS_SB(sb)->private_data); ++ MSDOS_SB(sb)->private_data=NULL; + MOD_DEC_USE_COUNT; + return NULL; + } ++ ++ if(i>=0) ++ { MSDOS_SB(sb)->cvf_format=cvf_formats[i]; ++ ++cvf_format_use_count[i]; ++ } + + return sb; + } +@@ -459,7 +500,13 @@ + { + int free,nr; + struct statfs tmp; +- ++ ++ if(MSDOS_SB(sb)->cvf_format) ++ if(MSDOS_SB(sb)->cvf_format->cvf_statfs) ++ { MSDOS_SB(sb)->cvf_format->cvf_statfs(sb,buf,bufsiz); ++ return; ++ } ++ + lock_fat(sb); + if (MSDOS_SB(sb)->free_clusters != -1) + free = MSDOS_SB(sb)->free_clusters; +@@ -488,6 +535,10 @@ + int cluster,offset; + + sb = MSDOS_SB(inode->i_sb); ++ if(sb->cvf_format) ++ if(sb->cvf_format->cvf_bmap) ++ return sb->cvf_format->cvf_bmap(inode,block); ++ + if ((inode->i_ino == MSDOS_ROOT_INO) && (sb->fat_bits != 32)) { + return sb->dir_start + block; + } +@@ -600,7 +651,12 @@ + !is_exec(raw_entry->ext))) + ? S_IRUGO|S_IWUGO : S_IRWXUGO) + & ~MSDOS_SB(sb)->options.fs_umask) | S_IFREG; +- inode->i_op = (sb->s_blocksize == 1024) ++ if(MSDOS_SB(sb)->cvf_format) ++ inode->i_op = (MSDOS_SB(sb)->cvf_format->flags&CVF_USE_READPAGE) ++ ? &fat_file_inode_operations_readpage ++ : &fat_file_inode_operations_1024; ++ else ++ inode->i_op = (sb->s_blocksize == 1024) + ? &fat_file_inode_operations_1024 + : &fat_file_inode_operations; + MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start); +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/misc.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/misc.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/misc.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/misc.c Sun Jan 4 11:59:56 1998 +@@ -225,6 +225,10 @@ + #endif + sector = MSDOS_SB(sb)->data_start+(nr-2)*cluster_size; + last_sector = sector + cluster_size; ++ if(MSDOS_SB(sb)->cvf_format&& ++ MSDOS_SB(sb)->cvf_format->zero_out_cluster) ++ MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode,nr); ++ else + for ( ; sector < last_sector; sector++) { + #ifdef DEBUG + printk("zeroing sector %d\n",sector); +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/fat/mmap.c linux-2.0.33-cyrix-patched-fat32-test/fs/fat/mmap.c +--- linux-2.0.33-cyrix-patched-fat32/fs/fat/mmap.c Sun Jan 4 11:55:32 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/fat/mmap.c Sun Jan 4 11:59:56 1998 +@@ -100,6 +100,9 @@ + */ + int fat_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma) + { ++ if(MSDOS_SB(inode->i_sb)->cvf_format) ++ if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_mmap) ++ return MSDOS_SB(inode->i_sb)->cvf_format->cvf_mmap(inode,file,vma); + if (vma->vm_flags & VM_SHARED) /* only PAGE_COW or read-only supported now */ + return -EINVAL; + if (vma->vm_offset & (inode->i_sb->s_blocksize - 1)) +@@ -117,4 +120,12 @@ + return 0; + } + ++int fat_readpage(struct inode * inode, struct page * page) ++{ ++ if(MSDOS_SB(inode->i_sb)->cvf_format) ++ if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage) ++ return MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage(inode,page); + ++ printk("fat_readpage called with no handler (shouldn't happen)\n"); ++ return -1; ++} +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/umsdos/emd.c linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/emd.c +--- linux-2.0.33-cyrix-patched-fat32/fs/umsdos/emd.c Wed Feb 7 08:39:29 1996 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/emd.c Sun Jan 4 11:59:56 1998 +@@ -32,6 +32,7 @@ + int ret; + int old_fs = get_fs(); + set_fs (KERNEL_DS); ++ MSDOS_I(inode)->i_binary=2; + ret = fat_file_read(inode,filp,buf,count); + set_fs (old_fs); + return ret; +@@ -48,6 +49,7 @@ + int ret; + int old_fs = get_fs(); + set_fs (KERNEL_DS); ++ MSDOS_I(inode)->i_binary=2; + ret = fat_file_write(inode,filp,buf,count); + set_fs (old_fs); + return ret; +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/umsdos/file.c linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/file.c +--- linux-2.0.33-cyrix-patched-fat32/fs/umsdos/file.c Tue Feb 20 09:28:13 1996 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/file.c Sun Jan 4 11:59:56 1998 +@@ -129,3 +129,38 @@ + NULL, /* smap */ + }; + ++/* For other with larger and unaligned file system with readpage */ ++struct file_operations umsdos_file_operations_readpage = { ++ NULL, /* lseek - default */ ++ UMSDOS_file_read, /* read */ ++ UMSDOS_file_write, /* write */ ++ NULL, /* readdir - bad */ ++ NULL, /* select - default */ ++ NULL, /* ioctl - default */ ++ generic_file_mmap, /* mmap */ ++ NULL, /* no special open is needed */ ++ NULL, /* release */ ++ file_fsync /* fsync */ ++}; ++ ++struct inode_operations umsdos_file_inode_operations_readpage = { ++ &umsdos_file_operations_readpage, /* default file operations */ ++ NULL, /* create */ ++ NULL, /* lookup */ ++ NULL, /* link */ ++ NULL, /* unlink */ ++ NULL, /* symlink */ ++ NULL, /* mkdir */ ++ NULL, /* rmdir */ ++ NULL, /* mknod */ ++ NULL, /* rename */ ++ NULL, /* readlink */ ++ NULL, /* follow_link */ ++ fat_readpage, /* readpage */ ++ NULL, /* writepage */ ++ NULL, /* bmap */ ++ UMSDOS_truncate,/* truncate */ ++ NULL, /* permission */ ++ NULL, /* smap */ ++}; ++ +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/umsdos/inode.c linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/inode.c +--- linux-2.0.33-cyrix-patched-fat32/fs/umsdos/inode.c Sat Nov 30 11:21:22 1996 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/inode.c Sun Jan 4 11:59:56 1998 +@@ -149,11 +149,20 @@ + if (!umsdos_isinit(inode)){ + inode->u.umsdos_i.i_emd_dir = 0; + if (S_ISREG(inode->i_mode)){ ++ if (MSDOS_SB(inode->i_sb)->cvf_format){ ++ if (MSDOS_SB(inode->i_sb)->cvf_format->flags ++ &CVF_USE_READPAGE){ ++ inode->i_op = &umsdos_file_inode_operations_readpage; ++ }else{ ++ inode->i_op = &umsdos_file_inode_operations_no_bmap; ++ } ++ } else { + if (inode->i_op->bmap != NULL){ + inode->i_op = &umsdos_file_inode_operations; + }else{ + inode->i_op = &umsdos_file_inode_operations_no_bmap; + } ++ } + }else if (S_ISDIR(inode->i_mode)){ + if (dir != NULL){ + umsdos_setup_dir_inode(inode); +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/fs/umsdos/ioctl.c linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/ioctl.c +--- linux-2.0.33-cyrix-patched-fat32/fs/umsdos/ioctl.c Wed Jul 3 15:39:48 1996 ++++ linux-2.0.33-cyrix-patched-fat32-test/fs/umsdos/ioctl.c Sun Jan 4 11:59:56 1998 +@@ -60,6 +60,21 @@ + { + int ret = -EPERM; + int err; ++ ++ /* forward non-umsdos ioctls - this hopefully doesn't cause conflicts */ ++ if(cmd!=UMSDOS_GETVERSION ++ &&cmd!=UMSDOS_READDIR_DOS ++ &&cmd!=UMSDOS_READDIR_EMD ++ &&cmd!=UMSDOS_INIT_EMD ++ &&cmd!=UMSDOS_CREAT_EMD ++ &&cmd!=UMSDOS_RENAME_DOS ++ &&cmd!=UMSDOS_UNLINK_EMD ++ &&cmd!=UMSDOS_UNLINK_DOS ++ &&cmd!=UMSDOS_RMDIR_DOS ++ &&cmd!=UMSDOS_STAT_DOS ++ &&cmd!=UMSDOS_DOS_SETUP) ++ return fat_dir_ioctl(dir,filp,cmd,data); ++ + /* #Specification: ioctl / acces + Only root (effective id) is allowed to do IOCTL on directory + in UMSDOS. EPERM is returned for other user. +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/include/linux/fat_cvf.h linux-2.0.33-cyrix-patched-fat32-test/include/linux/fat_cvf.h +--- linux-2.0.33-cyrix-patched-fat32/include/linux/fat_cvf.h Thu Jan 1 01:00:00 1970 ++++ linux-2.0.33-cyrix-patched-fat32-test/include/linux/fat_cvf.h Sun Jan 4 11:59:56 1998 +@@ -0,0 +1,55 @@ ++#ifndef _FAT_CVF ++#define _FAT_CVF ++ ++#define CVF_USE_READPAGE 0x0001 ++ ++struct cvf_format ++{ int cvf_version; ++ char* cvf_version_text; ++ unsigned long flags; ++ int (*detect_cvf) (struct super_block*sb); ++ int (*mount_cvf) (struct super_block*sb,char*options); ++ int (*unmount_cvf) (struct super_block*sb); ++ struct buffer_head* (*cvf_bread) (struct super_block*sb,int block); ++ struct buffer_head* (*cvf_getblk) (struct super_block*sb,int block); ++ void (*cvf_brelse) (struct super_block *sb,struct buffer_head *bh); ++ void (*cvf_mark_buffer_dirty) (struct super_block *sb, ++ struct buffer_head *bh, ++ int dirty_val); ++ void (*cvf_set_uptodate) (struct super_block *sb, ++ struct buffer_head *bh, ++ int val); ++ int (*cvf_is_uptodate) (struct super_block *sb,struct buffer_head *bh); ++ void (*cvf_ll_rw_block) (struct super_block *sb, ++ int opr, ++ int nbreq, ++ struct buffer_head *bh[32]); ++ int (*fat_access) (struct super_block *sb,int nr,int new_value); ++ void (*cvf_statfs) (struct super_block *sb,struct statfs *buf, int bufsiz); ++ int (*cvf_bmap) (struct inode *inode,int block); ++ int (*cvf_smap) (struct inode *inode,int sector); ++ int (*cvf_file_read) ( struct inode *inode, ++ struct file *filp, ++ char *buf, ++ int count); ++ int (*cvf_file_write) ( struct inode *inode, ++ struct file *filp, ++ const char *buf, ++ int count); ++ int (*cvf_mmap) (struct inode*, struct file *, struct vm_area_struct *); ++ int (*cvf_readpage) (struct inode *, struct page *); ++ int (*cvf_writepage) (struct inode *, struct page *); ++ int (*cvf_dir_ioctl) (struct inode * inode, struct file * filp, ++ unsigned int cmd, unsigned long arg); ++ void (*zero_out_cluster) (struct inode*, int clusternr); ++}; ++ ++int register_cvf_format(struct cvf_format*cvf_format); ++int unregister_cvf_format(struct cvf_format*cvf_format); ++void dec_cvf_format_use_count_by_version(int version); ++int detect_cvf(struct super_block*sb,char*force); ++ ++extern struct cvf_format *cvf_formats[]; ++extern int cvf_format_use_count[]; ++ ++#endif +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/include/linux/msdos_fs.h linux-2.0.33-cyrix-patched-fat32-test/include/linux/msdos_fs.h +--- linux-2.0.33-cyrix-patched-fat32/include/linux/msdos_fs.h Sun Jan 4 11:55:33 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/include/linux/msdos_fs.h Sun Jan 4 12:40:48 1998 +@@ -246,12 +246,14 @@ + /* file.c */ + extern struct inode_operations fat_file_inode_operations; + extern struct inode_operations fat_file_inode_operations_1024; ++extern struct inode_operations fat_file_inode_operations_readpage; + extern int fat_file_read(struct inode *, struct file *, char *, int); + extern int fat_file_write(struct inode *, struct file *, const char *, int); + extern void fat_truncate(struct inode *inode); + + /* mmap.c */ + extern int fat_mmap(struct inode *, struct file *, struct vm_area_struct *); ++extern int fat_readpage(struct inode *, struct page *); + + + /* vfat.c */ +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/include/linux/msdos_fs_sb.h linux-2.0.33-cyrix-patched-fat32-test/include/linux/msdos_fs_sb.h +--- linux-2.0.33-cyrix-patched-fat32/include/linux/msdos_fs_sb.h Sun Jan 4 11:55:33 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/include/linux/msdos_fs_sb.h Sun Jan 4 12:02:05 1998 +@@ -1,5 +1,6 @@ + #ifndef _MSDOS_FS_SB + #define _MSDOS_FS_SB ++#include<linux/fat_cvf.h> + + /* + * MS-DOS file system in-core superblock data +@@ -46,6 +47,8 @@ + struct fat_mount_options options; + struct nls_table *nls_disk; /* Codepage used on disk */ + struct nls_table *nls_io; /* Charset used for input and display */ ++ struct cvf_format* cvf_format; ++ void* private_data; + }; + + #endif +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/include/linux/umsdos_fs.h linux-2.0.33-cyrix-patched-fat32-test/include/linux/umsdos_fs.h +--- linux-2.0.33-cyrix-patched-fat32/include/linux/umsdos_fs.h Tue Dec 23 22:50:14 1997 ++++ linux-2.0.33-cyrix-patched-fat32-test/include/linux/umsdos_fs.h Sun Jan 4 12:40:48 1998 +@@ -135,6 +135,7 @@ + extern struct file_operations umsdos_file_operations; + extern struct inode_operations umsdos_file_inode_operations; + extern struct inode_operations umsdos_file_inode_operations_no_bmap; ++extern struct inode_operations umsdos_file_inode_operations_readpage; + extern struct inode_operations umsdos_symlink_inode_operations; + extern int init_umsdos_fs(void); + +diff -u -r -N linux-2.0.33-cyrix-patched-fat32/kernel/ksyms.c linux-2.0.33-cyrix-patched-fat32-test/kernel/ksyms.c +--- linux-2.0.33-cyrix-patched-fat32/kernel/ksyms.c Sun Jan 4 11:55:33 1998 ++++ linux-2.0.33-cyrix-patched-fat32-test/kernel/ksyms.c Sun Jan 4 11:59:56 1998 +@@ -124,6 +124,9 @@ + X(do_mmap), + X(do_munmap), + X(exit_mm), ++ X(exit_sighand), ++ X(exit_fs), ++ X(exit_files), + + /* internal kernel memory management */ + X(__get_free_pages), diff --git a/patches/fat-truncate-bugfix.diff b/patches/fat-truncate-bugfix.diff new file mode 100644 index 0000000..f4967d9 --- /dev/null +++ b/patches/fat-truncate-bugfix.diff @@ -0,0 +1,13 @@ +--- linux/fs/fat/file.c.orig Thu Jan 7 18:38:59 1999 ++++ linux/fs/fat/file.c Thu Jan 7 19:17:40 1999 +@@ -442,6 +442,10 @@ + /* Why no return value? Surely the disk could fail... */ + if (IS_IMMUTABLE(inode)) + return /* -EPERM */; ++ if(inode->i_sb->s_flags&MS_RDONLY) { ++ printk("FAT: fat_truncate called though fs is read-only, uhh...\n"); ++ return /* -EROFS */; ++ } + cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size; + (void) fat_free(inode,(inode->i_size+(cluster-1))/cluster); + MSDOS_I(inode)->i_attrs |= ATTR_ARCH; diff --git a/patches/fat_cvf.txt b/patches/fat_cvf.txt new file mode 100644 index 0000000..4ddcf3e --- /dev/null +++ b/patches/fat_cvf.txt @@ -0,0 +1,210 @@ +This is the main documentation for the CVF-FAT filesystem extension. 18Nov1998 + + +Table of Contents: + +1. The idea of CVF-FAT +2. Restrictions +3. Mount options +4. Description of the CVF-FAT interface +5. CVF Modules + +------------------------------------------------------------------------------ + + +1. The idea of CVF-FAT +------------------------------------------------------------------------------ + +CVF-FAT is a FAT filesystem extension that provides a generic interface for +Compressed Volume Files in FAT partitions. Popular CVF software, for +example, are Microsoft's Doublespace/Drivespace and Stac's Stacker. +Using the CVF-FAT interface, it is possible to load a module that handles +all the low-level disk access that has to do with on-the-fly compression +and decompression. Any other part of FAT filesystem access is still handled +by the FAT, MSDOS or VFAT or even UMSDOS driver. + +CVF access works by redirecting certain low-level routines from the FAT +driver to a loadable, CVF-format specific module. This module must fake +a normal FAT filesystem to the FAT driver while doing all the extra stuff +like compression and decompression silently. + + +2. Restrictions +------------------------------------------------------------------------------ + +- BMAP problems + + CVF filesystems cannot do bmap. It's impossible in principle. Thus + all actions that require bmap do not work (swapping, writable mmapping). + Read-only mmapping works because the FAT driver has a hack for this + situation :) Well, writable mmapping should now work using the readpage + interface function which has been hacked into the FAT driver just for + CVF-FAT :) + +- attention, DOSEmu users + + You may have to unmount all CVF partitions before running DOSEmu depending + on your configuration. If DOSEmu is configured to use wholedisk or + partition access (this is often the case to let DOSEmu access + compressed partitions) there's a risk of destroying your compressed + partitions or crashing your system because of confused drivers. + + Note that it is always safe to redirect the compressed partitions with + lredir or emufs.sys. Refer to the DOSEmu documentation for details. + + +3. Mount options +------------------------------------------------------------------------------ + +The CVF-FAT extension currently adds the following options to the FAT +driver's standard options: + + cvf_format=xxx + Forces the driver to use the CVF module "xxx" instead of auto-detection. + Without this option, the CVF-FAT interface asks all currently loaded + CVF modules whether they recognize the CVF. Therefore, this option is + only necessary if the CVF format is not recognized correctly + because of bugs or incompatibilities in the CVF modules. (It skips + the detect_cvf call.) "xxx" may be the text "none" (without the quotes) + to inhibit using any of the loaded CVF modules, just in case a CVF + module insists on mounting plain FAT filesystems by misunderstanding. + "xxx" may also be the text "autoload", which has a special meaning for + kerneld, but does not skip auto-detection. + + If the kernel supports kerneld, the cvf_format=xxx option also controls + on-demand CVF module loading. Without this option, nothing is loaded + on demand. With cvf_format=xxx, a module "xxx" is requested automatically + before mounting the compressed filesystem (unless "xxx" is "none"). In + case there is a difference between the CVF format name and the module + name, setup aliases in your kerneld configuration. If the string "xxx" + is "autoload", a non-existent module "cvf_autoload" is requested which + can be used together with a special kerneld configuration (alias and + pre-install statements) in order to load more than one CVF module, let + them detect automatically which kind of CVF is to be mounted, and only + keep the "right" module in memory. For examples please refer to the + dmsdos documentation (ftp and http addresses see below). + + cvf_options=yyy + Option string passed to the CVF module. I.e. only the "yyy" is passed + (without the quotes). The documentation for each CVF module should + explain it since it is interpreted only by the CVF module. Note that + the string must not contain a comma (",") - this would lead to + misinterpretation by the FAT driver, which would recognize the text + after a comma as a FAT driver option and might get confused or print + strange error messages. The documentation for the CVF module should + offer a different separation symbol, for example the dot "." or the + plus sign "+", which is only valid inside the string "yyy". + + +4. Description of the CVF-FAT interface +------------------------------------------------------------------------------ + +Assuming you want to write your own CVF module, you need to write a lot of +interface functions. Most of them are covered in the kernel documentation +you can find on the net, and thus won't be described here. They have been +marked with "[...]" :-) Take a look at include/linux/fat_cvf.h. + +struct cvf_format +{ int cvf_version; + char* cvf_version_text; + unsigned long int flags; + int (*detect_cvf) (struct super_block*sb); + int (*mount_cvf) (struct super_block*sb,char*options); + int (*unmount_cvf) (struct super_block*sb); + [...] + void (*cvf_zero_cluster) (struct inode*inode,int clusternr); +} + +This structure defines the capabilities of a CVF module. It must be filled +out completely by a CVF module. Consider it as a kind of form that is used +to introduce the module to the FAT/CVF-FAT driver. + +It contains... + - cvf_version: + A version id which must be unique. Choose one. + - cvf_version_text: + A human readable version string that should be one short word + describing the CVF format the module implements. This text is used + for the cvf_format option. This name must also be unique. + - flags: + Bit coded flags, currently only used for a readpage/mmap hack that + provides both mmap and readpage functionality. If CVF_USE_READPAGE + is set, mmap is set to generic_file_mmap and readpage is caught + and redirected to the cvf_readpage function. If it is not set, + readpage is set to generic_readpage and mmap is caught and redirected + to cvf_mmap. (If you want writable mmap use the readpage interface.) + - detect_cvf: + A function that is called to decide whether the filesystem is a CVF of + the type the module supports. The detect_cvf function must return 0 + for "NO, I DON'T KNOW THIS GARBAGE" or anything >0 for "YES, THIS IS + THE KIND OF CVF I SUPPORT". The function must maintain the module + usage counters for safety, i.e. do MOD_INC_USE_COUNT at the beginning + and MOD_DEC_USE_COUNT at the end. The function *must not* assume that + successful recongition would lead to a call of the mount_cvf function + later. + - mount_cvf: + A function that sets up some values or initializes something additional + to what has to be done when a CVF is mounted. This is called at the + end of fat_read_super and must return 0 on success. Definitely, this + function must increment the module usage counter by MOD_INC_USE_COUNT. + This mount_cvf function is also responsible for interpreting a CVF + module specific option string (the "yyy" from the FAT mount option + "cvf_options=yyy") which cannot contain a comma (use for example the + dot "." as option separator symbol). + - unmount_cvf: + A function that is called when the filesystem is unmounted. Most likely + it only frees up some memory and calls MOD_DEC_USE_COUNT. The return + value might be ignored (it currently is ignored). + - [...]: + All other interface functions are "caught" FAT driver functions, i.e. + are executed by the FAT driver *instead* of the original FAT driver + functions. NULL means use the original FAT driver functions instead. + If you really want "no action", write a function that does nothing and + hang it in instead. + - cvf_zero_cluster: + The cvf_zero_cluster function is called when the fat driver wants to + zero out a (new) cluster. This is important for directories (mkdir). + If it is NULL, the FAT driver defaults to overwriting the whole + cluster with zeros. Note that clusternr is absolute, not relative + to the provided inode. + +Notes: + 1. The cvf_bmap function should be ignored. It really should never + get called from somewhere. I recommend redirecting it to a panic + or fatal error message so bugs show up immediately. + 2. The cvf_writepage function is ignored. This is because the fat + driver doesn't support it. This might change in future. I recommend + setting it to NULL (i.e use default). + +int register_cvf_format(struct cvf_format*cvf_format); + If you have just set up a variable containing the above structure, + call this function to introduce your CVF format to the FAT/CVF-FAT + driver. This is usually done in init_module. Be sure to check the + return value. Zero means success, everything else causes a kernel + message printed in the syslog describing the error that occurred. + Typical errors are: + - a module with the same version id is already registered or + - too many CVF formats. Hack fs/fat/cvf.c if you need more. + +int unregister_cvf_format(struct cvf_format*cvf_format); + This is usually called in cleanup_module. Return value =0 means + success. An error only occurs if you try to unregister a CVF format + that has not been previously registered. The code uses the version id + to distinguish the modules, so be sure to keep it unique. + +5. CVF Modules +------------------------------------------------------------------------------ + +Refer to the dmsdos module (the successor of the dmsdos filesystem) for a +sample implementation. It can currently be found at + + ftp://fb9nt.uni-duisburg.de/pub/linux/dmsdos/dmsdos-x.y.z.tgz + ftp://sunsite.unc.edu/pub/Linux/system/Filesystems/dosfs/dmsdos-x.y.z.tgz + ftp://ftp.uni-stuttgart.de/pub/systems/linux/local/system/dmsdos-x.y.z.tgz + +(where x.y.z is to be replaced with the actual version number). Full +documentation about dmsdos is included in the dmsdos package, but can also +be found at + + http://fb9nt.uni-duisburg.de/mitarbeiter/gockel/software/dmsdos/index.html + http://www.yk.rim.or.jp/~takafumi/dmsdos/index.html (in Japanese). diff --git a/patches/fat_cvf.txt-2.1.128 b/patches/fat_cvf.txt-2.1.128 new file mode 100644 index 0000000..c1cf27b --- /dev/null +++ b/patches/fat_cvf.txt-2.1.128 @@ -0,0 +1,210 @@ +This is the main documentation for the CVF-FAT filesystem extension. 18Nov1998 + + +Table of Contents: + +1. The idea of CVF-FAT +2. Restrictions +3. Mount options +4. Description of the CVF-FAT interface +5. CVF Modules + +------------------------------------------------------------------------------ + + +1. The idea of CVF-FAT +------------------------------------------------------------------------------ + +CVF-FAT is a FAT filesystem extension that provides a generic interface for +Compressed Volume Files in FAT partitions. Popular CVF software, for +example, are Microsoft's Doublespace/Drivespace and Stac's Stacker. +Using the CVF-FAT interface, it is possible to load a module that handles +all the low-level disk access that has to do with on-the-fly compression +and decompression. Any other part of FAT filesystem access is still handled +by the FAT, MSDOS or VFAT or even UMSDOS driver. + +CVF access works by redirecting certain low-level routines from the FAT +driver to a loadable, CVF-format specific module. This module must fake +a normal FAT filesystem to the FAT driver while doing all the extra stuff +like compression and decompression silently. + + +2. Restrictions +------------------------------------------------------------------------------ + +- BMAP problems + + CVF filesystems cannot do bmap. It's impossible in principle. Thus + all actions that require bmap do not work (swapping, writable mmapping). + Read-only mmapping works because the FAT driver has a hack for this + situation :) Well, writable mmapping should now work using the readpage + interface function which has been hacked into the FAT driver just for + CVF-FAT :) + +- attention, DOSEmu users + + You may have to unmount all CVF partitions before running DOSEmu depending + on your configuration. If DOSEmu is configured to use wholedisk or + partition access (this is often the case to let DOSEmu access + compressed partitions) there's a risk of destroying your compressed + partitions or crashing your system because of confused drivers. + + Note that it is always safe to redirect the compressed partitions with + lredir or emufs.sys. Refer to the DOSEmu documentation for details. + + +3. Mount options +------------------------------------------------------------------------------ + +The CVF-FAT extension currently adds the following options to the FAT +driver's standard options: + + cvf_format=xxx + Forces the driver to use the CVF module "xxx" instead of auto-detection. + Without this option, the CVF-FAT interface asks all currently loaded + CVF modules whether they recognize the CVF. Therefore, this option is + only necessary if the CVF format is not recognized correctly + because of bugs or incompatibilities in the CVF modules. (It skips + the detect_cvf call.) "xxx" may be the text "none" (without the quotes) + to inhibit using any of the loaded CVF modules, just in case a CVF + module insists on mounting plain FAT filesystems by misunderstanding. + "xxx" may also be the text "autoload", which has a special meaning for + a module loader, but does not skip auto-detection. + + If the kernel supports kmod, the cvf_format=xxx option also controls + on-demand CVF module loading. Without this option, nothing is loaded + on demand. With cvf_format=xxx, a module "xxx" is requested automatically + before mounting the compressed filesystem (unless "xxx" is "none"). In + case there is a difference between the CVF format name and the module + name, setup aliases in your modules configuration. If the string "xxx" + is "autoload", a non-existent module "cvf_autoload" is requested which + can be used together with a special modules configuration (alias and + pre-install statements) in order to load more than one CVF module, let + them detect automatically which kind of CVF is to be mounted, and only + keep the "right" module in memory. For examples please refer to the + dmsdos documentation (ftp and http addresses see below). + + cvf_options=yyy + Option string passed to the CVF module. I.e. only the "yyy" is passed + (without the quotes). The documentation for each CVF module should + explain it since it is interpreted only by the CVF module. Note that + the string must not contain a comma (",") - this would lead to + misinterpretation by the FAT driver, which would recognize the text + after a comma as a FAT driver option and might get confused or print + strange error messages. The documentation for the CVF module should + offer a different separation symbol, for example the dot "." or the + plus sign "+", which is only valid inside the string "yyy". + + +4. Description of the CVF-FAT interface +------------------------------------------------------------------------------ + +Assuming you want to write your own CVF module, you need to write a lot of +interface functions. Most of them are covered in the kernel documentation +you can find on the net, and thus won't be described here. They have been +marked with "[...]" :-) Take a look at include/linux/fat_cvf.h. + +struct cvf_format +{ int cvf_version; + char* cvf_version_text; + unsigned long int flags; + int (*detect_cvf) (struct super_block*sb); + int (*mount_cvf) (struct super_block*sb,char*options); + int (*unmount_cvf) (struct super_block*sb); + [...] + void (*cvf_zero_cluster) (struct inode*inode,int clusternr); +} + +This structure defines the capabilities of a CVF module. It must be filled +out completely by a CVF module. Consider it as a kind of form that is used +to introduce the module to the FAT/CVF-FAT driver. + +It contains... + - cvf_version: + A version id which must be unique. Choose one. + - cvf_version_text: + A human readable version string that should be one short word + describing the CVF format the module implements. This text is used + for the cvf_format option. This name must also be unique. + - flags: + Bit coded flags, currently only used for a readpage/mmap hack that + provides both mmap and readpage functionality. If CVF_USE_READPAGE + is set, mmap is set to generic_file_mmap and readpage is caught + and redirected to the cvf_readpage function. If it is not set, + readpage is set to generic_readpage and mmap is caught and redirected + to cvf_mmap. (If you want writable mmap use the readpage interface.) + - detect_cvf: + A function that is called to decide whether the filesystem is a CVF of + the type the module supports. The detect_cvf function must return 0 + for "NO, I DON'T KNOW THIS GARBAGE" or anything >0 for "YES, THIS IS + THE KIND OF CVF I SUPPORT". The function must maintain the module + usage counters for safety, i.e. do MOD_INC_USE_COUNT at the beginning + and MOD_DEC_USE_COUNT at the end. The function *must not* assume that + successful recongition would lead to a call of the mount_cvf function + later. + - mount_cvf: + A function that sets up some values or initializes something additional + to what has to be done when a CVF is mounted. This is called at the + end of fat_read_super and must return 0 on success. Definitely, this + function must increment the module usage counter by MOD_INC_USE_COUNT. + This mount_cvf function is also responsible for interpreting a CVF + module specific option string (the "yyy" from the FAT mount option + "cvf_options=yyy") which cannot contain a comma (use for example the + dot "." as option separator symbol). + - unmount_cvf: + A function that is called when the filesystem is unmounted. Most likely + it only frees up some memory and calls MOD_DEC_USE_COUNT. The return + value might be ignored (it currently is ignored). + - [...]: + All other interface functions are "caught" FAT driver functions, i.e. + are executed by the FAT driver *instead* of the original FAT driver + functions. NULL means use the original FAT driver functions instead. + If you really want "no action", write a function that does nothing and + hang it in instead. + - cvf_zero_cluster: + The cvf_zero_cluster function is called when the fat driver wants to + zero out a (new) cluster. This is important for directories (mkdir). + If it is NULL, the FAT driver defaults to overwriting the whole + cluster with zeros. Note that clusternr is absolute, not relative + to the provided inode. + +Notes: + 1. The cvf_bmap function should be ignored. It really should never + get called from somewhere. I recommend redirecting it to a panic + or fatal error message so bugs show up immediately. + 2. The cvf_writepage function is ignored. This is because the fat + driver doesn't support it. This might change in future. I recommend + setting it to NULL (i.e use default). + +int register_cvf_format(struct cvf_format*cvf_format); + If you have just set up a variable containing the above structure, + call this function to introduce your CVF format to the FAT/CVF-FAT + driver. This is usually done in init_module. Be sure to check the + return value. Zero means success, everything else causes a kernel + message printed in the syslog describing the error that occurred. + Typical errors are: + - a module with the same version id is already registered or + - too many CVF formats. Hack fs/fat/cvf.c if you need more. + +int unregister_cvf_format(struct cvf_format*cvf_format); + This is usually called in cleanup_module. Return value =0 means + success. An error only occurs if you try to unregister a CVF format + that has not been previously registered. The code uses the version id + to distinguish the modules, so be sure to keep it unique. + +5. CVF Modules +------------------------------------------------------------------------------ + +Refer to the dmsdos module (the successor of the dmsdos filesystem) for a +sample implementation. It can currently be found at + + ftp://fb9nt.uni-duisburg.de/pub/linux/dmsdos/dmsdos-x.y.z.tgz + ftp://sunsite.unc.edu/pub/Linux/system/Filesystems/dosfs/dmsdos-x.y.z.tgz + ftp://ftp.uni-stuttgart.de/pub/systems/linux/local/system/dmsdos-x.y.z.tgz + +(where x.y.z is to be replaced with the actual version number). Full +documentation about dmsdos is included in the dmsdos package, but can also +be found at + + http://fb9nt.uni-duisburg.de/mitarbeiter/gockel/software/dmsdos/index.html + http://www.yk.rim.or.jp/~takafumi/dmsdos/index.html (in Japanese). diff --git a/patches/in-kernel-2.0.35.diff b/patches/in-kernel-2.0.35.diff new file mode 100644 index 0000000..5bfbee2 --- /dev/null +++ b/patches/in-kernel-2.0.35.diff @@ -0,0 +1,62 @@ +--- linux-orig/fs/Makefile Thu Jun 11 14:23:31 1998 ++++ linux/fs/Makefile Sun Aug 23 14:23:39 1998 +@@ -18,7 +18,7 @@ + + MOD_LIST_NAME := FS_MODULES + ALL_SUB_DIRS = minix ext ext2 fat msdos vfat proc isofs nfs xiafs umsdos \ +- hpfs sysv smbfs ncpfs ufs affs autofs ++ hpfs sysv smbfs ncpfs ufs affs autofs dmsdos + + ifeq ($(CONFIG_QUOTA),y) + O_OBJS += dquot.o +@@ -55,6 +55,14 @@ + else + ifeq ($(CONFIG_FAT_FS),m) + MOD_SUB_DIRS += fat ++ endif ++endif ++ ++ifeq ($(CONFIG_DMSDOS_FS),y) ++SUB_DIRS += dmsdos ++else ++ ifeq ($(CONFIG_DMSDOS_FS),m) ++ MOD_SUB_DIRS += dmsdos + endif + endif + +--- linux-orig/fs/Config.in Sat Jul 18 00:31:37 1998 ++++ linux/fs/Config.in Sun Aug 23 14:33:10 1998 +@@ -16,6 +16,10 @@ + + # msdos filesystems + dep_tristate 'DOS FAT fs support' CONFIG_FAT_FS $CONFIG_NLS ++ dep_tristate 'DMSDOS (dblspace/drvspace/stacker) support' CONFIG_DMSDOS_FS $CONFIG_FAT_FS ++ if [ "$CONFIG_DMSDOS_FS" = "y" -o "$CONFIG_DMSDOS_FS" = "m" ]; then ++ source fs/dmsdos/Config.in ++ fi + dep_tristate 'MSDOS fs support' CONFIG_MSDOS_FS $CONFIG_FAT_FS + dep_tristate 'umsdos: Unix like fs on top of std MSDOS FAT fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS + dep_tristate 'VFAT (Windows-95) fs support' CONFIG_VFAT_FS $CONFIG_FAT_FS +--- linux-orig/fs/filesystems.c Thu Jun 11 14:23:32 1998 ++++ linux/fs/filesystems.c Sun Aug 23 14:54:27 1998 +@@ -32,6 +32,9 @@ + + extern void device_setup(void); + extern void binfmt_setup(void); ++#ifdef CONFIG_DMSDOS_FS ++extern int init_dmsdos(void); ++#endif + + /* This may be used only once, enforced by 'static int callable' */ + asmlinkage int sys_setup(void) +@@ -72,6 +75,10 @@ + + #ifdef CONFIG_FAT_FS + init_fat_fs(); ++#endif ++ ++#ifdef CONFIG_DMSDOS_FS ++ init_dmsdos(); + #endif + + #ifdef CONFIG_MSDOS_FS diff --git a/patches/linux-2.2.13-dmsdos.patch-1 b/patches/linux-2.2.13-dmsdos.patch-1 new file mode 100644 index 0000000..e126359 --- /dev/null +++ b/patches/linux-2.2.13-dmsdos.patch-1 @@ -0,0 +1,16 @@ +diff -u -r -r linux-2.2.13-orig/fs/fat/misc.c linux-2.2.13-new1/fs/fat/misc.c +--- linux-2.2.13-orig/fs/fat/misc.c Mon Aug 9 19:04:41 1999 ++++ linux-2.2.13-new1/fs/fat/misc.c Sun Dec 5 11:43:02 1999 +@@ -222,9 +222,10 @@ + sector = MSDOS_SB(sb)->data_start+(nr-2)*cluster_size; + last_sector = sector + cluster_size; + if (MSDOS_SB(sb)->cvf_format && +- MSDOS_SB(sb)->cvf_format->zero_out_cluster) ++ MSDOS_SB(sb)->cvf_format->zero_out_cluster) { + MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode,nr); +- else ++ res=fat_bread(sb,fat_smap(inode,inode->i_blocks)); ++ }else + for ( ; sector < last_sector; sector++) { + #ifdef DEBUG + printk("zeroing sector %d\n",sector); diff --git a/patches/linux-2.3.30-pre6-dmsdos.patch-1 b/patches/linux-2.3.30-pre6-dmsdos.patch-1 new file mode 100644 index 0000000..bc4757b --- /dev/null +++ b/patches/linux-2.3.30-pre6-dmsdos.patch-1 @@ -0,0 +1,284 @@ +diff -u -r linux-2.3.30-6-orig/fs/fat/cvf.c linux-2.3.30-6-new1/fs/fat/cvf.c +--- linux-2.3.30-6-orig/fs/fat/cvf.c Mon Aug 9 18:43:49 1999 ++++ linux-2.3.30-6-new1/fs/fat/cvf.c Wed Nov 3 00:28:53 1999 +@@ -53,49 +53,55 @@ + loff_t *ppos); + + struct cvf_format default_cvf = { +- 0, /* version - who cares? */ +- "plain", +- 0, /* flags - who cares? */ +- NULL, +- NULL, +- NULL, +- default_fat_bread, +- default_fat_getblk, +- default_fat_brelse, +- default_fat_mark_buffer_dirty, +- default_fat_set_uptodate, +- default_fat_is_uptodate, +- default_fat_ll_rw_block, +- default_fat_access, +- NULL, +- default_fat_bmap, +- generic_file_read, +- default_fat_file_write, +- NULL, +- NULL ++ 0, /* cvf unique version number - 0 for fat internal CVF */ ++ "plain", /* cvf version name */ ++ 0, /* flags - capabilities, ex. CVF_USE_READPAGE */ ++ NULL, /* detect_cvf */ ++ NULL, /* mount_cvf */ ++ NULL, /* unmount_cvf */ ++ default_fat_bread, /* cvf_bread */ ++ default_fat_getblk, /* cvf_getblk */ ++ default_fat_brelse, /* cvf_brelse */ ++ default_fat_mark_buffer_dirty, /* cvf_mark_buffer_dirty */ ++ default_fat_set_uptodate, /* cvf_set_uptodate */ ++ default_fat_is_uptodate, /* cvf_is_uptodate */ ++ default_fat_ll_rw_block, /* cvf_ll_rw_block */ ++ default_fat_access, /* fat_access */ ++ NULL, /* cvf_statfs */ ++ default_fat_bmap, /* cvf_bmap */ ++ generic_file_read, /* cvf_file_read */ ++ default_fat_file_write, /* cvf_file_write */ ++ NULL, /* cvf_mmap */ ++ block_read_full_page, /* cvf_readpage */ ++ NULL, /* cvf_writepage */ ++ NULL, /* cvf_dir_ioctl */ ++ NULL /* zero_out_cluster */ + }; + + struct cvf_format bigblock_cvf = { +- 0, /* version - who cares? */ +- "big_blocks", +- 0, /* flags - who cares? */ +- NULL, +- NULL, +- NULL, +- bigblock_fat_bread, +- bigblock_fat_bread, +- bigblock_fat_brelse, +- bigblock_fat_mark_buffer_dirty, +- bigblock_fat_set_uptodate, +- bigblock_fat_is_uptodate, +- bigblock_fat_ll_rw_block, +- default_fat_access, +- NULL, +- default_fat_bmap, +- NULL, +- default_fat_file_write, +- NULL, +- NULL ++ 0, /* cvf unique version number - 0 for fat internal CVF */ ++ "big_blocks", /* cvf version name */ ++ 0, /* flags - capabilities, ex. CVF_USE_READPAGE */ ++ NULL, /* detect_cvf */ ++ NULL, /* mount_cvf */ ++ NULL, /* unmount_cvf */ ++ bigblock_fat_bread, /* cvf_bread */ ++ bigblock_fat_bread, /* cvf_getblk */ ++ bigblock_fat_brelse, /* cvf_brelse */ ++ bigblock_fat_mark_buffer_dirty, /* cvf_mark_buffer_dirty */ ++ bigblock_fat_set_uptodate, /* cvf_set_uptodate */ ++ bigblock_fat_is_uptodate, /* cvf_is_uptodate */ ++ bigblock_fat_ll_rw_block, /* cvf_ll_rw_block */ ++ default_fat_access, /* fat_access */ ++ NULL, /* cvf_statfs */ ++ default_fat_bmap, /* cvf_bmap */ ++ NULL, /* ?????? */ /* cvf_file_read */ ++ default_fat_file_write, /* cvf_file_write */ ++ NULL, /* cvf_mmap */ ++ block_read_full_page, /* cvf_readpage */ ++ NULL, /* cvf_writepage */ ++ NULL, /* cvf_dir_ioctl */ ++ NULL /* zero_out_cluster */ + }; + + struct cvf_format *cvf_formats[MAX_CVF_FORMATS]={NULL,NULL,NULL}; +diff -u -r linux-2.3.30-6-orig/fs/fat/fatfs_syms.c linux-2.3.30-6-new1/fs/fat/fatfs_syms.c +--- linux-2.3.30-6-orig/fs/fat/fatfs_syms.c Tue Oct 26 18:21:46 1999 ++++ linux-2.3.30-6-new1/fs/fat/fatfs_syms.c Mon Nov 1 22:29:25 1999 +@@ -17,6 +17,7 @@ + + extern struct file_operations fat_dir_operations; + ++EXPORT_SYMBOL(fat_add_cluster); + EXPORT_SYMBOL(fat_new_dir); + EXPORT_SYMBOL(fat_bmap); + EXPORT_SYMBOL(fat_get_block); +@@ -55,6 +56,12 @@ + EXPORT_SYMBOL(fat_dir_ioctl); + EXPORT_SYMBOL(fat_add_entries); + EXPORT_SYMBOL(fat_dir_empty); ++ ++#if 0 /* will be reenabled again for CVF mmap support */ ++EXPORT_SYMBOL(fat_mmap); ++EXPORT_SYMBOL(fat_readpage); ++EXPORT_SYMBOL(fat_writepage); ++#endif + + int init_fat_fs(void) + { +diff -u -r linux-2.3.30-6-orig/fs/fat/inode.c linux-2.3.30-6-new1/fs/fat/inode.c +--- linux-2.3.30-6-orig/fs/fat/inode.c Sat Nov 6 00:27:28 1999 ++++ linux-2.3.30-6-new1/fs/fat/inode.c Sun Dec 5 01:16:44 1999 +@@ -434,12 +434,15 @@ + struct msdos_sb_info *sbi = MSDOS_SB(sb); + char *p; + int data_sectors,logical_sector_size,sector_mult,fat_clusters=0; +- int debug,error,fat,cp; ++ int debug; ++ int error = 0; ++ int fat,cp; + int blksize = 512; + int fat32; + struct fat_mount_options opts; + char buf[50]; +- int i; ++ int cvf_index=-1; ++ /* int i; */ + char cvf_format[21]; + char cvf_options[101]; + +@@ -514,14 +517,15 @@ + sbi->cluster_size = b->cluster_size*sector_mult; + if (!sbi->cluster_size || (sbi->cluster_size & (sbi->cluster_size-1))) { + printk("fatfs: bogus cluster size\n"); +- brelse(bh); +- goto out_invalid; ++ error = 1; ++ /* brelse(bh);goto out_invalid; */ ++ }else{ ++ for (sbi->cluster_bits=0; ++ 1<<sbi->cluster_bits<sbi->cluster_size; ++ sbi->cluster_bits++) ++ ; ++ sbi->cluster_bits += SECTOR_BITS; + } +- for (sbi->cluster_bits=0; +- 1<<sbi->cluster_bits<sbi->cluster_size; +- sbi->cluster_bits++) +- ; +- sbi->cluster_bits += SECTOR_BITS; + sbi->fats = b->fats; + sbi->fat_start = CF_LE_W(b->reserved)*sector_mult; + if (!b->fat_length && b->fat32_length) { +@@ -573,7 +577,7 @@ + data_sectors = CF_LE_L(b->total_sect); + } + data_sectors = data_sectors * sector_mult - sbi->data_start; +- error = !b->cluster_size || !sector_mult; ++ error |= !sector_mult; + if (!error) { + sbi->clusters = b->cluster_size ? data_sectors/ + b->cluster_size/sector_mult : 0; +@@ -599,11 +603,14 @@ + /* on odd sectors. */ + sb->s_blocksize_bits = blksize == 512 ? 9 : (blksize == 1024 ? 10 : 11); + if (!strcmp(cvf_format,"none")) +- i = -1; ++ cvf_index = -1; + else +- i = detect_cvf(sb,cvf_format); +- if (i >= 0) +- error = cvf_formats[i]->mount_cvf(sb,cvf_options); ++ cvf_index = detect_cvf(sb,cvf_format); ++ if (cvf_index >= 0) { ++ ++cvf_format_use_count[cvf_index]; ++ sbi->cvf_format = cvf_formats[cvf_index]; ++ error = cvf_formats[cvf_index]->mount_cvf(sb,cvf_options); ++ } + else if (sb->s_blocksize == 512) + sbi->cvf_format = &default_cvf; + else +@@ -627,7 +634,7 @@ + sbi->root_cluster,sbi->free_clusters); + printk ("Transaction block size = %d\n",blksize); + } +- if (i<0) if (sbi->clusters+2 > fat_clusters) ++ if (cvf_index<0) if (sbi->clusters+2 > fat_clusters) + sbi->clusters = fat_clusters-2; + if (error) + goto out_invalid; +@@ -672,10 +679,6 @@ + sb->s_root = d_alloc_root(root_inode); + if (!sb->s_root) + goto out_no_root; +- if(i>=0) { +- sbi->cvf_format = cvf_formats[i]; +- ++cvf_format_use_count[i]; +- } + return sb; + + out_no_root: +@@ -687,6 +690,8 @@ + unload_nls(sbi->nls_disk); + goto out_fail; + out_invalid: ++ if(cvf_index>=0) ++ --cvf_format_use_count[cvf_index]; + if (!silent) + printk("VFS: Can't find a valid MSDOS filesystem on dev %s.\n", + kdevname(sb->s_dev)); +diff -u -r linux-2.3.30-6-orig/fs/fat/misc.c linux-2.3.30-6-new1/fs/fat/misc.c +--- linux-2.3.30-6-orig/fs/fat/misc.c Mon Aug 30 17:23:14 1999 ++++ linux-2.3.30-6-new1/fs/fat/misc.c Sun Dec 5 03:11:47 1999 +@@ -209,8 +209,16 @@ + int cluster_size = MSDOS_SB(sb)->cluster_size; + + if (MSDOS_SB(sb)->fat_bits != 32) { +- if (inode->i_ino == MSDOS_ROOT_INO) return res; ++ if (inode->i_ino == MSDOS_ROOT_INO){ ++#ifdef DEBUG ++printk("FAT extend dir called for root\n"); ++#endif ++ return res; ++ } + } ++#ifdef DEBUG ++printk("FAT extend dir called for NON-root\n"); ++#endif + if (!MSDOS_SB(sb)->free_clusters) return res; + lock_fat(sb); + limit = MSDOS_SB(sb)->clusters; +@@ -279,9 +287,11 @@ + sector = MSDOS_SB(sb)->data_start+(nr-2)*cluster_size; + last_sector = sector + cluster_size; + if (MSDOS_SB(sb)->cvf_format && +- MSDOS_SB(sb)->cvf_format->zero_out_cluster) ++ MSDOS_SB(sb)->cvf_format->zero_out_cluster){ ++ /* CVF zeroes full cluster only */ + MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode,nr); +- else ++ res=fat_bread(sb,fat_bmap(inode,inode->i_blocks)); ++ }else + for ( ; sector < last_sector; sector++) { + #ifdef DEBUG + printk("zeroing sector %d\n",sector); +diff -u -r linux-2.3.30-6-orig/include/linux/fat_cvf.h linux-2.3.30-6-new1/include/linux/fat_cvf.h +--- linux-2.3.30-6-orig/include/linux/fat_cvf.h Mon Aug 9 18:43:49 1999 ++++ linux-2.3.30-6-new1/include/linux/fat_cvf.h Sat Dec 4 23:25:26 1999 +@@ -30,8 +30,8 @@ + ssize_t (*cvf_file_read) ( struct file *, char *, size_t, loff_t *); + ssize_t (*cvf_file_write) ( struct file *, const char *, size_t, loff_t *); + int (*cvf_mmap) (struct file *, struct vm_area_struct *); +- int (*cvf_readpage) (struct inode *, struct page *); +- int (*cvf_writepage) (struct inode *, struct page *); ++ int (*cvf_readpage) (struct dentry *, struct page *); ++ int (*cvf_writepage) (struct dentry *, struct page *); + int (*cvf_dir_ioctl) (struct inode * inode, struct file * filp, + unsigned int cmd, unsigned long arg); + void (*zero_out_cluster) (struct inode*, int clusternr); +diff -u -r linux-2.3.30-6-orig/include/linux/msdos_fs.h linux-2.3.30-6-new1/include/linux/msdos_fs.h +--- linux-2.3.30-6-orig/include/linux/msdos_fs.h Wed Oct 27 23:19:11 1999 ++++ linux-2.3.30-6-new1/include/linux/msdos_fs.h Wed Nov 24 22:25:31 1999 +@@ -274,6 +274,7 @@ + /* mmap.c */ + extern int fat_mmap(struct file *, struct vm_area_struct *); + extern int fat_readpage(struct file *, struct page *); ++extern int fat_writepage(struct file *, struct page *); + + + /* vfat.c */ diff --git a/patches/magic b/patches/magic new file mode 100644 index 0000000..9ee8ebb --- /dev/null +++ b/patches/magic @@ -0,0 +1,16 @@ +#------------------------------------------------------------------------------ +# +# dmsdos: file(1) magic for the CVF formats supported by dmsdos +# + +3 string MSDBL6.0 +>51 byte 0 +>>13 byte 16 Doublespace CVF (version 1) +>>13 byte 64 Drivespace 3 CVF +>51 byte 2 Drivespace CVF (version 2) +3 string MSDSP6.0 +>51 byte 0 +>>13 byte 16 Doublespace CVF (version 1) +>>13 byte 64 Drivespace 3 CVF +>51 byte 2 Drivespace CVF (version 2) +0 string STACKER Stacker CVF diff --git a/patches/msdos-rmdir-bugfix.diff b/patches/msdos-rmdir-bugfix.diff new file mode 100644 index 0000000..cd8305f --- /dev/null +++ b/patches/msdos-rmdir-bugfix.diff @@ -0,0 +1,19 @@ +--- linux.vanilla/fs/msdos/namei.c Sun Jun 21 18:40:55 1998 ++++ linux/fs/msdos/namei.c Fri Sep 11 04:07:28 1998 +@@ -369,7 +369,7 @@ + if (MSDOS_I(dir)->i_start) { /* may be zero in mkdir */ + pos = 0; + bh = NULL; +- while (fat_get_entry(dir,&pos,&bh,&de) > -1) ++ while (fat_get_entry(dir,&pos,&bh,&de) > -1) { + /* Ignore vfat longname entries */ + if (de->attr == ATTR_EXT) + continue; +@@ -379,6 +379,7 @@ + fat_brelse(sb, bh); + return -ENOTEMPTY; + } ++ } + if (bh) + fat_brelse(sb, bh); + } diff --git a/patches/vfat-brelse-bugfix.diff b/patches/vfat-brelse-bugfix.diff new file mode 100644 index 0000000..ec9e750 --- /dev/null +++ b/patches/vfat-brelse-bugfix.diff @@ -0,0 +1,15 @@ +--- linux/fs/vfat/namei.c.orig Fri Feb 26 14:42:54 1999 ++++ linux/fs/vfat/namei.c Fri Feb 26 14:43:28 1999 +@@ -506,10 +506,10 @@ + continue; + if (memcmp(de->name,name,MSDOS_NAME)) + continue; +- brelse(bh); ++ fat_brelse(dir->i_sb,bh); + return 0; + } +- brelse(bh); ++ fat_brelse(dir->i_sb,bh); + return -ENOENT; + } + |
