Commit 976a8f38 authored by Anton Altaparmakov's avatar Anton Altaparmakov

Merge cantab.net:/usr/src/bklinux-2.5 into cantab.net:/usr/src/ntfs-2.5

parents 6923b9bd 4db49ba4
......@@ -247,6 +247,12 @@ ChangeLog
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.1.0:
- Add configuration option for developmental write support.
- Initial implementation of file overwriting. (Writes to resident files
are not written out to disk yet, so avoid writing to files smaller
than about 1kiB.)
- Intercept/abort changes in file size as they are not implemented yet.
2.0.25:
- Minor bugfixes in error code paths and small cleanups.
2.0.24:
......
......@@ -572,6 +572,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -385,6 +385,7 @@ CONFIG_MSDOS_FS=m
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -529,6 +529,7 @@ CONFIG_RAMFS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -479,6 +479,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -509,6 +509,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -658,6 +658,7 @@ CONFIG_TMPFS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -844,6 +844,7 @@ CONFIG_MINIX_FS=m
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -223,6 +223,7 @@ CONFIG_UNIX98_PTY_COUNT=32
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -647,6 +647,7 @@ CONFIG_RAMFS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -685,6 +685,7 @@ CONFIG_RAMFS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -649,6 +649,7 @@ CONFIG_RAMFS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -420,6 +420,8 @@ CONFIG_CLPS7500_FLASH=y
# CONFIG_ISO9660_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -531,6 +531,7 @@ CONFIG_MINIX_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -330,6 +330,7 @@ CONFIG_RAMFS=y
CONFIG_MINIX_FS=y
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
#
#
# Example empeg-car kernel configuration file.
#
CONFIG_ARM=y
......
......@@ -544,6 +544,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -642,6 +642,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -615,6 +615,7 @@ CONFIG_JOLIET=y
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -455,6 +455,7 @@ CONFIG_JFFS_FS_VERBOSE=0
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -492,6 +492,7 @@ CONFIG_RAMFS=y
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -512,6 +512,7 @@ CONFIG_RAMFS=y
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -585,6 +585,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -560,6 +560,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -650,6 +650,7 @@ CONFIG_RAMFS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -336,6 +336,7 @@ CONFIG_CRAMFS=y
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -543,6 +543,7 @@ CONFIG_MINIX_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -638,6 +638,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -667,6 +667,7 @@ CONFIG_ISO9660_FS=m
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -655,6 +655,7 @@ CONFIG_JOLIET=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -702,6 +702,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -417,6 +417,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -762,6 +762,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -422,6 +422,7 @@ CONFIG_MSDOS_FS=y
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -559,6 +559,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -598,6 +598,7 @@ CONFIG_JFFS_FS_VERBOSE=0
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -598,6 +598,7 @@ CONFIG_JFFS_FS_VERBOSE=0
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -591,6 +591,7 @@ CONFIG_JFFS_FS_VERBOSE=0
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -598,6 +598,7 @@ CONFIG_JFFS_FS_VERBOSE=0
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -460,6 +460,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -620,6 +620,7 @@ CONFIG_JOLIET=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -534,6 +534,8 @@ CONFIG_RAMFS=y
CONFIG_MINIX_FS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -681,6 +681,7 @@ CONFIG_JOLIET=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -151,6 +151,8 @@ CONFIG_SERIAL_SA1100_CONSOLE=y
# CONFIG_JOLIET is not set
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_QNX4FS_FS is not set
......
......@@ -649,6 +649,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -684,6 +684,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -421,6 +421,7 @@ CONFIG_PSMOUSE=y
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -441,6 +441,7 @@ CONFIG_RAMFS=y
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -779,6 +779,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -628,6 +628,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -526,6 +526,7 @@ CONFIG_JOLIET=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -526,6 +526,7 @@ CONFIG_JOLIET=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -288,6 +288,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -288,6 +288,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -283,6 +283,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -283,6 +283,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -253,6 +253,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -363,6 +363,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -497,6 +497,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -499,6 +499,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -497,6 +497,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -497,6 +497,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -289,6 +289,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -288,6 +288,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -288,6 +288,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -496,6 +496,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -498,6 +498,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -371,6 +371,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -496,6 +496,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -228,6 +228,8 @@ CONFIG_MSDOS_FS=y
# CONFIG_JOLIET is not set
CONFIG_MINIX_FS=y
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -443,6 +443,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -433,6 +433,7 @@ CONFIG_EFS_FS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -467,6 +467,7 @@ CONFIG_PSMOUSE=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -394,6 +394,7 @@ CONFIG_AUTOFS4_FS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -430,6 +430,7 @@ CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -443,6 +443,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -546,6 +546,7 @@ CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -459,6 +459,7 @@ CONFIG_EFS_FS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -270,6 +270,7 @@ CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -395,6 +395,7 @@ CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -382,6 +382,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -313,6 +313,7 @@ CONFIG_RTC=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -400,6 +400,7 @@ CONFIG_AUTOFS_FS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -405,6 +405,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -400,6 +400,7 @@ CONFIG_AUTOFS_FS=y
# CONFIG_FREEVXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -430,6 +430,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -294,6 +294,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -376,6 +376,7 @@ CONFIG_UNIX98_PTY_COUNT=32
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -404,6 +404,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -372,6 +372,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -371,6 +371,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -372,6 +372,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -345,6 +345,7 @@ CONFIG_AMD_FLASH=y
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -372,6 +372,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -417,6 +417,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -514,6 +514,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -659,6 +659,7 @@ CONFIG_MINIX_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -432,6 +432,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -371,6 +371,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -434,6 +434,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -725,6 +725,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -458,6 +458,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -428,6 +428,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -355,6 +355,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -473,6 +473,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -453,6 +453,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -364,6 +364,7 @@ CONFIG_JOLIET=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -593,6 +593,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -494,6 +494,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -681,6 +681,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -364,6 +364,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -404,6 +404,7 @@ CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -503,6 +503,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -552,6 +552,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -407,6 +407,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -504,6 +504,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -805,6 +805,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -577,6 +577,7 @@ CONFIG_JOLIET=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -596,6 +596,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -440,6 +440,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -454,6 +454,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -433,6 +433,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -372,6 +372,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -371,6 +371,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -371,6 +371,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -687,6 +687,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -402,6 +402,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -428,6 +428,7 @@ CONFIG_TMPFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -409,6 +409,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -725,6 +725,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -584,6 +584,7 @@ CONFIG_JFS_FS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -295,6 +295,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -295,6 +295,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
......
......@@ -156,6 +156,7 @@ CONFIG_SERIAL_CONSOLE=y
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -302,6 +302,7 @@ CONFIG_MINIX_FS=m
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
CONFIG_HPFS_FS=m
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -703,6 +703,7 @@ CONFIG_MINIX_FS=m
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
CONFIG_HPFS_FS=m
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -513,6 +513,7 @@ CONFIG_RAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_DEBUG is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
......
......@@ -606,6 +606,15 @@ CONFIG_NTFS_DEBUG
When reporting bugs, please try to have available a full dump of
debugging messages while the misbehaviour was occurring.
CONFIG_NTFS_RW
This enables the experimental write support in the NTFS driver.
WARNING: Do not use this option unless you are actively developing
NTFS as it is currently guaranteed to be broken and you
may lose all your data!
It is strongly recommended and perfectly safe to say N here.
CONFIG_SYSV_FS
SCO, Xenix and Coherent are commercial Unix systems for Intel
machines, and Version 7 was used on the DEC PDP-11. Saying Y
......
......@@ -70,6 +70,7 @@ tristate 'FreeVxFS file system support (VERITAS VxFS(TM) compatible)' CONFIG_VXF
tristate 'NTFS file system support (read only)' CONFIG_NTFS_FS
dep_mbool ' NTFS debugging support' CONFIG_NTFS_DEBUG $CONFIG_NTFS_FS
dep_mbool ' NTFS write support (DANGEROUS)' CONFIG_NTFS_RW $CONFIG_NTFS_FS $CONFIG_EXPERIMENTAL
tristate 'OS/2 HPFS file system support' CONFIG_HPFS_FS
......
ToDo:
- Find and fix bugs.
- Enable NFS exporting of NTFS.
- Implement aops->set_page_dirty() in order to take control of buffer
dirtying. Not having it means if page_has_buffers(), all buffers
will be dirtied with the page. And if not they won't be. That is
fine for the moment but will break once we enable metadata updates.
- Implement sops->dirty_inode() to implement {a,m,c} time updates and
such things.
- Implement sops->write_inode().
- In between ntfs_prepare/commit_write, need exclusion between
simultaneous file extensions. Need perhaps an NInoResizeUnderway()
flag which we can set in ntfs_prepare_write() and clear again in
ntfs_commit_write(). Just have to be careful in readpage/writepage,
as well as in truncate, that we play nice... We might need to have
a data_size field in the ntfs_inode to store the real attribute
length. Also need to be careful with initialized_size extention in
ntfs_prepare_write. Basically, just be _very_ careful in this code...
OTOH, perhaps i_sem, which is held accross generic_file_write is
sufficient for synchronisation here. We then just need to make sure
ntfs_readpage/writepage/truncate interoperate properly with us.
2.1.0 - First steps towards write support: implement file overwrite.
- Add configuration option for developmental write support with an
appropriately scary configuration help text.
- Initial implementation of fs/ntfs/aops.c::ntfs_writepage() and its
helper fs/ntfs/aops.c::ntfs_write_block(). This enables mmap(2) based
overwriting of existing files on ntfs. Note: Resident files are
only written into memory, and not written out to disk at present, so
avoid writing to files smaller than about 1kiB.
- Initial implementation of fs/ntfs/aops.c::ntfs_prepare_write(), its
helper fs/ntfs/aops.c::ntfs_prepare_nonresident_write() and their
counterparts, fs/ntfs/aops.c::ntfs_commit_write(), and
fs/ntfs/aops.c::ntfs_commit_nonresident_write(), respectively. Also,
add generic_file_write() to the ntfs file operations (fs/ntfs/file.c).
This enables write(2) based overwriting of existing files on ntfs.
Note: As with mmap(2) based overwriting, resident files are only
written into memory, and not written out to disk at present, so avoid
writing to files smaller than about 1kiB.
- Implement ->truncate (fs/ntfs/inode.c::ntfs_truncate()) and
->setattr() (fs/ntfs/inode.c::ntfs_setattr()) inode operations for
files with the purpose of intercepting and aborting all i_size
changes which we do not support yet. ntfs_truncate() actually only
emits a warning message but AFAICS our interception of i_size changes
elsewhere means ntfs_truncate() never gets called for i_size changes.
It is only called from generic_file_write() when we fail in
ntfs_prepare_{,nonresident_}write() in order to discard any
instantiated buffers beyond i_size. Thus i_size is not actually
changed so our warning message is enough. Unfortunately it is not
possible to easily determine if i_size is being changed or not hence
we just emit an appropriately worded error message.
2.0.25 - Small bug fixes and cleanups.
......
......@@ -5,15 +5,15 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o
ntfs-objs := aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o \
mst.o namei.o super.o sysctl.o time.o unistr.o upcase.o
EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.25\"
EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.0\"
ifeq ($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
#ifeq ($(CONFIG_NTFS_RW),y)
#EXTRA_CFLAGS += -DNTFS_RW
#endif
ifeq ($(CONFIG_NTFS_RW),y)
EXTRA_CFLAGS += -DNTFS_RW
endif
include $(TOPDIR)/Rules.make
......@@ -385,7 +385,7 @@ int ntfs_readpage(struct file *file, struct page *page)
else
base_ni = ni->_INE(base_ntfs_ino);
/* Map, pin and lock the mft record. */
/* Map, pin, and lock the mft record. */
mrec = map_mft_record(base_ni);
if (unlikely(IS_ERR(mrec))) {
err = PTR_ERR(mrec);
......@@ -435,6 +435,1337 @@ int ntfs_readpage(struct file *file, struct page *page)
return err;
}
#ifdef NTFS_RW
/**
* ntfs_write_block - write a @page to the backing store
* @page: page cache page to write out
*
* This function is for writing pages belonging to non-resident, non-mst
* protected attributes to their backing store.
*
* For a page with buffers, map and write the dirty buffers asynchronously
* under page writeback. For a page without buffers, create buffers for the
* page, then proceed as above.
*
* If a page doesn't have buffers the page dirty state is definitive. If a page
* does have buffers, the page dirty state is just a hint, and the buffer dirty
* state is definitive. (A hint which has rules: dirty buffers against a clean
* page is illegal. Other combinations are legal and need to be handled. In
* particular a dirty page containing clean buffers for example.)
*
* Return 0 on success and -errno on error.
*
* Based on ntfs_read_block() and __block_write_full_page().
*/
static int ntfs_write_block(struct page *page)
{
VCN vcn;
LCN lcn;
sector_t block, dblock, iblock;
struct inode *vi;
ntfs_inode *ni;
ntfs_volume *vol;
run_list_element *rl;
struct buffer_head *bh, *head;
unsigned int blocksize, vcn_ofs;
int err;
BOOL need_end_writeback;
unsigned char blocksize_bits;
vi = page->mapping->host;
ni = NTFS_I(vi);
vol = ni->vol;
ntfs_debug("Entering for inode %li, attribute type 0x%x, page index "
"0x%lx.\n", vi->i_ino, ni->type, page->index);
BUG_ON(!NInoNonResident(ni));
BUG_ON(NInoMstProtected(ni));
blocksize_bits = vi->i_blkbits;
blocksize = 1 << blocksize_bits;
if (!page_has_buffers(page)) {
BUG_ON(!PageUptodate(page));
create_empty_buffers(page, blocksize,
(1 << BH_Uptodate) | (1 << BH_Dirty));
}
bh = head = page_buffers(page);
if (unlikely(!bh)) {
ntfs_warning(vol->sb, "Error allocating page buffers. "
"Redirtying page so we try again later.");
/*
* Put the page back on mapping->dirty_pages, but leave its
* buffer's dirty state as-is.
*/
// FIXME: Once Andrew's -EAGAIN patch goes in, remove the
// __set_page_dirty_nobuffers(page) and return -EAGAIN instead
// of zero.
__set_page_dirty_nobuffers(page);
unlock_page(page);
return 0;
}
/* NOTE: Different naming scheme to ntfs_read_block()! */
/* The first block in the page. */
block = page->index << (PAGE_CACHE_SHIFT - blocksize_bits);
/* The first out of bounds block for the data size. */
dblock = (vi->i_size + blocksize - 1) >> blocksize_bits;
/* The last (fully or partially) initialized block. */
iblock = ni->initialized_size >> blocksize_bits;
/*
* Be very careful. We have no exclusion from __set_page_dirty_buffers
* here, and the (potentially unmapped) buffers may become dirty at
* any time. If a buffer becomes dirty here after we've inspected it
* then we just miss that fact, and the page stays dirty.
*
* Buffers outside i_size may be dirtied by __set_page_dirty_buffers;
* handle that here by just cleaning them.
*/
/*
* Loop through all the buffers in the page, mapping all the dirty
* buffers to disk addresses and handling any aliases from the
* underlying block device's mapping.
*/
rl = NULL;
err = 0;
do {
BOOL is_retry = FALSE;
if (unlikely(block >= dblock)) {
/*
* Mapped buffers outside i_size will occur, because
* this page can be outside i_size when there is a
* truncate in progress. The contents of such buffers
* were zeroed by ntfs_writepage().
*
* FIXME: What about the small race window where
* ntfs_writepage() has not done any clearing because
* the page was within i_size but before we get here,
* vmtruncate() modifies i_size?
*/
clear_buffer_dirty(bh);
set_buffer_uptodate(bh);
continue;
}
/* Clean buffers are not written out, so no need to map them. */
if (!buffer_dirty(bh))
continue;
/* Make sure we have enough initialized size. */
if (unlikely((block >= iblock) &&
(ni->initialized_size < vi->i_size))) {
/*
* If this page is fully outside initialized size, zero
* out all pages between the current initialized size
* and the current page. Just use ntfs_readpage() to do
* the zeroing transparently.
*/
if (block > iblock) {
// TODO:
// For each page do:
// - read_cache_page()
// Again for each page do:
// - wait_on_page_locked()
// - Check (PageUptodate(page) &&
// !PageError(page))
// Update initialized size in the attribute and
// in the inode.
// Again, for each page do:
// __set_page_dirty_buffers();
// page_cache_release()
// We don't need to wait on the writes.
// Update iblock.
}
/*
* The current page straddles initialized size. Zero
* all non-uptodate buffers and set them uptodate (and
* dirty?). Note, there aren't any non-uptodate buffers
* if the page is uptodate.
* FIXME: For an uptodate page, the buffers may need to
* be written out because they were not initialized on
* disk before.
*/
if (!PageUptodate(page)) {
// TODO:
// Zero any non-uptodate buffers up to i_size.
// Set them uptodate and dirty.
}
// TODO:
// Update initialized size in the attribute and in the
// inode (up to i_size).
// Update iblock.
// FIXME: This is inefficient. Try to batch the two
// size changes to happen in one go.
ntfs_error(vol->sb, "Writing beyond initialized size "
"is not supported yet. Sorry.");
err = -EOPNOTSUPP;
break;
// Do NOT set_buffer_new() BUT DO clear buffer range
// outside write request range.
// set_buffer_uptodate() on complete buffers as well as
// set_buffer_dirty().
}
/* No need to map buffers that are already mapped. */
if (buffer_mapped(bh))
continue;
/* Unmapped, dirty buffer. Need to map it. */
bh->b_bdev = vol->sb->s_bdev;
/* Convert block into corresponding vcn and offset. */
vcn = (VCN)block << blocksize_bits >> vol->cluster_size_bits;
vcn_ofs = ((VCN)block << blocksize_bits) &
vol->cluster_size_mask;
if (!rl) {
lock_retry_remap:
down_read(&ni->run_list.lock);
rl = ni->run_list.rl;
}
if (likely(rl != NULL)) {
/* Seek to element containing target vcn. */
while (rl->length && rl[1].vcn <= vcn)
rl++;
lcn = vcn_to_lcn(rl, vcn);
} else
lcn = (LCN)LCN_RL_NOT_MAPPED;
/* Successful remap. */
if (lcn >= 0) {
/* Setup buffer head to point to correct block. */
bh->b_blocknr = ((lcn << vol->cluster_size_bits) +
vcn_ofs) >> blocksize_bits;
set_buffer_mapped(bh);
continue;
}
/* It is a hole, need to instantiate it. */
if (lcn == LCN_HOLE) {
// TODO: Instantiate the hole.
// clear_buffer_new(bh);
// unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr);
ntfs_error(vol->sb, "Writing into sparse regions is "
"not supported yet. Sorry.");
err = -EOPNOTSUPP;
break;
}
/* If first try and run list unmapped, map and retry. */
if (!is_retry && lcn == LCN_RL_NOT_MAPPED) {
is_retry = TRUE;
/*
* Attempt to map run list, dropping lock for
* the duration.
*/
up_read(&ni->run_list.lock);
err = map_run_list(ni, vcn);
if (likely(!err))
goto lock_retry_remap;
rl = NULL;
}
/* Failed to map the buffer, even after retrying. */
bh->b_blocknr = -1UL;
ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%Lx) failed "
"with error code 0x%Lx%s.",
(long long)vcn, (long long)-lcn,
is_retry ? " even after retrying" : "");
// FIXME: Depending on vol->on_errors, do something.
if (!err)
err = -EIO;
break;
} while (block++, (bh = bh->b_this_page) != head);
/* Release the lock if we took it. */
if (rl)
up_read(&ni->run_list.lock);
/* For the error case, need to reset bh to the beginning. */
bh = head;
/* Just an optimization, so ->readpage() isn't called later. */
if (unlikely(!PageUptodate(page))) {
int uptodate = 1;
do {
if (!buffer_uptodate(bh)) {
uptodate = 0;
bh = head;
break;
}
} while ((bh = bh->b_this_page) != head);
if (uptodate)
SetPageUptodate(page);
}
/* Setup all mapped, dirty buffers for async write i/o. */
do {
get_bh(bh);
if (buffer_mapped(bh) && buffer_dirty(bh)) {
lock_buffer(bh);
if (test_clear_buffer_dirty(bh)) {
BUG_ON(!buffer_uptodate(bh));
mark_buffer_async_write(bh);
} else
unlock_buffer(bh);
} else if (unlikely(err)) {
/*
* For the error case. The buffer may have been set
* dirty during attachment to a dirty page.
*/
if (err != -ENOMEM)
clear_buffer_dirty(bh);
}
} while ((bh = bh->b_this_page) != head);
if (unlikely(err)) {
// TODO: Remove the -EOPNOTSUPP check later on...
if (unlikely(err == -EOPNOTSUPP))
err = 0;
else if (err == -ENOMEM) {
ntfs_warning(vol->sb, "Error allocating memory. "
"Redirtying page so we try again "
"later.");
/*
* Put the page back on mapping->dirty_pages, but
* leave its buffer's dirty state as-is.
*/
// FIXME: Once Andrew's -EAGAIN patch goes in, remove
// the __set_page_dirty_nobuffers(page) and set err to
// -EAGAIN instead of zero.
__set_page_dirty_nobuffers(page);
err = 0;
} else
SetPageError(page);
}
BUG_ON(PageWriteback(page));
SetPageWriteback(page); /* Keeps try_to_free_buffers() away. */
unlock_page(page);
/*
* Submit the prepared buffers for i/o. Note the page is unlocked,
* and the async write i/o completion handler can end_page_writeback()
* at any time after the *first* submit_bh(). So the buffers can then
* disappear...
*/
need_end_writeback = TRUE;
do {
struct buffer_head *next = bh->b_this_page;
if (buffer_async_write(bh)) {
submit_bh(WRITE, bh);
need_end_writeback = FALSE;
}
put_bh(bh);
bh = next;
} while (bh != head);
/* If no i/o was started, need to end_page_writeback(). */
if (unlikely(need_end_writeback))
end_page_writeback(page);
ntfs_debug("Done.");
return err;
}
/**
* ntfs_writepage - write a @page to the backing store
* @page: page cache page to write out
*
* For non-resident attributes, ntfs_writepage() writes the @page by calling
* the ntfs version of the generic block_write_full_page() function,
* ntfs_write_block(), which in turn if necessary creates and writes the
* buffers associated with the page asynchronously.
*
* For resident attributes, OTOH, ntfs_writepage() writes the @page by copying
* the data to the mft record (which at this stage is most likely in memory).
* Thus, in this case, I/O is synchronous, as even if the mft record is not
* cached at this point in time, we need to wait for it to be read in before we
* can do the copy.
*
* Note the caller clears the page dirty flag before calling ntfs_writepage().
*
* Based on ntfs_readpage() and fs/buffer.c::block_write_full_page().
*
* Return 0 on success and -errno on error.
*/
static int ntfs_writepage(struct page *page)
{
s64 attr_pos;
struct inode *vi;
ntfs_inode *ni, *base_ni;
char *kaddr;
attr_search_context *ctx;
MFT_RECORD *m;
u32 attr_len, bytes;
int err;
BUG_ON(!PageLocked(page));
vi = page->mapping->host;
/* Is the page fully outside i_size? (truncate in progress) */
if (unlikely(page->index >= (vi->i_size + PAGE_CACHE_SIZE - 1) >>
PAGE_CACHE_SHIFT)) {
unlock_page(page);
ntfs_debug("Write outside i_size. Returning i/o error.");
return -EIO;
}
ni = NTFS_I(vi);
if (NInoNonResident(ni)) {
/*
* Only unnamed $DATA attributes can be compressed, encrypted,
* and/or sparse.
*/
if (ni->type == AT_DATA && !ni->name_len) {
/* If file is encrypted, deny access, just like NT4. */
if (NInoEncrypted(ni)) {
unlock_page(page);
ntfs_debug("Denying write access to encrypted "
"file.");
return -EACCES;
}
/* Compressed data streams are handled in compress.c. */
if (NInoCompressed(ni)) {
// TODO: Implement and replace this check with
// return ntfs_write_compressed_block(page);
unlock_page(page);
ntfs_error(vi->i_sb, "Writing to compressed "
"files is not supported yet. "
"Sorry.");
return -EOPNOTSUPP;
}
// TODO: Implement and remove this check.
if (NInoSparse(ni)) {
unlock_page(page);
ntfs_error(vi->i_sb, "Writing to sparse files "
"is not supported yet. Sorry.");
return -EOPNOTSUPP;
}
}
/* We have to zero every time due to mmap-at-end-of-file. */
if (page->index >= (vi->i_size >> PAGE_CACHE_SHIFT)) {
/* The page straddles i_size. */
unsigned int ofs = vi->i_size & ~PAGE_CACHE_MASK;
kaddr = kmap_atomic(page, KM_USER0);
memset(kaddr + ofs, 0, PAGE_CACHE_SIZE - ofs);
flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);
}
// TODO: Implement and remove this check.
if (NInoMstProtected(ni)) {
unlock_page(page);
ntfs_error(vi->i_sb, "Writing to MST protected "
"attributes is not supported yet. "
"Sorry.");
return -EOPNOTSUPP;
}
/* Normal data stream. */
return ntfs_write_block(page);
}
/*
* Attribute is resident, implying it is not compressed, encrypted, or
* mst protected.
*/
BUG_ON(page_has_buffers(page));
BUG_ON(!PageUptodate(page));
// TODO: Consider using PageWriteback() + unlock_page() in 2.5 once the
// "VM fiddling has ended". Note, don't forget to replace all the
// unlock_page() calls further below with end_page_writeback() ones.
// FIXME: Make sure it is ok to SetPageError() on unlocked page under
// writeback before doing the change!
#if 0
SetPageWriteback(page);
unlock_page(page);
#endif
if (!NInoAttr(ni))
base_ni = ni;
else
base_ni = ni->_INE(base_ntfs_ino);
/* Map, pin, and lock the mft record. */
m = map_mft_record(base_ni);
if (unlikely(IS_ERR(m))) {
err = PTR_ERR(m);
m = NULL;
ctx = NULL;
goto err_out;
}
ctx = get_attr_search_ctx(base_ni, m);
if (unlikely(!ctx)) {
err = -ENOMEM;
goto err_out;
}
if (unlikely(!lookup_attr(ni->type, ni->name, ni->name_len,
IGNORE_CASE, 0, NULL, 0, ctx))) {
err = -ENOENT;
goto err_out;
}
/* Starting position of the page within the attribute value. */
attr_pos = page->index << PAGE_CACHE_SHIFT;
/* The total length of the attribute value. */
attr_len = le32_to_cpu(ctx->attr->_ARA(value_length));
if (unlikely(vi->i_size != attr_len)) {
ntfs_error(vi->i_sb, "BUG()! i_size (0x%Lx) doesn't match "
"attr_len (0x%x). Aborting write.", vi->i_size,
attr_len);
err = -EIO;
goto err_out;
}
if (unlikely(attr_pos >= attr_len)) {
ntfs_error(vi->i_sb, "BUG()! attr_pos (0x%Lx) > attr_len (0x%x)"
". Aborting write.", attr_pos, attr_len);
err = -EIO;
goto err_out;
}
bytes = attr_len - attr_pos;
if (unlikely(bytes > PAGE_CACHE_SIZE))
bytes = PAGE_CACHE_SIZE;
/*
* Here, we don't need to zero the out of bounds area everytime because
* the below memcpy() already takes care of the mmap-at-end-of-file
* requirements. If the file is converted to a non-resident one, then
* the code path use is switched to the non-resident one where the
* zeroing happens on each ntfs_writepage() invokation.
*
* The above also applies nicely when i_size is decreased.
*
* When i_size is increased, the memory between the old and new i_size
* _must_ be zeroed (or overwritten with new data). Otherwise we will
* expose data to userspace/disk which should never have been exposed.
*
* FIXME: Ensure that i_size increases do the zeroing/overwriting and
* if we cannot guarantee that, then enable the zeroing below.
*/
kaddr = kmap_atomic(page, KM_USER0);
/* Copy the data from the page to the mft record. */
memcpy((u8*)ctx->attr + le16_to_cpu(ctx->attr->_ARA(value_offset)) +
attr_pos, kaddr, bytes);
flush_dcache_mft_record_page(ctx->ntfs_ino);
#if 0
/* Zero out of bounds area. */
if (likely(bytes < PAGE_CACHE_SIZE)) {
memset(kaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
flush_dcache_page(page);
}
#endif
kunmap_atomic(kaddr, KM_USER0);
unlock_page(page);
// TODO: Mark mft record dirty so it gets written back.
ntfs_error(vi->i_sb, "Writing to resident files is not supported yet. "
"Wrote to memory only...");
put_attr_search_ctx(ctx);
unmap_mft_record(base_ni);
return 0;
err_out:
if (err == -ENOMEM) {
ntfs_warning(vi->i_sb, "Error allocating memory. Redirtying "
"page so we try again later.");
/*
* Put the page back on mapping->dirty_pages, but leave its
* buffer's dirty state as-is.
*/
// FIXME: Once Andrew's -EAGAIN patch goes in, remove the
// __set_page_dirty_nobuffers(page) and set err to -EAGAIN
// instead of zero.
__set_page_dirty_nobuffers(page);
err = 0;
} else {
ntfs_error(vi->i_sb, "Resident attribute write failed with "
"error %i. Setting page error flag.", -err);
SetPageError(page);
}
unlock_page(page);
if (ctx)
put_attr_search_ctx(ctx);
if (m)
unmap_mft_record(base_ni);
return err;
}
/**
* ntfs_prepare_nonresident_write -
*
*/
static int ntfs_prepare_nonresident_write(struct page *page,
unsigned from, unsigned to)
{
VCN vcn;
LCN lcn;
sector_t block, ablock, iblock;
struct inode *vi;
ntfs_inode *ni;
ntfs_volume *vol;
run_list_element *rl;
struct buffer_head *bh, *head, *wait[2], **wait_bh = wait;
char *kaddr = page_address(page);
unsigned int vcn_ofs, block_start, block_end, blocksize;
int err;
BOOL is_retry;
unsigned char blocksize_bits;
vi = page->mapping->host;
ni = NTFS_I(vi);
vol = ni->vol;
ntfs_debug("Entering for inode %li, attribute type 0x%x, page index "
"0x%lx, from = %u, to = %u.", vi->i_ino, ni->type,
page->index, from, to);
BUG_ON(!NInoNonResident(ni));
BUG_ON(NInoMstProtected(ni));
blocksize_bits = vi->i_blkbits;
blocksize = 1 << blocksize_bits;
/*
* create_empty_buffers() will create uptodate/dirty buffers if the
* page is uptodate/dirty.
*/
if (!page_has_buffers(page))
create_empty_buffers(page, blocksize, 0);
bh = head = page_buffers(page);
if (unlikely(!bh))
return -ENOMEM;
/* The first block in the page. */
block = page->index << (PAGE_CACHE_SHIFT - blocksize_bits);
/*
* The first out of bounds block for the allocated size. No need to
* round up as allocated_size is in multiples of cluster size and the
* minimum cluster size is 512 bytes, which is equal to the smallest
* blocksize.
*/
ablock = ni->allocated_size >> blocksize_bits;
/* The last (fully or partially) initialized block. */
iblock = ni->initialized_size >> blocksize_bits;
/* Loop through all the buffers in the page. */
block_start = 0;
rl = NULL;
err = 0;
do {
block_end = block_start + blocksize;
/*
* If buffer @bh is outside the write, just mark it uptodate
* if the page is uptodate and continue with the next buffer.
*/
if (block_end <= from || block_start >= to) {
if (PageUptodate(page)) {
if (!buffer_uptodate(bh))
set_buffer_uptodate(bh);
}
continue;
}
/*
* @bh is at least partially being written to.
* Make sure it is not marked as new.
*/
//if (buffer_new(bh))
// clear_buffer_new(bh);
if (block >= ablock) {
// TODO: block is above allocated_size, need to
// allocate it. Best done in one go to accomodate not
// only block but all above blocks up to and including:
// ((page->index << PAGE_CACHE_SHIFT) + to + blocksize
// - 1) >> blobksize_bits. Obviously will need to round
// up to next cluster boundary, too. This should be
// done with a helper function, so it can be reused.
ntfs_error(vol->sb, "Writing beyond allocated size "
"is not supported yet. Sorry.");
err = -EOPNOTSUPP;
goto err_out;
// Need to update ablock.
// Need to set_buffer_new() on all block bhs that are
// newly allocated.
}
/*
* Now we have enough allocated size to fulfill the whole
* request, i.e. block < ablock is true.
*/
if (unlikely((block >= iblock) &&
(ni->initialized_size < vi->i_size))) {
/*
* If this page is fully outside initialized size, zero
* out all pages between the current initialized size
* and the current page. Just use ntfs_readpage() to do
* the zeroing transparently.
*/
if (block > iblock) {
// TODO:
// For each page do:
// - read_cache_page()
// Again for each page do:
// - wait_on_page_locked()
// - Check (PageUptodate(page) &&
// !PageError(page))
// Update initialized size in the attribute and
// in the inode.
// Again, for each page do:
// __set_page_dirty_buffers();
// page_cache_release()
// We don't need to wait on the writes.
// Update iblock.
}
/*
* The current page straddles initialized size. Zero
* all non-uptodate buffers and set them uptodate (and
* dirty?). Note, there aren't any non-uptodate buffers
* if the page is uptodate.
* FIXME: For an uptodate page, the buffers may need to
* be written out because they were not initialized on
* disk before.
*/
if (!PageUptodate(page)) {
// TODO:
// Zero any non-uptodate buffers up to i_size.
// Set them uptodate and dirty.
}
// TODO:
// Update initialized size in the attribute and in the
// inode (up to i_size).
// Update iblock.
// FIXME: This is inefficient. Try to batch the two
// size changes to happen in one go.
ntfs_error(vol->sb, "Writing beyond initialized size "
"is not supported yet. Sorry.");
err = -EOPNOTSUPP;
goto err_out;
// Do NOT set_buffer_new() BUT DO clear buffer range
// outside write request range.
// set_buffer_uptodate() on complete buffers as well as
// set_buffer_dirty().
}
/* Need to map unmapped buffers. */
if (!buffer_mapped(bh)) {
/* Unmapped buffer. Need to map it. */
bh->b_bdev = vol->sb->s_bdev;
/* Convert block into corresponding vcn and offset. */
vcn = (VCN)block << blocksize_bits >>
vol->cluster_size_bits;
vcn_ofs = ((VCN)block << blocksize_bits) &
vol->cluster_size_mask;
is_retry = FALSE;
if (!rl) {
lock_retry_remap:
down_read(&ni->run_list.lock);
rl = ni->run_list.rl;
}
if (likely(rl != NULL)) {
/* Seek to element containing target vcn. */
while (rl->length && rl[1].vcn <= vcn)
rl++;
lcn = vcn_to_lcn(rl, vcn);
} else
lcn = (LCN)LCN_RL_NOT_MAPPED;
if (unlikely(lcn < 0)) {
/*
* We extended the attribute allocation above.
* If we hit an ENOENT here it means that the
* allocation was insufficient which is a bug.
*/
BUG_ON(lcn == LCN_ENOENT);
/* It is a hole, need to instantiate it. */
if (lcn == LCN_HOLE) {
// TODO: Instantiate the hole.
// clear_buffer_new(bh);
// unmap_underlying_metadata(bh->b_bdev,
// bh->b_blocknr);
// For non-uptodate buffers, need to
// zero out the region outside the
// request in this bh or all bhs,
// depending on what we implemented
// above.
// Need to flush_dcache_page().
// Or could use set_buffer_new()
// instead?
ntfs_error(vol->sb, "Writing into "
"sparse regions is "
"not supported yet. "
"Sorry.");
err = -EOPNOTSUPP;
goto err_out;
} else if (!is_retry &&
lcn == LCN_RL_NOT_MAPPED) {
is_retry = TRUE;
/*
* Attempt to map run list, dropping
* lock for the duration.
*/
up_read(&ni->run_list.lock);
err = map_run_list(ni, vcn);
if (likely(!err))
goto lock_retry_remap;
rl = NULL;
}
/*
* Failed to map the buffer, even after
* retrying.
*/
bh->b_blocknr = -1UL;
ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%Lx) "
"failed with error code "
"0x%Lx%s.", (long long)vcn,
(long long)-lcn, is_retry ?
" even after retrying" : "");
// FIXME: Depending on vol->on_errors, do
// something.
if (!err)
err = -EIO;
goto err_out;
}
/* We now have a successful remap, i.e. lcn >= 0. */
/* Setup buffer head to correct block. */
bh->b_blocknr = ((lcn << vol->cluster_size_bits)
+ vcn_ofs) >> blocksize_bits;
set_buffer_mapped(bh);
// FIXME: Something analogous to this is needed for
// each newly allocated block, i.e. BH_New.
// FIXME: Might need to take this out of the
// if (!buffer_mapped(bh)) {}, depending on how we
// implement things during the allocated_size and
// initialized_size extension code above.
if (buffer_new(bh)) {
clear_buffer_new(bh);
unmap_underlying_metadata(bh->b_bdev,
bh->b_blocknr);
if (PageUptodate(page)) {
set_buffer_uptodate(bh);
continue;
}
/*
* Page is _not_ uptodate, zero surrounding
* region. NOTE: This is how we decide if to
* zero or not!
*/
if (block_end > to)
memset(kaddr + to, 0, block_end - to);
if (block_start < from)
memset(kaddr + block_start, 0,
from - block_start);
if (block_end > to || block_start < from)
flush_dcache_page(page);
continue;
}
}
/* @bh is mapped, set it uptodate if the page is uptodate. */
if (PageUptodate(page)) {
if (!buffer_uptodate(bh))
set_buffer_uptodate(bh);
continue;
}
/*
* The page is not uptodate. The buffer is mapped. If it is not
* uptodate, and it is only partially being written to, we need
* to read the buffer in before the write, i.e. right now.
*/
if (!buffer_uptodate(bh) &&
(block_start < from || block_end > to)) {
ll_rw_block(READ, 1, &bh);
*wait_bh++ = bh;
}
} while (block++, block_start = block_end,
(bh = bh->b_this_page) != head);
/* Release the lock if we took it. */
if (rl) {
up_read(&ni->run_list.lock);
rl = NULL;
}
/* If we issued read requests, let them complete. */
while (wait_bh > wait) {
wait_on_buffer(*--wait_bh);
if (!buffer_uptodate(*wait_bh))
return -EIO;
}
ntfs_debug("Done.");
return 0;
err_out:
/*
* Zero out any newly allocated blocks to avoid exposing stale data.
* If BH_New is set, we know that the block was newly allocated in the
* above loop.
* FIXME: What about initialized_size increments? Have we done all the
* required zeroing above? If not this error handling is broken, and
* in particular the if (block_end <= from) check is completely bogus.
*/
bh = head;
block_start = 0;
is_retry = FALSE;
do {
block_end = block_start + blocksize;
if (block_end <= from)
continue;
if (block_start >= to)
break;
if (buffer_new(bh)) {
clear_buffer_new(bh);
if (buffer_uptodate(bh))
buffer_error();
memset(kaddr + block_start, 0, bh->b_size);
set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
is_retry = TRUE;
}
} while (block_start = block_end, (bh = bh->b_this_page) != head);
if (is_retry)
flush_dcache_page(page);
if (rl)
up_read(&ni->run_list.lock);
return err;
}
/**
* ntfs_prepare_write - prepare a page for receiving data
*
* This is called from generic_file_write() with i_sem held on the inode
* (@page->mapping->host). The @page is locked and kmap()ped so page_address()
* can simply be used. The source data has not yet been copied into the @page.
*
* Need to extend the attribute/fill in holes if necessary, create blocks and
* make partially overwritten blocks uptodate,
*
* i_size is not to be modified yet.
*
* Return 0 on success or -errno on error.
*
* Should be using block_prepare_write() [support for sparse files] or
* cont_prepare_write() [no support for sparse files]. Can't do that due to
* ntfs specifics but can look at them for implementation guidancea.
*
* Note: In the range, @from is inclusive and @to is exclusive, i.e. @from is
* the first byte in the page that will be written to and @to is the first byte
* after the last byte that will be written to.
*/
static int ntfs_prepare_write(struct file *file, struct page *page,
unsigned from, unsigned to)
{
struct inode *vi = page->mapping->host;
ntfs_inode *ni = NTFS_I(vi);
ntfs_debug("Entering for inode %li, attribute type 0x%x, page index "
"0x%lx, from = %u, to = %u.", vi->i_ino, ni->type,
page->index, from, to);
BUG_ON(!PageLocked(page));
BUG_ON(from > PAGE_CACHE_SIZE);
BUG_ON(to > PAGE_CACHE_SIZE);
BUG_ON(from > to);
if (NInoNonResident(ni)) {
/*
* Only unnamed $DATA attributes can be compressed, encrypted,
* and/or sparse.
*/
if (ni->type == AT_DATA && !ni->name_len) {
/* If file is encrypted, deny access, just like NT4. */
if (NInoEncrypted(ni)) {
ntfs_debug("Denying write access to encrypted "
"file.");
return -EACCES;
}
/* Compressed data streams are handled in compress.c. */
if (NInoCompressed(ni)) {
// TODO: Implement and replace this check with
// return ntfs_write_compressed_block(page);
ntfs_error(vi->i_sb, "Writing to compressed "
"files is not supported yet. "
"Sorry.");
return -EOPNOTSUPP;
}
// TODO: Implement and remove this check.
if (NInoSparse(ni)) {
ntfs_error(vi->i_sb, "Writing to sparse files "
"is not supported yet. Sorry.");
return -EOPNOTSUPP;
}
}
// TODO: Implement and remove this check.
if (NInoMstProtected(ni)) {
ntfs_error(vi->i_sb, "Writing to MST protected "
"attributes is not supported yet. "
"Sorry.");
return -EOPNOTSUPP;
}
/* Normal data stream. */
return ntfs_prepare_nonresident_write(page, from, to);
}
/*
* Attribute is resident, implying it is not compressed, encrypted, or
* mst protected.
*/
BUG_ON(page_has_buffers(page));
/* Do we need to resize the attribute? */
if (((s64)page->index << PAGE_CACHE_SHIFT) + to > vi->i_size) {
// TODO: Implement resize...
ntfs_error(vi->i_sb, "Writing beyond the existing file size is "
"not supported yet. Sorry.");
return -EOPNOTSUPP;
}
/*
* Because resident attributes are handled by memcpy() to/from the
* corresponding MFT record, and because this form of i/o is byte
* aligned rather than block aligned, there is no need to bring the
* page uptodate here as in the non-resident case where we need to
* bring the buffers straddled by the write uptodate before
* generic_file_write() does the copying from userspace.
*
* We thus defer the uptodate bringing of the page region outside the
* region written to to ntfs_commit_write(). The reason for doing this
* is that we save one round of:
* map_mft_record(), get_attr_search_ctx(), lookup_attr(),
* kmap_atomic(), kunmap_atomic(), put_attr_search_ctx(),
* unmap_mft_record().
* Which is obviously a very worthwhile save.
*
* Thus we just return success now...
*/
ntfs_debug("Done.");
return 0;
}
/*
* NOTES: There is a disparity between the apparent need to extend the
* attribute in prepare write but to update i_size only in commit write.
* Need to make sure i_sem protection is sufficient. And if not will need to
* handle this in some way or another.
*/
/**
* ntfs_commit_nonresident_write -
*
*/
static int ntfs_commit_nonresident_write(struct page *page,
unsigned from, unsigned to)
{
s64 pos = ((s64)page->index << PAGE_CACHE_SHIFT) + to;
struct inode *vi;
struct buffer_head *bh, *head;
unsigned int block_start, block_end, blocksize;
BOOL partial;
vi = page->mapping->host;
ntfs_debug("Entering for inode %li, attribute type 0x%x, page index "
"0x%lx, from = %u, to = %u.", vi->i_ino,
NTFS_I(vi)->type, page->index, from, to);
blocksize = 1 << vi->i_blkbits;
// FIXME: We need a whole slew of special cases in here for MST
// protected attributes for example. For compressed files, too...
// For now, we know ntfs_prepare_write() would have failed so we can't
// get here in any of the cases which we have to special case, so we
// are just a ripped off unrolled generic_commit_write() at present.
bh = head = page_buffers(page);
block_start = 0;
partial = FALSE;
do {
block_end = block_start + blocksize;
if (block_end <= from || block_start >= to) {
if (!buffer_uptodate(bh))
partial = TRUE;
} else {
set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
}
} while (block_start = block_end, (bh = bh->b_this_page) != head);
/*
* If this is a partial write which happened to make all buffers
* uptodate then we can optimize away a bogus ->readpage() for the next
* read(). Here we 'discover' whether the page went uptodate as a
* result of this (potentially partial) write.
*/
if (!partial)
SetPageUptodate(page);
/*
* Not convinced about this at all. See disparity comment above. For
* now we know ntfs_prepare_write() would have failed in the write
* exceeds i_size case, so this will never trigger which is fine.
*/
if (pos > vi->i_size) {
ntfs_error(vi->i_sb, "Writing beyond the existing file size is "
"not supported yet. Sorry.");
// vi->i_size = pos;
// mark_inode_dirty(vi);
}
ntfs_debug("Done.");
return 0;
}
/**
* ntfs_commit_write - commit the received data
*
* This is called from generic_file_write() with i_sem held on the inode
* (@page->mapping->host). The @page is locked and kmap()ped so page_address()
* can simply be used. The source data has already been copied into the @page.
*
* Need to mark modified blocks dirty so they get written out later when
* ntfs_writepage() is invoked by the VM.
*
* Return 0 on success or -errno on error.
*
* Should be using generic_commit_write(). This marks buffers uptodate and
* dirty, sets the page uptodate if all buffers in the page are uptodate, and
* updates i_size if the end of io is beyond i_size. In that case, it also
* marks the inode dirty. - We could still use this (obviously except for
* NInoMstProtected() attributes, where we will need to duplicate the core code
* because we need our own async_io completion handler) but we could just do
* the i_size update in prepare write, when we resize the attribute. Then
* we would avoid the i_size update and mark_inode_dirty() happening here.
*
* Can't use generic_commit_write() due to ntfs specialities but can look at
* it for implementation guidance.
*
* If things have gone as outlined in ntfs_prepare_write(), then we do not
* need to do any page content modifications here at all, except in the write
* to resident attribute case, where we need to do the uptodate bringing here
* which we combine with the copying into the mft record which means we only
* need to map the mft record and find the attribute record in it only once.
*/
static int ntfs_commit_write(struct file *file, struct page *page,
unsigned from, unsigned to)
{
s64 attr_pos;
struct inode *vi;
ntfs_inode *ni, *base_ni;
char *kaddr, *kattr;
attr_search_context *ctx;
MFT_RECORD *m;
u32 attr_len, bytes;
int err;
vi = page->mapping->host;
ni = NTFS_I(vi);
ntfs_debug("Entering for inode %li, attribute type 0x%x, page index "
"0x%lx, from = %u, to = %u.", vi->i_ino, ni->type,
page->index, from, to);
if (NInoNonResident(ni)) {
/*
* Only unnamed $DATA attributes can be compressed, encrypted,
* and/or sparse.
*/
if (ni->type == AT_DATA && !ni->name_len) {
/* If file is encrypted, deny access, just like NT4. */
if (NInoEncrypted(ni)) {
// Should never get here!
ntfs_debug("Denying write access to encrypted "
"file.");
return -EACCES;
}
/* Compressed data streams are handled in compress.c. */
if (NInoCompressed(ni)) {
// TODO: Implement and replace this check with
// return ntfs_write_compressed_block(page);
// Should never get here!
ntfs_error(vi->i_sb, "Writing to compressed "
"files is not supported yet. "
"Sorry.");
return -EOPNOTSUPP;
}
// TODO: Implement and remove this check.
if (NInoSparse(ni)) {
// Should never get here!
ntfs_error(vi->i_sb, "Writing to sparse files "
"is not supported yet. Sorry.");
return -EOPNOTSUPP;
}
}
// TODO: Implement and remove this check.
if (NInoMstProtected(ni)) {
// Should never get here!
ntfs_error(vi->i_sb, "Writing to MST protected "
"attributes is not supported yet. "
"Sorry.");
return -EOPNOTSUPP;
}
/* Normal data stream. */
return ntfs_commit_nonresident_write(page, from, to);
}
/*
* Attribute is resident, implying it is not compressed, encrypted, or
* mst protected.
*/
/* Do we need to resize the attribute? */
if (((s64)page->index << PAGE_CACHE_SHIFT) + to > vi->i_size) {
// TODO: Implement resize...
// pos = ((s64)page->index << PAGE_CACHE_SHIFT) + to;
// vi->i_size = pos;
// mark_inode_dirty(vi);
// Should never get here!
ntfs_error(vi->i_sb, "Writing beyond the existing file size is "
"not supported yet. Sorry.");
return -EOPNOTSUPP;
}
if (!NInoAttr(ni))
base_ni = ni;
else
base_ni = ni->_INE(base_ntfs_ino);
/* Map, pin, and lock the mft record. */
m = map_mft_record(base_ni);
if (unlikely(IS_ERR(m))) {
err = PTR_ERR(m);
m = NULL;
ctx = NULL;
goto err_out;
}
ctx = get_attr_search_ctx(base_ni, m);
if (unlikely(!ctx)) {
err = -ENOMEM;
goto err_out;
}
if (unlikely(!lookup_attr(ni->type, ni->name, ni->name_len,
IGNORE_CASE, 0, NULL, 0, ctx))) {
err = -ENOENT;
goto err_out;
}
/* Starting position of the page within the attribute value. */
attr_pos = page->index << PAGE_CACHE_SHIFT;
/* The total length of the attribute value. */
attr_len = le32_to_cpu(ctx->attr->_ARA(value_length));
if (unlikely(vi->i_size != attr_len)) {
ntfs_error(vi->i_sb, "BUG()! i_size (0x%Lx) doesn't match "
"attr_len (0x%x). Aborting write.", vi->i_size,
attr_len);
err = -EIO;
goto err_out;
}
if (unlikely(attr_pos >= attr_len)) {
ntfs_error(vi->i_sb, "BUG()! attr_pos (0x%Lx) > attr_len (0x%x)"
". Aborting write.", attr_pos, attr_len);
err = -EIO;
goto err_out;
}
bytes = attr_len - attr_pos;
if (unlikely(bytes > PAGE_CACHE_SIZE))
bytes = PAGE_CACHE_SIZE;
/*
* Calculate the address of the attribute value corresponding to the
* beginning of the current data @page.
*/
kattr = (u8*)ctx->attr + le16_to_cpu(ctx->attr->_ARA(value_offset)) +
attr_pos;
kaddr = kmap_atomic(page, KM_USER0);
/* Copy the received data from the page to the mft record. */
memcpy(kattr + from, kaddr + from, to - from);
flush_dcache_mft_record_page(ctx->ntfs_ino);
if (!PageUptodate(page)) {
/*
* Bring the out of bounds area(s) uptodate by copying data
* from the mft record to the page.
*/
if (from > 0)
memcpy(kaddr, kattr, from);
if (to < bytes)
memcpy(kaddr + to, kattr + to, bytes - to);
/* Zero the region outside the end of the attribute value. */
if (likely(bytes < PAGE_CACHE_SIZE))
memset(kaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
/*
* The probability of not having done any of the above is
* extremely small, so we just flush unconditionally.
*/
flush_dcache_page(page);
SetPageUptodate(page);
}
kunmap_atomic(kaddr, KM_USER0);
// TODO: Mark mft record dirty so it gets written back.
ntfs_error(vi->i_sb, "Writing to resident files is not supported yet. "
"Wrote to memory only...");
put_attr_search_ctx(ctx);
unmap_mft_record(base_ni);
ntfs_debug("Done.");
return 0;
err_out:
if (err == -ENOMEM) {
ntfs_warning(vi->i_sb, "Error allocating memory required to "
"commit the write.");
if (PageUptodate(page)) {
ntfs_warning(vi->i_sb, "Page is uptodate, setting "
"dirty so the write will be retried "
"later on by the VM.");
/*
* Put the page on mapping->dirty_pages, but leave its
* buffer's dirty state as-is.
*/
__set_page_dirty_nobuffers(page);
err = 0;
} else
ntfs_error(vi->i_sb, "Page is not uptodate. Written "
"data has been lost. )-:");
} else {
ntfs_error(vi->i_sb, "Resident attribute write failed with "
"error %i. Setting page error flag.", -err);
SetPageError(page);
}
if (ctx)
put_attr_search_ctx(ctx);
if (m)
unmap_mft_record(base_ni);
return err;
}
#endif /* NTFS_RW */
/**
* ntfs_aops - general address space operations for inodes and attributes
*/
......@@ -442,5 +1773,11 @@ struct address_space_operations ntfs_aops = {
.readpage = ntfs_readpage, /* Fill page with data. */
.sync_page = block_sync_page, /* Currently, just unplugs the
disk request queue. */
#ifdef NTFS_RW
.writepage = ntfs_writepage, /* Write dirty page to disk. */
.prepare_write = ntfs_prepare_write, /* Prepare page and buffers
ready to receive data. */
.commit_write = ntfs_commit_write, /* Commit received data. */
#endif
};
......@@ -1182,8 +1182,9 @@ BOOL find_attr(const ATTR_TYPES type, const uchar_t *name, const u32 name_len,
else {
register int rc;
rc = memcmp(val, (u8*)a +le16_to_cpu(a->_ARA(value_offset)),
min(val_len, le32_to_cpu(a->_ARA(value_length))));
rc = memcmp(val, (u8*)a + le16_to_cpu(
a->_ARA(value_offset)), min(val_len,
le32_to_cpu(a->_ARA(value_length))));
/*
* If @val collates before the current attribute's
* value, there is no matching attribute.
......@@ -1676,7 +1677,7 @@ void reinit_attr_search_ctx(attr_search_context *ctx)
return;
} /* Attribute list. */
if (ctx->ntfs_ino != ctx->base_ntfs_ino)
unmap_mft_record(ctx->ntfs_ino);
unmap_extent_mft_record(ctx->ntfs_ino);
init_attr_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec);
return;
}
......@@ -1709,7 +1710,7 @@ attr_search_context *get_attr_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
void put_attr_search_ctx(attr_search_context *ctx)
{
if (ctx->base_ntfs_ino && ctx->ntfs_ino != ctx->base_ntfs_ino)
unmap_mft_record(ctx->ntfs_ino);
unmap_extent_mft_record(ctx->ntfs_ino);
kmem_cache_free(ntfs_attr_ctx_cache, ctx);
return;
}
......
......@@ -609,18 +609,18 @@ int ntfs_read_compressed_block(struct page *page)
if (buffer_uptodate(tbh))
continue;
wait_on_buffer(tbh);
/*
/*
* We need an optimization barrier here, otherwise we start
* hitting the below fixup code when accessing a loopback
* mounted ntfs partition. This indicates either there is a
* race condition in the loop driver or, more likely, gcc
* overoptimises the code without the barrier and it doesn't
* overoptimises the code without the barrier and it doesn't
* do the Right Thing(TM).
*/
*/
barrier();
if (unlikely(!buffer_uptodate(tbh))) {
ntfs_warning(vol->sb, "Buffer is unlocked but not "
"uptodate! Unplugging the disk queue "
"uptodate! Unplugging the disk queue "
"and rescheduling.");
get_bh(tbh);
blk_run_queues();
......
......@@ -1048,9 +1048,7 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t *fpos,
/*
* VFS calls readdir without BKL but with i_sem held. This protects the VFS
* parts (e.g. ->f_pos and ->i_size, and it also protects against directory
* modifications). Together with the rw semaphore taken by the call to
* map_mft_record(), the directory is truly locked down so we have a race free
* ntfs_readdir() without the BKL. (-:
* modifications).
*
* We use the same basic approach as the old NTFS driver, i.e. we parse the
* index root entries and then the index allocation entries that are marked
......@@ -1181,7 +1179,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
*/
put_attr_search_ctx(ctx);
unmap_mft_record(ndir);
m = NULL;
m = NULL;
ctx = NULL;
/* If there is no index allocation attribute we are finished. */
if (!NInoIndexAllocPresent(ndir))
......
......@@ -51,6 +51,9 @@ static int ntfs_file_open(struct inode *vi, struct file *filp)
struct file_operations ntfs_file_ops = {
.llseek = generic_file_llseek, /* Seek inside file. */
.read = generic_file_read, /* Read from file. */
#ifdef NTFS_RW
.write = generic_file_write, /* Write to a file. */
#endif
.mmap = generic_file_mmap, /* Mmap file. */
.sendfile = generic_file_sendfile,/* Zero-copy data send with the
data source being on the
......@@ -60,7 +63,12 @@ struct file_operations ntfs_file_ops = {
.open = ntfs_file_open, /* Open file. */
};
struct inode_operations ntfs_file_inode_ops = {};
struct inode_operations ntfs_file_inode_ops = {
#ifdef NTFS_RW
.truncate = ntfs_truncate,
.setattr = ntfs_setattr,
#endif
};
struct file_operations ntfs_empty_file_ops = {};
......
......@@ -21,6 +21,8 @@
#include <linux/pagemap.h>
#include <linux/buffer_head.h>
#include <linux/smp_lock.h>
#include <linux/quotaops.h>
#include "ntfs.h"
#include "dir.h"
......@@ -844,7 +846,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
ctx->attr->_ANR(allocated_size));
/*
* We are done with the mft record, so we release it. Otherwise
*
* we would deadlock in ntfs_attr_iget().
*/
put_attr_search_ctx(ctx);
unmap_mft_record(ni);
......@@ -1926,3 +1928,96 @@ int ntfs_show_options(struct seq_file *sf, struct vfsmount *mnt)
return 0;
}
#ifdef NTFS_RW
/**
* ntfs_truncate - called when the i_size of an ntfs inode is changed
* @vi: inode for which the i_size was changed
*
* We don't support i_size changes yet.
*
* Called with ->i_sem held.
*/
void ntfs_truncate(struct inode *vi)
{
// TODO: Implement...
ntfs_warning(vi->i_sb, "Eeek: i_size may have changed! If you see "
"this right after a message from "
"ntfs_{prepare,commit}_{,nonresident_}write() then "
"just ignore it. Otherwise it is bad news.");
// TODO: reset i_size now!
return;
}
/**
* ntfs_setattr - called from notify_change() when an attribute is being changed
* @dentry: dentry whose attributes to change
* @attr: structure describing the attributes and the changes
*
* We have to trap VFS attempts to truncate the file described by @dentry as
* soon as possible, because we do not implement changes in i_size yet. So we
* abort all i_size changes here.
*
* Called with ->i_sem held.
*
* Basically this is a copy of generic notify_change() and inode_setattr()
* functionality, except we intercept and abort changes in i_size.
*/
int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
{
struct inode *vi;
int err;
unsigned int ia_valid = attr->ia_valid;
vi = dentry->d_inode;
err = inode_change_ok(vi, attr);
if (err)
return err;
if ((ia_valid & ATTR_UID && attr->ia_uid != vi->i_uid) ||
(ia_valid & ATTR_GID && attr->ia_gid != vi->i_gid)) {
err = DQUOT_TRANSFER(vi, attr) ? -EDQUOT : 0;
if (err)
return err;
}
lock_kernel();
if (ia_valid & ATTR_SIZE) {
ntfs_error(vi->i_sb, "Changes in i_size are not supported "
"yet. Sorry.");
// TODO: Implement...
// err = vmtruncate(vi, attr->ia_size);
err = -EOPNOTSUPP;
if (err)
goto trunc_err;
}
if (ia_valid & ATTR_UID)
vi->i_uid = attr->ia_uid;
if (ia_valid & ATTR_GID)
vi->i_gid = attr->ia_gid;
if (ia_valid & ATTR_ATIME)
vi->i_atime = attr->ia_atime;
if (ia_valid & ATTR_MTIME)
vi->i_mtime = attr->ia_mtime;
if (ia_valid & ATTR_CTIME)
vi->i_ctime = attr->ia_ctime;
if (ia_valid & ATTR_MODE) {
vi->i_mode = attr->ia_mode;
if (!in_group_p(vi->i_gid) &&
!capable(CAP_FSETID))
vi->i_mode &= ~S_ISGID;
}
mark_inode_dirty(vi);
trunc_err:
unlock_kernel();
return err;
}
#endif
......@@ -36,8 +36,8 @@ typedef struct _ntfs_inode ntfs_inode;
* fields already provided in the VFS inode.
*/
struct _ntfs_inode {
s64 initialized_size; /* Copy from $DATA/$INDEX_ALLOCATION. */
s64 allocated_size; /* Copy from $DATA/$INDEX_ALLOCATION. */
s64 initialized_size; /* Copy from the attribute record. */
s64 allocated_size; /* Copy from the attribute record. */
unsigned long state; /* NTFS specific flags describing this inode.
See ntfs_inode_state_bits below. */
unsigned long mft_no; /* Number of the mft record / inode. */
......@@ -245,5 +245,13 @@ extern void ntfs_put_inode(struct inode *vi);
extern int ntfs_show_options(struct seq_file *sf, struct vfsmount *mnt);
#ifdef NTFS_RW
extern void ntfs_truncate(struct inode *vi);
extern int ntfs_setattr(struct dentry *dentry, struct iattr *attr);
#endif
#endif /* _LINUX_NTFS_FS_INODE_H */
......@@ -98,7 +98,7 @@ int format_mft_record(ntfs_inode *ni, MFT_RECORD *mft_rec)
}
/**
* From fs/ntfs/aops.c
* ntfs_readpage - external declaration, function is in fs/ntfs/aops.c
*/
extern int ntfs_readpage(struct file *, struct page *);
......@@ -109,12 +109,9 @@ extern int ntfs_readpage(struct file *, struct page *);
* ntfs_map_page() in map_mft_record_page().
*/
struct address_space_operations ntfs_mft_aops = {
.writepage = NULL, /* Write dirty page to disk. */
.readpage = ntfs_readpage, /* Fill page with data. */
.sync_page = block_sync_page, /* Currently, just unplugs the
disk request queue. */
.prepare_write = NULL, /* . */
.commit_write = NULL, /* . */
};
/**
......@@ -176,8 +173,8 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni)
* First, take the mrec_lock semaphore. We might now be sleeping, while waiting
* for the semaphore if it was already locked by someone else.
*
* The page of the record is first mapped using map_mft_record_page() before
* being returned to the caller.
* The page of the record is mapped using map_mft_record_page() before being
* returned to the caller.
*
* This in turn uses ntfs_map_page() to get the page containing the wanted mft
* record (it in turn calls read_cache_page() which reads it in from disk if
......
......@@ -43,5 +43,19 @@ static inline void unmap_extent_mft_record(ntfs_inode *ni)
return;
}
/*
* flush_dcache_mft_record_page - flush_dcache_page() for mft records
* @ni: ntfs inode structure of mft record
*
* Call flush_dcache_page() for the page in which an mft record resides.
*
* This must be called every time an mft record is modified, just after the
* modification.
*/
static inline void flush_dcache_mft_record_page(ntfs_inode *ni)
{
flush_dcache_page(ni->page);
}
#endif /* _LINUX_NTFS_MFT_H */
......@@ -139,8 +139,8 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
dent_inode = ERR_PTR(-EIO);
} else
ntfs_error(vol->sb, "ntfs_iget(0x%lx) failed with "
"error code %li.", dent_ino,
PTR_ERR(dent_inode));
"error code %li.", dent_ino,
PTR_ERR(dent_inode));
if (name)
kfree(name);
/* Return the error code. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment