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
...@@ -113,36 +113,64 @@ typedef struct { ...@@ -113,36 +113,64 @@ typedef struct {
* records (like mft records for example). * records (like mft records for example).
*/ */
typedef enum { typedef enum {
magic_BAAD = const_cpu_to_le32(0x44414142), /* BAAD == corrupt record */ /* Found in $MFT/$DATA. */
magic_CHKD = const_cpu_to_le32(0x424b4843), /* CHKD == chkdsk ??? */ magic_FILE = const_cpu_to_le32(0x454c4946), /* Mft entry. */
magic_FILE = const_cpu_to_le32(0x454c4946), /* FILE == mft entry */ magic_INDX = const_cpu_to_le32(0x58444e49), /* Index buffer. */
magic_HOLE = const_cpu_to_le32(0x454c4f48), /* HOLE == ? (NTFS 3.0+?) */ magic_HOLE = const_cpu_to_le32(0x454c4f48), /* ? (NTFS 3.0+?) */
magic_INDX = const_cpu_to_le32(0x58444e49), /* INDX == index buffer */
/* Found in $LogFile/$DATA. */
magic_RSTR = const_cpu_to_le32(0x52545352), /* Restart page. */
magic_RCRD = const_cpu_to_le32(0x44524352), /* Log record page. */
/* Found in $LogFile/$DATA. (May be found in $MFT/$DATA, also?) */
magic_CHKD = const_cpu_to_le32(0x424b4843), /* Modified by chkdsk. */
/* Found in all ntfs record containing records. */
magic_BAAD = const_cpu_to_le32(0x44414142), /* Failed multi sector
transfer was detected. */
/*
* Found in $LogFile/$DATA when a page is full or 0xff bytes and is
* thus not initialized. User has to initialize the page before using
* it.
*/
magic_empty = const_cpu_to_le32(0xffffffff),/* Record is empty and has
to be initialized before
it can be used. */
} NTFS_RECORD_TYPES; } NTFS_RECORD_TYPES;
/* /*
* Generic magic comparison macros. Finally found a use for the ## preprocessor * Generic magic comparison macros. Finally found a use for the ## preprocessor
* operator! (-8 * operator! (-8
*/ */
#define is_magic(x, m) ( (u32)(x) == magic_##m ) #define ntfs_is_magic(x, m) ( (u32)(x) == magic_##m )
#define is_magicp(p, m) ( *(u32*)(p) == magic_##m ) #define ntfs_is_magicp(p, m) ( *(u32*)(p) == magic_##m )
/* /*
* Specialised magic comparison macros. * Specialised magic comparison macros for the NTFS_RECORD_TYPES defined above.
*/ */
#define is_baad_record(x) ( is_magic (x, BAAD) ) #define ntfs_is_file_record(x) ( ntfs_is_magic (x, FILE) )
#define is_baad_recordp(p) ( is_magicp(p, BAAD) ) #define ntfs_is_file_recordp(p) ( ntfs_is_magicp(p, FILE) )
#define is_chkd_record(x) ( is_magic (x, CHKD) ) #define ntfs_is_mft_record(x) ( ntfs_is_file_record(x) )
#define is_chkd_recordp(p) ( is_magicp(p, CHKD) ) #define ntfs_is_mft_recordp(p) ( ntfs_is_file_recordp(p) )
#define is_file_record(x) ( is_magic (x, FILE) ) #define ntfs_is_indx_record(x) ( ntfs_is_magic (x, INDX) )
#define is_file_recordp(p) ( is_magicp(p, FILE) ) #define ntfs_is_indx_recordp(p) ( ntfs_is_magicp(p, INDX) )
#define is_hole_record(x) ( is_magic (x, HOLE) ) #define ntfs_is_hole_record(x) ( ntfs_is_magic (x, HOLE) )
#define is_hole_recordp(p) ( is_magicp(p, HOLE) ) #define ntfs_is_hole_recordp(p) ( ntfs_is_magicp(p, HOLE) )
#define is_indx_record(x) ( is_magic (x, INDX) )
#define is_indx_recordp(p) ( is_magicp(p, INDX) ) #define ntfs_is_rstr_record(x) ( ntfs_is_magic (x, RSTR) )
#define ntfs_is_rstr_recordp(p) ( ntfs_is_magicp(p, RSTR) )
#define ntfs_is_rcrd_record(x) ( ntfs_is_magic (x, RCRD) )
#define ntfs_is_rcrd_recordp(p) ( ntfs_is_magicp(p, RCRD) )
#define ntfs_is_chkd_record(x) ( ntfs_is_magic (x, CHKD) )
#define ntfs_is_chkd_recordp(p) ( ntfs_is_magicp(p, CHKD) )
#define ntfs_is_baad_record(x) ( ntfs_is_magic (x, BAAD) )
#define ntfs_is_baad_recordp(p) ( ntfs_is_magicp(p, BAAD) )
#define is_mft_record(x) ( is_file_record(x) ) #define ntfs_is_empty_record(x) ( ntfs_is_magic (x, empty) )
#define is_mft_recordp(p) ( is_file_recordp(p) ) #define ntfs_is_empty_recordp(p) ( ntfs_is_magicp(p, empty) )
/* /*
* The Update Sequence Array (usa) is an array of the u16 values which belong * The Update Sequence Array (usa) is an array of the u16 values which belong
...@@ -1513,49 +1541,46 @@ typedef enum { ...@@ -1513,49 +1541,46 @@ typedef enum {
/* /*
* The security descriptor control flags (16-bit). * The security descriptor control flags (16-bit).
* *
* SE_OWNER_DEFAULTED - This boolean flag, when set, indicates that the * SE_OWNER_DEFAULTED - This boolean flag, when set, indicates that the SID
* SID pointed to by the Owner field was provided by a * pointed to by the Owner field was provided by a defaulting mechanism
* defaulting mechanism rather than explicitly provided by the * rather than explicitly provided by the original provider of the
* original provider of the security descriptor. This may * security descriptor. This may affect the treatment of the SID with
* affect the treatment of the SID with respect to inheritence * respect to inheritence of an owner.
* of an owner. *
* * SE_GROUP_DEFAULTED - This boolean flag, when set, indicates that the SID in
* SE_GROUP_DEFAULTED - This boolean flag, when set, indicates that the * the Group field was provided by a defaulting mechanism rather than
* SID in the Group field was provided by a defaulting mechanism * explicitly provided by the original provider of the security
* rather than explicitly provided by the original provider of * descriptor. This may affect the treatment of the SID with respect to
* the security descriptor. This may affect the treatment of * inheritence of a primary group.
* the SID with respect to inheritence of a primary group. *
* * SE_DACL_PRESENT - This boolean flag, when set, indicates that the security
* SE_DACL_PRESENT - This boolean flag, when set, indicates that the * descriptor contains a discretionary ACL. If this flag is set and the
* security descriptor contains a discretionary ACL. If this * Dacl field of the SECURITY_DESCRIPTOR is null, then a null ACL is
* flag is set and the Dacl field of the SECURITY_DESCRIPTOR is * explicitly being specified.
* null, then a null ACL is explicitly being specified. *
* * SE_DACL_DEFAULTED - This boolean flag, when set, indicates that the ACL
* SE_DACL_DEFAULTED - This boolean flag, when set, indicates that the * pointed to by the Dacl field was provided by a defaulting mechanism
* ACL pointed to by the Dacl field was provided by a defaulting * rather than explicitly provided by the original provider of the
* mechanism rather than explicitly provided by the original * security descriptor. This may affect the treatment of the ACL with
* provider of the security descriptor. This may affect the * respect to inheritence of an ACL. This flag is ignored if the
* treatment of the ACL with respect to inheritence of an ACL. * DaclPresent flag is not set.
* This flag is ignored if the DaclPresent flag is not set. *
* * SE_SACL_PRESENT - This boolean flag, when set, indicates that the security
* SE_SACL_PRESENT - This boolean flag, when set, indicates that the * descriptor contains a system ACL pointed to by the Sacl field. If this
* security descriptor contains a system ACL pointed to by the * flag is set and the Sacl field of the SECURITY_DESCRIPTOR is null, then
* Sacl field. If this flag is set and the Sacl field of the * an empty (but present) ACL is being specified.
* SECURITY_DESCRIPTOR is null, then an empty (but present) *
* ACL is being specified. * SE_SACL_DEFAULTED - This boolean flag, when set, indicates that the ACL
* * pointed to by the Sacl field was provided by a defaulting mechanism
* SE_SACL_DEFAULTED - This boolean flag, when set, indicates that the * rather than explicitly provided by the original provider of the
* ACL pointed to by the Sacl field was provided by a defaulting * security descriptor. This may affect the treatment of the ACL with
* mechanism rather than explicitly provided by the original * respect to inheritence of an ACL. This flag is ignored if the
* provider of the security descriptor. This may affect the * SaclPresent flag is not set.
* treatment of the ACL with respect to inheritence of an ACL. *
* This flag is ignored if the SaclPresent flag is not set. * SE_SELF_RELATIVE - This boolean flag, when set, indicates that the security
* * descriptor is in self-relative form. In this form, all fields of the
* SE_SELF_RELATIVE - This boolean flag, when set, indicates that the * security descriptor are contiguous in memory and all pointer fields are
* security descriptor is in self-relative form. In this form, * expressed as offsets from the beginning of the security descriptor.
* all fields of the security descriptor are contiguous in memory
* and all pointer fields are expressed as offsets from the
* beginning of the security descriptor.
*/ */
typedef enum { typedef enum {
SE_OWNER_DEFAULTED = const_cpu_to_le16(0x0001), SE_OWNER_DEFAULTED = const_cpu_to_le16(0x0001),
......
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
...@@ -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 */
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* 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
...@@ -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);
...@@ -199,4 +200,3 @@ void post_write_mst_fixup(NTFS_RECORD *b) ...@@ -199,4 +200,3 @@ void post_write_mst_fixup(NTFS_RECORD *b)
data_pos += NTFS_BLOCK_SIZE/sizeof(u16); data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
} }
} }
...@@ -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;
...@@ -869,6 +871,35 @@ static BOOL check_mft_mirror(ntfs_volume *vol) ...@@ -869,6 +871,35 @@ static BOOL check_mft_mirror(ntfs_volume *vol)
} }
} 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,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* 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
...@@ -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,6 +34,13 @@ typedef u16 uchar_t; ...@@ -42,6 +34,13 @@ 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
...@@ -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