Commit 589ab626 authored by Anton Altaparmakov's avatar Anton Altaparmakov

NTFS: Read the journal ($LogFile) and determine if the volume has been shutdown cleanly

      and force a read-only mount if not (fs/ntfs/super.c and fs/ntfs/logfile.c).  This
      is a little bit of a crude check in that we only look at the restart areas and
      not at the actual log records so that there will be a very small number of cases
      where we think that a volume is dirty when in fact it is clean.  This should only
      affect volumes that have not been shutdown cleanly and did not have any pending,
      non-check-pointed i/o.
parent ffa625ad
...@@ -38,11 +38,20 @@ ToDo: ...@@ -38,11 +38,20 @@ ToDo:
- Determine the mft mirror size as the number of mirrored mft records - Determine the mft mirror size as the number of mirrored mft records
and store it in ntfs_volume->mftmirr_size (fs/ntfs/super.c). 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 - 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). in it to the ones in the mft. Force a read-only mount if the two do
not match (fs/ntfs/super.c).
- Fix type casting related warnings on 64-bit architectures. Thanks - Fix type casting related warnings on 64-bit architectures. Thanks
to Meelis Roos for reporting them. to Meelis Roos for reporting them.
- Move %L to %ll as %L is floating point and %ll is integer which is - Move %L to %ll as %L is floating point and %ll is integer which is
what we want. what we want.
- Read the journal ($LogFile) and determine if the volume has been
shutdown cleanly and force a read-only mount if not (fs/ntfs/super.c
and fs/ntfs/logfile.c). This is a little bit of a crude check in
that we only look at the restart areas and not at the actual log
records so that there will be a very small number of cases where we
think that a volume is dirty when in fact it is clean. This should
only affect volumes that have not been shutdown cleanly and did not
have any pending, non-check-pointed i/o.
2.1.7 - Enable NFS exporting of mounted NTFS volumes. 2.1.7 - Enable NFS exporting of mounted NTFS volumes.
......
...@@ -2,15 +2,15 @@ ...@@ -2,15 +2,15 @@
obj-$(CONFIG_NTFS_FS) += ntfs.o obj-$(CONFIG_NTFS_FS) += ntfs.o
ntfs-objs := aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o \ ntfs-objs := aops.o attrib.o compress.o debug.o dir.o file.o inode.o logfile.o \
mst.o namei.o super.o sysctl.o unistr.o upcase.o mft.o mst.o namei.o super.o sysctl.o unistr.o upcase.o
EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.8-WIP\" EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.8-WIP\"
ifeq ($(CONFIG_NTFS_DEBUG),y) ifeq ($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG #EXTRA_CFLAGS += -DDEBUG
endif endif
ifeq ($(CONFIG_NTFS_RW),y) ifeq ($(CONFIG_NTFS_RW),y)
EXTRA_CFLAGS += -DNTFS_RW #EXTRA_CFLAGS += -DNTFS_RW
endif endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* /*
* malloc.h - NTFS kernel memory handling. Part of the Linux-NTFS project. * malloc.h - NTFS kernel memory handling. 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 * 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 * 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 * by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program/include file is distributed in the hope that it will be * This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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 * distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
...@@ -38,7 +38,7 @@ static inline void *ntfs_malloc_nofs(unsigned long size) ...@@ -38,7 +38,7 @@ static inline void *ntfs_malloc_nofs(unsigned long size)
{ {
if (likely(size <= PAGE_SIZE)) { if (likely(size <= PAGE_SIZE)) {
if (likely(size)) { if (likely(size)) {
/* kmalloc() has per-CPU caches so if faster for now. */ /* kmalloc() has per-CPU caches so is faster for now. */
return kmalloc(PAGE_SIZE, GFP_NOFS); return kmalloc(PAGE_SIZE, GFP_NOFS);
/* return (void *)__get_free_page(GFP_NOFS | /* return (void *)__get_free_page(GFP_NOFS |
__GFP_HIGHMEM); */ __GFP_HIGHMEM); */
...@@ -61,4 +61,3 @@ static inline void ntfs_free(void *addr) ...@@ -61,4 +61,3 @@ static inline void ntfs_free(void *addr)
} }
#endif /* _LINUX_NTFS_MALLOC_H */ #endif /* _LINUX_NTFS_MALLOC_H */
/* /*
* mst.c - NTFS multi sector transfer protection handling code. Part of the * mst.c - NTFS multi sector transfer protection handling code. Part of the
* Linux-NTFS project. * Linux-NTFS project.
* *
* Copyright (c) 2001 Anton Altaparmakov. * Copyright (c) 2001-2004 Anton Altaparmakov.
* *
* This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published * 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 * by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program/include file is distributed in the hope that it will be * This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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 * distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* post_read_mst_fixup - deprotect multi sector transfer protected data * post_read_mst_fixup - deprotect multi sector transfer protected data
* @b: pointer to the data to deprotect * @b: pointer to the data to deprotect
* @size: size in bytes of @b * @size: size in bytes of @b
* *
* Perform the necessary post read multi sector transfer fixup and detect the * Perform the necessary post read multi sector transfer fixup and detect the
* presence of incomplete multi sector transfers. - In that case, overwrite the * presence of incomplete multi sector transfers. - In that case, overwrite the
* magic of the ntfs record header being processed with "BAAD" (in memory only!) * magic of the ntfs record header being processed with "BAAD" (in memory only!)
...@@ -54,13 +54,13 @@ int post_read_mst_fixup(NTFS_RECORD *b, const u32 size) ...@@ -54,13 +54,13 @@ int post_read_mst_fixup(NTFS_RECORD *b, const u32 size)
usa_ofs + (usa_count * 2) > size || usa_ofs + (usa_count * 2) > size ||
(size >> NTFS_BLOCK_SIZE_BITS) != usa_count) (size >> NTFS_BLOCK_SIZE_BITS) != usa_count)
return 0; return 0;
/* Position of usn in update sequence array. */ /* Position of usn in update sequence array. */
usa_pos = (u16*)b + usa_ofs/sizeof(u16); usa_pos = (u16*)b + usa_ofs/sizeof(u16);
/* /*
* The update sequence number which has to be equal to each of the * The update sequence number which has to be equal to each of the
* u16 values before they are fixed up. Note no need to care for * u16 values before they are fixed up. Note no need to care for
* endianness since we are comparing and moving data for on disk * endianness since we are comparing and moving data for on disk
* structures which means the data is consistent. - If it is * structures which means the data is consistent. - If it is
* consistenty the wrong endianness it doesn't make any difference. * consistenty the wrong endianness it doesn't make any difference.
*/ */
usn = *usa_pos; usn = *usa_pos;
...@@ -68,18 +68,18 @@ int post_read_mst_fixup(NTFS_RECORD *b, const u32 size) ...@@ -68,18 +68,18 @@ int post_read_mst_fixup(NTFS_RECORD *b, const u32 size)
* Position in protected data of first u16 that needs fixing up. * Position in protected data of first u16 that needs fixing up.
*/ */
data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1; data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
/* /*
* Check for incomplete multi sector transfer(s). * Check for incomplete multi sector transfer(s).
*/ */
while (usa_count--) { while (usa_count--) {
if (*data_pos != usn) { if (*data_pos != usn) {
/* /*
* Incomplete multi sector transfer detected! )-: * Incomplete multi sector transfer detected! )-:
* Set the magic to "BAAD" and return failure. * Set the magic to "BAAD" and return failure.
* Note that magic_BAAD is already converted to le32. * Note that magic_BAAD is already converted to le32.
*/ */
b->magic = magic_BAAD; b->magic = magic_BAAD;
return -EINVAL; return -EINVAL;
} }
data_pos += NTFS_BLOCK_SIZE/sizeof(u16); data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
} }
...@@ -93,9 +93,9 @@ int post_read_mst_fixup(NTFS_RECORD *b, const u32 size) ...@@ -93,9 +93,9 @@ int post_read_mst_fixup(NTFS_RECORD *b, const u32 size)
* the usa into the data buffer. * the usa into the data buffer.
*/ */
*data_pos = *(++usa_pos); *data_pos = *(++usa_pos);
/* Increment position in data as well. */ /* Increment position in data as well. */
data_pos += NTFS_BLOCK_SIZE/sizeof(u16); data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
} }
return 0; return 0;
} }
...@@ -103,7 +103,7 @@ int post_read_mst_fixup(NTFS_RECORD *b, const u32 size) ...@@ -103,7 +103,7 @@ int post_read_mst_fixup(NTFS_RECORD *b, const u32 size)
* pre_write_mst_fixup - apply multi sector transfer protection * pre_write_mst_fixup - apply multi sector transfer protection
* @b: pointer to the data to protect * @b: pointer to the data to protect
* @size: size in bytes of @b * @size: size in bytes of @b
* *
* Perform the necessary pre write multi sector transfer fixup on the data * Perform the necessary pre write multi sector transfer fixup on the data
* pointer to by @b of @size. * pointer to by @b of @size.
* *
...@@ -126,7 +126,8 @@ int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size) ...@@ -126,7 +126,8 @@ int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size)
u16 *usa_pos, *data_pos; u16 *usa_pos, *data_pos;
/* Sanity check + only fixup if it makes sense. */ /* Sanity check + only fixup if it makes sense. */
if (!b || is_baad_record(b->magic) || is_hole_record(b->magic)) if (!b || ntfs_is_baad_record(b->magic) ||
ntfs_is_hole_record(b->magic))
return -EINVAL; return -EINVAL;
/* Setup the variables. */ /* Setup the variables. */
usa_ofs = le16_to_cpu(b->usa_ofs); usa_ofs = le16_to_cpu(b->usa_ofs);
...@@ -138,10 +139,10 @@ int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size) ...@@ -138,10 +139,10 @@ int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size)
usa_ofs + (usa_count * 2) > size || usa_ofs + (usa_count * 2) > size ||
(size >> NTFS_BLOCK_SIZE_BITS) != usa_count) (size >> NTFS_BLOCK_SIZE_BITS) != usa_count)
return -EINVAL; return -EINVAL;
/* Position of usn in update sequence array. */ /* Position of usn in update sequence array. */
usa_pos = (u16*)((u8*)b + usa_ofs); usa_pos = (u16*)((u8*)b + usa_ofs);
/* /*
* Cyclically increment the update sequence number * Cyclically increment the update sequence number
* (skipping 0 and -1, i.e. 0xffff). * (skipping 0 and -1, i.e. 0xffff).
*/ */
usn = le16_to_cpup(usa_pos) + 1; usn = le16_to_cpup(usa_pos) + 1;
...@@ -151,10 +152,10 @@ int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size) ...@@ -151,10 +152,10 @@ int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size)
*usa_pos = usn; *usa_pos = usn;
/* Position in data of first u16 that needs fixing up. */ /* Position in data of first u16 that needs fixing up. */
data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1; data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
/* Fixup all sectors. */ /* Fixup all sectors. */
while (usa_count--) { while (usa_count--) {
/* /*
* Increment the position in the usa and save the * Increment the position in the usa and save the
* original data from the data buffer into the usa. * original data from the data buffer into the usa.
*/ */
*(++usa_pos) = *data_pos; *(++usa_pos) = *data_pos;
...@@ -162,14 +163,14 @@ int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size) ...@@ -162,14 +163,14 @@ int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size)
*data_pos = usn; *data_pos = usn;
/* Increment position in data as well. */ /* Increment position in data as well. */
data_pos += NTFS_BLOCK_SIZE/sizeof(u16); data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
} }
return 0; return 0;
} }
/** /**
* post_write_mst_fixup - fast deprotect multi sector transfer protected data * post_write_mst_fixup - fast deprotect multi sector transfer protected data
* @b: pointer to the data to deprotect * @b: pointer to the data to deprotect
* *
* Perform the necessary post write multi sector transfer fixup, not checking * Perform the necessary post write multi sector transfer fixup, not checking
* for any errors, because we assume we have just used pre_write_mst_fixup(), * for any errors, because we assume we have just used pre_write_mst_fixup(),
* thus the data will be fine or we would never have gotten here. * thus the data will be fine or we would never have gotten here.
...@@ -181,13 +182,13 @@ void post_write_mst_fixup(NTFS_RECORD *b) ...@@ -181,13 +182,13 @@ void post_write_mst_fixup(NTFS_RECORD *b)
u16 usa_ofs = le16_to_cpu(b->usa_ofs); u16 usa_ofs = le16_to_cpu(b->usa_ofs);
u16 usa_count = le16_to_cpu(b->usa_count) - 1; u16 usa_count = le16_to_cpu(b->usa_count) - 1;
/* Position of usn in update sequence array. */ /* Position of usn in update sequence array. */
usa_pos = (u16*)b + usa_ofs/sizeof(u16); usa_pos = (u16*)b + usa_ofs/sizeof(u16);
/* Position in protected data of first u16 that needs fixing up. */ /* Position in protected data of first u16 that needs fixing up. */
data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1; data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
/* Fixup all sectors. */ /* Fixup all sectors. */
while (usa_count--) { while (usa_count--) {
/* /*
* Increment position in usa and restore original data from * Increment position in usa and restore original data from
...@@ -195,8 +196,7 @@ void post_write_mst_fixup(NTFS_RECORD *b) ...@@ -195,8 +196,7 @@ void post_write_mst_fixup(NTFS_RECORD *b)
*/ */
*data_pos = *(++usa_pos); *data_pos = *(++usa_pos);
/* Increment position in data as well. */ /* Increment position in data as well. */
data_pos += NTFS_BLOCK_SIZE/sizeof(u16); data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
} }
} }
...@@ -10,13 +10,13 @@ ...@@ -10,13 +10,13 @@
* by the Free Software Foundation; either version 2 of the License, or * by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program/include file is distributed in the hope that it will be * This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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 * distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
...@@ -77,10 +77,10 @@ extern struct inode_operations ntfs_empty_inode_ops; ...@@ -77,10 +77,10 @@ extern struct inode_operations ntfs_empty_inode_ops;
/* Generic macros to convert pointers to values and vice versa. */ /* Generic macros to convert pointers to values and vice versa. */
#ifndef p2n #ifndef p2n
#define p2n(p) ((ptrdiff_t)((ptrdiff_t*)(p))) #define p2n(p) ((ptrdiff_t)((ptrdiff_t*)(p)))
#endif #endif
#ifndef n2p #ifndef n2p
#define n2p(p) ((ptrdiff_t*)((ptrdiff_t)(p))) #define n2p(p) ((ptrdiff_t*)((ptrdiff_t)(p)))
#endif #endif
/** /**
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "ntfs.h" #include "ntfs.h"
#include "sysctl.h" #include "sysctl.h"
#include "logfile.h"
/* Number of mounted file systems which have compression enabled. */ /* Number of mounted file systems which have compression enabled. */
static unsigned long ntfs_nr_compression_users; static unsigned long ntfs_nr_compression_users;
...@@ -318,7 +319,7 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt) ...@@ -318,7 +319,7 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
*/ */
if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
if (NVolErrors(vol)) { if (NVolErrors(vol)) {
ntfs_error(sb, "Volume has errors and is read-only." ntfs_error(sb, "Volume has errors and is read-only. "
"Cannot remount read-write."); "Cannot remount read-write.");
return -EROFS; return -EROFS;
} }
...@@ -728,7 +729,7 @@ static BOOL load_and_init_mft_mirror(ntfs_volume *vol) ...@@ -728,7 +729,7 @@ static BOOL load_and_init_mft_mirror(ntfs_volume *vol)
if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) { if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) {
if (!IS_ERR(tmp_ino)) if (!IS_ERR(tmp_ino))
iput(tmp_ino); iput(tmp_ino);
ntfs_error(vol->sb, "Failed to load $MFTMirr."); /* Caller will display error message. */
return FALSE; return FALSE;
} }
/* /*
...@@ -773,6 +774,7 @@ static BOOL check_mft_mirror(ntfs_volume *vol) ...@@ -773,6 +774,7 @@ static BOOL check_mft_mirror(ntfs_volume *vol)
run_list_element *rl, rl2[2]; run_list_element *rl, rl2[2];
int mrecs_per_page, i; int mrecs_per_page, i;
ntfs_debug("Entering.");
/* Compare contents of $MFT and $MFTMirr. */ /* Compare contents of $MFT and $MFTMirr. */
mrecs_per_page = PAGE_CACHE_SIZE / vol->mft_record_size; mrecs_per_page = PAGE_CACHE_SIZE / vol->mft_record_size;
BUG_ON(!mrecs_per_page); BUG_ON(!mrecs_per_page);
...@@ -808,7 +810,7 @@ static BOOL check_mft_mirror(ntfs_volume *vol) ...@@ -808,7 +810,7 @@ static BOOL check_mft_mirror(ntfs_volume *vol)
++index; ++index;
} }
/* Make sure the record is ok. */ /* Make sure the record is ok. */
if (is_baad_recordp(kmft)) { if (ntfs_is_baad_recordp(kmft)) {
ntfs_error(sb, "Incomplete multi sector transfer " ntfs_error(sb, "Incomplete multi sector transfer "
"detected in mft record %i.", i); "detected in mft record %i.", i);
mm_unmap_out: mm_unmap_out:
...@@ -817,7 +819,7 @@ static BOOL check_mft_mirror(ntfs_volume *vol) ...@@ -817,7 +819,7 @@ static BOOL check_mft_mirror(ntfs_volume *vol)
ntfs_unmap_page(mft_page); ntfs_unmap_page(mft_page);
return FALSE; return FALSE;
} }
if (is_baad_recordp(kmirr)) { if (ntfs_is_baad_recordp(kmirr)) {
ntfs_error(sb, "Incomplete multi sector transfer " ntfs_error(sb, "Incomplete multi sector transfer "
"detected in mft mirror record %i.", i); "detected in mft mirror record %i.", i);
goto mm_unmap_out; goto mm_unmap_out;
...@@ -832,7 +834,7 @@ static BOOL check_mft_mirror(ntfs_volume *vol) ...@@ -832,7 +834,7 @@ static BOOL check_mft_mirror(ntfs_volume *vol)
/* Compare the two records. */ /* Compare the two records. */
if (memcmp(kmft, kmirr, bytes)) { if (memcmp(kmft, kmirr, bytes)) {
ntfs_error(sb, "$MFT and $MFTMirr (record %i) do not " ntfs_error(sb, "$MFT and $MFTMirr (record %i) do not "
"match. Run ntfsfix or chkdsk.", i); "match. Run ntfsfix or chkdsk.", i);
goto mm_unmap_out; goto mm_unmap_out;
} }
kmft += vol->mft_record_size; kmft += vol->mft_record_size;
...@@ -862,13 +864,42 @@ static BOOL check_mft_mirror(ntfs_volume *vol) ...@@ -862,13 +864,42 @@ static BOOL check_mft_mirror(ntfs_volume *vol)
do { do {
if (rl2[i].vcn != rl[i].vcn || rl2[i].lcn != rl[i].lcn || if (rl2[i].vcn != rl[i].vcn || rl2[i].lcn != rl[i].lcn ||
rl2[i].length != rl[i].length) { rl2[i].length != rl[i].length) {
ntfs_error(sb, "$MFTMirr location mismatch. " ntfs_error(sb, "$MFTMirr location mismatch. "
"Run chkdsk."); "Run chkdsk.");
up_read(&mirr_ni->run_list.lock); up_read(&mirr_ni->run_list.lock);
return FALSE; return FALSE;
} }
} while (rl2[i++].length); } while (rl2[i++].length);
up_read(&mirr_ni->run_list.lock); up_read(&mirr_ni->run_list.lock);
ntfs_debug("Done.");
return TRUE;
}
/**
* load_and_check_logfile - load and check the logfile inode for a volume
* @vol: ntfs super block describing device whose logfile to load
*
* Return TRUE on success or FALSE on error.
*/
static BOOL load_and_check_logfile(ntfs_volume *vol)
{
struct inode *tmp_ino;
ntfs_debug("Entering.");
tmp_ino = ntfs_iget(vol->sb, FILE_LogFile);
if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) {
if (!IS_ERR(tmp_ino))
iput(tmp_ino);
/* Caller will display error message. */
return FALSE;
}
if (!ntfs_check_logfile(tmp_ino)) {
iput(tmp_ino);
/* ntfs_check_logfile() will have displayed error output. */
return FALSE;
}
vol->logfile_ino = tmp_ino;
ntfs_debug("Done.");
return TRUE; return TRUE;
} }
...@@ -926,7 +957,7 @@ static BOOL load_and_init_upcase(ntfs_volume *vol) ...@@ -926,7 +957,7 @@ static BOOL load_and_init_upcase(ntfs_volume *vol)
goto read_partial_upcase_page; goto read_partial_upcase_page;
} }
vol->upcase_len = ino->i_size >> UCHAR_T_SIZE_BITS; vol->upcase_len = ino->i_size >> UCHAR_T_SIZE_BITS;
ntfs_debug("Read %lu bytes from $UpCase (expected %u bytes).", ntfs_debug("Read %llu bytes from $UpCase (expected %u bytes).",
ino->i_size, 64 * 1024 * sizeof(uchar_t)); ino->i_size, 64 * 1024 * sizeof(uchar_t));
iput(ino); iput(ino);
down(&ntfs_lock); down(&ntfs_lock);
...@@ -1094,25 +1125,42 @@ static BOOL load_system_files(ntfs_volume *vol) ...@@ -1094,25 +1125,42 @@ static BOOL load_system_files(ntfs_volume *vol)
unmap_mft_record(NTFS_I(vol->vol_ino)); unmap_mft_record(NTFS_I(vol->vol_ino));
printk(KERN_INFO "NTFS volume version %i.%i.\n", vol->major_ver, printk(KERN_INFO "NTFS volume version %i.%i.\n", vol->major_ver,
vol->minor_ver); vol->minor_ver);
#ifdef NTFS_RW
/* /*
* Get the inode for the logfile and empty it if this is a read-write * Get the inode for the logfile, check it and determine if the volume
* mount. * was shutdown cleanly.
*/ */
// TODO: vol->logfile_ino = ; if (!load_and_check_logfile(vol) ||
// TODO: Cleanup for error case at end of function. !ntfs_is_logfile_clean(vol->logfile_ino)) {
tmp_ino = ntfs_iget(sb, FILE_LogFile); static const char *es1 = "Failed to load $LogFile";
if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) { static const char *es2 = "$LogFile is not clean";
if (!IS_ERR(tmp_ino)) static const char *es3 = ". Mount in Windows.";
iput(tmp_ino);
ntfs_error(sb, "Failed to load $LogFile."); /* If a read-write mount, convert it to a read-only mount. */
// FIMXE: We only want to empty the thing so pointless bailing if (!(sb->s_flags & MS_RDONLY)) {
// out. Can recover/ignore. if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO |
goto iput_vol_err_out; ON_ERRORS_CONTINUE))) {
ntfs_error(sb, "%s and neither on_errors="
"continue nor on_errors="
"remount-ro was specified%s",
!vol->logfile_ino ? es1 : es2,
es3);
goto iput_logfile_err_out;
}
sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
ntfs_error(sb, "%s. Mounting read-only%s",
!vol->logfile_ino ? es1 : es2, es3);
} else
ntfs_warning(sb, "%s. Will not be able to remount "
"read-write%s",
!vol->logfile_ino ? es1 : es2, es3);
/* This will prevent a read-write remount. */
NVolSetErrors(vol);
} }
// FIXME: Empty the logfile, but only if not read-only. // FIXME: Empty the logfile, but only if not read-only.
// FIXME: What happens if someone remounts rw? We need to empty the file // FIXME: What happens if someone remounts rw? We need to empty the file
// then. We need a flag to tell us whether we have done it already. // then. We need a flag to tell us whether we have done it already.
iput(tmp_ino); #endif
/* /*
* Get the inode for the attribute definitions file and parse the * Get the inode for the attribute definitions file and parse the
* attribute definitions. * attribute definitions.
...@@ -1122,7 +1170,7 @@ static BOOL load_system_files(ntfs_volume *vol) ...@@ -1122,7 +1170,7 @@ static BOOL load_system_files(ntfs_volume *vol)
if (!IS_ERR(tmp_ino)) if (!IS_ERR(tmp_ino))
iput(tmp_ino); iput(tmp_ino);
ntfs_error(sb, "Failed to load $AttrDef."); ntfs_error(sb, "Failed to load $AttrDef.");
goto iput_vol_err_out; goto iput_logfile_err_out;
} }
// FIXME: Parse the attribute definitions. // FIXME: Parse the attribute definitions.
iput(tmp_ino); iput(tmp_ino);
...@@ -1132,7 +1180,7 @@ static BOOL load_system_files(ntfs_volume *vol) ...@@ -1132,7 +1180,7 @@ static BOOL load_system_files(ntfs_volume *vol)
if (!IS_ERR(vol->root_ino)) if (!IS_ERR(vol->root_ino))
iput(vol->root_ino); iput(vol->root_ino);
ntfs_error(sb, "Failed to load root directory."); ntfs_error(sb, "Failed to load root directory.");
goto iput_vol_err_out; goto iput_logfile_err_out;
} }
/* If on NTFS versions before 3.0, we are done. */ /* If on NTFS versions before 3.0, we are done. */
if (vol->major_ver < 3) if (vol->major_ver < 3)
...@@ -1166,7 +1214,11 @@ static BOOL load_system_files(ntfs_volume *vol) ...@@ -1166,7 +1214,11 @@ static BOOL load_system_files(ntfs_volume *vol)
iput(vol->secure_ino); iput(vol->secure_ino);
iput_root_err_out: iput_root_err_out:
iput(vol->root_ino); iput(vol->root_ino);
iput_vol_err_out: iput_logfile_err_out:
#ifdef NTFS_RW
if (vol->logfile_ino)
iput(vol->logfile_ino);
#endif /* NTFS_RW */
iput(vol->vol_ino); iput(vol->vol_ino);
iput_lcnbmp_err_out: iput_lcnbmp_err_out:
iput(vol->lcnbmp_ino); iput(vol->lcnbmp_ino);
......
...@@ -2,20 +2,20 @@ ...@@ -2,20 +2,20 @@
* types.h - Defines for NTFS Linux kernel driver specific types. * types.h - Defines for NTFS Linux kernel driver specific types.
* Part of the Linux-NTFS project. * 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 * 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 * 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 * by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program/include file is distributed in the hope that it will be * This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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 * distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
...@@ -23,14 +23,6 @@ ...@@ -23,14 +23,6 @@
#ifndef _LINUX_NTFS_TYPES_H #ifndef _LINUX_NTFS_TYPES_H
#define _LINUX_NTFS_TYPES_H #define _LINUX_NTFS_TYPES_H
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
#define SN(X) X /* Struct Name */
#define SC(P,N) P.N /* ShortCut: Prefix, Name */
#else
#define SN(X)
#define SC(P,N) N
#endif
/* 2-byte Unicode character type. */ /* 2-byte Unicode character type. */
typedef u16 uchar_t; typedef u16 uchar_t;
#define UCHAR_T_SIZE_BITS 1 #define UCHAR_T_SIZE_BITS 1
...@@ -42,15 +34,22 @@ typedef u16 uchar_t; ...@@ -42,15 +34,22 @@ typedef u16 uchar_t;
typedef s64 VCN; typedef s64 VCN;
typedef s64 LCN; typedef s64 LCN;
/*
* The NTFS journal $LogFile uses log sequence numbers which are signed 64-bit
* values. We define our own type LSN, to allow for type checking and better
* code readability.
*/
typedef s64 LSN;
/** /**
* run_list_element - in memory vcn to lcn mapping array element * run_list_element - in memory vcn to lcn mapping array element
* @vcn: starting vcn of the current array element * @vcn: starting vcn of the current array element
* @lcn: starting lcn of the current array element * @lcn: starting lcn of the current array element
* @length: length in clusters of the current array element * @length: length in clusters of the current array element
* *
* The last vcn (in fact the last vcn + 1) is reached when length == 0. * The last vcn (in fact the last vcn + 1) is reached when length == 0.
* *
* When lcn == -1 this means that the count vcns starting at vcn are not * When lcn == -1 this means that the count vcns starting at vcn are not
* physically allocated (i.e. this is a hole / data is sparse). * physically allocated (i.e. this is a hole / data is sparse).
*/ */
typedef struct { /* In memory vcn to lcn mapping structure element. */ typedef struct { /* In memory vcn to lcn mapping structure element. */
...@@ -63,7 +62,7 @@ typedef struct { /* In memory vcn to lcn mapping structure element. */ ...@@ -63,7 +62,7 @@ typedef struct { /* In memory vcn to lcn mapping structure element. */
* run_list - in memory vcn to lcn mapping array including a read/write lock * run_list - in memory vcn to lcn mapping array including a read/write lock
* @rl: pointer to an array of run list elements * @rl: pointer to an array of run list elements
* @lock: read/write spinlock for serializing access to @rl * @lock: read/write spinlock for serializing access to @rl
* *
*/ */
typedef struct { typedef struct {
run_list_element *rl; run_list_element *rl;
...@@ -81,4 +80,3 @@ typedef enum { ...@@ -81,4 +80,3 @@ typedef enum {
} IGNORE_CASE_BOOL; } IGNORE_CASE_BOOL;
#endif /* _LINUX_NTFS_TYPES_H */ #endif /* _LINUX_NTFS_TYPES_H */
...@@ -116,6 +116,7 @@ typedef enum { ...@@ -116,6 +116,7 @@ typedef enum {
create filenames in the POSIX namespace. create filenames in the POSIX namespace.
Otherwise be case insensitive and create Otherwise be case insensitive and create
file names in WIN32 namespace. */ file names in WIN32 namespace. */
NV_LogFileEmpty, /* 1: $LogFile journal is empty. */
} ntfs_volume_flags; } ntfs_volume_flags;
/* /*
...@@ -140,5 +141,6 @@ static inline void NVolClear##flag(ntfs_volume *vol) \ ...@@ -140,5 +141,6 @@ static inline void NVolClear##flag(ntfs_volume *vol) \
NVOL_FNS(Errors) NVOL_FNS(Errors)
NVOL_FNS(ShowSystemFiles) NVOL_FNS(ShowSystemFiles)
NVOL_FNS(CaseSensitive) NVOL_FNS(CaseSensitive)
NVOL_FNS(LogFileEmpty)
#endif /* _LINUX_NTFS_VOLUME_H */ #endif /* _LINUX_NTFS_VOLUME_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment