http://linux-ntfs.bkbits.net/ntfs-2.6 aia21@cantab.net|ChangeSet|20040428101909|56086 aia21 # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/04/28 10:14:05+01:00 aia21@cantab.net # NTFS: - Fix compiler warnings related to type casting. # - Move %L to %ll as %L is floating point and %ll is integer which # is what we want. # - Add logfile inode to ntfs_volume structure and the code to clean # it up in super.c. # # fs/ntfs/volume.h # 2004/04/28 10:13:59+01:00 aia21@cantab.net +2 -0 # Add the logfile inode to the ntfs_volume structure. # # fs/ntfs/super.c # 2004/04/28 10:13:59+01:00 aia21@cantab.net +27 -16 # - Move %L to %ll as %L is floating point and %ll is integer which is what we want. # - Fix compiler warnings related to type casting. # - Add cleaning up of logfile inode. # # fs/ntfs/ntfs.h # 2004/04/28 10:13:59+01:00 aia21@cantab.net +4 -1 # Add n2p() macro to convert values to pointers. # # fs/ntfs/inode.c # 2004/04/28 10:13:58+01:00 aia21@cantab.net +5 -5 # Move %L to %ll as %L is floating point and %ll is integer which is what we want. # # fs/ntfs/dir.c # 2004/04/28 10:13:58+01:00 aia21@cantab.net +51 -47 # Move %L to %ll as %L is floating point and %ll is integer which is what we want. # # fs/ntfs/compress.c # 2004/04/28 10:13:58+01:00 aia21@cantab.net +3 -2 # Move %L to %ll as %L is floating point and %ll is integer which is what we want. # # fs/ntfs/attrib.c # 2004/04/28 10:13:58+01:00 aia21@cantab.net +20 -19 # Move %L to %ll as %L is floating point and %ll is integer which is what we want. # # fs/ntfs/aops.c # 2004/04/28 10:13:58+01:00 aia21@cantab.net +26 -20 # Move %L to %ll as %L is floating point and %ll is integer which is what we want. # # fs/ntfs/ChangeLog # 2004/04/28 10:13:58+01:00 aia21@cantab.net +4 -0 # Update ChangeLog. # # ChangeSet # 2004/04/27 12:27:16+01:00 aia21@cantab.net # NTFS: Load the mft mirror at mount time and compare the mft records # stored in it to the ones in the mft (fs/ntfs/super.c). # # fs/ntfs/volume.h # 2004/04/27 12:27:11+01:00 aia21@cantab.net +3 -1 # Wrap mftmirr_ino and mftmirr_size in #ifdef NTFS_RW. # # fs/ntfs/super.c # 2004/04/27 12:27:11+01:00 aia21@cantab.net +214 -24 # Load the mft mirror at mount time and compare the mft records stored # in it to the ones in the mft (fs/ntfs/super.c). # # fs/ntfs/ChangeLog # 2004/04/27 10:38:02+01:00 aia21@cantab.net +2 -0 # Update. # # Documentation/filesystems/ntfs.txt # 2004/04/27 10:38:02+01:00 aia21@cantab.net +1 -0 # Update. # # fs/ntfs/volume.h # 2004/04/25 22:12:35+01:00 aia21@cantab.net +1 -1 # Minor comment update. # # ChangeSet # 2004/04/25 22:04:57+01:00 aia21@cantab.net # NTFS: Determine the mft mirror size as the number of mirrored mft records # and store it in ntfs_volume->mftmirr_size (fs/ntfs/super.c). # # fs/ntfs/volume.h # 2004/04/25 22:03:23+01:00 aia21@cantab.net +10 -6 # Add mftmirr_size to ntfs_volume structure. # # fs/ntfs/super.c # 2004/04/25 22:02:54+01:00 aia21@cantab.net +16 -2 # Determine the mft mirror size as the number of mirrored mft records # and store it in ntfs_volume->mftmirr_size. # # fs/ntfs/ChangeLog # 2004/04/25 22:02:49+01:00 aia21@cantab.net +2 -0 # Update # # fs/ntfs/mft.h # 2004/04/25 15:26:00+01:00 aia21@cantab.net +1 -1 # Update comment. # # ChangeSet # 2004/04/25 15:22:09+01:00 aia21@cantab.net # NTFS: Move typedefs for ntfs_attr and test_t from fs/ntfs/inode.c to # fs/ntfs/inode.h so they can be used elsewhere. # # fs/ntfs/inode.h # 2004/04/25 15:21:15+01:00 aia21@cantab.net +24 -0 # Move typedefs for ntfs_attr and test_t to fs/ntfs/inode.h so # they can be used elsewhere. # # fs/ntfs/inode.c # 2004/04/25 15:20:07+01:00 aia21@cantab.net +1 -22 # Move typedefs for ntfs_attr and test_t to fs/ntfs/inode.h so # they can be used elsewhere. # # fs/ntfs/ChangeLog # 2004/04/25 15:20:02+01:00 aia21@cantab.net +2 -0 # Update # # ChangeSet # 2004/04/25 15:11:52+01:00 aia21@cantab.net # NTFS: Add NInoTestSetFoo() and NInoTestClearFoo() macro magic to # fs/ntfs/inode.h and use it to declare NInoTest{Set,Clear}Dirty. # # fs/ntfs/inode.h # 2004/04/25 15:10:49+01:00 aia21@cantab.net +16 -2 # Add NInoTestSetFoo() and NInoTestClearFoo() macro magic and # use it to declare NInoTest{Set,Clear}Dirty. # # fs/ntfs/ChangeLog # 2004/04/25 15:10:46+01:00 aia21@cantab.net +2 -0 # Update # # ChangeSet # 2004/04/25 15:03:50+01:00 aia21@cantab.net # NTFS: Wrap flush_dcache_mft_record_page() in #ifdef NTFS_RW. # # fs/ntfs/mft.h # 2004/04/25 15:02:57+01:00 aia21@cantab.net +8 -5 # Wrap flush_dcache_mft_record_page() in #ifdef NTFS_RW and cleanup trailing whitespace. # # fs/ntfs/ChangeLog # 2004/04/25 15:02:53+01:00 aia21@cantab.net +1 -0 # Update # # ChangeSet # 2004/04/25 14:42:00+01:00 aia21@cantab.net # NTFS: - Remove unused ntfs_dirty_inode(). # - Cleanup super operations declaration. # # fs/ntfs/super.c # 2004/04/25 14:39:59+01:00 aia21@cantab.net +44 -32 # Cleanup super operations declaration and trailing whitespace. # # fs/ntfs/inode.h # 2004/04/25 14:39:47+01:00 aia21@cantab.net +4 -7 # Remove unused ntfs_dirty_inode() and cleanup trailing whitespace. # # fs/ntfs/inode.c # 2004/04/25 14:38:51+01:00 aia21@cantab.net +1 -34 # Remove unused ntfs_dirty_inode() and cleanup trailing whitespace. # # fs/ntfs/ChangeLog # 2004/04/25 14:38:47+01:00 aia21@cantab.net +3 -1 # Update # # ChangeSet # 2004/04/24 22:52:18+01:00 aia21@cantab.net # NTFS: - Modify fs/ntfs/time.c::ntfs2utc(), get_current_ntfs_time(), and # utc2ntfs() to work with struct timespec instead of time_t on the # Linux UTC time side thus preserving the full precision of the NTFS # time and only loosing up to 99 nano-seconds in the Linux UTC time. # - Move fs/ntfs/time.c to fs/ntfs/time.h and make the time functions # static inline. # # fs/ntfs/time.h # 2004/04/24 22:50:07+01:00 aia21@cantab.net +47 -29 # - Modify fs/ntfs/time.c::ntfs2utc(), get_current_ntfs_time(), and # utc2ntfs() to work with struct timespec instead of time_t on the # Linux UTC time side thus preserving the full precision of the NTFS # time and only loosing up to 99 nano-seconds in the Linux UTC time. # - Move fs/ntfs/time.c to fs/ntfs/time.h and make the time functions # static inline. # # fs/ntfs/ntfs.h # 2004/04/24 22:49:50+01:00 aia21@cantab.net +1 -6 # Remove declarations for ntfs time conversion functions. # # fs/ntfs/inode.c # 2004/04/24 22:49:25+01:00 aia21@cantab.net +7 -10 # Update for new ntfs time conversion functions. # # fs/ntfs/Makefile # 2004/04/24 22:49:09+01:00 aia21@cantab.net +1 -1 # Remove time.c from build as it no longer exists. # # fs/ntfs/ChangeLog # 2004/04/24 22:49:05+01:00 aia21@cantab.net +6 -0 # Update # # fs/ntfs/time.h # 2004/04/24 22:45:59+01:00 aia21@cantab.net +0 -0 # Rename: fs/ntfs/time.c -> fs/ntfs/time.h # # ChangeSet # 2004/04/24 22:32:35+01:00 aia21@cantab.net # NTFS: Use get_bh() instead of manual atomic_inc() in fs/ntfs/compress.c. # # fs/ntfs/compress.c # 2004/04/24 22:28:50+01:00 aia21@cantab.net +6 -7 # Use get_bh() instead of manual atomic_inc() in fs/ntfs/compress.c. Also a few white space cleanups (space at EOL and such like). # # fs/ntfs/Makefile # 2004/04/24 22:28:40+01:00 aia21@cantab.net +1 -1 # Update version to 2.1.8-WIP. # # fs/ntfs/ChangeLog # 2004/04/24 22:28:35+01:00 aia21@cantab.net +4 -0 # Update # diff -Nru a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt --- a/Documentation/filesystems/ntfs.txt Thu Apr 29 23:19:49 2004 +++ b/Documentation/filesystems/ntfs.txt Thu Apr 29 23:19:49 2004 @@ -71,6 +71,7 @@ compatibility, we implement access to files using their short file names if they exist. The driver will not create short file names however, and a rename will discard any existing short file name. +- The new driver supports exporting of mounted NTFS volumes via NFS. Supported mount options diff -Nru a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog --- a/fs/ntfs/ChangeLog Thu Apr 29 23:19:49 2004 +++ b/fs/ntfs/ChangeLog Thu Apr 29 23:19:49 2004 @@ -19,6 +19,31 @@ sufficient for synchronisation here. We then just need to make sure ntfs_readpage/writepage/truncate interoperate properly with us. +2.1.8-WIP + + - Use get_bh() instead of manual atomic_inc() in fs/ntfs/compress.c. + - Modify fs/ntfs/time.c::ntfs2utc(), get_current_ntfs_time(), and + utc2ntfs() to work with struct timespec instead of time_t on the + Linux UTC time side thus preserving the full precision of the NTFS + time and only loosing up to 99 nano-seconds in the Linux UTC time. + - Move fs/ntfs/time.c to fs/ntfs/time.h and make the time functions + static inline. + - Remove unused ntfs_dirty_inode(). + - Cleanup super operations declaration in fs/ntfs/super.c. + - Wrap flush_dcache_mft_record_page() in #ifdef NTFS_RW. + - Add NInoTestSetFoo() and NInoTestClearFoo() macro magic to + fs/ntfs/inode.h and use it to declare NInoTest{Set,Clear}Dirty. + - Move typedefs for ntfs_attr and test_t from fs/ntfs/inode.c to + fs/ntfs/inode.h so they can be used elsewhere. + - Determine the mft mirror size as the number of mirrored mft records + and store it in ntfs_volume->mftmirr_size (fs/ntfs/super.c). + - Load the mft mirror at mount time and compare the mft records stored + in it to the ones in the mft (fs/ntfs/super.c). + - Fix type casting related warnings on 64-bit architectures. Thanks + to Meelis Roos for reporting them. + - Move %L to %ll as %L is floating point and %ll is integer which is + what we want. + 2.1.7 - Enable NFS exporting of mounted NTFS volumes. - Set i_generation in the VFS inode from the seq_no of the NTFS inode. diff -Nru a/fs/ntfs/Makefile b/fs/ntfs/Makefile --- a/fs/ntfs/Makefile Thu Apr 29 23:19:49 2004 +++ b/fs/ntfs/Makefile Thu Apr 29 23:19:49 2004 @@ -3,9 +3,9 @@ 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 + mst.o namei.o super.o sysctl.o unistr.o upcase.o -EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.7\" +EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.8-WIP\" ifeq ($(CONFIG_NTFS_DEBUG),y) EXTRA_CFLAGS += -DDEBUG diff -Nru a/fs/ntfs/aops.c b/fs/ntfs/aops.c --- a/fs/ntfs/aops.c Thu Apr 29 23:19:49 2004 +++ b/fs/ntfs/aops.c Thu Apr 29 23:19:49 2004 @@ -77,7 +77,7 @@ } } else { clear_buffer_uptodate(bh); - ntfs_error(ni->vol->sb, "Buffer I/O error, logical block %Lu.", + ntfs_error(ni->vol->sb, "Buffer I/O error, logical block %llu.", (unsigned long long)bh->b_blocknr); SetPageError(page); } @@ -120,10 +120,10 @@ continue; nr_err++; ntfs_error(ni->vol->sb, "post_read_mst_fixup() failed, " - "corrupt %s record 0x%Lx. Run chkdsk.", + "corrupt %s record 0x%llx. Run chkdsk.", ni->mft_no ? "index" : "mft", - (long long)(((s64)page->index << - PAGE_CACHE_SHIFT >> + (unsigned long long)(((s64)page->index + << PAGE_CACHE_SHIFT >> ni->itype.index.block_size_bits) + i)); } flush_dcache_page(page); @@ -263,9 +263,10 @@ } /* Hard error, zero out region. */ SetPageError(page); - ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%Lx) failed " - "with error code 0x%Lx%s.", - (long long)vcn, (long long)-lcn, + ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%llx) failed " + "with error code 0x%llx%s.", + (unsigned long long)vcn, + (unsigned long long)-lcn, is_retry ? " even after retrying" : ""); // FIXME: Depending on vol->on_errors, do something. } @@ -667,9 +668,10 @@ } /* Failed to map the buffer, even after retrying. */ bh->b_blocknr = -1UL; - ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%Lx) failed " - "with error code 0x%Lx%s.", - (long long)vcn, (long long)-lcn, + ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%llx) failed " + "with error code 0x%llx%s.", + (unsigned long long)vcn, + (unsigned long long)-lcn, is_retry ? " even after retrying" : ""); // FIXME: Depending on vol->on_errors, do something. if (!err) @@ -914,15 +916,16 @@ 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 " + ntfs_error(vi->i_sb, "BUG()! i_size (0x%llx) doesn't match " "attr_len (0x%x). Aborting write.", vi->i_size, attr_len); err = -EIO; goto err_out; } if (unlikely(attr_pos >= attr_len)) { - ntfs_error(vi->i_sb, "BUG()! attr_pos (0x%Lx) > attr_len (0x%x)" - ". Aborting write.", attr_pos, attr_len); + ntfs_error(vi->i_sb, "BUG()! attr_pos (0x%llx) > attr_len " + "(0x%x). Aborting write.", + (unsigned long long)attr_pos, attr_len); err = -EIO; goto err_out; } @@ -1221,11 +1224,13 @@ * retrying. */ bh->b_blocknr = -1UL; - ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%Lx) " + ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%llx) " "failed with error code " - "0x%Lx%s.", (long long)vcn, - (long long)-lcn, is_retry ? - " even after retrying" : ""); + "0x%llx%s.", + (unsigned long long)vcn, + (unsigned long long)-lcn, + is_retry ? " even after " + "retrying" : ""); // FIXME: Depending on vol->on_errors, do // something. if (!err) @@ -1675,15 +1680,16 @@ 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 " + ntfs_error(vi->i_sb, "BUG()! i_size (0x%llx) doesn't match " "attr_len (0x%x). Aborting write.", vi->i_size, attr_len); err = -EIO; goto err_out; } if (unlikely(attr_pos >= attr_len)) { - ntfs_error(vi->i_sb, "BUG()! attr_pos (0x%Lx) > attr_len (0x%x)" - ". Aborting write.", attr_pos, attr_len); + ntfs_error(vi->i_sb, "BUG()! attr_pos (0x%llx) > attr_len " + "(0x%x). Aborting write.", + (unsigned long long)attr_pos, attr_len); err = -EIO; goto err_out; } diff -Nru a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c --- a/fs/ntfs/attrib.c Thu Apr 29 23:19:49 2004 +++ b/fs/ntfs/attrib.c Thu Apr 29 23:19:49 2004 @@ -1,7 +1,7 @@ /** * attrib.c - NTFS attribute operations. Part of the Linux-NTFS project. * - * Copyright (c) 2001-2003 Anton Altaparmakov + * Copyright (c) 2001-2004 Anton Altaparmakov * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or @@ -9,13 +9,13 @@ * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program/include file is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * This program/include file is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program (in the main directory of the Linux-NTFS + * along with this program (in the main directory of the Linux-NTFS * distribution in the file COPYING); if not, write to the Free Software * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -623,8 +623,8 @@ int slots = 0; if (drl[ds].vcn == marker_vcn) { - ntfs_debug("Old marker = 0x%Lx, replacing with " - "LCN_ENOENT.\n", + ntfs_debug("Old marker = 0x%llx, replacing " + "with LCN_ENOENT.\n", (unsigned long long) drl[ds].lcn); drl[ds].lcn = (LCN)LCN_ENOENT; @@ -889,19 +889,19 @@ * likely, there are more extents following this one. */ if (deltaxcn < --max_cluster) { - ntfs_debug("More extents to follow; deltaxcn = 0x%Lx, " - "max_cluster = 0x%Lx", - (long long)deltaxcn, - (long long)max_cluster); + ntfs_debug("More extents to follow; deltaxcn = 0x%llx, " + "max_cluster = 0x%llx", + (unsigned long long)deltaxcn, + (unsigned long long)max_cluster); rl[rlpos].vcn = vcn; vcn += rl[rlpos].length = max_cluster - deltaxcn; rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED; rlpos++; } else if (unlikely(deltaxcn > max_cluster)) { ntfs_error(vol->sb, "Corrupt attribute. deltaxcn = " - "0x%Lx, max_cluster = 0x%Lx", - (long long)deltaxcn, - (long long)max_cluster); + "0x%llx, max_cluster = 0x%llx", + (unsigned long long)deltaxcn, + (unsigned long long)max_cluster); goto mpa_err; } rl[rlpos].lcn = (LCN)LCN_ENOENT; @@ -933,7 +933,7 @@ /** * map_run_list - map (a part of) a run list of an ntfs inode - * @ni: ntfs inode for which to map (part of) a run list + * @ni: ntfs inode for which to map (part of) a run list * @vcn: map run list part containing this vcn * * Map the part of a run list containing the @vcn of an the ntfs inode @ni. @@ -947,8 +947,8 @@ MFT_RECORD *mrec; int err = 0; - ntfs_debug("Mapping run list part containing vcn 0x%Lx.", - (long long)vcn); + ntfs_debug("Mapping run list part containing vcn 0x%llx.", + (unsigned long long)vcn); if (!NInoAttr(ni)) base_ni = ni; @@ -1136,7 +1136,7 @@ break; if (a->type != type) continue; - /* + /* * If @name is present, compare the two names. If @name is * missing, assume we want an unnamed attribute. */ @@ -1257,8 +1257,9 @@ /* Read all clusters specified by the run list one run at a time. */ while (rl->length) { lcn = vcn_to_lcn(rl, rl->vcn); - ntfs_debug("Reading vcn = 0x%Lx, lcn = 0x%Lx.", - (long long)rl->vcn, (long long)lcn); + ntfs_debug("Reading vcn = 0x%llx, lcn = 0x%llx.", + (unsigned long long)rl->vcn, + (unsigned long long)lcn); /* The attribute list cannot be sparse. */ if (lcn < 0) { ntfs_error(sb, "vcn_to_lcn() failed. Cannot read " diff -Nru a/fs/ntfs/compress.c b/fs/ntfs/compress.c --- a/fs/ntfs/compress.c Thu Apr 29 23:19:49 2004 +++ b/fs/ntfs/compress.c Thu Apr 29 23:19:49 2004 @@ -2,7 +2,7 @@ * compress.c - NTFS kernel compressed attributes handling. * Part of the Linux-NTFS project. * - * Copyright (c) 2001-2003 Anton Altaparmakov + * Copyright (c) 2001-2004 Anton Altaparmakov * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or @@ -10,13 +10,13 @@ * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program/include file is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * This program/include file is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program (in the main directory of the Linux-NTFS + * along with this program (in the main directory of the Linux-NTFS * distribution in the file COPYING); if not, write to the Free Software * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -357,7 +357,7 @@ continue; } - /* + /* * We have a phrase token. Make sure it is not the first tag in * the sb as this is illegal and would confuse the code below. */ @@ -597,8 +597,9 @@ lcn = vcn_to_lcn(rl, vcn); } else lcn = (LCN)LCN_RL_NOT_MAPPED; - ntfs_debug("Reading vcn = 0x%Lx, lcn = 0x%Lx.", - (long long)vcn, (long long)lcn); + ntfs_debug("Reading vcn = 0x%llx, lcn = 0x%llx.", + (unsigned long long)vcn, + (unsigned long long)lcn); if (lcn < 0) { /* * When we reach the first sparse cluster we have @@ -643,7 +644,7 @@ unlock_buffer(tbh); continue; } - atomic_inc(&tbh->b_count); + get_bh(tbh); tbh->b_end_io = end_buffer_read_sync; submit_bh(READ, tbh); } @@ -943,4 +944,3 @@ kfree(pages); return -EIO; } - diff -Nru a/fs/ntfs/dir.c b/fs/ntfs/dir.c --- a/fs/ntfs/dir.c Thu Apr 29 23:19:49 2004 +++ b/fs/ntfs/dir.c Thu Apr 29 23:19:49 2004 @@ -9,13 +9,13 @@ * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program/include file is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * This program/include file is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program (in the main directory of the Linux-NTFS + * along with this program (in the main directory of the Linux-NTFS * distribution in the file COPYING); if not, write to the Free Software * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -322,22 +322,22 @@ goto unm_err_out; } if (sle64_to_cpu(ia->index_block_vcn) != vcn) { - ntfs_error(sb, "Actual VCN (0x%Lx) of index buffer is " - "different from expected VCN (0x%Lx). " + ntfs_error(sb, "Actual VCN (0x%llx) of index buffer is " + "different from expected VCN (0x%llx). " "Directory inode 0x%lx is corrupt or driver " - "bug.", - (long long)sle64_to_cpu(ia->index_block_vcn), - (long long)vcn, dir_ni->mft_no); + "bug.", (unsigned long long) + sle64_to_cpu(ia->index_block_vcn), + (unsigned long long)vcn, dir_ni->mft_no); err = -EIO; goto unm_err_out; } if (le32_to_cpu(ia->index.allocated_size) + 0x18 != dir_ni->itype.index.block_size) { - ntfs_error(sb, "Index buffer (VCN 0x%Lx) of directory inode " + ntfs_error(sb, "Index buffer (VCN 0x%llx) 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, + (unsigned long long)vcn, dir_ni->mft_no, le32_to_cpu(ia->index.allocated_size) + 0x18, dir_ni->itype.index.block_size); err = -EIO; @@ -345,18 +345,19 @@ } 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 " + ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode " "0x%lx crosses page boundary. Impossible! " "Cannot access! This is probably a bug in the " - "driver.", (long long)vcn, dir_ni->mft_no); + "driver.", (unsigned long long)vcn, + dir_ni->mft_no); err = -EIO; goto unm_err_out; } index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length); if (index_end > (u8*)ia + dir_ni->itype.index.block_size) { - ntfs_error(sb, "Size of index buffer (VCN 0x%Lx) of directory " + ntfs_error(sb, "Size of index buffer (VCN 0x%llx) of directory " "inode 0x%lx exceeds maximum size.", - (long long)vcn, dir_ni->mft_no); + (unsigned long long)vcn, dir_ni->mft_no); err = -EIO; goto unm_err_out; } @@ -790,22 +791,22 @@ goto unm_err_out; } if (sle64_to_cpu(ia->index_block_vcn) != vcn) { - ntfs_error(sb, "Actual VCN (0x%Lx) of index buffer is " - "different from expected VCN (0x%Lx). " + ntfs_error(sb, "Actual VCN (0x%llx) of index buffer is " + "different from expected VCN (0x%llx). " "Directory inode 0x%lx is corrupt or driver " - "bug.", - (long long)sle64_to_cpu(ia->index_block_vcn), - (long long)vcn, dir_ni->mft_no); + "bug.", (unsigned long long) + sle64_to_cpu(ia->index_block_vcn), + (unsigned long long)vcn, dir_ni->mft_no); err = -EIO; goto unm_err_out; } if (le32_to_cpu(ia->index.allocated_size) + 0x18 != dir_ni->itype.index.block_size) { - ntfs_error(sb, "Index buffer (VCN 0x%Lx) of directory inode " + ntfs_error(sb, "Index buffer (VCN 0x%llx) 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, + (unsigned long long)vcn, dir_ni->mft_no, le32_to_cpu(ia->index.allocated_size) + 0x18, dir_ni->itype.index.block_size); err = -EIO; @@ -813,18 +814,19 @@ } 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 " + ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode " "0x%lx crosses page boundary. Impossible! " "Cannot access! This is probably a bug in the " - "driver.", (long long)vcn, dir_ni->mft_no); + "driver.", (unsigned long long)vcn, + dir_ni->mft_no); err = -EIO; goto unm_err_out; } index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length); if (index_end > (u8*)ia + dir_ni->itype.index.block_size) { - ntfs_error(sb, "Size of index buffer (VCN 0x%Lx) of directory " + ntfs_error(sb, "Size of index buffer (VCN 0x%llx) of directory " "inode 0x%lx exceeds maximum size.", - (long long)vcn, dir_ni->mft_no); + (unsigned long long)vcn, dir_ni->mft_no); err = -EIO; goto unm_err_out; } @@ -1037,7 +1039,7 @@ dt_type = DT_DIR; else dt_type = DT_REG; - ntfs_debug("Calling filldir for %s with len %i, fpos 0x%Lx, inode " + ntfs_debug("Calling filldir for %s with len %i, fpos 0x%llx, inode " "0x%lx, DT_%s.", name, name_len, *fpos, MREF_LE(ie->data.dir.indexed_file), dt_type == DT_DIR ? "DIR" : "REG"); @@ -1076,7 +1078,7 @@ attr_search_context *ctx; fpos = filp->f_pos; - ntfs_debug("Entering for inode 0x%lx, fpos 0x%Lx.", + ntfs_debug("Entering for inode 0x%lx, fpos 0x%llx.", vdir->i_ino, fpos); rc = err = 0; /* Are we at end of dir yet? */ @@ -1215,9 +1217,10 @@ cur_bmp_pos = bmp_pos & ((PAGE_CACHE_SIZE * 8) - 1); bmp_pos &= ~(u64)((PAGE_CACHE_SIZE * 8) - 1); get_next_bmp_page: - ntfs_debug("Reading bitmap with page index 0x%Lx, bit ofs 0x%Lx", - (long long)bmp_pos >> (3 + PAGE_CACHE_SHIFT), - (long long)bmp_pos & ((PAGE_CACHE_SIZE * 8) - 1)); + ntfs_debug("Reading bitmap with page index 0x%llx, bit ofs 0x%llx", + (unsigned long long)bmp_pos >> (3 + PAGE_CACHE_SHIFT), + (unsigned long long)bmp_pos & + ((PAGE_CACHE_SIZE * 8) - 1)); bmp_page = ntfs_map_page(bmp_mapping, bmp_pos >> (3 + PAGE_CACHE_SHIFT)); if (unlikely(IS_ERR(bmp_page))) { @@ -1247,8 +1250,8 @@ ia_pos = (bmp_pos + cur_bmp_pos) << ndir->itype.index.block_size_bits; } - ntfs_debug("Handling index buffer 0x%Lx.", - (long long)bmp_pos + cur_bmp_pos); + ntfs_debug("Handling index buffer 0x%llx.", + (unsigned long long)bmp_pos + cur_bmp_pos); /* If the current index buffer is in the same page we reuse the page. */ if ((prev_ia_pos & PAGE_CACHE_MASK) != (ia_pos & PAGE_CACHE_MASK)) { prev_ia_pos = ia_pos; @@ -1279,22 +1282,22 @@ if (unlikely(sle64_to_cpu(ia->index_block_vcn) != (ia_pos & ~(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). " + ntfs_error(sb, "Actual VCN (0x%llx) of index buffer is " + "different from expected VCN (0x%llx). " "Directory inode 0x%lx is corrupt or driver " - "bug. ", - (long long)sle64_to_cpu(ia->index_block_vcn), - (long long)ia_pos >> + "bug. ", (unsigned long long) + sle64_to_cpu(ia->index_block_vcn), + (unsigned long long)ia_pos >> ndir->itype.index.vcn_size_bits, vdir->i_ino); goto err_out; } if (unlikely(le32_to_cpu(ia->index.allocated_size) + 0x18 != ndir->itype.index.block_size)) { - ntfs_error(sb, "Index buffer (VCN 0x%Lx) of directory inode " + ntfs_error(sb, "Index buffer (VCN 0x%llx) 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 >> + (unsigned long long)ia_pos >> ndir->itype.index.vcn_size_bits, vdir->i_ino, le32_to_cpu(ia->index.allocated_size) + 0x18, ndir->itype.index.block_size); @@ -1302,19 +1305,19 @@ } 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 " + ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode " "0x%lx crosses page boundary. Impossible! " "Cannot access! This is probably a bug in the " - "driver.", (long long)ia_pos >> + "driver.", (unsigned long long)ia_pos >> ndir->itype.index.vcn_size_bits, vdir->i_ino); goto err_out; } 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->itype.index.block_size)) { - ntfs_error(sb, "Size of index buffer (VCN 0x%Lx) of directory " + ntfs_error(sb, "Size of index buffer (VCN 0x%llx) of directory " "inode 0x%lx exceeds maximum size.", - (long long)ia_pos >> + (unsigned long long)ia_pos >> ndir->itype.index.vcn_size_bits, vdir->i_ino); goto err_out; } @@ -1327,8 +1330,9 @@ * or signals an error (both covered by the rc test). */ 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)); + ntfs_debug("In index allocation, offset 0x%llx.", + (unsigned long long)ia_start + ((u8*)ie - + (u8*)ia)); /* Bounds checks. */ if (unlikely((u8*)ie < (u8*)ia || (u8*)ie + sizeof(INDEX_ENTRY_HEADER) > index_end || @@ -1363,9 +1367,9 @@ done: #ifdef DEBUG if (!rc) - ntfs_debug("EOD, fpos 0x%Lx, returning 0.", fpos); + ntfs_debug("EOD, fpos 0x%llx, returning 0.", fpos); else - ntfs_debug("filldir returned %i, fpos 0x%Lx, returning 0.", + ntfs_debug("filldir returned %i, fpos 0x%llx, returning 0.", rc, fpos); #endif filp->f_pos = fpos; diff -Nru a/fs/ntfs/inode.c b/fs/ntfs/inode.c --- a/fs/ntfs/inode.c Thu Apr 29 23:19:49 2004 +++ b/fs/ntfs/inode.c Thu Apr 29 23:19:49 2004 @@ -8,13 +8,13 @@ * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program/include file is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * This program/include file is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program (in the main directory of the Linux-NTFS + * along with this program (in the main directory of the Linux-NTFS * distribution in the file COPYING); if not, write to the Free Software * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -29,26 +29,7 @@ #include "dir.h" #include "inode.h" #include "attrib.h" - -/** - * ntfs_attr - ntfs in memory attribute structure - * @mft_no: mft record number of the base mft record of this attribute - * @name: Unicode name of the attribute (NULL if unnamed) - * @name_len: length of @name in Unicode characters (0 if unnamed) - * @type: attribute type (see layout.h) - * - * This structure exists only to provide a small structure for the - * ntfs_{attr_}iget()/ntfs_test_inode()/ntfs_init_locked_inode() mechanism. - * - * NOTE: Elements are ordered by size to make the structure as compact as - * possible on all architectures. - */ -typedef struct { - unsigned long mft_no; - uchar_t *name; - u32 name_len; - ATTR_TYPES type; -} ntfs_attr; +#include "time.h" /** * ntfs_test_inode - compare two (possibly fake) inodes for equality @@ -66,7 +47,7 @@ * NOTE: This function runs with the inode_lock spin lock held so it is not * allowed to sleep. */ -static int ntfs_test_inode(struct inode *vi, ntfs_attr *na) +int ntfs_test_inode(struct inode *vi, ntfs_attr *na) { ntfs_inode *ni; @@ -150,7 +131,6 @@ return 0; } -typedef int (*test_t)(struct inode *, void *); typedef int (*set_t)(struct inode *, void *); static int ntfs_read_locked_inode(struct inode *vi); static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi); @@ -380,7 +360,7 @@ * Search all file name attributes in the inode described by the attribute * search context @ctx and check if any of the names are in the $Extend system * directory. - * + * * Return values: * 1: file is in $Extend directory * 0: file is not in $Extend directory @@ -590,21 +570,18 @@ * mtime is the last change of the data within the file. Not changed * when only metadata is changed, e.g. a rename doesn't affect mtime. */ - vi->i_mtime.tv_sec = ntfs2utc(si->last_data_change_time); - vi->i_mtime.tv_nsec = 0; + vi->i_mtime = ntfs2utc(si->last_data_change_time); /* * ctime is the last change of the metadata of the file. This obviously * always changes, when mtime is changed. ctime can be changed on its * own, mtime is then not changed, e.g. when a file is renamed. */ - vi->i_ctime.tv_sec = ntfs2utc(si->last_mft_change_time); - vi->i_ctime.tv_nsec = 0; + vi->i_ctime = ntfs2utc(si->last_mft_change_time); /* * Last access to the data within the file. Not changed during a rename * for example but changed whenever the file is written to. */ - vi->i_atime.tv_sec = ntfs2utc(si->last_access_time); - vi->i_atime.tv_nsec = 0; + vi->i_atime = ntfs2utc(si->last_access_time); /* Find the attribute list attribute if present. */ reinit_attr_search_ctx(ctx); @@ -876,8 +853,8 @@ /* Consistency check bitmap size vs. index allocation size. */ if ((bvi->i_size << 3) < (vi->i_size >> ni->itype.index.block_size_bits)) { - ntfs_error(vi->i_sb, "Index bitmap too small (0x%Lx) " - "for index allocation (0x%Lx).", + ntfs_error(vi->i_sb, "Index bitmap too small (0x%llx) " + "for index allocation (0x%llx).", bvi->i_size << 3, vi->i_size); goto unm_err_out; } @@ -1715,9 +1692,9 @@ ntfs_error(sb, "Failed to load the complete run list " "for $MFT/$DATA. Driver bug or " "corrupt $MFT. Run chkdsk."); - ntfs_debug("highest_vcn = 0x%Lx, last_vcn - 1 = 0x%Lx", - (long long)highest_vcn, - (long long)last_vcn - 1); + ntfs_debug("highest_vcn = 0x%llx, last_vcn - 1 = 0x%llx", + (unsigned long long)highest_vcn, + (unsigned long long)last_vcn - 1); goto put_err_out; } put_attr_search_ctx(ctx); @@ -1739,39 +1716,6 @@ } /** - * ntfs_dirty_inode - mark the inode's metadata dirty - * @vi: inode to mark dirty - * - * This is called from fs/inode.c::__mark_inode_dirty(), when the inode itself - * is being marked dirty. An example is when update_atime() is invoked. - * - * We mark the inode dirty by setting both the page in which the mft record - * resides and the buffer heads in that page which correspond to the mft record - * dirty. This ensures that the changes will eventually be propagated to disk - * when the inode is set dirty. - * - * FIXME: Can we do that with the buffer heads? I am not too sure. Because if we - * do that we need to make sure that the kernel will not write out those buffer - * heads or we are screwed as it will write corrupt data to disk. The only way - * a mft record can be written correctly is by mst protecting it, writting it - * synchronously and fast mst deprotecting it. During this period, obviously, - * the mft record must be marked as not uptodate, be locked for writing or - * whatever, so that nobody attempts anything stupid. - * - * FIXME: Do we need to check that the fs is not mounted read only? And what - * about the inode? Anything else? - * - * FIXME: As we are only a read only driver it is safe to just return here for - * the moment. - */ -void ntfs_dirty_inode(struct inode *vi) -{ - ntfs_debug("Entering for inode 0x%lx.", vi->i_ino); - NInoSetDirty(NTFS_I(vi)); - return; -} - -/** * ntfs_commit_inode - write out a dirty inode * @ni: inode to write out * @@ -2029,4 +1973,3 @@ } #endif - diff -Nru a/fs/ntfs/inode.h b/fs/ntfs/inode.h --- a/fs/ntfs/inode.h Thu Apr 29 23:19:49 2004 +++ b/fs/ntfs/inode.h Thu Apr 29 23:19:49 2004 @@ -2,7 +2,7 @@ * inode.h - Defines for inode structures NTFS Linux kernel driver. Part of * the Linux-NTFS project. * - * Copyright (c) 2001-2003 Anton Altaparmakov + * Copyright (c) 2001-2004 Anton Altaparmakov * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or @@ -10,13 +10,13 @@ * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program/include file is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * This program/include file is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program (in the main directory of the Linux-NTFS + * along with this program (in the main directory of the Linux-NTFS * distribution in the file COPYING); if not, write to the Free Software * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -181,8 +181,22 @@ clear_bit(NI_##flag, &(ni)->state); \ } +/* + * As above for NInoTestSetFoo() and NInoTestClearFoo(). + */ +#define TAS_NINO_FNS(flag) \ +static inline int NInoTestSet##flag(ntfs_inode *ni) \ +{ \ + return test_and_set_bit(NI_##flag, &(ni)->state); \ +} \ +static inline int NInoTestClear##flag(ntfs_inode *ni) \ +{ \ + return test_and_clear_bit(NI_##flag, &(ni)->state); \ +} + /* Emit the ntfs inode bitops functions. */ NINO_FNS(Dirty) +TAS_NINO_FNS(Dirty) NINO_FNS(AttrList) NINO_FNS(AttrListNonResident) NINO_FNS(Attr) @@ -219,6 +233,30 @@ return &((big_ntfs_inode *)ni)->vfs_inode; } +/** + * ntfs_attr - ntfs in memory attribute structure + * @mft_no: mft record number of the base mft record of this attribute + * @name: Unicode name of the attribute (NULL if unnamed) + * @name_len: length of @name in Unicode characters (0 if unnamed) + * @type: attribute type (see layout.h) + * + * This structure exists only to provide a small structure for the + * ntfs_{attr_}iget()/ntfs_test_inode()/ntfs_init_locked_inode() mechanism. + * + * NOTE: Elements are ordered by size to make the structure as compact as + * possible on all architectures. + */ +typedef struct { + unsigned long mft_no; + uchar_t *name; + u32 name_len; + ATTR_TYPES type; +} ntfs_attr; + +typedef int (*test_t)(struct inode *, void *); + +extern int ntfs_test_inode(struct inode *vi, ntfs_attr *na); + extern struct inode *ntfs_iget(struct super_block *sb, unsigned long mft_no); extern struct inode *ntfs_attr_iget(struct inode *base_vi, ATTR_TYPES type, uchar_t *name, u32 name_len); @@ -233,8 +271,6 @@ extern void ntfs_read_inode_mount(struct inode *vi); -extern void ntfs_dirty_inode(struct inode *vi); - extern void ntfs_put_inode(struct inode *vi); extern int ntfs_show_options(struct seq_file *sf, struct vfsmount *mnt); @@ -245,7 +281,6 @@ extern int ntfs_setattr(struct dentry *dentry, struct iattr *attr); -#endif - -#endif /* _LINUX_NTFS_FS_INODE_H */ +#endif /* NTFS_RW */ +#endif /* _LINUX_NTFS_INODE_H */ diff -Nru a/fs/ntfs/mft.h b/fs/ntfs/mft.h --- a/fs/ntfs/mft.h Thu Apr 29 23:19:49 2004 +++ b/fs/ntfs/mft.h Thu Apr 29 23:19:49 2004 @@ -2,20 +2,20 @@ * mft.h - Defines for mft record handling in NTFS Linux kernel driver. * Part of the Linux-NTFS project. * - * Copyright (c) 2001,2002 Anton Altaparmakov. + * Copyright (c) 2001-2004 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 * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program/include file is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * This program/include file is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program (in the main directory of the Linux-NTFS + * along with this program (in the main directory of the Linux-NTFS * distribution in the file COPYING); if not, write to the Free Software * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -43,7 +43,9 @@ return; } -/* +#ifdef NTFS_RW + +/** * flush_dcache_mft_record_page - flush_dcache_page() for mft records * @ni: ntfs inode structure of mft record * @@ -57,5 +59,6 @@ flush_dcache_page(ni->page); } -#endif /* _LINUX_NTFS_MFT_H */ +#endif /* NTFS_RW */ +#endif /* _LINUX_NTFS_MFT_H */ diff -Nru a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h --- a/fs/ntfs/ntfs.h Thu Apr 29 23:19:49 2004 +++ b/fs/ntfs/ntfs.h Thu Apr 29 23:19:49 2004 @@ -2,7 +2,7 @@ * ntfs.h - Defines for NTFS Linux kernel driver. Part of the Linux-NTFS * project. * - * Copyright (c) 2001,2002 Anton Altaparmakov. + * Copyright (c) 2001-2004 Anton Altaparmakov. * Copyright (C) 2002 Richard Russon. * * This program/include file is free software; you can redistribute it and/or @@ -75,10 +75,13 @@ extern struct file_operations ntfs_empty_file_ops; extern struct inode_operations ntfs_empty_inode_ops; -/* Generic macro to convert pointers to values for comparison purposes. */ +/* Generic macros to convert pointers to values and vice versa. */ #ifndef p2n #define p2n(p) ((ptrdiff_t)((ptrdiff_t*)(p))) #endif +#ifndef n2p +#define n2p(p) ((ptrdiff_t*)((ptrdiff_t)(p))) +#endif /** * NTFS_SB - return the ntfs volume given a vfs super block @@ -179,11 +182,6 @@ extern int post_read_mst_fixup(NTFS_RECORD *b, const u32 size); extern int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size); extern void post_write_mst_fixup(NTFS_RECORD *b); - -/* From fs/ntfs/time.c */ -extern inline s64 utc2ntfs(const time_t time); -extern inline s64 get_current_ntfs_time(void); -extern time_t ntfs2utc(const s64 time); /* From fs/ntfs/unistr.c */ extern BOOL ntfs_are_names_equal(const uchar_t *s1, size_t s1_len, diff -Nru a/fs/ntfs/super.c b/fs/ntfs/super.c --- a/fs/ntfs/super.c Thu Apr 29 23:19:49 2004 +++ b/fs/ntfs/super.c Thu Apr 29 23:19:49 2004 @@ -9,13 +9,13 @@ * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program/include file is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * This program/include file is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program (in the main directory of the Linux-NTFS + * along with this program (in the main directory of the Linux-NTFS * distribution in the file COPYING); if not, write to the Free Software * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -102,7 +102,7 @@ if (*v) \ goto needs_val; \ } \ - } + } #define NTFS_GETOPT(option, variable) \ if (!strcmp(p, option)) { \ if (!v || !*v) \ @@ -110,14 +110,14 @@ variable = simple_strtoul(ov = v, &v, 0); \ if (*v) \ goto needs_val; \ - } + } #define NTFS_GETOPT_BOOL(option, variable) \ if (!strcmp(p, option)) { \ BOOL val; \ if (!simple_getbool(v, &val)) \ goto needs_bool; \ variable = val; \ - } + } #define NTFS_GETOPT_OPTIONS_ARRAY(option, variable, opt_array) \ if (!strcmp(p, option)) { \ int _i; \ @@ -400,7 +400,7 @@ le32_to_cpu(b->bpb.large_sectors) || b->bpb.fats) goto not_ntfs; /* Check clusters per file mft record value is valid. */ - if ((u8)b->clusters_per_mft_record < 0xe1 || + if ((u8)b->clusters_per_mft_record < 0xe1 || (u8)b->clusters_per_mft_record > 0xf7) switch (b->clusters_per_mft_record) { case 1: case 2: case 4: case 8: case 16: case 32: case 64: @@ -409,7 +409,7 @@ goto not_ntfs; } /* Check clusters per index block value is valid. */ - if ((u8)b->clusters_per_index_record < 0xe1 || + if ((u8)b->clusters_per_index_record < 0xe1 || (u8)b->clusters_per_index_record > 0xf7) switch (b->clusters_per_index_record) { case 1: case 2: case 4: case 8: case 16: case 32: case 64: @@ -529,7 +529,7 @@ * parse_ntfs_boot_sector - parse the boot sector and store the data in @vol * @vol: volume structure to initialise with data from boot sector * @b: boot sector to parse - * + * * Parse the ntfs boot sector @b and store all imporant information therein in * the ntfs super block @vol. Return TRUE on success and FALSE on error. */ @@ -592,10 +592,10 @@ ntfs_debug("vol->mft_record_size_mask = 0x%x", vol->mft_record_size_mask); ntfs_debug("vol->mft_record_size_bits = %i (0x%x)", - vol->mft_record_size_bits, vol->mft_record_size_bits); + vol->mft_record_size_bits, vol->mft_record_size_bits); clusters_per_index_record = b->clusters_per_index_record; ntfs_debug("clusters_per_index_record = %i (0x%x)", - clusters_per_index_record, clusters_per_index_record); + clusters_per_index_record, clusters_per_index_record); if (clusters_per_index_record > 0) vol->index_record_size = vol->cluster_size << (ffs(clusters_per_index_record) - 1); @@ -610,7 +610,7 @@ vol->index_record_size_mask = vol->index_record_size - 1; vol->index_record_size_bits = ffs(vol->index_record_size) - 1; ntfs_debug("vol->index_record_size = %i (0x%x)", - vol->index_record_size, vol->index_record_size); + vol->index_record_size, vol->index_record_size); ntfs_debug("vol->index_record_size_mask = 0x%x", vol->index_record_size_mask); ntfs_debug("vol->index_record_size_bits = %i (0x%x)", @@ -627,7 +627,7 @@ return FALSE; } vol->nr_clusters = ll; - ntfs_debug("vol->nr_clusters = 0x%Lx", (long long)vol->nr_clusters); + ntfs_debug("vol->nr_clusters = 0x%llx", (long long)vol->nr_clusters); /* * On an architecture where unsigned long is 32-bits, we restrict the * volume size to 2TiB (2^41). On a 64-bit architecture, the compiler @@ -635,10 +635,11 @@ */ if (sizeof(unsigned long) < 8) { if ((ll << vol->cluster_size_bits) >= (1ULL << 41)) { - ntfs_error(vol->sb, "Volume size (%LuTiB) is too large " - "for this architecture. Maximim " + ntfs_error(vol->sb, "Volume size (%lluTiB) is too " + "large for this architecture. Maximum " "supported is 2TiB. Sorry.", - ll >> (40 - vol->cluster_size_bits)); + (unsigned long long)ll >> (40 - + vol->cluster_size_bits)); return FALSE; } } @@ -648,7 +649,7 @@ return FALSE; } vol->mft_lcn = ll; - ntfs_debug("vol->mft_lcn = 0x%Lx", (long long)vol->mft_lcn); + ntfs_debug("vol->mft_lcn = 0x%llx", (long long)vol->mft_lcn); ll = sle64_to_cpu(b->mftmirr_lcn); if (ll >= vol->nr_clusters) { ntfs_error(vol->sb, "MFTMirr LCN is beyond end of volume. " @@ -656,9 +657,25 @@ return FALSE; } vol->mftmirr_lcn = ll; - ntfs_debug("vol->mftmirr_lcn = 0x%Lx", (long long)vol->mftmirr_lcn); + ntfs_debug("vol->mftmirr_lcn = 0x%llx", (long long)vol->mftmirr_lcn); +#ifdef NTFS_RW + /* + * Work out the size of the mft mirror in number of mft records. If the + * cluster size is less than or equal to the size taken by four mft + * records, the mft mirror stores the first four mft records. If the + * cluster size is bigger than the size taken by four mft records, the + * mft mirror contains as many mft records as will fit into one + * cluster. + */ + if (vol->cluster_size <= (4 << vol->mft_record_size_bits)) + vol->mftmirr_size = 4; + else + vol->mftmirr_size = vol->cluster_size >> + vol->mft_record_size_bits; + ntfs_debug("vol->mftmirr_size = %i", vol->mftmirr_size); +#endif /* NTFS_RW */ vol->serial_no = le64_to_cpu(b->volume_serial_number); - ntfs_debug("vol->serial_no = 0x%Lx", + ntfs_debug("vol->serial_no = 0x%llx", (unsigned long long)vol->serial_no); /* * Determine MFT zone size. This is not strictly the right place to do @@ -687,15 +704,176 @@ vol->mft_zone_multiplier); vol->mft_zone_start = vol->mft_lcn; vol->mft_zone_end += vol->mft_lcn; - ntfs_debug("vol->mft_zone_start = 0x%Lx", + ntfs_debug("vol->mft_zone_start = 0x%llx", (long long)vol->mft_zone_start); - ntfs_debug("vol->mft_zone_end = 0x%Lx", (long long)vol->mft_zone_end); - /* And another misplaced defaults setting. */ - if (!vol->on_errors) - vol->on_errors = ON_ERRORS_PANIC; + ntfs_debug("vol->mft_zone_end = 0x%llx", (long long)vol->mft_zone_end); + return TRUE; +} + +#ifdef NTFS_RW + +/** + * load_and_init_mft_mirror - load and setup the mft mirror inode for a volume + * @vol: ntfs super block describing device whose mft mirror to load + * + * Return TRUE on success or FALSE on error. + */ +static BOOL load_and_init_mft_mirror(ntfs_volume *vol) +{ + struct inode *tmp_ino; + ntfs_inode *tmp_ni; + + /* Get mft mirror inode. */ + tmp_ino = ntfs_iget(vol->sb, FILE_MFTMirr); + if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) { + if (!IS_ERR(tmp_ino)) + iput(tmp_ino); + ntfs_error(vol->sb, "Failed to load $MFTMirr."); + return FALSE; + } + /* + * Re-initialize some specifics about $MFTMirr's inode as + * ntfs_read_inode() will have set up the default ones. + */ + /* Set uid and gid to root. */ + tmp_ino->i_uid = tmp_ino->i_gid = 0; + /* Regular file. No access for anyone. */ + tmp_ino->i_mode = S_IFREG; + /* No VFS initiated operations allowed for $MFTMirr. */ + tmp_ino->i_op = &ntfs_empty_inode_ops; + tmp_ino->i_fop = &ntfs_empty_file_ops; + /* Put back our special address space operations. */ + tmp_ino->i_mapping->a_ops = &ntfs_mft_aops; + tmp_ni = NTFS_I(tmp_ino); + /* The $MFTMirr, like the $MFT is multi sector transfer protected. */ + NInoSetMstProtected(tmp_ni); + /* + * Set up our little cheat allowing us to reuse the async io + * completion handler for directories. + */ + tmp_ni->itype.index.block_size = vol->mft_record_size; + tmp_ni->itype.index.block_size_bits = vol->mft_record_size_bits; + vol->mftmirr_ino = tmp_ino; + return TRUE; +} + +/** + * check_mft_mirror - compare contents of the mft mirror with the mft + * @vol: ntfs super block describing device whose mft mirror to check + * + * Return TRUE on success or FALSE on error. + */ +static BOOL check_mft_mirror(ntfs_volume *vol) +{ + unsigned long index; + struct super_block *sb = vol->sb; + ntfs_inode *mirr_ni; + struct page *mft_page, *mirr_page; + u8 *kmft, *kmirr; + run_list_element *rl, rl2[2]; + int mrecs_per_page, i; + + /* Compare contents of $MFT and $MFTMirr. */ + mrecs_per_page = PAGE_CACHE_SIZE / vol->mft_record_size; + BUG_ON(!mrecs_per_page); + BUG_ON(!vol->mftmirr_size); + mft_page = mirr_page = NULL; + kmft = kmirr = NULL; + index = i = 0; + do { + u32 bytes; + + /* Switch pages if necessary. */ + if (!(i % mrecs_per_page)) { + if (index) { + ntfs_unmap_page(mft_page); + ntfs_unmap_page(mirr_page); + } + /* Get the $MFT page. */ + mft_page = ntfs_map_page(vol->mft_ino->i_mapping, + index); + if (IS_ERR(mft_page)) { + ntfs_error(sb, "Failed to read $MFT."); + return FALSE; + } + kmft = page_address(mft_page); + /* Get the $MFTMirr page. */ + mirr_page = ntfs_map_page(vol->mftmirr_ino->i_mapping, + index); + if (IS_ERR(mirr_page)) { + ntfs_error(sb, "Failed to read $MFTMirr."); + goto mft_unmap_out; + } + kmirr = page_address(mirr_page); + ++index; + } + /* Make sure the record is ok. */ + if (is_baad_recordp(kmft)) { + ntfs_error(sb, "Incomplete multi sector transfer " + "detected in mft record %i.", i); +mm_unmap_out: + ntfs_unmap_page(mirr_page); +mft_unmap_out: + ntfs_unmap_page(mft_page); + return FALSE; + } + if (is_baad_recordp(kmirr)) { + ntfs_error(sb, "Incomplete multi sector transfer " + "detected in mft mirror record %i.", i); + goto mm_unmap_out; + } + /* Get the amount of data in the current record. */ + bytes = le32_to_cpu(((MFT_RECORD*)kmft)->bytes_in_use); + if (!bytes || bytes > vol->mft_record_size) { + bytes = le32_to_cpu(((MFT_RECORD*)kmirr)->bytes_in_use); + if (!bytes || bytes > vol->mft_record_size) + bytes = vol->mft_record_size; + } + /* Compare the two records. */ + if (memcmp(kmft, kmirr, bytes)) { + ntfs_error(sb, "$MFT and $MFTMirr (record %i) do not " + "match. Run ntfsfix or chkdsk.", i); + goto mm_unmap_out; + } + kmft += vol->mft_record_size; + kmirr += vol->mft_record_size; + } while (++i < vol->mftmirr_size); + /* Release the last pages. */ + ntfs_unmap_page(mft_page); + ntfs_unmap_page(mirr_page); + + /* Construct the mft mirror run list by hand. */ + rl2[0].vcn = 0; + rl2[0].lcn = vol->mftmirr_lcn; + rl2[0].length = (vol->mftmirr_size * vol->mft_record_size + + vol->cluster_size - 1) / vol->cluster_size; + rl2[1].vcn = rl2[0].length; + rl2[1].lcn = LCN_ENOENT; + rl2[1].length = 0; + /* + * Because we have just read all of the mft mirror, we know we have + * mapped the full run list for it. + */ + mirr_ni = NTFS_I(vol->mftmirr_ino); + down_read(&mirr_ni->run_list.lock); + rl = mirr_ni->run_list.rl; + /* Compare the two run lists. They must be identical. */ + i = 0; + do { + if (rl2[i].vcn != rl[i].vcn || rl2[i].lcn != rl[i].lcn || + rl2[i].length != rl[i].length) { + ntfs_error(sb, "$MFTMirr location mismatch. " + "Run chkdsk."); + up_read(&mirr_ni->run_list.lock); + return FALSE; + } + } while (rl2[i++].length); + up_read(&mirr_ni->run_list.lock); return TRUE; } +#endif /* NTFS_RW */ + /** * load_and_init_upcase - load the upcase table for an ntfs volume * @vol: ntfs super block describing device whose upcase to load @@ -748,7 +926,7 @@ goto read_partial_upcase_page; } vol->upcase_len = ino->i_size >> UCHAR_T_SIZE_BITS; - ntfs_debug("Read %Lu bytes from $UpCase (expected %u bytes).", + ntfs_debug("Read %lu bytes from $UpCase (expected %u bytes).", ino->i_size, 64 * 1024 * sizeof(uchar_t)); iput(ino); down(&ntfs_lock); @@ -816,28 +994,44 @@ attr_search_context *ctx; ntfs_debug("Entering."); +#ifdef NTFS_RW + /* Get mft mirror inode compare the contents of $MFT and $MFTMirr. */ + if (!load_and_init_mft_mirror(vol) || !check_mft_mirror(vol)) { + static const char *es1 = "Failed to load $MFTMirr"; + static const char *es2 = "$MFTMirr does not match $MFT"; + static const char *es3 = ". Run ntfsfix and/or chkdsk."; + /* If a read-write mount, convert it to a read-only mount. */ + if (!(sb->s_flags & MS_RDONLY)) { + if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO | + ON_ERRORS_CONTINUE))) { + ntfs_error(sb, "%s and neither on_errors=" + "continue nor on_errors=" + "remount-ro was specified%s", + !vol->mftmirr_ino ? es1 : es2, + es3); + goto iput_mirr_err_out; + } + sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME; + ntfs_error(sb, "%s. Mounting read-only%s", + !vol->mftmirr_ino ? es1 : es2, es3); + } else + ntfs_warning(sb, "%s. Will not be able to remount " + "read-write%s", + !vol->mftmirr_ino ? es1 : es2, es3); + /* This will prevent a read-write remount. */ + NVolSetErrors(vol); + } +#endif /* NTFS_RW */ /* Get mft bitmap attribute inode. */ vol->mftbmp_ino = ntfs_attr_iget(vol->mft_ino, AT_BITMAP, NULL, 0); if (IS_ERR(vol->mftbmp_ino)) { ntfs_error(sb, "Failed to load $MFT/$BITMAP attribute."); - return FALSE; - } - - /* Get mft mirror inode. */ - vol->mftmirr_ino = ntfs_iget(sb, FILE_MFTMirr); - if (IS_ERR(vol->mftmirr_ino) || is_bad_inode(vol->mftmirr_ino)) { - if (!IS_ERR(vol->mftmirr_ino)) - iput(vol->mftmirr_ino); - ntfs_error(sb, "Failed to load $MFTMirr."); - goto iput_mftbmp_err_out; + goto iput_mirr_err_out; } - // FIXME: Compare mftmirr with mft and repair if appropriate and not - // a read-only mount. - - /* Read upcase table and setup vol->upcase and vol->upcase_len. */ + /* Read upcase table and setup @vol->upcase and @vol->upcase_len. */ if (!load_and_init_upcase(vol)) - goto iput_mirr_err_out; + goto iput_mftbmp_err_out; /* * Get the cluster allocation bitmap inode and verify the size, no * need for any locking at this stage as we are already running @@ -904,6 +1098,8 @@ * Get the inode for the logfile and empty it if this is a read-write * mount. */ + // TODO: vol->logfile_ino = ; + // TODO: Cleanup for error case at end of function. tmp_ino = ntfs_iget(sb, FILE_LogFile); if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) { if (!IS_ERR(tmp_ino)) @@ -920,7 +1116,7 @@ /* * Get the inode for the attribute definitions file and parse the * attribute definitions. - */ + */ tmp_ino = ntfs_iget(sb, FILE_AttrDef); if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) { if (!IS_ERR(tmp_ino)) @@ -974,10 +1170,13 @@ iput(vol->vol_ino); iput_lcnbmp_err_out: iput(vol->lcnbmp_ino); -iput_mirr_err_out: - iput(vol->mftmirr_ino); iput_mftbmp_err_out: iput(vol->mftbmp_ino); +iput_mirr_err_out: +#ifdef NTFS_RW + if (vol->mftmirr_ino) + iput(vol->mftmirr_ino); +#endif /* NTFS_RW */ return FALSE; } @@ -1015,14 +1214,23 @@ vol->lcnbmp_ino = NULL; up_write(&vol->lcnbmp_lock); - iput(vol->mftmirr_ino); - vol->mftmirr_ino = NULL; - down_write(&vol->mftbmp_lock); iput(vol->mftbmp_ino); vol->mftbmp_ino = NULL; up_write(&vol->mftbmp_lock); +#ifdef NTFS_RW + if (vol->logfile_ino) { + iput(vol->logfile_ino); + vol->logfile_ino = NULL; + } + + if (vol->mftmirr_ino) { + iput(vol->mftmirr_ino); + vol->mftmirr_ino = NULL; + } +#endif /* NTFS_RW */ + iput(vol->mft_ino); vol->mft_ino = NULL; @@ -1321,24 +1529,37 @@ struct super_operations ntfs_sops = { .alloc_inode = ntfs_alloc_big_inode, /* VFS: Allocate new inode. */ .destroy_inode = ntfs_destroy_big_inode, /* VFS: Deallocate inode. */ - //.dirty_inode = ntfs_dirty_inode, /* VFS: Called from - // __mark_inode_dirty(). */ - //.write_inode = NULL, /* VFS: Write dirty inode to disk. */ - .put_inode = ntfs_put_inode, /* VFS: Called just before the inode - reference count is decreased. */ - //.delete_inode = NULL, /* VFS: Delete inode from disk. Called - // when i_count becomes 0 and i_nlink - // is also 0. */ - .put_super = ntfs_put_super, /* Syscall: umount. */ - //write_super = NULL, /* Flush dirty super block to disk. */ - //write_super_lockfs = NULL, /* ? */ - //unlockfs = NULL, /* ? */ - .statfs = ntfs_statfs, /* Syscall: statfs */ - .remount_fs = ntfs_remount, /* Syscall: mount -o remount. */ + .put_inode = ntfs_put_inode, /* VFS: Called just before + the inode reference count + is decreased. */ +#ifdef NTFS_RW + //.dirty_inode = NULL, /* VFS: Called from + // __mark_inode_dirty(). */ + //.write_inode = NULL, /* VFS: Write dirty inode to + // disk. */ + //.drop_inode = NULL, /* VFS: Called just after the + // inode reference count has + // been decreased to zero. + // NOTE: The inode lock is + // held. See fs/inode.c:: + // generic_drop_inode(). */ + //.delete_inode = NULL, /* VFS: Delete inode from disk. + // Called when i_count becomes + // 0 and i_nlink is also 0. */ + //.write_super = NULL, /* Flush dirty super block to + // disk. */ + //.sync_fs = NULL, /* ? */ + //.write_super_lockfs = NULL, /* ? */ + //.unlockfs = NULL, /* ? */ +#endif /* NTFS_RW */ + .put_super = ntfs_put_super, /* Syscall: umount. */ + .statfs = ntfs_statfs, /* Syscall: statfs */ + .remount_fs = ntfs_remount, /* Syscall: mount -o remount. */ .clear_inode = ntfs_clear_big_inode, /* VFS: Called when an inode is removed from memory. */ - //.umount_begin = NULL, /* Forced umount. */ - .show_options = ntfs_show_options, /* Show mount options in proc. */ + //.umount_begin = NULL, /* Forced umount. */ + .show_options = ntfs_show_options, /* Show mount options in + proc. */ }; @@ -1424,7 +1645,11 @@ vol->mft_ino = NULL; vol->mftbmp_ino = NULL; init_rwsem(&vol->mftbmp_lock); +#ifdef NTFS_RW vol->mftmirr_ino = NULL; + vol->mftmirr_size = 0; + vol->logfile_ino = NULL; +#endif /* NTFS_RW */ vol->lcnbmp_ino = NULL; init_rwsem(&vol->lcnbmp_lock); vol->vol_ino = NULL; @@ -1474,7 +1699,7 @@ ntfs_error(sb, "Not an NTFS volume."); goto err_out_now; } - + /* * Extract the data from the boot sector and setup the ntfs super block * using it. @@ -1489,7 +1714,7 @@ goto err_out_now; } - /* + /* * TODO: When we start coping with sector sizes different from * NTFS_BLOCK_SIZE, we now probably need to set the blocksize of the * device (probably to NTFS_BLOCK_SIZE). @@ -1500,7 +1725,7 @@ /* * Ntfs allows 63 bits for the file size, i.e. correct would be: - * sb->s_maxbytes = ~0ULL >> 1; + * sb->s_maxbytes = ~0ULL >> 1; * But the kernel uses a long as the page cache page index which on * 32-bit architectures is only 32-bits. MAX_LFS_FILESIZE is kernel * defined to the maximum the page cache page index can cope with @@ -1519,7 +1744,7 @@ * Poison vol->mft_ino so we know whether iget() called into our * ntfs_read_inode_mount() method. */ -#define OGIN ((struct inode*)le32_to_cpu(0x4e49474f)) /* OGIN */ +#define OGIN ((struct inode*)n2p(le32_to_cpu(0x4e49474f))) /* OGIN */ vol->mft_ino = OGIN; sb->s_op = &ntfs_mount_sops; tmp_ino = iget(vol->sb, FILE_MFT); @@ -1601,8 +1826,10 @@ vol->root_ino = NULL; iput(vol->lcnbmp_ino); vol->lcnbmp_ino = NULL; +#ifdef NTFS_RW iput(vol->mftmirr_ino); vol->mftmirr_ino = NULL; +#endif /* NTFS_RW */ iput(vol->mftbmp_ino); vol->mftbmp_ino = NULL; vol->upcase_len = 0; @@ -1757,7 +1984,7 @@ } ntfs_inode_cache = kmem_cache_create(ntfs_inode_cache_name, - sizeof(ntfs_inode), 0, + sizeof(ntfs_inode), 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, NULL, NULL); if (!ntfs_inode_cache) { printk(KERN_CRIT "NTFS: Failed to create %s!\n", @@ -1766,7 +1993,7 @@ } ntfs_big_inode_cache = kmem_cache_create(ntfs_big_inode_cache_name, - sizeof(big_ntfs_inode), 0, + sizeof(big_ntfs_inode), 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, ntfs_big_inode_init_once, NULL); if (!ntfs_big_inode_cache) { diff -Nru a/fs/ntfs/time.c b/fs/ntfs/time.c --- a/fs/ntfs/time.c Thu Apr 29 23:19:49 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,82 +0,0 @@ -/* - * time.c - NTFS time conversion functions. Part of the Linux-NTFS project. - * - * Copyright (c) 2001 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 - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include /* For CURRENT_TIME. */ -#include /* For do_div(). */ - -#include "ntfs.h" - -#define NTFS_TIME_OFFSET ((s64)(369 * 365 + 89) * 24 * 3600 * 10000000) - -/** - * utc2ntfs - convert Linux time to NTFS time - * @time: Linux time to convert to NTFS - * - * Convert the Linux time @time to its corresponding NTFS time and return that - * in little endian format. - * - * Linux stores time in a long at present and measures it as the number of - * 1-second intervals since 1st January 1970, 00:00:00 UTC. - * - * NTFS uses Microsoft's standard time format which is stored in a s64 and is - * measured as the number of 100 nano-second intervals since 1st January 1601, - * 00:00:00 UTC. - */ -inline s64 utc2ntfs(const time_t time) -{ - /* Convert to 100ns intervals and then add the NTFS time offset. */ - return cpu_to_sle64((s64)time * 10000000 + NTFS_TIME_OFFSET); -} - -/** - * get_current_ntfs_time - get the current time in little endian NTFS format - * - * Get the current time from the Linux kernel, convert it to its corresponding - * NTFS time and return that in little endian format. - */ -inline s64 get_current_ntfs_time(void) -{ - /* ignores leap second */ - return utc2ntfs(get_seconds()) + xtime.tv_nsec/1000; -} - -/** - * ntfs2utc - convert NTFS time to Linux time - * @time: NTFS time (little endian) to convert to Linux - * - * Convert the little endian NTFS time @time to its corresponding Linux time - * and return that in cpu format. - * - * Linux stores time in a long at present and measures it as the number of - * 1-second intervals since 1st January 1970, 00:00:00 UTC. - * - * NTFS uses Microsoft's standard time format which is stored in a s64 and is - * measured as the number of 100 nano-second intervals since 1st January 1601, - * 00:00:00 UTC. - */ -inline time_t ntfs2utc(const s64 time) -{ - /* Subtract the NTFS time offset, then convert to 1s intervals. */ - s64 t = sle64_to_cpu(time) - NTFS_TIME_OFFSET; - do_div(t, 10000000); - return (time_t)t; -} - diff -Nru a/fs/ntfs/time.h b/fs/ntfs/time.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/ntfs/time.h Thu Apr 29 23:19:49 2004 @@ -0,0 +1,100 @@ +/* + * time.h - NTFS time conversion functions. Part of the Linux-NTFS project. + * + * Copyright (c) 2001-2004 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 + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program/include file is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program (in the main directory of the Linux-NTFS + * distribution in the file COPYING); if not, write to the Free Software + * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _LINUX_NTFS_TIME_H +#define _LINUX_NTFS_TIME_H + +#include /* For current_kernel_time(). */ +#include /* For do_div(). */ + +#include "endian.h" + +#define NTFS_TIME_OFFSET ((s64)(369 * 365 + 89) * 24 * 3600 * 10000000) + +/** + * utc2ntfs - convert Linux UTC time to NTFS time + * @ts: Linux UTC time to convert to NTFS time + * + * Convert the Linux UTC time @ts to its corresponding NTFS time and return + * that in little endian format. + * + * Linux stores time in a struct timespec consisting of a time_t (long at + * present) tv_sec and a long tv_nsec where tv_sec is the number of 1-second + * intervals since 1st January 1970, 00:00:00 UTC and tv_nsec is the number of + * 1-nano-second intervals since the value of tv_sec. + * + * NTFS uses Microsoft's standard time format which is stored in a s64 and is + * measured as the number of 100-nano-second intervals since 1st January 1601, + * 00:00:00 UTC. + */ +static inline s64 utc2ntfs(const struct timespec ts) +{ + /* + * Convert the seconds to 100ns intervals, add the nano-seconds + * converted to 100ns intervals, and then add the NTFS time offset. + */ + return cpu_to_sle64((s64)ts.tv_sec * 10000000 + ts.tv_nsec / 100 + + NTFS_TIME_OFFSET); +} + +/** + * get_current_ntfs_time - get the current time in little endian NTFS format + * + * Get the current time from the Linux kernel, convert it to its corresponding + * NTFS time and return that in little endian format. + */ +static inline s64 get_current_ntfs_time(void) +{ + return utc2ntfs(current_kernel_time()); +} + +/** + * ntfs2utc - convert NTFS time to Linux time + * @time: NTFS time (little endian) to convert to Linux UTC + * + * Convert the little endian NTFS time @time to its corresponding Linux UTC + * time and return that in cpu format. + * + * Linux stores time in a struct timespec consisting of a time_t (long at + * present) tv_sec and a long tv_nsec where tv_sec is the number of 1-second + * intervals since 1st January 1970, 00:00:00 UTC and tv_nsec is the number of + * 1-nano-second intervals since the value of tv_sec. + * + * NTFS uses Microsoft's standard time format which is stored in a s64 and is + * measured as the number of 100 nano-second intervals since 1st January 1601, + * 00:00:00 UTC. + */ +static inline struct timespec ntfs2utc(const s64 time) +{ + struct timespec ts; + + /* Subtract the NTFS time offset. */ + s64 t = sle64_to_cpu(time) - NTFS_TIME_OFFSET; + /* + * Convert the time to 1-second intervals and the remainder to + * 1-nano-second intervals. + */ + ts.tv_nsec = do_div(t, 10000000) * 100; + ts.tv_sec = t; + return ts; +} + +#endif /* _LINUX_NTFS_TIME_H */ diff -Nru a/fs/ntfs/volume.h b/fs/ntfs/volume.h --- a/fs/ntfs/volume.h Thu Apr 29 23:19:49 2004 +++ b/fs/ntfs/volume.h Thu Apr 29 23:19:49 2004 @@ -2,7 +2,7 @@ * volume.h - Defines for volume structures in NTFS Linux kernel driver. Part * of the Linux-NTFS project. * - * Copyright (c) 2001,2002 Anton Altaparmakov. + * Copyright (c) 2001-2004 Anton Altaparmakov. * Copyright (c) 2002 Richard Russon. * * This program/include file is free software; you can redistribute it and/or @@ -10,13 +10,13 @@ * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program/include file is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * This program/include file is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program (in the main directory of the Linux-NTFS + * along with this program (in the main directory of the Linux-NTFS * distribution in the file COPYING); if not, write to the Free Software * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -25,6 +25,7 @@ #define _LINUX_NTFS_VOLUME_H #include "types.h" +#include "layout.h" /* * The NTFS in memory super block structure. @@ -44,7 +45,7 @@ LCN nr_blocks; /* Number of NTFS_BLOCK_SIZE bytes sized blocks on the device. */ /* Configuration provided by user at mount time. */ - unsigned long flags; /* Miscellaneous flags, see above. */ + unsigned long flags; /* Miscellaneous flags, see below. */ uid_t uid; /* uid that files will be mounted as. */ gid_t gid; /* gid that files will be mounted as. */ mode_t fmask; /* The mask for file permissions. */ @@ -82,14 +83,22 @@ unsigned long nr_mft_records; /* Number of mft records == number of bits in mft bitmap. */ +#ifdef NTFS_RW struct inode *mftmirr_ino; /* The VFS inode of $MFTMirr. */ + int mftmirr_size; /* Size of mft mirror in mft records. */ + + struct inode *logfile_ino; /* The VFS inode of $LogFile. */ +#endif /* NTFS_RW */ + struct inode *lcnbmp_ino; /* The VFS inode of $Bitmap. */ struct rw_semaphore lcnbmp_lock; /* Lock for serializing accesses to the cluster bitmap ($Bitmap/$DATA). */ + struct inode *vol_ino; /* The VFS inode of $Volume. */ - unsigned long vol_flags; /* Volume flags (VOLUME_*). */ + VOLUME_FLAGS vol_flags; /* Volume flags. */ u8 major_ver; /* Ntfs major version of volume. */ u8 minor_ver; /* Ntfs minor version of volume. */ + struct inode *root_ino; /* The VFS inode of the root directory. */ struct inode *secure_ino; /* The VFS inode of $Secure (NTFS3.0+ @@ -133,4 +142,3 @@ NVOL_FNS(CaseSensitive) #endif /* _LINUX_NTFS_VOLUME_H */ -