diff options
| -rw-r--r-- | Documentation/filesystems/ntfs.txt | 13 | ||||
| -rw-r--r-- | fs/ntfs/ChangeLog | 25 | ||||
| -rw-r--r-- | fs/ntfs/Makefile | 2 | ||||
| -rw-r--r-- | fs/ntfs/aops.c | 33 | ||||
| -rw-r--r-- | fs/ntfs/attrib.c | 52 | ||||
| -rw-r--r-- | fs/ntfs/attrib.h | 8 | ||||
| -rw-r--r-- | fs/ntfs/compress.c | 96 | ||||
| -rw-r--r-- | fs/ntfs/dir.c | 146 | ||||
| -rw-r--r-- | fs/ntfs/inode.c | 240 | ||||
| -rw-r--r-- | fs/ntfs/inode.h | 38 | ||||
| -rw-r--r-- | fs/ntfs/layout.h | 182 | ||||
| -rw-r--r-- | fs/ntfs/mft.c | 28 | ||||
| -rw-r--r-- | fs/ntfs/namei.c | 10 | ||||
| -rw-r--r-- | fs/ntfs/super.c | 189 | ||||
| -rw-r--r-- | fs/ntfs/unistr.c | 8 | ||||
| -rw-r--r-- | fs/ntfs/upcase.c | 10 |
16 files changed, 614 insertions, 466 deletions
diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt index 4483b90a31d3..850354876aa6 100644 --- a/Documentation/filesystems/ntfs.txt +++ b/Documentation/filesystems/ntfs.txt @@ -247,6 +247,19 @@ ChangeLog Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. +2.1.4: + - Minor update allowing compilation with all gcc versions (well, the + ones the kernel can be compiled with anyway). +2.1.3: + - Major bug fixes for reading files and volumes in corner cases which + were being hit by Windows 2k/XP users. +2.1.2: + - Major bug fixes aleviating the hangs in statfs experienced by some + users. +2.1.1: + - Update handling of compressed files so people no longer get the + frequently reported warning messages about initialized_size != + data_size. 2.1.0: - Add configuration option for developmental write support. - Initial implementation of file overwriting. (Writes to resident files diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index d547c1d957b9..27a8b478c356 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -20,6 +20,31 @@ ToDo: sufficient for synchronisation here. We then just need to make sure ntfs_readpage/writepage/truncate interoperate properly with us. +2.1.4 - Reduce compiler requirements. + + - Remove all uses of unnamed structs and unions in the driver to make + old and newer gcc versions happy. Makes it a bit uglier IMO but at + least people will stop hassling me about it. + +2.1.3 - Important bug fixes in corner cases. + + - super.c::parse_ntfs_boot_sector(): Correct the check for 64-bit + clusters. (Philipp Thomas) + - attrib.c::load_attribute_list(): Fix bug when initialized_size is a + multiple of the block_size but not the cluster size. (Szabolcs + Szakacsits <szaka@sienet.hu>) + +2.1.2 - Important bug fixes aleviating the hangs in statfs. + + - Fix buggy free cluster and free inode determination logic. + +2.1.1 - Minor updates. + + - Add handling for initialized_size != data_size in compressed files. + - Reduce function local stack usage from 0x3d4 bytes to just noise in + fs/ntfs/upcase.c. (Randy Dunlap <rddunlap@osdl.ord>) + - Remove compiler warnings for newer gcc. + 2.1.0 - First steps towards write support: implement file overwrite. - Add configuration option for developmental write support with an diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile index 7482eb2e777d..5e2a43f18188 100644 --- a/fs/ntfs/Makefile +++ b/fs/ntfs/Makefile @@ -5,7 +5,7 @@ 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.1.0\" +EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.4\" ifeq ($(CONFIG_NTFS_DEBUG),y) EXTRA_CFLAGS += -DDEBUG diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index f69f5c599eb3..7f47bd418fdf 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c @@ -2,8 +2,8 @@ * aops.c - NTFS kernel address space operations and page cache handling. * Part of the Linux-NTFS project. * - * Copyright (c) 2001,2002 Anton Altaparmakov. - * Copyright (c) 2002 Richard Russon. + * Copyright (c) 2001-2003 Anton Altaparmakov + * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -111,7 +111,7 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate) unsigned int i, recs, nr_err; u32 rec_size; - rec_size = ni->_IDM(index_block_size); + rec_size = ni->itype.index.block_size; recs = PAGE_CACHE_SIZE / rec_size; addr = kmap_atomic(page, KM_BIO_SRC_IRQ); for (i = nr_err = 0; i < recs; i++) { @@ -124,7 +124,7 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate) ni->mft_no ? "index" : "mft", (long long)(((s64)page->index << PAGE_CACHE_SHIFT >> - ni->_IDM(index_block_size_bits)) + i)); + ni->itype.index.block_size_bits) + i)); } flush_dcache_page(page); kunmap_atomic(addr, KM_BIO_SRC_IRQ); @@ -383,7 +383,7 @@ int ntfs_readpage(struct file *file, struct page *page) if (!NInoAttr(ni)) base_ni = ni; else - base_ni = ni->_INE(base_ntfs_ino); + base_ni = ni->ext.base_ntfs_ino; /* Map, pin, and lock the mft record. */ mrec = map_mft_record(base_ni); @@ -406,7 +406,7 @@ int ntfs_readpage(struct file *file, struct page *page) attr_pos = page->index << PAGE_CACHE_SHIFT; /* The total length of the attribute value. */ - attr_len = le32_to_cpu(ctx->attr->_ARA(value_length)); + attr_len = le32_to_cpu(ctx->attr->data.resident.value_length); addr = kmap(page); /* Copy over in bounds data, zeroing the remainder of the page. */ @@ -418,8 +418,8 @@ int ntfs_readpage(struct file *file, struct page *page) memset(addr + bytes, 0, PAGE_CACHE_SIZE - bytes); /* Copy the data to the page. */ memcpy(addr, attr_pos + (char*)ctx->attr + - le16_to_cpu(ctx->attr->_ARA(value_offset)), - bytes); + le16_to_cpu( + ctx->attr->data.resident.value_offset), bytes); } else memset(addr, 0, PAGE_CACHE_SIZE); flush_dcache_page(page); @@ -892,7 +892,7 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc) if (!NInoAttr(ni)) base_ni = ni; else - base_ni = ni->_INE(base_ntfs_ino); + base_ni = ni->ext.base_ntfs_ino; /* Map, pin, and lock the mft record. */ m = map_mft_record(base_ni); @@ -917,7 +917,7 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc) attr_pos = page->index << PAGE_CACHE_SHIFT; /* The total length of the attribute value. */ - attr_len = le32_to_cpu(ctx->attr->_ARA(value_length)); + attr_len = le32_to_cpu(ctx->attr->data.resident.value_length); if (unlikely(vi->i_size != attr_len)) { ntfs_error(vi->i_sb, "BUG()! i_size (0x%Lx) doesn't match " @@ -956,8 +956,9 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc) 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); + memcpy((u8*)ctx->attr + le16_to_cpu( + ctx->attr->data.resident.value_offset) + attr_pos, + kaddr, bytes); flush_dcache_mft_record_page(ctx->ntfs_ino); #if 0 /* Zero out of bounds area. */ @@ -1656,7 +1657,7 @@ static int ntfs_commit_write(struct file *file, struct page *page, if (!NInoAttr(ni)) base_ni = ni; else - base_ni = ni->_INE(base_ntfs_ino); + base_ni = ni->ext.base_ntfs_ino; /* Map, pin, and lock the mft record. */ m = map_mft_record(base_ni); @@ -1681,7 +1682,7 @@ static int ntfs_commit_write(struct file *file, struct page *page, attr_pos = page->index << PAGE_CACHE_SHIFT; /* The total length of the attribute value. */ - attr_len = le32_to_cpu(ctx->attr->_ARA(value_length)); + attr_len = le32_to_cpu(ctx->attr->data.resident.value_length); if (unlikely(vi->i_size != attr_len)) { ntfs_error(vi->i_sb, "BUG()! i_size (0x%Lx) doesn't match " @@ -1705,8 +1706,8 @@ static int ntfs_commit_write(struct file *file, struct page *page, * 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; + kattr = (u8*)ctx->attr + le16_to_cpu( + ctx->attr->data.resident.value_offset) + attr_pos; kaddr = kmap_atomic(page, KM_USER0); diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index f2e945da1db9..b47366fe9baa 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -1,8 +1,8 @@ /** * attrib.c - NTFS attribute operations. Part of the Linux-NTFS project. * - * Copyright (c) 2001,2002 Anton Altaparmakov. - * Copyright (C) 2002 Richard Russon. + * Copyright (c) 2001-2003 Anton Altaparmakov + * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -731,17 +731,18 @@ run_list_element *decompress_mapping_pairs(const ntfs_volume *vol, #ifdef DEBUG /* Make sure attr exists and is non-resident. */ - if (!attr || !attr->non_resident || - sle64_to_cpu(attr->_ANR(lowest_vcn)) < (VCN)0) { + if (!attr || !attr->non_resident || sle64_to_cpu( + attr->data.non_resident.lowest_vcn) < (VCN)0) { ntfs_error(vol->sb, "Invalid arguments."); return ERR_PTR(-EINVAL); } #endif /* Start at vcn = lowest_vcn and lcn 0. */ - vcn = sle64_to_cpu(attr->_ANR(lowest_vcn)); + vcn = sle64_to_cpu(attr->data.non_resident.lowest_vcn); lcn = 0; /* Get start of the mapping pairs array. */ - buf = (u8*)attr + le16_to_cpu(attr->_ANR(mapping_pairs_offset)); + buf = (u8*)attr + le16_to_cpu( + attr->data.non_resident.mapping_pairs_offset); attr_end = (u8*)attr + le32_to_cpu(attr->length); if (unlikely(buf < (u8*)attr || buf > attr_end)) { ntfs_error(vol->sb, "Corrupt attribute."); @@ -867,7 +868,7 @@ run_list_element *decompress_mapping_pairs(const ntfs_volume *vol, * If there is a highest_vcn specified, it must be equal to the final * vcn in the run list - 1, or something has gone badly wrong. */ - deltaxcn = sle64_to_cpu(attr->_ANR(highest_vcn)); + deltaxcn = sle64_to_cpu(attr->data.non_resident.highest_vcn); if (unlikely(deltaxcn && vcn - 1 != deltaxcn)) { mpa_err: ntfs_error(vol->sb, "Corrupt mapping pairs array in " @@ -875,10 +876,11 @@ mpa_err: goto err_out; } /* Setup not mapped run list element if this is the base extent. */ - if (!attr->_ANR(lowest_vcn)) { + if (!attr->data.non_resident.lowest_vcn) { VCN max_cluster; - max_cluster = (sle64_to_cpu(attr->_ANR(allocated_size)) + + max_cluster = (sle64_to_cpu( + attr->data.non_resident.allocated_size) + vol->cluster_size - 1) >> vol->cluster_size_bits; /* @@ -951,7 +953,7 @@ int map_run_list(ntfs_inode *ni, VCN vcn) if (!NInoAttr(ni)) base_ni = ni; else - base_ni = ni->_INE(base_ntfs_ino); + base_ni = ni->ext.base_ntfs_ino; mrec = map_mft_record(base_ni); if (IS_ERR(mrec)) @@ -1180,19 +1182,23 @@ BOOL find_attr(const ATTR_TYPES type, const uchar_t *name, const u32 name_len, return TRUE; /* @val is present; compare values. */ else { + u32 vl; register int rc; - + + vl = le32_to_cpu(a->data.resident.value_length); + if (vl > val_len) + vl = val_len; + rc = memcmp(val, (u8*)a + le16_to_cpu( - a->_ARA(value_offset)), - min_t(const u32, val_len, - le32_to_cpu(a->_ARA(value_length)))); + a->data.resident.value_offset), vl); /* * If @val collates before the current attribute's * value, there is no matching attribute. */ if (!rc) { register u32 avl; - avl = le32_to_cpu(a->_ARA(value_length)); + avl = le32_to_cpu( + a->data.resident.value_length); if (val_len == avl) return TRUE; if (val_len < avl) @@ -1235,11 +1241,9 @@ int load_attribute_list(ntfs_volume *vol, run_list *run_list, u8 *al, unsigned char block_size_bits = sb->s_blocksize_bits; ntfs_debug("Entering."); -#ifdef DEBUG if (!vol || !run_list || !al || size <= 0 || initialized_size < 0 || initialized_size > size) return -EINVAL; -#endif if (!initialized_size) { memset(al, 0, size); return 0; @@ -1270,8 +1274,8 @@ int load_attribute_list(ntfs_volume *vol, run_list *run_list, u8 *al, "read attribute list."); goto err_out; } - if (al + block_size > al_end) - goto do_partial; + if (al + block_size >= al_end) + goto do_final; memcpy(al, bh->b_data, block_size); brelse(bh); al += block_size; @@ -1285,7 +1289,7 @@ initialize: done: up_read(&run_list->lock); return err; -do_partial: +do_final: if (al < al_end) { /* Partial block. */ memcpy(al, bh->b_data, al_end - al); @@ -1546,9 +1550,11 @@ do_next_attr_loop: * If no @val specified or @val specified and it matches, we * have found it! */ - if (!val || (!a->non_resident && le32_to_cpu(a->_ARA(value_length)) - == val_len && !memcmp((u8*)a + - le16_to_cpu(a->_ARA(value_offset)), val, val_len))) { + if (!val || (!a->non_resident && le32_to_cpu( + a->data.resident.value_length) == val_len && + !memcmp((u8*)a + + le16_to_cpu(a->data.resident.value_offset), + val, val_len))) { ntfs_debug("Done, found."); return TRUE; } diff --git a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h index 86f536bb1dd6..e7009a0703af 100644 --- a/fs/ntfs/attrib.h +++ b/fs/ntfs/attrib.h @@ -2,8 +2,8 @@ * attrib.h - Defines for attribute handling in NTFS Linux kernel driver. * Part of the Linux-NTFS project. * - * Copyright (c) 2001,2002 Anton Altaparmakov. - * Copyright (C) 2002 Richard Russon. + * Copyright (c) 2001-2003 Anton Altaparmakov + * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -93,8 +93,8 @@ extern int load_attribute_list(ntfs_volume *vol, run_list *rl, u8 *al, static inline s64 attribute_value_length(const ATTR_RECORD *a) { if (!a->non_resident) - return (s64)le32_to_cpu(a->_ARA(value_length)); - return sle64_to_cpu(a->_ANR(data_size)); + return (s64)le32_to_cpu(a->data.resident.value_length); + return sle64_to_cpu(a->data.non_resident.data_size); } extern void reinit_attr_search_ctx(attr_search_context *ctx); diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c index 292d069ddc0b..5568cc2a402f 100644 --- a/fs/ntfs/compress.c +++ b/fs/ntfs/compress.c @@ -2,8 +2,8 @@ * compress.c - NTFS kernel compressed attributes handling. * Part of the Linux-NTFS project. * - * Copyright (c) 2001,2002 Anton Altaparmakov. - * Copyright (C) 2002 Richard Russon. + * Copyright (c) 2001-2003 Anton Altaparmakov + * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -44,7 +44,7 @@ typedef enum { * The maximum compression block size is by definition 16 * the cluster * size, with the maximum supported cluster size being 4kiB. Thus the * maximum compression buffer size is 64kiB, so we use this when - * initializing the per-CPU buffers. + * initializing the compression buffer. */ NTFS_MAX_CB_SIZE = 64 * 1024, } ntfs_compression_constants; @@ -89,6 +89,40 @@ void free_compression_buffers(void) } /** + * zero_partial_compressed_page - zero out of bounds compressed page region + */ +static void zero_partial_compressed_page(ntfs_inode *ni, struct page *page) +{ + u8 *kp = page_address(page); + unsigned int kp_ofs; + + ntfs_debug("Zeroing page region outside initialized size."); + if (((s64)page->index << PAGE_CACHE_SHIFT) >= ni->initialized_size) { + /* + * FIXME: Using clear_page() will become wrong when we get + * PAGE_CACHE_SIZE != PAGE_SIZE but for now there is no problem. + */ + clear_page(kp); + return; + } + kp_ofs = ni->initialized_size & ~PAGE_CACHE_MASK; + memset(kp + kp_ofs, 0, PAGE_CACHE_SIZE - kp_ofs); + return; +} + +/** + * handle_bounds_compressed_page - test for&handle out of bounds compressed page + */ +static inline void handle_bounds_compressed_page(ntfs_inode *ni, + struct page *page) +{ + if ((page->index >= (ni->initialized_size >> PAGE_CACHE_SHIFT)) && + (ni->initialized_size < VFS_I(ni)->i_size)) + zero_partial_compressed_page(ni, page); + return; +} + +/** * ntfs_decompress - decompress a compression block into an array of pages * @dest_pages: destination array of pages * @dest_index: current index into @dest_pages (IN/OUT) @@ -164,7 +198,7 @@ do_next_sb: cb - cb_start); /* Have we reached the end of the compression block? */ - if (cb == cb_end || !le16_to_cpup(cb)) { + if (cb == cb_end || !le16_to_cpup((u16*)cb)) { int i; ntfs_debug("Completed. Returning success (0)."); @@ -173,19 +207,29 @@ return_error: /* We can sleep from now on, so we drop lock. */ spin_unlock(&ntfs_cb_lock); /* Second stage: finalize completed pages. */ - for (i = 0; i < nr_completed_pages; i++) { - int di = completed_pages[i]; - - dp = dest_pages[di]; - flush_dcache_page(dp); - kunmap(dp); - SetPageUptodate(dp); - unlock_page(dp); - if (di == xpage) - *xpage_done = 1; - else - page_cache_release(dp); - dest_pages[di] = NULL; + if (nr_completed_pages > 0) { + struct page *page = dest_pages[completed_pages[0]]; + ntfs_inode *ni = NTFS_I(page->mapping->host); + + for (i = 0; i < nr_completed_pages; i++) { + int di = completed_pages[i]; + + dp = dest_pages[di]; + /* + * If we are outside the initialized size, zero + * the out of bounds page range. + */ + handle_bounds_compressed_page(ni, dp); + flush_dcache_page(dp); + kunmap(dp); + SetPageUptodate(dp); + unlock_page(dp); + if (di == xpage) + *xpage_done = 1; + else + page_cache_release(dp); + dest_pages[di] = NULL; + } } return err; } @@ -204,7 +248,8 @@ return_error: /* Setup the current sub-block source pointers and validate range. */ cb_sb_start = cb; - cb_sb_end = cb_sb_start + (le16_to_cpup(cb) & NTFS_SB_SIZE_MASK) + 3; + cb_sb_end = cb_sb_start + (le16_to_cpup((u16*)cb) & NTFS_SB_SIZE_MASK) + + 3; if (cb_sb_end > cb_end) goto return_overflow; @@ -225,7 +270,7 @@ return_error: dp_addr = (u8*)page_address(dp) + do_sb_start; /* Now, we are ready to process the current sub-block (sb). */ - if (!(le16_to_cpup(cb) & NTFS_SB_IS_COMPRESSED)) { + if (!(le16_to_cpup((u16*)cb) & NTFS_SB_IS_COMPRESSED)) { ntfs_debug("Found uncompressed sub-block."); /* This sb is not compressed, just copy it into destination. */ @@ -330,7 +375,7 @@ do_next_tag: lg++; /* Get the phrase token into i. */ - pt = le16_to_cpup(cb); + pt = le16_to_cpup((u16*)cb); /* * Calculate starting position of the byte sequence in @@ -432,7 +477,7 @@ int ntfs_read_compressed_block(struct page *page) u8 *cb, *cb_pos, *cb_end; struct buffer_head **bhs; unsigned long offset, index = page->index; - u32 cb_size = ni->_ICF(compression_block_size); + u32 cb_size = ni->itype.compressed.block_size; u64 cb_size_mask = cb_size - 1UL; VCN vcn; LCN lcn; @@ -447,7 +492,7 @@ int ntfs_read_compressed_block(struct page *page) & ~cb_size_mask) >> vol->cluster_size_bits; /* Number of compression blocks (cbs) in the wanted vcn range. */ unsigned int nr_cbs = (end_vcn - start_vcn) << vol->cluster_size_bits - >> ni->_ICF(compression_block_size_bits); + >> ni->itype.compressed.block_size_bits; /* * Number of pages required to store the uncompressed data from all * compression blocks (cbs) overlapping @page. Due to alignment @@ -528,7 +573,7 @@ int ntfs_read_compressed_block(struct page *page) */ cur_page = 0; cur_ofs = 0; - cb_clusters = ni->_ICF(compression_block_clusters); + cb_clusters = ni->itype.compressed.block_clusters; do_next_cb: nr_cbs--; nr_bhs = 0; @@ -763,6 +808,11 @@ lock_retry_remap: for (; cur2_page < cb_max_page; cur2_page++) { page = pages[cur2_page]; if (page) { + /* + * If we are outside the initialized size, zero + * the out of bounds page range. + */ + handle_bounds_compressed_page(ni, page); flush_dcache_page(page); kunmap(page); SetPageUptodate(page); diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index 4f4dda5cf68e..30dee6372e46 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c @@ -1,8 +1,8 @@ /** * dir.c - NTFS kernel directory operations. Part of the Linux-NTFS project. * - * Copyright (c) 2001,2002 Anton Altaparmakov. - * Copyright (c) 2002 Richard Russon. + * Copyright (c) 2001-2003 Anton Altaparmakov + * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -105,7 +105,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname, } /* Get to the index root value (it's been verified in read_inode). */ ir = (INDEX_ROOT*)((u8*)ctx->attr + - le16_to_cpu(ctx->attr->_ARA(value_offset))); + le16_to_cpu(ctx->attr->data.resident.value_offset)); index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length); /* The first index entry. */ ie = (INDEX_ENTRY*)((u8*)&ir->index + @@ -114,18 +114,18 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname, * Loop until we exceed valid memory (corruption case) or until we * reach the last entry. */ - for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->_IEH(length)))) { + for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { /* Bounds checks. */ if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie + sizeof(INDEX_ENTRY_HEADER) > index_end || - (u8*)ie + le16_to_cpu(ie->_IEH(key_length)) > + (u8*)ie + le16_to_cpu(ie->key_length) > index_end) goto dir_err_out; /* * The last entry cannot contain a name. It can however contain * a pointer to a child node in the B+tree so we just break out. */ - if (ie->_IEH(flags) & INDEX_ENTRY_END) + if (ie->flags & INDEX_ENTRY_END) break; /* * We perform a case sensitive comparison and if that matches @@ -159,7 +159,7 @@ found_it: } } name->mref = le64_to_cpu( - ie->_IIF(indexed_file)); + ie->data.dir.indexed_file); name->type = FILE_NAME_DOS; name->len = 0; *res = name; @@ -168,7 +168,7 @@ found_it: kfree(name); *res = NULL; } - mref = le64_to_cpu(ie->_IIF(indexed_file)); + mref = le64_to_cpu(ie->data.dir.indexed_file); put_attr_search_ctx(ctx); unmap_mft_record(dir_ni); return mref; @@ -211,7 +211,7 @@ found_it: err = -ENOMEM; goto err_out; } - name->mref = le64_to_cpu(ie->_IIF(indexed_file)); + name->mref = le64_to_cpu(ie->data.dir.indexed_file); name->type = type; if (type != FILE_NAME_DOS) { name->len = len; @@ -265,7 +265,7 @@ found_it: * we have got a matching name cached in name in which case return the * mft reference associated with it. */ - if (!(ie->_IEH(flags) & INDEX_ENTRY_NODE)) { + if (!(ie->flags & INDEX_ENTRY_NODE)) { if (name) { put_attr_search_ctx(ctx); unmap_mft_record(dir_ni); @@ -284,7 +284,7 @@ found_it: goto err_out; } /* Get the starting vcn of the index_block holding the child node. */ - vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->_IEH(length)) - 8); + vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8); ia_mapping = VFS_I(dir_ni)->i_mapping; /* * We are done with the index root and the mft record. Release them, @@ -301,7 +301,7 @@ descend_into_child_node: * disk if necessary. */ page = ntfs_map_page(ia_mapping, vcn << - dir_ni->_IDM(index_vcn_size_bits) >> PAGE_CACHE_SHIFT); + dir_ni->itype.index.vcn_size_bits >> PAGE_CACHE_SHIFT); if (IS_ERR(page)) { ntfs_error(sb, "Failed to map directory index page, error %ld.", -PTR_ERR(page)); @@ -312,7 +312,7 @@ descend_into_child_node: fast_descend_into_child_node: /* Get to the index allocation block. */ ia = (INDEX_ALLOCATION*)(kaddr + ((vcn << - dir_ni->_IDM(index_vcn_size_bits)) & ~PAGE_CACHE_MASK)); + dir_ni->itype.index.vcn_size_bits) & ~PAGE_CACHE_MASK)); /* Bounds checks. */ if ((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE) { ntfs_error(sb, "Out of bounds check failed. Corrupt directory " @@ -331,18 +331,18 @@ fast_descend_into_child_node: goto unm_err_out; } if (le32_to_cpu(ia->index.allocated_size) + 0x18 != - dir_ni->_IDM(index_block_size)) { + dir_ni->itype.index.block_size) { ntfs_error(sb, "Index buffer (VCN 0x%Lx) of directory inode " "0x%lx has a size (%u) differing from the " "directory specified size (%u). Directory " "inode is corrupt or driver bug.", (long long)vcn, dir_ni->mft_no, le32_to_cpu(ia->index.allocated_size) + 0x18, - dir_ni->_IDM(index_block_size)); + dir_ni->itype.index.block_size); err = -EIO; goto unm_err_out; } - index_end = (u8*)ia + dir_ni->_IDM(index_block_size); + index_end = (u8*)ia + dir_ni->itype.index.block_size; if (index_end > kaddr + PAGE_CACHE_SIZE) { ntfs_error(sb, "Index buffer (VCN 0x%Lx) of directory inode " "0x%lx crosses page boundary. Impossible! " @@ -352,7 +352,7 @@ fast_descend_into_child_node: goto unm_err_out; } index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length); - if (index_end > (u8*)ia + dir_ni->_IDM(index_block_size)) { + if (index_end > (u8*)ia + dir_ni->itype.index.block_size) { ntfs_error(sb, "Size of index buffer (VCN 0x%Lx) of directory " "inode 0x%lx exceeds maximum size.", (long long)vcn, dir_ni->mft_no); @@ -367,11 +367,11 @@ fast_descend_into_child_node: * loop until we exceed valid memory (corruption case) or until we * reach the last entry. */ - for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->_IEH(length)))) { + for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { /* Bounds check. */ if ((u8*)ie < (u8*)ia || (u8*)ie + sizeof(INDEX_ENTRY_HEADER) > index_end || - (u8*)ie + le16_to_cpu(ie->_IEH(key_length)) > + (u8*)ie + le16_to_cpu(ie->key_length) > index_end) { ntfs_error(sb, "Index entry out of bounds in " "directory inode 0x%lx.", @@ -383,7 +383,7 @@ fast_descend_into_child_node: * The last entry cannot contain a name. It can however contain * a pointer to a child node in the B+tree so we just break out. */ - if (ie->_IEH(flags) & INDEX_ENTRY_END) + if (ie->flags & INDEX_ENTRY_END) break; /* * We perform a case sensitive comparison and if that matches @@ -417,7 +417,7 @@ found_it2: } } name->mref = le64_to_cpu( - ie->_IIF(indexed_file)); + ie->data.dir.indexed_file); name->type = FILE_NAME_DOS; name->len = 0; *res = name; @@ -426,7 +426,7 @@ found_it2: kfree(name); *res = NULL; } - mref = le64_to_cpu(ie->_IIF(indexed_file)); + mref = le64_to_cpu(ie->data.dir.indexed_file); ntfs_unmap_page(page); return mref; } @@ -469,7 +469,7 @@ found_it2: err = -ENOMEM; goto unm_err_out; } - name->mref = le64_to_cpu(ie->_IIF(indexed_file)); + name->mref = le64_to_cpu(ie->data.dir.indexed_file); name->type = type; if (type != FILE_NAME_DOS) { name->len = len; @@ -521,7 +521,7 @@ found_it2: * We have finished with this index buffer without success. Check for * the presence of a child node. */ - if (ie->_IEH(flags) & INDEX_ENTRY_NODE) { + if (ie->flags & INDEX_ENTRY_NODE) { if ((ia->index.flags & NODE_MASK) == LEAF_NODE) { ntfs_error(sb, "Index entry with child node found in " "a leaf node in directory inode 0x%lx.", @@ -531,8 +531,7 @@ found_it2: } /* Child node present, descend into it. */ old_vcn = vcn; - vcn = sle64_to_cpup((u8*)ie + - le16_to_cpu(ie->_IEH(length)) - 8); + vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8); if (vcn >= 0) { /* If vcn is in the same page cache page as old_vcn we * recycle the mapped page. */ @@ -646,7 +645,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname, } /* Get to the index root value (it's been verified in read_inode). */ ir = (INDEX_ROOT*)((u8*)ctx->attr + - le16_to_cpu(ctx->attr->_ARA(value_offset))); + le16_to_cpu(ctx->attr->data.resident.value_offset)); index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length); /* The first index entry. */ ie = (INDEX_ENTRY*)((u8*)&ir->index + @@ -655,18 +654,18 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname, * Loop until we exceed valid memory (corruption case) or until we * reach the last entry. */ - for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->_IEH(length)))) { + for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { /* Bounds checks. */ if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie + sizeof(INDEX_ENTRY_HEADER) > index_end || - (u8*)ie + le16_to_cpu(ie->_IEH(key_length)) > + (u8*)ie + le16_to_cpu(ie->key_length) > index_end) goto dir_err_out; /* * The last entry cannot contain a name. It can however contain * a pointer to a child node in the B+tree so we just break out. */ - if (ie->_IEH(flags) & INDEX_ENTRY_END) + if (ie->flags & INDEX_ENTRY_END) break; /* * If the current entry has a name type of POSIX, the name is @@ -691,7 +690,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname, ie->key.file_name.file_name_length, ic, vol->upcase, vol->upcase_len)) { found_it: - mref = le64_to_cpu(ie->_IIF(indexed_file)); + mref = le64_to_cpu(ie->data.dir.indexed_file); put_attr_search_ctx(ctx); unmap_mft_record(dir_ni); return mref; @@ -738,7 +737,7 @@ found_it: * We have finished with this index without success. Check for the * presence of a child node. */ - if (!(ie->_IEH(flags) & INDEX_ENTRY_NODE)) { + if (!(ie->flags & INDEX_ENTRY_NODE)) { /* No child node, return -ENOENT. */ err = -ENOENT; goto err_out; @@ -752,7 +751,7 @@ found_it: goto err_out; } /* Get the starting vcn of the index_block holding the child node. */ - vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->_IEH(length)) - 8); + vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8); ia_mapping = VFS_I(dir_ni)->i_mapping; /* * We are done with the index root and the mft record. Release them, @@ -769,7 +768,7 @@ descend_into_child_node: * disk if necessary. */ page = ntfs_map_page(ia_mapping, vcn << - dir_ni->_IDM(index_vcn_size_bits) >> PAGE_CACHE_SHIFT); + dir_ni->itype.index.vcn_size_bits >> PAGE_CACHE_SHIFT); if (IS_ERR(page)) { ntfs_error(sb, "Failed to map directory index page, error %ld.", -PTR_ERR(page)); @@ -780,7 +779,7 @@ descend_into_child_node: fast_descend_into_child_node: /* Get to the index allocation block. */ ia = (INDEX_ALLOCATION*)(kaddr + ((vcn << - dir_ni->_IDM(index_vcn_size_bits)) & ~PAGE_CACHE_MASK)); + dir_ni->itype.index.vcn_size_bits) & ~PAGE_CACHE_MASK)); /* Bounds checks. */ if ((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE) { ntfs_error(sb, "Out of bounds check failed. Corrupt directory " @@ -799,18 +798,18 @@ fast_descend_into_child_node: goto unm_err_out; } if (le32_to_cpu(ia->index.allocated_size) + 0x18 != - dir_ni->_IDM(index_block_size)) { + dir_ni->itype.index.block_size) { ntfs_error(sb, "Index buffer (VCN 0x%Lx) of directory inode " "0x%lx has a size (%u) differing from the " "directory specified size (%u). Directory " "inode is corrupt or driver bug.", (long long)vcn, dir_ni->mft_no, le32_to_cpu(ia->index.allocated_size) + 0x18, - dir_ni->_IDM(index_block_size)); + dir_ni->itype.index.block_size); err = -EIO; goto unm_err_out; } - index_end = (u8*)ia + dir_ni->_IDM(index_block_size); + index_end = (u8*)ia + dir_ni->itype.index.block_size; if (index_end > kaddr + PAGE_CACHE_SIZE) { ntfs_error(sb, "Index buffer (VCN 0x%Lx) of directory inode " "0x%lx crosses page boundary. Impossible! " @@ -820,7 +819,7 @@ fast_descend_into_child_node: goto unm_err_out; } index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length); - if (index_end > (u8*)ia + dir_ni->_IDM(index_block_size)) { + if (index_end > (u8*)ia + dir_ni->itype.index.block_size) { ntfs_error(sb, "Size of index buffer (VCN 0x%Lx) of directory " "inode 0x%lx exceeds maximum size.", (long long)vcn, dir_ni->mft_no); @@ -835,11 +834,11 @@ fast_descend_into_child_node: * loop until we exceed valid memory (corruption case) or until we * reach the last entry. */ - for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->_IEH(length)))) { + for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { /* Bounds check. */ if ((u8*)ie < (u8*)ia || (u8*)ie + sizeof(INDEX_ENTRY_HEADER) > index_end || - (u8*)ie + le16_to_cpu(ie->_IEH(key_length)) > + (u8*)ie + le16_to_cpu(ie->key_length) > index_end) { ntfs_error(sb, "Index entry out of bounds in " "directory inode 0x%lx.", @@ -851,7 +850,7 @@ fast_descend_into_child_node: * The last entry cannot contain a name. It can however contain * a pointer to a child node in the B+tree so we just break out. */ - if (ie->_IEH(flags) & INDEX_ENTRY_END) + if (ie->flags & INDEX_ENTRY_END) break; /* * If the current entry has a name type of POSIX, the name is @@ -876,7 +875,7 @@ fast_descend_into_child_node: ie->key.file_name.file_name_length, ic, vol->upcase, vol->upcase_len)) { found_it2: - mref = le64_to_cpu(ie->_IIF(indexed_file)); + mref = le64_to_cpu(ie->data.dir.indexed_file); ntfs_unmap_page(page); return mref; } @@ -922,7 +921,7 @@ found_it2: * We have finished with this index buffer without success. Check for * the presence of a child node. */ - if (ie->_IEH(flags) & INDEX_ENTRY_NODE) { + if (ie->flags & INDEX_ENTRY_NODE) { if ((ia->index.flags & NODE_MASK) == LEAF_NODE) { ntfs_error(sb, "Index entry with child node found in " "a leaf node in directory inode 0x%lx.", @@ -932,8 +931,7 @@ found_it2: } /* Child node present, descend into it. */ old_vcn = vcn; - vcn = sle64_to_cpup((u8*)ie + - le16_to_cpu(ie->_IEH(length)) - 8); + vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8); if (vcn >= 0) { /* If vcn is in the same page cache page as old_vcn we * recycle the mapped page. */ @@ -1007,7 +1005,7 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t *fpos, if (index_type == INDEX_TYPE_ALLOCATION) *fpos = (u8*)ie - (u8*)iu.ia + (sle64_to_cpu(iu.ia->index_block_vcn) << - ndir->_IDM(index_vcn_size_bits)) + + ndir->itype.index.vcn_size_bits) + vol->mft_record_size; else /* if (index_type == INDEX_TYPE_ROOT) */ *fpos = (u8*)ie - (u8*)iu.ir; @@ -1016,11 +1014,11 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t *fpos, ntfs_debug("Skipping DOS name space entry."); return 0; } - if (MREF_LE(ie->_IIF(indexed_file)) == FILE_root) { + if (MREF_LE(ie->data.dir.indexed_file) == FILE_root) { ntfs_debug("Skipping root directory self reference entry."); return 0; } - if (MREF_LE(ie->_IIF(indexed_file)) < FILE_first_user && + if (MREF_LE(ie->data.dir.indexed_file) < FILE_first_user && !NVolShowSystemFiles(vol)) { ntfs_debug("Skipping system file."); return 0; @@ -1039,10 +1037,10 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t *fpos, dt_type = DT_REG; ntfs_debug("Calling filldir for %s with len %i, fpos 0x%Lx, inode " "0x%lx, DT_%s.", name, name_len, *fpos, - MREF_LE(ie->_IIF(indexed_file)), + MREF_LE(ie->data.dir.indexed_file), dt_type == DT_DIR ? "DIR" : "REG"); return filldir(dirent, name, name_len, *fpos, - MREF_LE(ie->_IIF(indexed_file)), dt_type); + MREF_LE(ie->data.dir.indexed_file), dt_type); } /* @@ -1139,7 +1137,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) } /* Get to the index root value (it's been verified in read_inode). */ ir = (INDEX_ROOT*)((u8*)ctx->attr + - le16_to_cpu(ctx->attr->_ARA(value_offset))); + le16_to_cpu(ctx->attr->data.resident.value_offset)); index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length); /* The first index entry. */ ie = (INDEX_ENTRY*)((u8*)&ir->index + @@ -1149,16 +1147,16 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) * reach the last entry or until filldir tells us it has had enough * or signals an error (both covered by the rc test). */ - for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->_IEH(length)))) { + for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { ntfs_debug("In index root, offset 0x%x.", (u8*)ie - (u8*)ir); /* Bounds checks. */ if (unlikely((u8*)ie < (u8*)ctx->mrec || (u8*)ie + sizeof(INDEX_ENTRY_HEADER) > index_end || - (u8*)ie + le16_to_cpu(ie->_IEH(key_length)) > + (u8*)ie + le16_to_cpu(ie->key_length) > index_end)) goto err_out; /* The last entry cannot contain a name. */ - if (ie->_IEH(flags) & INDEX_ENTRY_END) + if (ie->flags & INDEX_ENTRY_END) break; /* Skip index root entry if continuing previous readdir. */ if (ir_pos > (u8*)ie - (u8*)ir) @@ -1192,7 +1190,7 @@ skip_index_root: /* Get the offset into the index allocation attribute. */ ia_pos = (s64)fpos - vol->mft_record_size; ia_mapping = vdir->i_mapping; - bmp_vi = ndir->_IDM(bmp_ino); + bmp_vi = ndir->itype.index.bmp_ino; if (unlikely(!bmp_vi)) { ntfs_debug("Inode %lu, regetting index bitmap.", vdir->i_ino); bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4); @@ -1201,11 +1199,11 @@ skip_index_root: err = PTR_ERR(bmp_vi); goto err_out; } - ndir->_IDM(bmp_ino) = bmp_vi; + ndir->itype.index.bmp_ino = bmp_vi; } bmp_mapping = bmp_vi->i_mapping; /* Get the starting bitmap bit position and sanity check it. */ - bmp_pos = ia_pos >> ndir->_IDM(index_block_size_bits); + bmp_pos = ia_pos >> ndir->itype.index.block_size_bits; if (unlikely(bmp_pos >> 3 >= bmp_vi->i_size)) { ntfs_error(sb, "Current index allocation position exceeds " "index bitmap size."); @@ -1245,7 +1243,7 @@ find_next_index_buffer: if (unlikely(((bmp_pos + cur_bmp_pos) >> 3) >= vdir->i_size)) goto unm_EOD; ia_pos = (bmp_pos + cur_bmp_pos) << - ndir->_IDM(index_block_size_bits); + ndir->itype.index.block_size_bits; } ntfs_debug("Handling index buffer 0x%Lx.", (long long)bmp_pos + cur_bmp_pos); @@ -1269,7 +1267,7 @@ find_next_index_buffer: } /* Get the current index buffer. */ ia = (INDEX_ALLOCATION*)(kaddr + (ia_pos & ~PAGE_CACHE_MASK & - ~(s64)(ndir->_IDM(index_block_size) - 1))); + ~(s64)(ndir->itype.index.block_size - 1))); /* Bounds checks. */ if (unlikely((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE)) { ntfs_error(sb, "Out of bounds check failed. Corrupt directory " @@ -1277,45 +1275,45 @@ find_next_index_buffer: goto err_out; } if (unlikely(sle64_to_cpu(ia->index_block_vcn) != (ia_pos & - ~(s64)(ndir->_IDM(index_block_size) - 1)) >> - ndir->_IDM(index_vcn_size_bits))) { + ~(s64)(ndir->itype.index.block_size - 1)) >> + ndir->itype.index.vcn_size_bits)) { ntfs_error(sb, "Actual VCN (0x%Lx) of index buffer is " "different from expected VCN (0x%Lx). " "Directory inode 0x%lx is corrupt or driver " "bug. ", (long long)sle64_to_cpu(ia->index_block_vcn), (long long)ia_pos >> - ndir->_IDM(index_vcn_size_bits), vdir->i_ino); + ndir->itype.index.vcn_size_bits, vdir->i_ino); goto err_out; } if (unlikely(le32_to_cpu(ia->index.allocated_size) + 0x18 != - ndir->_IDM(index_block_size))) { + ndir->itype.index.block_size)) { ntfs_error(sb, "Index buffer (VCN 0x%Lx) of directory inode " "0x%lx has a size (%u) differing from the " "directory specified size (%u). Directory " "inode is corrupt or driver bug.", (long long)ia_pos >> - ndir->_IDM(index_vcn_size_bits), vdir->i_ino, + ndir->itype.index.vcn_size_bits, vdir->i_ino, le32_to_cpu(ia->index.allocated_size) + 0x18, - ndir->_IDM(index_block_size)); + ndir->itype.index.block_size); goto err_out; } - index_end = (u8*)ia + ndir->_IDM(index_block_size); + index_end = (u8*)ia + ndir->itype.index.block_size; if (unlikely(index_end > kaddr + PAGE_CACHE_SIZE)) { ntfs_error(sb, "Index buffer (VCN 0x%Lx) of directory inode " "0x%lx crosses page boundary. Impossible! " "Cannot access! This is probably a bug in the " "driver.", (long long)ia_pos >> - ndir->_IDM(index_vcn_size_bits), vdir->i_ino); + ndir->itype.index.vcn_size_bits, vdir->i_ino); goto err_out; } - ia_start = ia_pos & ~(s64)(ndir->_IDM(index_block_size) - 1); + ia_start = ia_pos & ~(s64)(ndir->itype.index.block_size - 1); index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length); - if (unlikely(index_end > (u8*)ia + ndir->_IDM(index_block_size))) { + if (unlikely(index_end > (u8*)ia + ndir->itype.index.block_size)) { ntfs_error(sb, "Size of index buffer (VCN 0x%Lx) of directory " "inode 0x%lx exceeds maximum size.", (long long)ia_pos >> - ndir->_IDM(index_vcn_size_bits), vdir->i_ino); + ndir->itype.index.vcn_size_bits, vdir->i_ino); goto err_out; } /* The first index entry in this index buffer. */ @@ -1326,17 +1324,17 @@ find_next_index_buffer: * reach the last entry or until filldir tells us it has had enough * or signals an error (both covered by the rc test). */ - for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->_IEH(length)))) { + for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { ntfs_debug("In index allocation, offset 0x%Lx.", (long long)ia_start + ((u8*)ie - (u8*)ia)); /* Bounds checks. */ if (unlikely((u8*)ie < (u8*)ia || (u8*)ie + sizeof(INDEX_ENTRY_HEADER) > index_end || - (u8*)ie + le16_to_cpu(ie->_IEH(key_length)) > + (u8*)ie + le16_to_cpu(ie->key_length) > index_end)) goto err_out; /* The last entry cannot contain a name. */ - if (ie->_IEH(flags) & INDEX_ENTRY_END) + if (ie->flags & INDEX_ENTRY_END) break; /* Skip index block entry if continuing previous readdir. */ if (ia_pos - ia_start > (u8*)ie - (u8*)ia) diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index c821b2415528..cb4f82cfb522 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -1,7 +1,7 @@ /** * inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project. * - * Copyright (c) 2001,2002 Anton Altaparmakov. + * Copyright (c) 2001-2003 Anton Altaparmakov * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -336,14 +336,14 @@ static void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni) ni->attr_list_size = 0; ni->attr_list = NULL; init_run_list(&ni->attr_list_rl); - ni->_IDM(bmp_ino) = NULL; - ni->_IDM(index_block_size) = 0; - ni->_IDM(index_vcn_size) = 0; - ni->_IDM(index_block_size_bits) = 0; - ni->_IDM(index_vcn_size_bits) = 0; + ni->itype.index.bmp_ino = NULL; + ni->itype.index.block_size = 0; + ni->itype.index.vcn_size = 0; + ni->itype.index.block_size_bits = 0; + ni->itype.index.vcn_size_bits = 0; init_MUTEX(&ni->extent_lock); ni->nr_extents = 0; - ni->_INE(base_ntfs_ino) = NULL; + ni->ext.base_ntfs_ino = NULL; return; } @@ -426,14 +426,14 @@ err_corrupt_attr: "chkdsk."); return -EIO; } - if (!(attr->_ARA(resident_flags) & RESIDENT_ATTR_IS_INDEXED)) { + if (!(attr->data.resident.flags & RESIDENT_ATTR_IS_INDEXED)) { ntfs_error(ctx->ntfs_ino->vol->sb, "Unindexed file " "name. You should run chkdsk."); return -EIO; } file_name_attr = (FILE_NAME_ATTR*)((u8*)attr + - le16_to_cpu(attr->_ARA(value_offset))); - p2 = (u8*)attr + le32_to_cpu(attr->_ARA(value_length)); + le16_to_cpu(attr->data.resident.value_offset)); + p2 = (u8*)attr + le32_to_cpu(attr->data.resident.value_length); if (p2 < (u8*)attr || p2 > p) goto err_corrupt_attr; /* This attribute is ok, but is it in the $Extend directory? */ @@ -578,7 +578,7 @@ static int ntfs_read_locked_inode(struct inode *vi) } /* Get the standard information attribute value. */ si = (STANDARD_INFORMATION*)((char*)ctx->attr + - le16_to_cpu(ctx->attr->_ARA(value_offset))); + le16_to_cpu(ctx->attr->data.resident.value_offset)); /* Transfer information from the standard information into vfs_ino. */ /* @@ -633,7 +633,7 @@ static int ntfs_read_locked_inode(struct inode *vi) } if (ctx->attr->non_resident) { NInoSetAttrListNonResident(ni); - if (ctx->attr->_ANR(lowest_vcn)) { + if (ctx->attr->data.non_resident.lowest_vcn) { ntfs_error(vi->i_sb, "Attribute list has non " "zero lowest_vcn. Inode is " "corrupt. You should run " @@ -659,17 +659,17 @@ static int ntfs_read_locked_inode(struct inode *vi) /* Now load the attribute list. */ if ((err = load_attribute_list(vol, &ni->attr_list_rl, ni->attr_list, ni->attr_list_size, - sle64_to_cpu( - ctx->attr->_ANR(initialized_size))))) { + sle64_to_cpu(ctx->attr->data. + non_resident.initialized_size)))) { ntfs_error(vi->i_sb, "Failed to load " "attribute list attribute."); goto unm_err_out; } } else /* if (!ctx.attr->non_resident) */ { if ((u8*)ctx->attr + le16_to_cpu( - ctx->attr->_ARA(value_offset)) + + ctx->attr->data.resident.value_offset) + le32_to_cpu( - ctx->attr->_ARA(value_length)) > + ctx->attr->data.resident.value_length) > (u8*)ctx->mrec + vol->mft_record_size) { ntfs_error(vi->i_sb, "Corrupt attribute list " "in inode."); @@ -677,9 +677,9 @@ static int ntfs_read_locked_inode(struct inode *vi) } /* Now copy the attribute list. */ memcpy(ni->attr_list, (u8*)ctx->attr + le16_to_cpu( - ctx->attr->_ARA(value_offset)), + ctx->attr->data.resident.value_offset), le32_to_cpu( - ctx->attr->_ARA(value_length))); + ctx->attr->data.resident.value_length)); } } skip_attr_list_load: @@ -728,9 +728,10 @@ skip_attr_list_load: } if (ctx->attr->flags & ATTR_IS_SPARSE) NInoSetSparse(ni); - ir = (INDEX_ROOT*)((char*)ctx->attr + - le16_to_cpu(ctx->attr->_ARA(value_offset))); - ir_end = (char*)ir + le32_to_cpu(ctx->attr->_ARA(value_length)); + ir = (INDEX_ROOT*)((char*)ctx->attr + le16_to_cpu( + ctx->attr->data.resident.value_offset)); + ir_end = (char*)ir + le32_to_cpu( + ctx->attr->data.resident.value_length); if (ir_end > (char*)ctx->mrec + vol->mft_record_size) { ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is " "corrupt."); @@ -752,41 +753,41 @@ skip_attr_list_load: "COLLATION_FILE_NAME. Not allowed."); goto unm_err_out; } - ni->_IDM(index_block_size) = le32_to_cpu(ir->index_block_size); - if (ni->_IDM(index_block_size) & - (ni->_IDM(index_block_size) - 1)) { + ni->itype.index.block_size = le32_to_cpu(ir->index_block_size); + if (ni->itype.index.block_size & + (ni->itype.index.block_size - 1)) { ntfs_error(vi->i_sb, "Index block size (%u) is not a " "power of two.", - ni->_IDM(index_block_size)); + ni->itype.index.block_size); goto unm_err_out; } - if (ni->_IDM(index_block_size) > PAGE_CACHE_SIZE) { + if (ni->itype.index.block_size > PAGE_CACHE_SIZE) { ntfs_error(vi->i_sb, "Index block size (%u) > " "PAGE_CACHE_SIZE (%ld) is not " "supported. Sorry.", - ni->_IDM(index_block_size), + ni->itype.index.block_size, PAGE_CACHE_SIZE); err = -EOPNOTSUPP; goto unm_err_out; } - if (ni->_IDM(index_block_size) < NTFS_BLOCK_SIZE) { + if (ni->itype.index.block_size < NTFS_BLOCK_SIZE) { ntfs_error(vi->i_sb, "Index block size (%u) < " "NTFS_BLOCK_SIZE (%i) is not " "supported. Sorry.", - ni->_IDM(index_block_size), + ni->itype.index.block_size, NTFS_BLOCK_SIZE); err = -EOPNOTSUPP; goto unm_err_out; } - ni->_IDM(index_block_size_bits) = - ffs(ni->_IDM(index_block_size)) - 1; + ni->itype.index.block_size_bits = + ffs(ni->itype.index.block_size) - 1; /* Determine the size of a vcn in the directory index. */ - if (vol->cluster_size <= ni->_IDM(index_block_size)) { - ni->_IDM(index_vcn_size) = vol->cluster_size; - ni->_IDM(index_vcn_size_bits) = vol->cluster_size_bits; + if (vol->cluster_size <= ni->itype.index.block_size) { + ni->itype.index.vcn_size = vol->cluster_size; + ni->itype.index.vcn_size_bits = vol->cluster_size_bits; } else { - ni->_IDM(index_vcn_size) = vol->sector_size; - ni->_IDM(index_vcn_size_bits) = vol->sector_size_bits; + ni->itype.index.vcn_size = vol->sector_size; + ni->itype.index.vcn_size_bits = vol->sector_size_bits; } /* Setup the index allocation attribute, even if not present. */ @@ -836,18 +837,19 @@ skip_attr_list_load: "is compressed."); goto unm_err_out; } - if (ctx->attr->_ANR(lowest_vcn)) { + if (ctx->attr->data.non_resident.lowest_vcn) { ntfs_error(vi->i_sb, "First extent of " "$INDEX_ALLOCATION attribute has non " "zero lowest_vcn. Inode is corrupt. " "You should run chkdsk."); goto unm_err_out; } - vi->i_size = sle64_to_cpu(ctx->attr->_ANR(data_size)); + vi->i_size = sle64_to_cpu( + ctx->attr->data.non_resident.data_size); ni->initialized_size = sle64_to_cpu( - ctx->attr->_ANR(initialized_size)); + ctx->attr->data.non_resident.initialized_size); ni->allocated_size = sle64_to_cpu( - ctx->attr->_ANR(allocated_size)); + ctx->attr->data.non_resident.allocated_size); /* * We are done with the mft record, so we release it. Otherwise * we would deadlock in ntfs_attr_iget(). @@ -863,7 +865,7 @@ skip_attr_list_load: err = PTR_ERR(bvi); goto unm_err_out; } - ni->_IDM(bmp_ino) = bvi; + ni->itype.index.bmp_ino = bvi; bni = NTFS_I(bvi); if (NInoCompressed(bni) || NInoEncrypted(bni) || NInoSparse(bni)) { @@ -873,7 +875,7 @@ skip_attr_list_load: } /* Consistency check bitmap size vs. index allocation size. */ if ((bvi->i_size << 3) < (vi->i_size >> - ni->_IDM(index_block_size_bits))) { + ni->itype.index.block_size_bits)) { ntfs_error(vi->i_sb, "Index bitmap too small (0x%Lx) " "for index allocation (0x%Lx).", bvi->i_size << 3, vi->i_size); @@ -950,25 +952,28 @@ skip_large_dir_stuff: "corrupt file."); goto unm_err_out; } - ni->_ICF(compression_block_clusters) = 1U << - ctx->attr->_ANR(compression_unit); - if (ctx->attr->_ANR(compression_unit) != 4) { + ni->itype.compressed.block_clusters = 1U << + ctx->attr->data.non_resident. + compression_unit; + if (ctx->attr->data.non_resident. + compression_unit != 4) { ntfs_error(vi->i_sb, "Found " "nonstandard compression unit " "(%u instead of 4). Cannot " "handle this. This might " "indicate corruption so you " "should run chkdsk.", - ctx->attr->_ANR(compression_unit)); + ctx->attr->data.non_resident. + compression_unit); err = -EOPNOTSUPP; goto unm_err_out; } - ni->_ICF(compression_block_size) = 1U << ( - ctx->attr->_ANR( - compression_unit) + + ni->itype.compressed.block_size = 1U << ( + ctx->attr->data.non_resident. + compression_unit + vol->cluster_size_bits); - ni->_ICF(compression_block_size_bits) = ffs( - ni->_ICF(compression_block_size)) - 1; + ni->itype.compressed.block_size_bits = ffs( + ni->itype.compressed.block_size) - 1; } if (ctx->attr->flags & ATTR_IS_ENCRYPTED) { if (ctx->attr->flags & ATTR_COMPRESSION_MASK) { @@ -980,7 +985,7 @@ skip_large_dir_stuff: } if (ctx->attr->flags & ATTR_IS_SPARSE) NInoSetSparse(ni); - if (ctx->attr->_ANR(lowest_vcn)) { + if (ctx->attr->data.non_resident.lowest_vcn) { ntfs_error(vi->i_sb, "First extent of $DATA " "attribute has non zero " "lowest_vcn. Inode is corrupt. " @@ -988,24 +993,18 @@ skip_large_dir_stuff: goto unm_err_out; } /* Setup all the sizes. */ - vi->i_size = sle64_to_cpu(ctx->attr->_ANR(data_size)); + vi->i_size = sle64_to_cpu( + ctx->attr->data.non_resident.data_size); ni->initialized_size = sle64_to_cpu( - ctx->attr->_ANR(initialized_size)); + ctx->attr->data.non_resident. + initialized_size); ni->allocated_size = sle64_to_cpu( - ctx->attr->_ANR(allocated_size)); + ctx->attr->data.non_resident. + allocated_size); if (NInoCompressed(ni)) { - ni->_ICF(compressed_size) = sle64_to_cpu( - ctx->attr->_ANR(compressed_size)); - if (vi->i_size != ni->initialized_size) - ntfs_warning(vi->i_sb, "BUG: Found " - "compressed file with " - "data_size not equal to " - "initialized_size. This will " - "probably cause problems when " - "trying to access the file. " - "Please notify linux-ntfs-dev@" - "lists.sf.net that you saw " - "this message. Thanks!"); + ni->itype.compressed.size = sle64_to_cpu( + ctx->attr->data.non_resident. + compressed_size); } } else { /* Resident attribute. */ /* @@ -1015,7 +1014,8 @@ skip_large_dir_stuff: * path. (Probably only affects truncate().) */ vi->i_size = ni->initialized_size = ni->allocated_size = - le32_to_cpu(ctx->attr->_ARA(value_length)); + le32_to_cpu( + ctx->attr->data.resident.value_length); } no_data_attr_special_case: /* We are done with the mft record, so we release it. */ @@ -1049,7 +1049,7 @@ no_data_attr_special_case: if (!NInoCompressed(ni)) vi->i_blocks = ni->allocated_size >> 9; else - vi->i_blocks = ni->_ICF(compressed_size) >> 9; + vi->i_blocks = ni->itype.compressed.size >> 9; ntfs_debug("Done."); return 0; @@ -1146,7 +1146,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) * read code paths. */ vi->i_size = ni->initialized_size = ni->allocated_size = - le32_to_cpu(ctx->attr->_ARA(value_length)); + le32_to_cpu(ctx->attr->data.resident.value_length); } else { NInoSetNonResident(ni); if (ctx->attr->flags & ATTR_COMPRESSION_MASK) { @@ -1189,25 +1189,27 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) "corrupt file."); goto unm_err_out; } - ni->_ICF(compression_block_clusters) = 1U << - ctx->attr->_ANR(compression_unit); - if (ctx->attr->_ANR(compression_unit) != 4) { + ni->itype.compressed.block_clusters = 1U << + ctx->attr->data.non_resident. + compression_unit; + if (ctx->attr->data.non_resident.compression_unit != 4) { ntfs_error(vi->i_sb, "Found " "nonstandard compression unit " "(%u instead of 4). Cannot " "handle this. This might " "indicate corruption so you " "should run chkdsk.", - ctx->attr->_ANR(compression_unit)); + ctx->attr->data.non_resident. + compression_unit); err = -EOPNOTSUPP; goto unm_err_out; } - ni->_ICF(compression_block_size) = 1U << ( - ctx->attr->_ANR( - compression_unit) + + ni->itype.compressed.block_size = 1U << ( + ctx->attr->data.non_resident. + compression_unit + vol->cluster_size_bits); - ni->_ICF(compression_block_size_bits) = ffs( - ni->_ICF(compression_block_size)) - 1; + ni->itype.compressed.block_size_bits = ffs( + ni->itype.compressed.block_size) - 1; } if (ctx->attr->flags & ATTR_IS_ENCRYPTED) { if (ctx->attr->flags & ATTR_COMPRESSION_MASK) { @@ -1242,30 +1244,23 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) } NInoSetSparse(ni); } - if (ctx->attr->_ANR(lowest_vcn)) { + if (ctx->attr->data.non_resident.lowest_vcn) { ntfs_error(vi->i_sb, "First extent of attribute has " "non-zero lowest_vcn. Inode is " "corrupt. You should run chkdsk."); goto unm_err_out; } /* Setup all the sizes. */ - vi->i_size = sle64_to_cpu(ctx->attr->_ANR(data_size)); + vi->i_size = sle64_to_cpu( + ctx->attr->data.non_resident.data_size); ni->initialized_size = sle64_to_cpu( - ctx->attr->_ANR(initialized_size)); + ctx->attr->data.non_resident.initialized_size); ni->allocated_size = sle64_to_cpu( - ctx->attr->_ANR(allocated_size)); + ctx->attr->data.non_resident.allocated_size); if (NInoCompressed(ni)) { - ni->_ICF(compressed_size) = sle64_to_cpu( - ctx->attr->_ANR(compressed_size)); - if (vi->i_size != ni->initialized_size) - ntfs_warning(vi->i_sb, "Compressed attribute " - "with data_size unequal to " - "initialized size found. This " - "will probably cause problems " - "when trying to access the " - "file. Please notify " - "linux-ntfs-dev@lists.sf.net " - "that you saw this message."); + ni->itype.compressed.size = sle64_to_cpu( + ctx->attr->data.non_resident. + compressed_size); } } @@ -1277,14 +1272,14 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) if (!NInoCompressed(ni)) vi->i_blocks = ni->allocated_size >> 9; else - vi->i_blocks = ni->_ICF(compressed_size) >> 9; + vi->i_blocks = ni->itype.compressed.size >> 9; /* * Make sure the base inode doesn't go away and attach it to the * attribute inode. */ igrab(base_vi); - ni->_INE(base_ntfs_ino) = base_ni; + ni->ext.base_ntfs_ino = base_ni; ni->nr_extents = -1; put_attr_search_ctx(ctx); @@ -1371,8 +1366,8 @@ void ntfs_read_inode_mount(struct inode *vi) * This sets up our little cheat allowing us to reuse the async io * completion handler for directories. */ - ni->_IDM(index_block_size) = vol->mft_record_size; - ni->_IDM(index_block_size_bits) = vol->mft_record_size_bits; + ni->itype.index.block_size = vol->mft_record_size; + ni->itype.index.block_size_bits = vol->mft_record_size_bits; /* Very important! Needed to be able to call map_mft_record*(). */ vol->mft_ino = vi; @@ -1456,7 +1451,7 @@ void ntfs_read_inode_mount(struct inode *vi) } if (ctx->attr->non_resident) { NInoSetAttrListNonResident(ni); - if (ctx->attr->_ANR(lowest_vcn)) { + if (ctx->attr->data.non_resident.lowest_vcn) { ntfs_error(sb, "Attribute list has non zero " "lowest_vcn. $MFT is corrupt. " "You should run chkdsk."); @@ -1476,8 +1471,8 @@ void ntfs_read_inode_mount(struct inode *vi) /* Now load the attribute list. */ if ((err = load_attribute_list(vol, &ni->attr_list_rl, ni->attr_list, ni->attr_list_size, - sle64_to_cpu( - ctx->attr->_ANR(initialized_size))))) { + sle64_to_cpu(ctx->attr->data. + non_resident.initialized_size)))) { ntfs_error(sb, "Failed to load attribute list " "attribute with error code %i.", -err); @@ -1485,9 +1480,9 @@ void ntfs_read_inode_mount(struct inode *vi) } } else /* if (!ctx.attr->non_resident) */ { if ((u8*)ctx->attr + le16_to_cpu( - ctx->attr->_ARA(value_offset)) + + ctx->attr->data.resident.value_offset) + le32_to_cpu( - ctx->attr->_ARA(value_length)) > + ctx->attr->data.resident.value_length) > (u8*)ctx->mrec + vol->mft_record_size) { ntfs_error(sb, "Corrupt attribute list " "attribute."); @@ -1495,9 +1490,9 @@ void ntfs_read_inode_mount(struct inode *vi) } /* Now copy the attribute list. */ memcpy(ni->attr_list, (u8*)ctx->attr + le16_to_cpu( - ctx->attr->_ARA(value_offset)), + ctx->attr->data.resident.value_offset), le32_to_cpu( - ctx->attr->_ARA(value_length))); + ctx->attr->data.resident.value_length)); } /* The attribute list is now setup in memory. */ /* @@ -1606,7 +1601,7 @@ void ntfs_read_inode_mount(struct inode *vi) if (!next_vcn) { u64 ll; - if (attr->_ANR(lowest_vcn)) { + if (attr->data.non_resident.lowest_vcn) { ntfs_error(sb, "First extent of $DATA " "attribute has non zero " "lowest_vcn. $MFT is corrupt. " @@ -1614,14 +1609,16 @@ void ntfs_read_inode_mount(struct inode *vi) goto put_err_out; } /* Get the last vcn in the $DATA attribute. */ - last_vcn = sle64_to_cpu(attr->_ANR(allocated_size)) >> - vol->cluster_size_bits; + last_vcn = sle64_to_cpu( + attr->data.non_resident.allocated_size) + >> vol->cluster_size_bits; /* Fill in the inode size. */ - vi->i_size = sle64_to_cpu(attr->_ANR(data_size)); - ni->initialized_size = sle64_to_cpu( - attr->_ANR(initialized_size)); + vi->i_size = sle64_to_cpu( + attr->data.non_resident.data_size); + ni->initialized_size = sle64_to_cpu(attr->data. + non_resident.initialized_size); ni->allocated_size = sle64_to_cpu( - attr->_ANR(allocated_size)); + attr->data.non_resident.allocated_size); /* Set the number of mft records. */ ll = vi->i_size >> vol->mft_record_size_bits; /* @@ -1687,7 +1684,7 @@ void ntfs_read_inode_mount(struct inode *vi) } /* Get the lowest vcn for the next extent. */ - highest_vcn = sle64_to_cpu(attr->_ANR(highest_vcn)); + highest_vcn = sle64_to_cpu(attr->data.non_resident.highest_vcn); next_vcn = highest_vcn + 1; /* Only one extent or error, which we catch below. */ @@ -1695,7 +1692,8 @@ void ntfs_read_inode_mount(struct inode *vi) break; /* Avoid endless loops due to corruption. */ - if (next_vcn < sle64_to_cpu(attr->_ANR(lowest_vcn))) { + if (next_vcn < sle64_to_cpu( + attr->data.non_resident.lowest_vcn)) { ntfs_error(sb, "$MFT has corrupt attribute list " "attribute. Run chkdsk."); goto put_err_out; @@ -1796,9 +1794,9 @@ void ntfs_put_inode(struct inode *vi) ntfs_inode *ni; ni = NTFS_I(vi); - if (NInoIndexAllocPresent(ni) && ni->_IDM(bmp_ino)) { - iput(ni->_IDM(bmp_ino)); - ni->_IDM(bmp_ino) = NULL; + if (NInoIndexAllocPresent(ni) && ni->itype.index.bmp_ino) { + iput(ni->itype.index.bmp_ino); + ni->itype.index.bmp_ino = NULL; } } return; @@ -1831,8 +1829,8 @@ void __ntfs_clear_inode(ntfs_inode *ni) // FIXME: Handle dirty case for each extent inode! for (i = 0; i < ni->nr_extents; i++) - ntfs_clear_extent_inode(ni->_INE(extent_ntfs_inos)[i]); - kfree(ni->_INE(extent_ntfs_inos)); + ntfs_clear_extent_inode(ni->ext.extent_ntfs_inos[i]); + kfree(ni->ext.extent_ntfs_inos); } /* Free all alocated memory. */ down_write(&ni->run_list.lock); @@ -1888,9 +1886,9 @@ void ntfs_clear_big_inode(struct inode *vi) if (NInoAttr(ni)) { /* Release the base inode if we are holding it. */ if (ni->nr_extents == -1) { - iput(VFS_I(ni->_INE(base_ntfs_ino))); + iput(VFS_I(ni->ext.base_ntfs_ino)); ni->nr_extents = 0; - ni->_INE(base_ntfs_ino) = NULL; + ni->ext.base_ntfs_ino = NULL; } } return; diff --git a/fs/ntfs/inode.h b/fs/ntfs/inode.h index 60ee56fe7174..82b3b22556a6 100644 --- a/fs/ntfs/inode.h +++ b/fs/ntfs/inode.h @@ -2,8 +2,8 @@ * inode.h - Defines for inode structures NTFS Linux kernel driver. Part of * the Linux-NTFS project. * - * Copyright (c) 2001,2002 Anton Altaparmakov. - * Copyright (c) 2002 Richard Russon. + * Copyright (c) 2001-2003 Anton Altaparmakov + * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -93,23 +93,21 @@ struct _ntfs_inode { struct { /* It is a directory or $MFT. */ struct inode *bmp_ino; /* Attribute inode for the directory index $BITMAP. */ - u32 index_block_size; /* Size of an index block. */ - u32 index_vcn_size; /* Size of a vcn in this + u32 block_size; /* Size of an index block. */ + u32 vcn_size; /* Size of a vcn in this directory index. */ - u8 index_block_size_bits; /* Log2 of the above. */ - u8 index_vcn_size_bits; /* Log2 of the above. */ - } SN(idm); + u8 block_size_bits; /* Log2 of the above. */ + u8 vcn_size_bits; /* Log2 of the above. */ + } index; struct { /* It is a compressed file or fake inode. */ - s64 compressed_size; /* Copy from $DATA. */ - u32 compression_block_size; /* Size of a compression - block (cb). */ - u8 compression_block_size_bits; /* Log2 of the size of - a cb. */ - u8 compression_block_clusters; /* Number of clusters - per compression - block. */ - } SN(icf); - } SN(idc); + s64 size; /* Copy of compressed_size from + $DATA. */ + u32 block_size; /* Size of a compression block + (cb). */ + u8 block_size_bits; /* Log2 of the size of a cb. */ + u8 block_clusters; /* Number of clusters per cb. */ + } compressed; + } itype; struct semaphore extent_lock; /* Lock for accessing/modifying the below . */ s32 nr_extents; /* For a base mft record, the number of attached extent @@ -126,13 +124,9 @@ struct _ntfs_inode { record. For fake inodes, the real (base) inode to which the attribute belongs. */ - } SN(ine); + } ext; }; -#define _IDM(X) SC(idc.idm,X) -#define _ICF(X) SC(idc.icf,X) -#define _INE(X) SC(ine,X) - /* * Defined bits for the state field in the ntfs_inode structure. * (f) = files only, (d) = directories only, (a) = attributes/fake inodes only diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h index bccc0e9e00d4..19ce024c2bbc 100644 --- a/fs/ntfs/layout.h +++ b/fs/ntfs/layout.h @@ -2,8 +2,8 @@ * layout.h - All NTFS associated on-disk structures. Part of the Linux-NTFS * project. * - * Copyright (c) 2001,2002 Anton Altaparmakov. - * Copyright (C) 2002 Richard Russon. + * Copyright (c) 2001-2003 Anton Altaparmakov + * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -296,7 +296,11 @@ typedef u64 MFT_REF; */ typedef struct { /*Ofs*/ -/* 0*/ NTFS_RECORD SN(mnr); /* Usually the magic is "FILE". */ +/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ + NTFS_RECORD_TYPES magic;/* Usually the magic is "FILE". */ + u16 usa_ofs; /* See NTFS_RECORD definition above. */ + u16 usa_count; /* See NTFS_RECORD definition above. */ + /* 8*/ u64 lsn; /* $LogFile sequence number for this record. Changed every time the record is modified. */ /* 16*/ u16 sequence_number; /* Number of times this mft record has been @@ -360,8 +364,6 @@ typedef struct { */ } __attribute__ ((__packed__)) MFT_RECORD; -#define _MNR(X) SC(mnr,X) - /* * System defined attributes (32-bit). Each attribute type has a corresponding * attribute name (Unicode string of maximum 64 character length) as described @@ -612,10 +614,10 @@ typedef struct { have a name present as this might not have a length of a multiple of 8-bytes. */ -/* 22 */ RESIDENT_ATTR_FLAGS resident_flags; /* See above. */ -/* 23 */ s8 reservedR; /* Reserved/alignment to 8-byte +/* 22 */ RESIDENT_ATTR_FLAGS flags; /* See above. */ +/* 23 */ s8 reserved; /* Reserved/alignment to 8-byte boundary. */ - } SN(ara) __attribute__ ((__packed__)); + } __attribute__ ((__packed__)) resident; /* Non-resident attributes. */ struct { /* 16*/ VCN lowest_vcn; /* Lowest valid virtual cluster number @@ -641,7 +643,7 @@ typedef struct { compressed. (This effectively limits the compression unit size to be a power of two clusters.) WinNT4 only uses a value of 4. */ -/* 35*/ u8 reserved1[5]; /* Align to 8-byte boundary. */ +/* 35*/ u8 reserved[5]; /* Align to 8-byte boundary. */ /* The sizes below are only used when lowest_vcn is zero, as otherwise it would be difficult to keep them up-to-date.*/ /* 40*/ s64 allocated_size; /* Byte size of disk space @@ -665,13 +667,10 @@ typedef struct { cluster size. Represents the actual amount of disk space being used on the disk. */ /* sizeof(compressed attr) = 72*/ - } SN(anr) __attribute__ ((__packed__)); - } SN(aua) __attribute__ ((__packed__)); + } __attribute__ ((__packed__)) non_resident; + } __attribute__ ((__packed__)) data; } __attribute__ ((__packed__)) ATTR_RECORD; -#define _ARA(X) SC(aua.ara,X) -#define _ANR(X) SC(aua.anr,X) - typedef ATTR_RECORD ATTR_REC; /* @@ -763,11 +762,13 @@ typedef struct { disabled altogether for speed. */ /* 32*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */ /* 36*/ union { - /* NTFS 1.2 (and previous, presumably) */ -/* 36 */ u8 reserved12[12]; /* Reserved/alignment to 8-byte - boundary. */ -/* sizeof() = 48 bytes */ - /* NTFS 3.0 */ + /* NTFS 1.2 */ + struct { + /* 36*/ u8 reserved12[12]; /* Reserved/alignment to 8-byte + boundary. */ + } __attribute__ ((__packed__)) v1; + /* sizeof() = 48 bytes */ + /* NTFS 3.x */ struct { /* * If a volume has been upgraded from a previous NTFS version, then these @@ -777,12 +778,12 @@ typedef struct { * the fields are present. Maybe just check like this: * if (resident.ValueLength < sizeof(STANDARD_INFORMATION)) { * Assume NTFS 1.2- format. - * If (volume version is 3.0+) - * Upgrade attribute to NTFS 3.0 format. + * If (volume version is 3.x) + * Upgrade attribute to NTFS 3.x format. * else * Use NTFS 1.2- format for access. * } else - * Use NTFS 3.0 format for access. + * Use NTFS 3.x format for access. * Only problem is that it might be legal to set the length of the value to * arbitrarily large values thus spoiling this check. - But chkdsk probably * views that as a corruption, assuming that it behaves like this for all @@ -818,13 +819,11 @@ typedef struct { partition. This, in contrast to disabling the journal is a very fast process, so the user won't even notice it. */ - } SN(svs); - } SN(sei); -/* sizeof() = 72 bytes (NTFS 3.0) */ + } __attribute__ ((__packed__)) v3; + /* sizeof() = 72 bytes (NTFS 3.x) */ + } __attribute__ ((__packed__)) ver; } __attribute__ ((__packed__)) STANDARD_INFORMATION; -#define _SVS(X) SC(sei.svs,X) - /* * Attribute: Attribute list (0x20). * @@ -956,21 +955,20 @@ typedef struct { pack the extended attributes (EAs), if such are present.*/ /* 3e*/ u16 reserved; /* Reserved for alignment. */ - } SN(fea) __attribute__ ((__packed__)); - /* 3c*/ u32 reparse_point_tag; /* Type of reparse point, + } __attribute__ ((__packed__)) ea; + /* 3c*/ struct { + /* 3c*/ u32 reparse_point_tag; /* Type of reparse point, present only in reparse points and only if there are no EAs. */ - } SN(fer) __attribute__ ((__packed__)); + } __attribute__ ((__packed__)) rp; + } __attribute__ ((__packed__)) type; /* 40*/ u8 file_name_length; /* Length of file name in (Unicode) characters. */ /* 41*/ FILE_NAME_TYPE_FLAGS file_name_type; /* Namespace of the file name.*/ /* 42*/ uchar_t file_name[0]; /* File name in Unicode. */ } __attribute__ ((__packed__)) FILE_NAME_ATTR; -#define _FEA(X) SC(fer.fea,X) -#define _FER(X) SC(fer,X) - /* * GUID structures store globally unique identifiers (GUID). A GUID is a * 128-bit value consisting of one group of eight hexadecimal digits, followed @@ -1008,9 +1006,9 @@ typedef struct { GUID birth_volume_id; GUID birth_object_id; GUID domain_id; - } SN(obv) __attribute__ ((__packed__)); + } __attribute__ ((__packed__)) origin; u8 extended_info[48]; - } SN(oei) __attribute__ ((__packed__)); + } __attribute__ ((__packed__)) opt; } __attribute__ ((__packed__)) OBJ_ID_INDEX_DATA; /* @@ -1032,13 +1030,11 @@ typedef struct { GUID birth_object_id; /* Unique id of file when it was first created. */ GUID domain_id; /* Reserved, zero. */ - } SN(obv) __attribute__ ((__packed__)); + } __attribute__ ((__packed__)) origin; u8 extended_info[48]; - } SN(oei) __attribute__ ((__packed__)); + } __attribute__ ((__packed__)) opt; } __attribute__ ((__packed__)) OBJECT_ID_ATTR; -#define _OBV(X) SC(oei.obv,X) - /* * The pre-defined IDENTIFIER_AUTHORITIES used as SID_IDENTIFIER_AUTHORITY in * the SID structure (see below). @@ -1174,14 +1170,12 @@ typedef enum { /* Identifier authority. */ */ typedef union { struct { - u32 low_part; /* Low 32-bits. */ - u16 high_part; /* High 16-bits. */ - } SN(sia) __attribute__ ((__packed__)); + u32 low; /* Low 32-bits. */ + u16 high; /* High 16-bits. */ + } __attribute__ ((__packed__)) parts; u8 value[6]; /* Value as individual bytes. */ } __attribute__ ((__packed__)) SID_IDENTIFIER_AUTHORITY; -#define _SIA(X) SC(sia,X) - /* * The SID structure is a variable-length structure used to uniquely identify * users or groups. SID stands for security identifier. @@ -1287,9 +1281,10 @@ typedef enum { * data depends on the ACE type. */ typedef struct { - ACE_TYPES type; /* Type of the ACE. */ - ACE_FLAGS flags; /* Flags describing the ACE. */ - u16 size; /* Size in bytes of the ACE. */ +/*Ofs*/ +/* 0*/ ACE_TYPES type; /* Type of the ACE. */ +/* 1*/ ACE_FLAGS flags; /* Flags describing the ACE. */ +/* 2*/ u16 size; /* Size in bytes of the ACE. */ } __attribute__ ((__packed__)) ACE_HEADER; /* @@ -1446,12 +1441,15 @@ typedef struct { * ACCESS_ALLOWED_ACE, ACCESS_DENIED_ACE, SYSTEM_AUDIT_ACE, SYSTEM_ALARM_ACE */ typedef struct { - ACE_HEADER SN(aah); /* The ACE header. */ - ACCESS_MASK mask; /* Access mask associated with the ACE. */ - SID sid; /* The SID associated with the ACE. */ +/* 0 ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */ + ACE_TYPES type; /* Type of the ACE. */ + ACE_FLAGS flags; /* Flags describing the ACE. */ + u16 size; /* Size in bytes of the ACE. */ +/* 4*/ ACCESS_MASK mask; /* Access mask associated with the ACE. */ + +/* 8*/ SID sid; /* The SID associated with the ACE. */ } __attribute__ ((__packed__)) ACCESS_ALLOWED_ACE, ACCESS_DENIED_ACE, SYSTEM_AUDIT_ACE, SYSTEM_ALARM_ACE; -#define _AAH(X) SC(aah,X) /* * The object ACE flags (32-bit). @@ -1462,12 +1460,17 @@ typedef enum { } OBJECT_ACE_FLAGS; typedef struct { - ACE_HEADER SN(aah); /* The ACE_HEADER. */ - ACCESS_MASK mask; /* Access mask associated with the ACE. */ - OBJECT_ACE_FLAGS flags; /* Flags describing the object ACE. */ - GUID object_type; - GUID inherited_object_type; - SID sid; /* The SID associated with the ACE. */ +/* 0 ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */ + ACE_TYPES type; /* Type of the ACE. */ + ACE_FLAGS flags; /* Flags describing the ACE. */ + u16 size; /* Size in bytes of the ACE. */ +/* 4*/ ACCESS_MASK mask; /* Access mask associated with the ACE. */ + +/* 8*/ OBJECT_ACE_FLAGS object_flags; /* Flags describing the object ACE. */ +/* 12*/ GUID object_type; +/* 28*/ GUID inherited_object_type; + +/* 44*/ SID sid; /* The SID associated with the ACE. */ } __attribute__ ((__packed__)) ACCESS_ALLOWED_OBJECT_ACE, ACCESS_DENIED_OBJECT_ACE, SYSTEM_AUDIT_OBJECT_ACE, @@ -1711,13 +1714,17 @@ typedef struct { * $SDS data stream and the second copy will be at offset 0x451d0. */ typedef struct { - SECURITY_DESCRIPTOR_HEADER SN(sdh); /* The security descriptor header. */ - SECURITY_DESCRIPTOR_RELATIVE sid; /* The self-relative security +/*Ofs*/ +/* 0 SECURITY_DESCRIPTOR_HEADER; -- Unfolded here as gcc doesn't like + unnamed structs. */ + u32 hash; /* Hash of the security descriptor. */ + u32 security_id; /* The security_id assigned to the descriptor. */ + u64 offset; /* Byte offset of this entry in the $SDS stream. */ + u32 length; /* Size in bytes of this entry in $SDS stream. */ +/* 20*/ SECURITY_DESCRIPTOR_RELATIVE sid; /* The self-relative security descriptor. */ } __attribute__ ((__packed__)) SDS_ENTRY; -#define _SDH(X) SC(sdh,X) - /* * The index entry key used in the $SII index. The collation type is * COLLATION_NTOFS_ULONG. @@ -1888,7 +1895,11 @@ typedef struct { * index entries (INDEX_ENTRY structures), as described by the INDEX_HEADER. */ typedef struct { -/* 0*/ NTFS_RECORD SN(inr); /* Magic is "INDX". */ +/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ + NTFS_RECORD_TYPES magic;/* Magic is "INDX". */ + u16 usa_ofs; /* See NTFS_RECORD definition. */ + u16 usa_count; /* See NTFS_RECORD definition. */ + /* 8*/ s64 lsn; /* $LogFile sequence number of the last modification of this index block. */ /* 16*/ VCN index_block_vcn; /* Virtual cluster number of the index block. @@ -1909,8 +1920,6 @@ typedef struct { */ } __attribute__ ((__packed__)) INDEX_BLOCK; -#define _INR(X) SC(inr,X) - typedef INDEX_BLOCK INDEX_ALLOCATION; /* @@ -2014,19 +2023,21 @@ typedef enum { * This the index entry header (see below). */ typedef struct { -/* 0*/ union { /* Only valid when INDEX_ENTRY_END is not set. */ - MFT_REF indexed_file; /* The mft reference of the file +/* 0*/ union { + struct { /* Only valid when INDEX_ENTRY_END is not set. */ + MFT_REF indexed_file; /* The mft reference of the file described by this index entry. Used for directory indexes. */ + } __attribute__ ((__packed__)) dir; struct { /* Used for views/indexes to find the entry's data. */ u16 data_offset; /* Data byte offset from this INDEX_ENTRY. Follows the index key. */ u16 data_length; /* Data length in bytes. */ u32 reservedV; /* Reserved (zero). */ - } SN(iev) __attribute__ ((__packed__)); - } SN(iif) __attribute__ ((__packed__)); + } __attribute__ ((__packed__)) vi; + } __attribute__ ((__packed__)) data; /* 8*/ u16 length; /* Byte size of this index entry, multiple of 8-bytes. */ /* 10*/ u16 key_length; /* Byte size of the key value, which is in the @@ -2037,9 +2048,6 @@ typedef struct { /* sizeof() = 16 bytes */ } __attribute__ ((__packed__)) INDEX_ENTRY_HEADER; -#define _IIF(X) SC(ieh.iif,X) -#define _IEV(X) SC(iif.iev,X) - /* * This is an index entry. A sequence of such entries follows each INDEX_HEADER * structure. Together they make up a complete index. The index follows either @@ -2048,7 +2056,31 @@ typedef struct { * NOTE: Before NTFS 3.0 only filename attributes were indexed. */ typedef struct { -/* 0*/ INDEX_ENTRY_HEADER SN(ieh); /* The index entry header (see above). */ +/*Ofs*/ +/* 0 INDEX_ENTRY_HEADER; -- Unfolded here as gcc dislikes unnamed structs. */ + union { + struct { /* Only valid when INDEX_ENTRY_END is not set. */ + MFT_REF indexed_file; /* The mft reference of the file + described by this index + entry. Used for directory + indexes. */ + } __attribute__ ((__packed__)) dir; + struct { /* Used for views/indexes to find the entry's data. */ + u16 data_offset; /* Data byte offset from this + INDEX_ENTRY. Follows the + index key. */ + u16 data_length; /* Data length in bytes. */ + u32 reservedV; /* Reserved (zero). */ + } __attribute__ ((__packed__)) vi; + } __attribute__ ((__packed__)) data; + u16 length; /* Byte size of this index entry, multiple of + 8-bytes. */ + u16 key_length; /* Byte size of the key value, which is in the + index entry. It follows field reserved. Not + multiple of 8-bytes. */ + INDEX_ENTRY_FLAGS flags; /* Bit field of INDEX_ENTRY_* flags. */ + u16 reserved; /* Reserved/align to 8-byte boundary. */ + /* 16*/ union { /* The key of the indexed attribute. NOTE: Only present if INDEX_ENTRY_END bit in flags is not set. NOTE: On NTFS versions before 3.0 the only valid key is the @@ -2060,7 +2092,8 @@ typedef struct { GUID object_id; /* $O index in FILE_Extend/$ObjId: The object_id of the mft record found in the data part of the index. */ - REPARSE_INDEX_KEY SN(iri); /* $R index in FILE_Extend/$Reparse. */ + REPARSE_INDEX_KEY reparse; /* $R index in + FILE_Extend/$Reparse. */ SID sid; /* $O index in FILE_Extend/$Quota: SID of the owner of the user_id. */ u32 owner_id; /* $Q index in FILE_Extend/$Quota: @@ -2083,9 +2116,6 @@ typedef struct { // where sizeof(VCN) can be hardcoded as 8 if wanted. */ } __attribute__ ((__packed__)) INDEX_ENTRY; -#define _IEH(X) SC(ieh,X) -#define _IRI(X) SC(key.iri,X) - /* * Attribute: Bitmap (0xb0). * diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 95f3cb04112f..ed793fbc5b3f 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -1,8 +1,8 @@ /** * mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project. * - * Copyright (c) 2001,2002 Anton Altaparmakov. - * Copyright (c) 2002 Richard Russon. + * Copyright (c) 2001-2003 Anton Altaparmakov + * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -39,18 +39,18 @@ static void __format_mft_record(MFT_RECORD *m, const int size, ATTR_RECORD *a; memset(m, 0, size); - m->_MNR(magic) = magic_FILE; + m->magic = magic_FILE; /* Aligned to 2-byte boundary. */ - m->_MNR(usa_ofs) = cpu_to_le16((sizeof(MFT_RECORD) + 1) & ~1); - m->_MNR(usa_count) = cpu_to_le16(size / NTFS_BLOCK_SIZE + 1); + m->usa_ofs = cpu_to_le16((sizeof(MFT_RECORD) + 1) & ~1); + m->usa_count = cpu_to_le16(size / NTFS_BLOCK_SIZE + 1); /* Set the update sequence number to 1. */ *(u16*)((char*)m + ((sizeof(MFT_RECORD) + 1) & ~1)) = cpu_to_le16(1); m->lsn = cpu_to_le64(0LL); m->sequence_number = cpu_to_le16(1); m->link_count = cpu_to_le16(0); /* Aligned to 8-byte boundary. */ - m->attrs_offset = cpu_to_le16((le16_to_cpu(m->_MNR(usa_ofs)) + - (le16_to_cpu(m->_MNR(usa_count)) << 1) + 7) & ~7); + m->attrs_offset = cpu_to_le16((le16_to_cpu(m->usa_ofs) + + (le16_to_cpu(m->usa_count) << 1) + 7) & ~7); m->flags = cpu_to_le16(0); /* * Using attrs_offset plus eight bytes (for the termination attribute), @@ -329,7 +329,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref, */ down(&base_ni->extent_lock); if (base_ni->nr_extents > 0) { - extent_nis = base_ni->_INE(extent_ntfs_inos); + extent_nis = base_ni->ext.extent_ntfs_inos; for (i = 0; i < base_ni->nr_extents; i++) { if (mft_no != extent_nis[i]->mft_no) continue; @@ -374,7 +374,7 @@ map_err_out: ni->vol = base_ni->vol; ni->seq_no = seq_no; ni->nr_extents = -1; - ni->_INE(base_ntfs_ino) = base_ni; + ni->ext.base_ntfs_ino = base_ni; /* Now map the record. */ m = map_mft_record(ni); if (unlikely(IS_ERR(m))) { @@ -404,14 +404,14 @@ map_err_out: m = ERR_PTR(-ENOMEM); goto unm_err_out; } - if (base_ni->_INE(extent_ntfs_inos)) { - memcpy(tmp, base_ni->_INE(extent_ntfs_inos), new_size - + if (base_ni->ext.extent_ntfs_inos) { + memcpy(tmp, base_ni->ext.extent_ntfs_inos, new_size - 4 * sizeof(ntfs_inode *)); - kfree(base_ni->_INE(extent_ntfs_inos)); + kfree(base_ni->ext.extent_ntfs_inos); } - base_ni->_INE(extent_ntfs_inos) = tmp; + base_ni->ext.extent_ntfs_inos = tmp; } - base_ni->_INE(extent_ntfs_inos)[base_ni->nr_extents++] = ni; + base_ni->ext.extent_ntfs_inos[base_ni->nr_extents++] = ni; up(&base_ni->extent_lock); atomic_dec(&base_ni->count); ntfs_debug("Done 2."); diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index a08ab2c9da5a..84d43247ba6e 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c @@ -2,7 +2,7 @@ * namei.c - NTFS kernel directory inode operations. Part of the Linux-NTFS * project. * - * Copyright (c) 2001,2002 Anton Altaparmakov. + * Copyright (c) 2001-2003 Anton Altaparmakov * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -210,12 +210,12 @@ handle_name: a = ctx->attr; if (a->non_resident || a->flags) goto eio_err_out; - val_len = le32_to_cpu(a->_ARA(value_length)); - if (le16_to_cpu(a->_ARA(value_offset)) + val_len > - le32_to_cpu(a->length)) + val_len = le32_to_cpu(a->data.resident.value_length); + if (le16_to_cpu(a->data.resident.value_offset) + + val_len > le32_to_cpu(a->length)) goto eio_err_out; fn = (FILE_NAME_ATTR*)((u8*)ctx->attr + le16_to_cpu( - ctx->attr->_ARA(value_offset))); + ctx->attr->data.resident.value_offset)); if ((u32)(fn->file_name_length * sizeof(uchar_t) + sizeof(FILE_NAME_ATTR)) > val_len) goto eio_err_out; diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 5361198e1b80..cb3aeea03410 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -1,8 +1,8 @@ /* * super.c - NTFS kernel super block handling. Part of the Linux-NTFS project. * - * Copyright (c) 2001,2002 Anton Altaparmakov. - * Copyright (c) 2001,2002 Richard Russon. + * Copyright (c) 2001-2003 Anton Altaparmakov + * Copyright (c) 2001,2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -619,9 +619,8 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b) * the same as it is much faster on 32-bit CPUs. */ ll = sle64_to_cpu(b->number_of_sectors) >> sectors_per_cluster_bits; - if ((u64)ll >= 1ULL << (sizeof(unsigned long) * 8)) { - ntfs_error(vol->sb, "Cannot handle %i-bit clusters. Sorry.", - sizeof(unsigned long) * 4); + if ((u64)ll >= 1ULL << 32) { + ntfs_error(vol->sb, "Cannot handle 64-bit clusters. Sorry."); return FALSE; } vol->nr_clusters = ll; @@ -884,10 +883,10 @@ get_ctx_vol_failed: goto iput_volume_failed; } vi = (VOLUME_INFORMATION*)((char*)ctx->attr + - le16_to_cpu(ctx->attr->_ARA(value_offset))); + le16_to_cpu(ctx->attr->data.resident.value_offset)); /* Some bounds checks. */ if ((u8*)vi < (u8*)ctx->attr || (u8*)vi + - le32_to_cpu(ctx->attr->_ARA(value_length)) > + le32_to_cpu(ctx->attr->data.resident.value_length) > (u8*)ctx->attr + le32_to_cpu(ctx->attr->length)) goto err_put_vol; /* Setup volume flags and version. */ @@ -1060,78 +1059,93 @@ static void ntfs_put_super(struct super_block *vfs_sb) * get_nr_free_clusters - return the number of free clusters on a volume * @vol: ntfs volume for which to obtain free cluster count * - * Calculate the number of free clusters on the mounted NTFS volume @vol. + * Calculate the number of free clusters on the mounted NTFS volume @vol. We + * actually calculate the number of clusters in use instead because this + * allows us to not care about partial pages as these will be just zero filled + * and hence not be counted as allocated clusters. * - * Errors are ignored and we just return the number of free clusters we have - * found. This means we return an underestimate on error. + * The only particularity is that clusters beyond the end of the logical ntfs + * volume will be marked as allocated to prevent errors which means we have to + * discount those at the end. This is important as the cluster bitmap always + * has a size in multiples of 8 bytes, i.e. up to 63 clusters could be outside + * the logical volume and marked in use when they are not as they do not exist. + * + * If any pages cannot be read we assume all clusters in the erroring pages are + * in use. This means we return an underestimate on errors which is better than + * an overestimate. */ static s64 get_nr_free_clusters(ntfs_volume *vol) { + s64 nr_free = vol->nr_clusters; + u32 *kaddr; struct address_space *mapping = vol->lcnbmp_ino->i_mapping; filler_t *readpage = (filler_t*)mapping->a_ops->readpage; struct page *page; unsigned long index, max_index; - unsigned int max_size, i; - s64 nr_free = 0LL; - u32 *b; + unsigned int max_size; ntfs_debug("Entering."); /* Serialize accesses to the cluster bitmap. */ down_read(&vol->lcnbmp_lock); /* * Convert the number of bits into bytes rounded up, then convert into - * multiples of PAGE_CACHE_SIZE. + * multiples of PAGE_CACHE_SIZE, rounding up so that if we have one + * full and one partial page max_index = 2. */ - max_index = (vol->nr_clusters + 7) >> (3 + PAGE_CACHE_SHIFT); + max_index = (((vol->nr_clusters + 7) >> 3) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT; /* Use multiples of 4 bytes. */ max_size = PAGE_CACHE_SIZE >> 2; - ntfs_debug("Reading $BITMAP, max_index = 0x%lx, max_size = 0x%x.", + ntfs_debug("Reading $Bitmap, max_index = 0x%lx, max_size = 0x%x.", max_index, max_size); - for (index = 0UL; index < max_index;) { -handle_partial_page: + for (index = 0UL; index < max_index; index++) { + unsigned int i; /* * Read the page from page cache, getting it from backing store * if necessary, and increment the use count. */ - page = read_cache_page(mapping, index++, (filler_t*)readpage, + page = read_cache_page(mapping, index, (filler_t*)readpage, NULL); /* Ignore pages which errored synchronously. */ if (IS_ERR(page)) { ntfs_debug("Sync read_cache_page() error. Skipping " - "page (index 0x%lx).", index - 1); + "page (index 0x%lx).", index); + nr_free -= PAGE_CACHE_SIZE * 8; continue; } wait_on_page_locked(page); + /* Ignore pages which errored asynchronously. */ if (!PageUptodate(page)) { ntfs_debug("Async read_cache_page() error. Skipping " - "page (index 0x%lx).", index - 1); - /* Ignore pages which errored asynchronously. */ + "page (index 0x%lx).", index); page_cache_release(page); + nr_free -= PAGE_CACHE_SIZE * 8; continue; } - b = (u32*)kmap(page); - /* For each 4 bytes, add up the number zero bits. */ - for (i = 0; i < max_size; i++) - nr_free += (s64)(32 - hweight32(b[i])); - kunmap(page); - page_cache_release(page); - } - if (max_size == PAGE_CACHE_SIZE >> 2) { + kaddr = (u32*)kmap_atomic(page, KM_USER0); /* - * Get the multiples of 4 bytes in use in the final partial - * page. + * For each 4 bytes, subtract the number of set bits. If this + * is the last page and it is partial we don't really care as + * it just means we do a little extra work but it won't affect + * the result as all out of range bytes are set to zero by + * ntfs_readpage(). */ - max_size = ((((vol->nr_clusters + 7) >> 3) & ~PAGE_CACHE_MASK) - + 3) >> 2; - /* If there is a partial page go back and do it. */ - if (max_size) { - ntfs_debug("Handling partial page, max_size = 0x%x.", - max_size); - goto handle_partial_page; - } + for (i = 0; i < max_size; i++) + nr_free -= (s64)hweight32(kaddr[i]); + kunmap_atomic(kaddr, KM_USER0); + page_cache_release(page); } - ntfs_debug("Finished reading $BITMAP, last index = 0x%lx", index - 1); + ntfs_debug("Finished reading $Bitmap, last index = 0x%lx.", index - 1); + /* + * Fixup for eventual bits outside logical ntfs volume (see function + * description above). + */ + if (vol->nr_clusters & 63) + nr_free += 64 - (vol->nr_clusters & 63); up_read(&vol->lcnbmp_lock); + /* If errors occured we may well have gone below zero, fix this. */ + if (nr_free < 0) + nr_free = 0; ntfs_debug("Exiting."); return nr_free; } @@ -1141,64 +1155,81 @@ handle_partial_page: * @vol: ntfs volume for which to obtain free inode count * * Calculate the number of free mft records (inodes) on the mounted NTFS - * volume @vol. + * volume @vol. We actually calculate the number of mft records in use instead + * because this allows us to not care about partial pages as these will be just + * zero filled and hence not be counted as allocated mft record. * - * Errors are ignored and we just return the number of free inodes we have - * found. This means we return an underestimate on error. + * If any pages cannot be read we assume all mft records in the erroring pages + * are in use. This means we return an underestimate on errors which is better + * than an overestimate. * * NOTE: Caller must hold mftbmp_lock rw_semaphore for reading or writing. */ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol) { - struct address_space *mapping; + s64 nr_free = vol->nr_mft_records; + u32 *kaddr; + struct address_space *mapping = vol->mftbmp_ino->i_mapping; + filler_t *readpage = (filler_t*)mapping->a_ops->readpage; struct page *page; - unsigned long index, max_index, nr_free = 0; - unsigned int max_size, i; - u32 *b; + unsigned long index, max_index; + unsigned int max_size; - mapping = vol->mftbmp_ino->i_mapping; + ntfs_debug("Entering."); /* - * Convert the number of bits into bytes rounded up to a multiple of 8 - * bytes, then convert into multiples of PAGE_CACHE_SIZE. + * Convert the number of bits into bytes rounded up, then convert into + * multiples of PAGE_CACHE_SIZE, rounding up so that if we have one + * full and one partial page max_index = 2. */ - max_index = (((vol->nr_mft_records + 7) >> 3) + 7) >> PAGE_CACHE_SHIFT; + max_index = (((vol->nr_mft_records + 7) >> 3) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT; /* Use multiples of 4 bytes. */ max_size = PAGE_CACHE_SIZE >> 2; ntfs_debug("Reading $MFT/$BITMAP, max_index = 0x%lx, max_size = " "0x%x.", max_index, max_size); - for (index = 0UL; index < max_index;) { -handle_partial_page: - page = ntfs_map_page(mapping, index++); + for (index = 0UL; index < max_index; index++) { + unsigned int i; + /* + * Read the page from page cache, getting it from backing store + * if necessary, and increment the use count. + */ + page = read_cache_page(mapping, index, (filler_t*)readpage, + NULL); + /* Ignore pages which errored synchronously. */ if (IS_ERR(page)) { - ntfs_debug("ntfs_map_page() error. Skipping page " - "(index 0x%lx).", index - 1); + ntfs_debug("Sync read_cache_page() error. Skipping " + "page (index 0x%lx).", index); + nr_free -= PAGE_CACHE_SIZE * 8; continue; } - b = (u32*)page_address(page); - /* For each 4 bytes, add up the number of zero bits. */ - for (i = 0; i < max_size; i++) - nr_free += 32 - hweight32(b[i]); - ntfs_unmap_page(page); - } - if (index == max_index) { + wait_on_page_locked(page); + /* Ignore pages which errored asynchronously. */ + if (!PageUptodate(page)) { + ntfs_debug("Async read_cache_page() error. Skipping " + "page (index 0x%lx).", index); + page_cache_release(page); + nr_free -= PAGE_CACHE_SIZE * 8; + continue; + } + kaddr = (u32*)kmap_atomic(page, KM_USER0); /* - * Get the multiples of 4 bytes in use in the final partial - * page. + * For each 4 bytes, subtract the number of set bits. If this + * is the last page and it is partial we don't really care as + * it just means we do a little extra work but it won't affect + * the result as all out of range bytes are set to zero by + * ntfs_readpage(). */ - max_size = ((((((vol->nr_mft_records + 7) >> 3) + 7) & ~7) & - ~PAGE_CACHE_MASK) + 3) >> 2; - /* If there is a partial page go back and do it. */ - if (max_size) { - /* Compensate for out of bounds zero bits. */ - if ((i = vol->nr_mft_records & 31)) - nr_free -= 32 - i; - ntfs_debug("Handling partial page, max_size = 0x%x", - max_size); - goto handle_partial_page; - } + for (i = 0; i < max_size; i++) + nr_free -= (s64)hweight32(kaddr[i]); + kunmap_atomic(kaddr, KM_USER0); + page_cache_release(page); } - ntfs_debug("Finished reading $MFT/$BITMAP, last index = 0x%lx", + ntfs_debug("Finished reading $MFT/$BITMAP, last index = 0x%lx.", index - 1); + /* If errors occured we may well have gone below zero, fix this. */ + if (nr_free < 0) + nr_free = 0; + ntfs_debug("Exiting."); return nr_free; } @@ -1761,7 +1792,7 @@ static void __exit exit_ntfs_fs(void) } MODULE_AUTHOR("Anton Altaparmakov <aia21@cantab.net>"); -MODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2002 Anton Altaparmakov"); +MODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2003 Anton Altaparmakov"); MODULE_LICENSE("GPL"); #ifdef DEBUG MODULE_PARM(debug_msgs, "i"); diff --git a/fs/ntfs/unistr.c b/fs/ntfs/unistr.c index b6333efea6d5..ab999db047fe 100644 --- a/fs/ntfs/unistr.c +++ b/fs/ntfs/unistr.c @@ -1,7 +1,7 @@ /* * unistr.c - NTFS Unicode string handling. Part of the Linux-NTFS project. * - * Copyright (c) 2001 Anton Altaparmakov. + * Copyright (c) 2001-2003 Anton Altaparmakov * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -96,10 +96,12 @@ int ntfs_collate_names(const uchar_t *name1, const u32 name1_len, const int err_val, const IGNORE_CASE_BOOL ic, const uchar_t *upcase, const u32 upcase_len) { - u32 cnt; - const u32 min_len = min_t(const u32, name1_len, name2_len); + u32 cnt, min_len; uchar_t c1, c2; + min_len = name1_len; + if (name1_len > name2_len) + min_len = name2_len; for (cnt = 0; cnt < min_len; ++cnt) { c1 = le16_to_cpu(*name1++); c2 = le16_to_cpu(*name2++); diff --git a/fs/ntfs/upcase.c b/fs/ntfs/upcase.c index 17f4a64c70b7..44789837eede 100644 --- a/fs/ntfs/upcase.c +++ b/fs/ntfs/upcase.c @@ -2,8 +2,8 @@ * upcase.c - Generate the full NTFS Unicode upcase table in little endian. * Part of the Linux-NTFS project. * - * Copyright (C) 2001 Richard Russon <ntfs@flatcap.org> - * Copyright (c) 2001,2002 Anton Altaparmakov + * Copyright (c) 2001 Richard Russon <ntfs@flatcap.org> + * Copyright (c) 2001-2003 Anton Altaparmakov * * Modified for mkntfs inclusion 9 June 2001 by Anton Altaparmakov. * Modified for kernel inclusion 10 September 2001 by Anton Altparmakov. @@ -28,7 +28,7 @@ uchar_t *generate_default_upcase(void) { - const int uc_run_table[][3] = { /* Start, End, Add */ + static const int uc_run_table[][3] = { /* Start, End, Add */ {0x0061, 0x007B, -32}, {0x0451, 0x045D, -80}, {0x1F70, 0x1F72, 74}, {0x00E0, 0x00F7, -32}, {0x045E, 0x0460, -80}, {0x1F72, 0x1F76, 86}, {0x00F8, 0x00FF, -32}, {0x0561, 0x0587, -48}, {0x1F76, 0x1F78, 100}, @@ -45,7 +45,7 @@ uchar_t *generate_default_upcase(void) {0} }; - const int uc_dup_table[][2] = { /* Start, End */ + static const int uc_dup_table[][2] = { /* Start, End */ {0x0100, 0x012F}, {0x01A0, 0x01A6}, {0x03E2, 0x03EF}, {0x04CB, 0x04CC}, {0x0132, 0x0137}, {0x01B3, 0x01B7}, {0x0460, 0x0481}, {0x04D0, 0x04EB}, {0x0139, 0x0149}, {0x01CD, 0x01DD}, {0x0490, 0x04BF}, {0x04EE, 0x04F5}, @@ -55,7 +55,7 @@ uchar_t *generate_default_upcase(void) {0} }; - const int uc_word_table[][2] = { /* Offset, Value */ + static const int uc_word_table[][2] = { /* Offset, Value */ {0x00FF, 0x0178}, {0x01AD, 0x01AC}, {0x01F3, 0x01F1}, {0x0269, 0x0196}, {0x0183, 0x0182}, {0x01B0, 0x01AF}, {0x0253, 0x0181}, {0x026F, 0x019C}, {0x0185, 0x0184}, {0x01B9, 0x01B8}, {0x0254, 0x0186}, {0x0272, 0x019D}, |
