Loading Documentation/filesystems/ntfs.txt +5 −0 Original line number Original line Diff line number Diff line Loading @@ -457,6 +457,11 @@ ChangeLog Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. 2.1.27: - Implement page migration support so the kernel can move memory used by NTFS files and directories around for management purposes. - Add support for writing to sparse files created with Windows XP SP2. - Many minor improvements and bug fixes. 2.1.26: 2.1.26: - Implement support for sector sizes above 512 bytes (up to the maximum - Implement support for sector sizes above 512 bytes (up to the maximum supported by NTFS which is 4096 bytes). supported by NTFS which is 4096 bytes). Loading fs/ntfs/ChangeLog +28 −2 Original line number Original line Diff line number Diff line Loading @@ -16,8 +16,34 @@ ToDo/Notes: inode having been discarded already. Whether this can actually ever inode having been discarded already. Whether this can actually ever happen is unclear however so it is worth waiting until someone hits happen is unclear however so it is worth waiting until someone hits the problem. the problem. - Enable the code for setting the NT4 compatibility flag when we start making NTFS 1.2 specific modifications. 2.1.27 - Various bug fixes and cleanups. - Fix two compiler warnings on Alpha. Thanks to Andrew Morton for reporting them. - Fix an (innocent) off-by-one error in the runlist code. - Fix a buggette in an "should be impossible" case handling where we continued the attribute lookup loop instead of aborting it. - Use buffer_migrate_page() for the ->migratepage function of all ntfs address space operations. - Fix comparison of $MFT and $MFTMirr to not bail out when there are unused, invalid mft records which are the same in both $MFT and $MFTMirr. - Add support for sparse files which have a compression unit of 0. - Remove all the make_bad_inode() calls. This should only be called from read inode and new inode code paths. - Limit name length in fs/ntfs/unistr.c::ntfs_nlstoucs() to maximum allowed by NTFS, i.e. 255 Unicode characters, not including the terminating NULL (which is not stored on disk). - Improve comments on file attribute flags in fs/ntfs/layout.h. - Fix a bug in fs/ntfs/inode.c::ntfs_read_locked_index_inode() where we forgot to update a temporary variable so loading index inodes which have an index allocation attribute failed. - Add a missing call to flush_dcache_mft_record_page() in fs/ntfs/inode.c::ntfs_write_inode(). - Handle the recently introduced -ENAMETOOLONG return value from fs/ntfs/unistr.c::ntfs_nlstoucs() in fs/ntfs/namei.c::ntfs_lookup(). - Semaphore to mutex conversion. (Ingo Molnar) 2.1.26 - Minor bug fixes and updates. 2.1.26 - Minor bug fixes and updates. Loading fs/ntfs/Makefile +1 −1 Original line number Original line Diff line number Diff line Loading @@ -6,7 +6,7 @@ ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \ index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ unistr.o upcase.o unistr.o upcase.o EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.26\" EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.27\" ifeq ($(CONFIG_NTFS_DEBUG),y) ifeq ($(CONFIG_NTFS_DEBUG),y) EXTRA_CFLAGS += -DDEBUG EXTRA_CFLAGS += -DDEBUG Loading fs/ntfs/aops.c +10 −4 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,7 @@ */ */ #include <linux/errno.h> #include <linux/errno.h> #include <linux/fs.h> #include <linux/mm.h> #include <linux/mm.h> #include <linux/pagemap.h> #include <linux/pagemap.h> #include <linux/swap.h> #include <linux/swap.h> Loading Loading @@ -1277,18 +1278,18 @@ static int ntfs_write_mst_block(struct page *page, tni = locked_nis[nr_locked_nis]; tni = locked_nis[nr_locked_nis]; /* Get the base inode. */ /* Get the base inode. */ down(&tni->extent_lock); mutex_lock(&tni->extent_lock); if (tni->nr_extents >= 0) if (tni->nr_extents >= 0) base_tni = tni; base_tni = tni; else { else { base_tni = tni->ext.base_ntfs_ino; base_tni = tni->ext.base_ntfs_ino; BUG_ON(!base_tni); BUG_ON(!base_tni); } } up(&tni->extent_lock); mutex_unlock(&tni->extent_lock); ntfs_debug("Unlocking %s inode 0x%lx.", ntfs_debug("Unlocking %s inode 0x%lx.", tni == base_tni ? "base" : "extent", tni == base_tni ? "base" : "extent", tni->mft_no); tni->mft_no); up(&tni->mrec_lock); mutex_unlock(&tni->mrec_lock); atomic_dec(&tni->count); atomic_dec(&tni->count); iput(VFS_I(base_tni)); iput(VFS_I(base_tni)); } } Loading Loading @@ -1529,7 +1530,6 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc) "error %i.", err); "error %i.", err); SetPageError(page); SetPageError(page); NVolSetErrors(ni->vol); NVolSetErrors(ni->vol); make_bad_inode(vi); } } unlock_page(page); unlock_page(page); if (ctx) if (ctx) Loading @@ -1551,6 +1551,9 @@ struct address_space_operations ntfs_aops = { #ifdef NTFS_RW #ifdef NTFS_RW .writepage = ntfs_writepage, /* Write dirty page to disk. */ .writepage = ntfs_writepage, /* Write dirty page to disk. */ #endif /* NTFS_RW */ #endif /* NTFS_RW */ .migratepage = buffer_migrate_page, /* Move a page cache page from one physical page to an other. */ }; }; /** /** Loading @@ -1567,6 +1570,9 @@ struct address_space_operations ntfs_mst_aops = { without touching the buffers without touching the buffers belonging to the page. */ belonging to the page. */ #endif /* NTFS_RW */ #endif /* NTFS_RW */ .migratepage = buffer_migrate_page, /* Move a page cache page from one physical page to an other. */ }; }; #ifdef NTFS_RW #ifdef NTFS_RW Loading fs/ntfs/attrib.c +19 −16 Original line number Original line Diff line number Diff line /** /** * attrib.c - NTFS attribute operations. Part of the Linux-NTFS project. * attrib.c - NTFS attribute operations. Part of the Linux-NTFS project. * * * Copyright (c) 2001-2005 Anton Altaparmakov * Copyright (c) 2001-2006 Anton Altaparmakov * Copyright (c) 2002 Richard Russon * Copyright (c) 2002 Richard Russon * * * This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or Loading Loading @@ -1048,7 +1048,7 @@ static int ntfs_external_attr_find(const ATTR_TYPE type, le32_to_cpu(ctx->mrec->bytes_allocated)) le32_to_cpu(ctx->mrec->bytes_allocated)) break; break; if (a->type == AT_END) if (a->type == AT_END) continue; break; if (!a->length) if (!a->length) break; break; if (al_entry->instance != a->instance) if (al_entry->instance != a->instance) Loading Loading @@ -1695,6 +1695,8 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size) a->data.non_resident.initialized_size = a->data.non_resident.initialized_size = cpu_to_sle64(attr_size); cpu_to_sle64(attr_size); if (NInoSparse(ni) || NInoCompressed(ni)) { if (NInoSparse(ni) || NInoCompressed(ni)) { a->data.non_resident.compression_unit = 0; if (NInoCompressed(ni) || vol->major_ver < 3) a->data.non_resident.compression_unit = 4; a->data.non_resident.compression_unit = 4; a->data.non_resident.compressed_size = a->data.non_resident.compressed_size = a->data.non_resident.allocated_size; a->data.non_resident.allocated_size; Loading @@ -1714,13 +1716,20 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size) ni->allocated_size = new_size; ni->allocated_size = new_size; if (NInoSparse(ni) || NInoCompressed(ni)) { if (NInoSparse(ni) || NInoCompressed(ni)) { ni->itype.compressed.size = ni->allocated_size; ni->itype.compressed.size = ni->allocated_size; ni->itype.compressed.block_size = 1U << if (a->data.non_resident.compression_unit) { (a->data.non_resident.compression_unit + ni->itype.compressed.block_size = 1U << (a->data. non_resident.compression_unit + vol->cluster_size_bits); vol->cluster_size_bits); ni->itype.compressed.block_size_bits = ni->itype.compressed.block_size_bits = ffs(ni->itype.compressed.block_size) - 1; ffs(ni->itype.compressed.block_size) - 1; ni->itype.compressed.block_clusters = 1U << ni->itype.compressed.block_clusters = 1U << a->data.non_resident.compression_unit; a->data.non_resident.compression_unit; } else { ni->itype.compressed.block_size = 0; ni->itype.compressed.block_size_bits = 0; ni->itype.compressed.block_clusters = 0; } vi->i_blocks = ni->itype.compressed.size >> 9; vi->i_blocks = ni->itype.compressed.size >> 9; } else } else vi->i_blocks = ni->allocated_size >> 9; vi->i_blocks = ni->allocated_size >> 9; Loading Loading @@ -2429,16 +2438,12 @@ s64 ntfs_attr_extend_allocation(ntfs_inode *ni, s64 new_alloc_size, "chkdsk to recover.", IS_ERR(m) ? "chkdsk to recover.", IS_ERR(m) ? "restore attribute search context" : "restore attribute search context" : "truncate attribute runlist"); "truncate attribute runlist"); make_bad_inode(vi); make_bad_inode(VFS_I(base_ni)); NVolSetErrors(vol); NVolSetErrors(vol); } else if (mp_rebuilt) { } else if (mp_rebuilt) { if (ntfs_attr_record_resize(m, a, attr_len)) { if (ntfs_attr_record_resize(m, a, attr_len)) { ntfs_error(vol->sb, "Failed to restore attribute " ntfs_error(vol->sb, "Failed to restore attribute " "record in error code path. Run " "record in error code path. Run " "chkdsk to recover."); "chkdsk to recover."); make_bad_inode(vi); make_bad_inode(VFS_I(base_ni)); NVolSetErrors(vol); NVolSetErrors(vol); } else /* if (success) */ { } else /* if (success) */ { if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu( if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu( Loading @@ -2451,8 +2456,6 @@ s64 ntfs_attr_extend_allocation(ntfs_inode *ni, s64 new_alloc_size, "mapping pairs array in error " "mapping pairs array in error " "code path. Run chkdsk to " "code path. Run chkdsk to " "recover."); "recover."); make_bad_inode(vi); make_bad_inode(VFS_I(base_ni)); NVolSetErrors(vol); NVolSetErrors(vol); } } flush_dcache_mft_record_page(ctx->ntfs_ino); flush_dcache_mft_record_page(ctx->ntfs_ino); Loading Loading
Documentation/filesystems/ntfs.txt +5 −0 Original line number Original line Diff line number Diff line Loading @@ -457,6 +457,11 @@ ChangeLog Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. 2.1.27: - Implement page migration support so the kernel can move memory used by NTFS files and directories around for management purposes. - Add support for writing to sparse files created with Windows XP SP2. - Many minor improvements and bug fixes. 2.1.26: 2.1.26: - Implement support for sector sizes above 512 bytes (up to the maximum - Implement support for sector sizes above 512 bytes (up to the maximum supported by NTFS which is 4096 bytes). supported by NTFS which is 4096 bytes). Loading
fs/ntfs/ChangeLog +28 −2 Original line number Original line Diff line number Diff line Loading @@ -16,8 +16,34 @@ ToDo/Notes: inode having been discarded already. Whether this can actually ever inode having been discarded already. Whether this can actually ever happen is unclear however so it is worth waiting until someone hits happen is unclear however so it is worth waiting until someone hits the problem. the problem. - Enable the code for setting the NT4 compatibility flag when we start making NTFS 1.2 specific modifications. 2.1.27 - Various bug fixes and cleanups. - Fix two compiler warnings on Alpha. Thanks to Andrew Morton for reporting them. - Fix an (innocent) off-by-one error in the runlist code. - Fix a buggette in an "should be impossible" case handling where we continued the attribute lookup loop instead of aborting it. - Use buffer_migrate_page() for the ->migratepage function of all ntfs address space operations. - Fix comparison of $MFT and $MFTMirr to not bail out when there are unused, invalid mft records which are the same in both $MFT and $MFTMirr. - Add support for sparse files which have a compression unit of 0. - Remove all the make_bad_inode() calls. This should only be called from read inode and new inode code paths. - Limit name length in fs/ntfs/unistr.c::ntfs_nlstoucs() to maximum allowed by NTFS, i.e. 255 Unicode characters, not including the terminating NULL (which is not stored on disk). - Improve comments on file attribute flags in fs/ntfs/layout.h. - Fix a bug in fs/ntfs/inode.c::ntfs_read_locked_index_inode() where we forgot to update a temporary variable so loading index inodes which have an index allocation attribute failed. - Add a missing call to flush_dcache_mft_record_page() in fs/ntfs/inode.c::ntfs_write_inode(). - Handle the recently introduced -ENAMETOOLONG return value from fs/ntfs/unistr.c::ntfs_nlstoucs() in fs/ntfs/namei.c::ntfs_lookup(). - Semaphore to mutex conversion. (Ingo Molnar) 2.1.26 - Minor bug fixes and updates. 2.1.26 - Minor bug fixes and updates. Loading
fs/ntfs/Makefile +1 −1 Original line number Original line Diff line number Diff line Loading @@ -6,7 +6,7 @@ ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \ index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ unistr.o upcase.o unistr.o upcase.o EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.26\" EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.27\" ifeq ($(CONFIG_NTFS_DEBUG),y) ifeq ($(CONFIG_NTFS_DEBUG),y) EXTRA_CFLAGS += -DDEBUG EXTRA_CFLAGS += -DDEBUG Loading
fs/ntfs/aops.c +10 −4 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,7 @@ */ */ #include <linux/errno.h> #include <linux/errno.h> #include <linux/fs.h> #include <linux/mm.h> #include <linux/mm.h> #include <linux/pagemap.h> #include <linux/pagemap.h> #include <linux/swap.h> #include <linux/swap.h> Loading Loading @@ -1277,18 +1278,18 @@ static int ntfs_write_mst_block(struct page *page, tni = locked_nis[nr_locked_nis]; tni = locked_nis[nr_locked_nis]; /* Get the base inode. */ /* Get the base inode. */ down(&tni->extent_lock); mutex_lock(&tni->extent_lock); if (tni->nr_extents >= 0) if (tni->nr_extents >= 0) base_tni = tni; base_tni = tni; else { else { base_tni = tni->ext.base_ntfs_ino; base_tni = tni->ext.base_ntfs_ino; BUG_ON(!base_tni); BUG_ON(!base_tni); } } up(&tni->extent_lock); mutex_unlock(&tni->extent_lock); ntfs_debug("Unlocking %s inode 0x%lx.", ntfs_debug("Unlocking %s inode 0x%lx.", tni == base_tni ? "base" : "extent", tni == base_tni ? "base" : "extent", tni->mft_no); tni->mft_no); up(&tni->mrec_lock); mutex_unlock(&tni->mrec_lock); atomic_dec(&tni->count); atomic_dec(&tni->count); iput(VFS_I(base_tni)); iput(VFS_I(base_tni)); } } Loading Loading @@ -1529,7 +1530,6 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc) "error %i.", err); "error %i.", err); SetPageError(page); SetPageError(page); NVolSetErrors(ni->vol); NVolSetErrors(ni->vol); make_bad_inode(vi); } } unlock_page(page); unlock_page(page); if (ctx) if (ctx) Loading @@ -1551,6 +1551,9 @@ struct address_space_operations ntfs_aops = { #ifdef NTFS_RW #ifdef NTFS_RW .writepage = ntfs_writepage, /* Write dirty page to disk. */ .writepage = ntfs_writepage, /* Write dirty page to disk. */ #endif /* NTFS_RW */ #endif /* NTFS_RW */ .migratepage = buffer_migrate_page, /* Move a page cache page from one physical page to an other. */ }; }; /** /** Loading @@ -1567,6 +1570,9 @@ struct address_space_operations ntfs_mst_aops = { without touching the buffers without touching the buffers belonging to the page. */ belonging to the page. */ #endif /* NTFS_RW */ #endif /* NTFS_RW */ .migratepage = buffer_migrate_page, /* Move a page cache page from one physical page to an other. */ }; }; #ifdef NTFS_RW #ifdef NTFS_RW Loading
fs/ntfs/attrib.c +19 −16 Original line number Original line Diff line number Diff line /** /** * attrib.c - NTFS attribute operations. Part of the Linux-NTFS project. * attrib.c - NTFS attribute operations. Part of the Linux-NTFS project. * * * Copyright (c) 2001-2005 Anton Altaparmakov * Copyright (c) 2001-2006 Anton Altaparmakov * Copyright (c) 2002 Richard Russon * Copyright (c) 2002 Richard Russon * * * This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or Loading Loading @@ -1048,7 +1048,7 @@ static int ntfs_external_attr_find(const ATTR_TYPE type, le32_to_cpu(ctx->mrec->bytes_allocated)) le32_to_cpu(ctx->mrec->bytes_allocated)) break; break; if (a->type == AT_END) if (a->type == AT_END) continue; break; if (!a->length) if (!a->length) break; break; if (al_entry->instance != a->instance) if (al_entry->instance != a->instance) Loading Loading @@ -1695,6 +1695,8 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size) a->data.non_resident.initialized_size = a->data.non_resident.initialized_size = cpu_to_sle64(attr_size); cpu_to_sle64(attr_size); if (NInoSparse(ni) || NInoCompressed(ni)) { if (NInoSparse(ni) || NInoCompressed(ni)) { a->data.non_resident.compression_unit = 0; if (NInoCompressed(ni) || vol->major_ver < 3) a->data.non_resident.compression_unit = 4; a->data.non_resident.compression_unit = 4; a->data.non_resident.compressed_size = a->data.non_resident.compressed_size = a->data.non_resident.allocated_size; a->data.non_resident.allocated_size; Loading @@ -1714,13 +1716,20 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size) ni->allocated_size = new_size; ni->allocated_size = new_size; if (NInoSparse(ni) || NInoCompressed(ni)) { if (NInoSparse(ni) || NInoCompressed(ni)) { ni->itype.compressed.size = ni->allocated_size; ni->itype.compressed.size = ni->allocated_size; ni->itype.compressed.block_size = 1U << if (a->data.non_resident.compression_unit) { (a->data.non_resident.compression_unit + ni->itype.compressed.block_size = 1U << (a->data. non_resident.compression_unit + vol->cluster_size_bits); vol->cluster_size_bits); ni->itype.compressed.block_size_bits = ni->itype.compressed.block_size_bits = ffs(ni->itype.compressed.block_size) - 1; ffs(ni->itype.compressed.block_size) - 1; ni->itype.compressed.block_clusters = 1U << ni->itype.compressed.block_clusters = 1U << a->data.non_resident.compression_unit; a->data.non_resident.compression_unit; } else { ni->itype.compressed.block_size = 0; ni->itype.compressed.block_size_bits = 0; ni->itype.compressed.block_clusters = 0; } vi->i_blocks = ni->itype.compressed.size >> 9; vi->i_blocks = ni->itype.compressed.size >> 9; } else } else vi->i_blocks = ni->allocated_size >> 9; vi->i_blocks = ni->allocated_size >> 9; Loading Loading @@ -2429,16 +2438,12 @@ s64 ntfs_attr_extend_allocation(ntfs_inode *ni, s64 new_alloc_size, "chkdsk to recover.", IS_ERR(m) ? "chkdsk to recover.", IS_ERR(m) ? "restore attribute search context" : "restore attribute search context" : "truncate attribute runlist"); "truncate attribute runlist"); make_bad_inode(vi); make_bad_inode(VFS_I(base_ni)); NVolSetErrors(vol); NVolSetErrors(vol); } else if (mp_rebuilt) { } else if (mp_rebuilt) { if (ntfs_attr_record_resize(m, a, attr_len)) { if (ntfs_attr_record_resize(m, a, attr_len)) { ntfs_error(vol->sb, "Failed to restore attribute " ntfs_error(vol->sb, "Failed to restore attribute " "record in error code path. Run " "record in error code path. Run " "chkdsk to recover."); "chkdsk to recover."); make_bad_inode(vi); make_bad_inode(VFS_I(base_ni)); NVolSetErrors(vol); NVolSetErrors(vol); } else /* if (success) */ { } else /* if (success) */ { if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu( if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu( Loading @@ -2451,8 +2456,6 @@ s64 ntfs_attr_extend_allocation(ntfs_inode *ni, s64 new_alloc_size, "mapping pairs array in error " "mapping pairs array in error " "code path. Run chkdsk to " "code path. Run chkdsk to " "recover."); "recover."); make_bad_inode(vi); make_bad_inode(VFS_I(base_ni)); NVolSetErrors(vol); NVolSetErrors(vol); } } flush_dcache_mft_record_page(ctx->ntfs_ino); flush_dcache_mft_record_page(ctx->ntfs_ino); Loading