Loading fs/ntfs/ChangeLog +3 −1 Original line number Diff line number Diff line ToDo/Notes: - Find and fix bugs. - Checkpoint or disable the user space journal ($UsnJrnl). - In between ntfs_prepare/commit_write, need exclusion between simultaneous file extensions. This is given to us by holding i_sem on the inode. The only places in the kernel when a file is resized Loading Loading @@ -119,6 +118,9 @@ ToDo/Notes: - Use C99 style structure initialization after memory allocation where possible (fs/ntfs/{attrib.c,index.c,super.c}). Thanks to Al Viro and Pekka Enberg. - Stamp the transaction log ($UsnJrnl), aka user space journal, if it is active on the volume and we are mounting read-write or remounting from read-only to read-write. 2.1.22 - Many bug and race fixes and error handling improvements. Loading fs/ntfs/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -15,5 +15,5 @@ endif ifeq ($(CONFIG_NTFS_RW),y) EXTRA_CFLAGS += -DNTFS_RW ntfs-objs += bitmap.o lcnalloc.o logfile.o quota.o ntfs-objs += bitmap.o lcnalloc.o logfile.o quota.o usnjrnl.o endif fs/ntfs/layout.h +7 −15 Original line number Diff line number Diff line Loading @@ -936,20 +936,12 @@ typedef struct { /* 56*/ le64 quota_charged; /* Byte size of the charge to the quota for all streams of the file. Note: Is zero if quotas are disabled. */ /* 64*/ le64 usn; /* Last update sequence number /* 64*/ USN usn; /* Last update sequence number of the file. This is a direct index into the change (aka usn) journal file. It is zero if the usn journal is disabled. NOTE: To disable the journal need to delete the journal file itself and to then walk the whole mft and set all Usn entries in all mft records to zero! (This can take a while!) The journal is FILE_Extend/$UsnJrnl. Win2k will recreate the journal and initiate logging if necessary when mounting the partition. This, in contrast to disabling the journal is a very fast process, so the user won't even notice it. */ transaction log file ($UsnJrnl). It is zero if the usn journal is disabled or this file has not been subject to logging yet. See usnjrnl.h for details. */ } __attribute__ ((__packed__)) v3; /* sizeof() = 72 bytes (NTFS 3.x) */ } __attribute__ ((__packed__)) ver; Loading Loading @@ -1912,7 +1904,7 @@ enum { VOLUME_FLAGS_MASK = const_cpu_to_le16(0x803f), /* To make our life easier when checking if we must mount read-only. */ VOLUME_MUST_MOUNT_RO_MASK = const_cpu_to_le16(0x8037), VOLUME_MUST_MOUNT_RO_MASK = const_cpu_to_le16(0x8027), } __attribute__ ((__packed__)); typedef le16 VOLUME_FLAGS; Loading fs/ntfs/super.c +251 −3 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include "sysctl.h" #include "logfile.h" #include "quota.h" #include "usnjrnl.h" #include "dir.h" #include "debug.h" #include "index.h" Loading Loading @@ -497,6 +498,12 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt) NVolSetErrors(vol); return -EROFS; } if (!ntfs_stamp_usnjrnl(vol)) { ntfs_error(sb, "Failed to stamp transation log " "($UsnJrnl)%s", es); NVolSetErrors(vol); return -EROFS; } } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) { /* Remounting read-only. */ if (!NVolErrors(vol)) { Loading Loading @@ -1218,6 +1225,167 @@ static BOOL load_and_init_quota(ntfs_volume *vol) return TRUE; } /** * load_and_init_usnjrnl - load and setup the transaction log if present * @vol: ntfs super block describing device whose usnjrnl file to load * * Return TRUE on success or FALSE on error. * * If $UsnJrnl is not present or in the process of being disabled, we set * NVolUsnJrnlStamped() and return success. * * If the $UsnJrnl $DATA/$J attribute has a size equal to the lowest valid usn, * i.e. transaction logging has only just been enabled or the journal has been * stamped and nothing has been logged since, we also set NVolUsnJrnlStamped() * and return success. */ static BOOL load_and_init_usnjrnl(ntfs_volume *vol) { MFT_REF mref; struct inode *tmp_ino; ntfs_inode *tmp_ni; struct page *page; ntfs_name *name = NULL; USN_HEADER *uh; static const ntfschar UsnJrnl[9] = { const_cpu_to_le16('$'), const_cpu_to_le16('U'), const_cpu_to_le16('s'), const_cpu_to_le16('n'), const_cpu_to_le16('J'), const_cpu_to_le16('r'), const_cpu_to_le16('n'), const_cpu_to_le16('l'), 0 }; static ntfschar Max[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('M'), const_cpu_to_le16('a'), const_cpu_to_le16('x'), 0 }; static ntfschar J[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('J'), 0 }; ntfs_debug("Entering."); /* * Find the inode number for the transaction log file by looking up the * filename $UsnJrnl in the extended system files directory $Extend. */ down(&vol->extend_ino->i_sem); mref = ntfs_lookup_inode_by_name(NTFS_I(vol->extend_ino), UsnJrnl, 8, &name); up(&vol->extend_ino->i_sem); if (IS_ERR_MREF(mref)) { /* * If the file does not exist, transaction logging is disabled, * just return success. */ if (MREF_ERR(mref) == -ENOENT) { ntfs_debug("$UsnJrnl not present. Volume does not " "have transaction logging enabled."); not_enabled: /* * No need to try to stamp the transaction log if * transaction logging is not enabled. */ NVolSetUsnJrnlStamped(vol); return TRUE; } /* A real error occured. */ ntfs_error(vol->sb, "Failed to find inode number for " "$UsnJrnl."); return FALSE; } /* We do not care for the type of match that was found. */ kfree(name); /* Get the inode. */ tmp_ino = ntfs_iget(vol->sb, MREF(mref)); if (unlikely(IS_ERR(tmp_ino) || is_bad_inode(tmp_ino))) { if (!IS_ERR(tmp_ino)) iput(tmp_ino); ntfs_error(vol->sb, "Failed to load $UsnJrnl."); return FALSE; } vol->usnjrnl_ino = tmp_ino; /* * If the transaction log is in the process of being deleted, we can * ignore it. */ if (unlikely(vol->vol_flags & VOLUME_DELETE_USN_UNDERWAY)) { ntfs_debug("$UsnJrnl in the process of being disabled. " "Volume does not have transaction logging " "enabled."); goto not_enabled; } /* Get the $DATA/$Max attribute. */ tmp_ino = ntfs_attr_iget(vol->usnjrnl_ino, AT_DATA, Max, 4); if (IS_ERR(tmp_ino)) { ntfs_error(vol->sb, "Failed to load $UsnJrnl/$DATA/$Max " "attribute."); return FALSE; } vol->usnjrnl_max_ino = tmp_ino; if (unlikely(i_size_read(tmp_ino) < sizeof(USN_HEADER))) { ntfs_error(vol->sb, "Found corrupt $UsnJrnl/$DATA/$Max " "attribute (size is 0x%llx but should be at " "least 0x%x bytes).", i_size_read(tmp_ino), sizeof(USN_HEADER)); return FALSE; } /* Get the $DATA/$J attribute. */ tmp_ino = ntfs_attr_iget(vol->usnjrnl_ino, AT_DATA, J, 2); if (IS_ERR(tmp_ino)) { ntfs_error(vol->sb, "Failed to load $UsnJrnl/$DATA/$J " "attribute."); return FALSE; } vol->usnjrnl_j_ino = tmp_ino; /* Verify $J is non-resident and sparse. */ tmp_ni = NTFS_I(vol->usnjrnl_j_ino); if (unlikely(!NInoNonResident(tmp_ni) || !NInoSparse(tmp_ni))) { ntfs_error(vol->sb, "$UsnJrnl/$DATA/$J attribute is resident " "and/or not sparse."); return FALSE; } /* Read the USN_HEADER from $DATA/$Max. */ page = ntfs_map_page(vol->usnjrnl_max_ino->i_mapping, 0); if (IS_ERR(page)) { ntfs_error(vol->sb, "Failed to read from $UsnJrnl/$DATA/$Max " "attribute."); return FALSE; } uh = (USN_HEADER*)page_address(page); /* Sanity check the $Max. */ if (unlikely(sle64_to_cpu(uh->allocation_delta) > sle64_to_cpu(uh->maximum_size))) { ntfs_error(vol->sb, "Allocation delta (0x%llx) exceeds " "maximum size (0x%llx). $UsnJrnl is corrupt.", (long long)sle64_to_cpu(uh->allocation_delta), (long long)sle64_to_cpu(uh->maximum_size)); ntfs_unmap_page(page); return FALSE; } /* * If the transaction log has been stamped and nothing has been written * to it since, we do not need to stamp it. */ if (unlikely(sle64_to_cpu(uh->lowest_valid_usn) >= i_size_read(vol->usnjrnl_j_ino))) { if (likely(sle64_to_cpu(uh->lowest_valid_usn) == i_size_read(vol->usnjrnl_j_ino))) { ntfs_unmap_page(page); ntfs_debug("$UsnJrnl is enabled but nothing has been " "logged since it was last stamped. " "Treating this as if the volume does " "not have transaction logging " "enabled."); goto not_enabled; } ntfs_error(vol->sb, "$UsnJrnl has lowest valid usn (0x%llx) " "which is out of bounds (0x%llx). $UsnJrnl " "is corrupt.", (long long)sle64_to_cpu(uh->lowest_valid_usn), i_size_read(vol->usnjrnl_j_ino)); ntfs_unmap_page(page); return FALSE; } ntfs_unmap_page(page); ntfs_debug("Done."); return TRUE; } /** * load_and_init_attrdef - load the attribute definitions table for a volume * @vol: ntfs super block describing device whose attrdef to load Loading Loading @@ -1653,7 +1821,7 @@ get_ctx_vol_failed: goto iput_logfile_err_out; } /* If on NTFS versions before 3.0, we are done. */ if (vol->major_ver < 3) if (unlikely(vol->major_ver < 3)) return TRUE; /* NTFS 3.0+ specific initialization. */ /* Get the security descriptors inode. */ Loading @@ -1664,7 +1832,7 @@ get_ctx_vol_failed: ntfs_error(sb, "Failed to load $Secure."); goto iput_root_err_out; } // FIXME: Initialize security. // TODO: Initialize security. /* Get the extended system files' directory inode. */ vol->extend_ino = ntfs_iget(sb, FILE_Extend); if (IS_ERR(vol->extend_ino) || is_bad_inode(vol->extend_ino)) { Loading Loading @@ -1715,10 +1883,60 @@ get_ctx_vol_failed: sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME; NVolSetErrors(vol); } // TODO: Delete or checkpoint the $UsnJrnl if it exists. /* * Find the transaction log file ($UsnJrnl), load it if present, check * it, and set it up. */ if (!load_and_init_usnjrnl(vol)) { static const char *es1 = "Failed to load $UsnJrnl"; static const char *es2 = ". Run 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", es1, es2); goto iput_usnjrnl_err_out; } sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME; ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); } else ntfs_warning(sb, "%s. Will not be able to remount " "read-write%s", es1, es2); /* This will prevent a read-write remount. */ NVolSetErrors(vol); } /* If (still) a read-write mount, stamp the transaction log. */ if (!(sb->s_flags & MS_RDONLY) && !ntfs_stamp_usnjrnl(vol)) { static const char *es1 = "Failed to stamp transaction log " "($UsnJrnl)"; static const char *es2 = ". Run chkdsk."; /* Convert to a read-only mount. */ 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", es1, es2); goto iput_usnjrnl_err_out; } ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME; NVolSetErrors(vol); } #endif /* NTFS_RW */ return TRUE; #ifdef NTFS_RW iput_usnjrnl_err_out: if (vol->usnjrnl_j_ino) iput(vol->usnjrnl_j_ino); if (vol->usnjrnl_max_ino) iput(vol->usnjrnl_max_ino); if (vol->usnjrnl_ino) iput(vol->usnjrnl_ino); iput_quota_err_out: if (vol->quota_q_ino) iput(vol->quota_q_ino); Loading Loading @@ -1792,6 +2010,12 @@ static void ntfs_put_super(struct super_block *sb) /* NTFS 3.0+ specific. */ if (vol->major_ver >= 3) { if (vol->usnjrnl_j_ino) ntfs_commit_inode(vol->usnjrnl_j_ino); if (vol->usnjrnl_max_ino) ntfs_commit_inode(vol->usnjrnl_max_ino); if (vol->usnjrnl_ino) ntfs_commit_inode(vol->usnjrnl_ino); if (vol->quota_q_ino) ntfs_commit_inode(vol->quota_q_ino); if (vol->quota_ino) Loading Loading @@ -1847,6 +2071,18 @@ static void ntfs_put_super(struct super_block *sb) /* NTFS 3.0+ specific clean up. */ if (vol->major_ver >= 3) { #ifdef NTFS_RW if (vol->usnjrnl_j_ino) { iput(vol->usnjrnl_j_ino); vol->usnjrnl_j_ino = NULL; } if (vol->usnjrnl_max_ino) { iput(vol->usnjrnl_max_ino); vol->usnjrnl_max_ino = NULL; } if (vol->usnjrnl_ino) { iput(vol->usnjrnl_ino); vol->usnjrnl_ino = NULL; } if (vol->quota_q_ino) { iput(vol->quota_q_ino); vol->quota_q_ino = NULL; Loading Loading @@ -2463,6 +2699,18 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) /* NTFS 3.0+ specific clean up. */ if (vol->major_ver >= 3) { #ifdef NTFS_RW if (vol->usnjrnl_j_ino) { iput(vol->usnjrnl_j_ino); vol->usnjrnl_j_ino = NULL; } if (vol->usnjrnl_max_ino) { iput(vol->usnjrnl_max_ino); vol->usnjrnl_max_ino = NULL; } if (vol->usnjrnl_ino) { iput(vol->usnjrnl_ino); vol->usnjrnl_ino = NULL; } if (vol->quota_q_ino) { iput(vol->quota_q_ino); vol->quota_q_ino = NULL; Loading fs/ntfs/types.h +9 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ * types.h - Defines for NTFS Linux kernel driver specific types. * Part of the Linux-NTFS project. * * Copyright (c) 2001-2004 Anton Altaparmakov * Copyright (c) 2001-2005 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 Loading Loading @@ -53,6 +53,14 @@ typedef sle64 leLCN; typedef s64 LSN; typedef sle64 leLSN; /* * The NTFS transaction log $UsnJrnl uses usn which are signed 64-bit values. * We define our own type USN, to allow for type checking and better code * readability. */ typedef s64 USN; typedef sle64 leUSN; typedef enum { FALSE = 0, TRUE = 1 Loading Loading
fs/ntfs/ChangeLog +3 −1 Original line number Diff line number Diff line ToDo/Notes: - Find and fix bugs. - Checkpoint or disable the user space journal ($UsnJrnl). - In between ntfs_prepare/commit_write, need exclusion between simultaneous file extensions. This is given to us by holding i_sem on the inode. The only places in the kernel when a file is resized Loading Loading @@ -119,6 +118,9 @@ ToDo/Notes: - Use C99 style structure initialization after memory allocation where possible (fs/ntfs/{attrib.c,index.c,super.c}). Thanks to Al Viro and Pekka Enberg. - Stamp the transaction log ($UsnJrnl), aka user space journal, if it is active on the volume and we are mounting read-write or remounting from read-only to read-write. 2.1.22 - Many bug and race fixes and error handling improvements. Loading
fs/ntfs/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -15,5 +15,5 @@ endif ifeq ($(CONFIG_NTFS_RW),y) EXTRA_CFLAGS += -DNTFS_RW ntfs-objs += bitmap.o lcnalloc.o logfile.o quota.o ntfs-objs += bitmap.o lcnalloc.o logfile.o quota.o usnjrnl.o endif
fs/ntfs/layout.h +7 −15 Original line number Diff line number Diff line Loading @@ -936,20 +936,12 @@ typedef struct { /* 56*/ le64 quota_charged; /* Byte size of the charge to the quota for all streams of the file. Note: Is zero if quotas are disabled. */ /* 64*/ le64 usn; /* Last update sequence number /* 64*/ USN usn; /* Last update sequence number of the file. This is a direct index into the change (aka usn) journal file. It is zero if the usn journal is disabled. NOTE: To disable the journal need to delete the journal file itself and to then walk the whole mft and set all Usn entries in all mft records to zero! (This can take a while!) The journal is FILE_Extend/$UsnJrnl. Win2k will recreate the journal and initiate logging if necessary when mounting the partition. This, in contrast to disabling the journal is a very fast process, so the user won't even notice it. */ transaction log file ($UsnJrnl). It is zero if the usn journal is disabled or this file has not been subject to logging yet. See usnjrnl.h for details. */ } __attribute__ ((__packed__)) v3; /* sizeof() = 72 bytes (NTFS 3.x) */ } __attribute__ ((__packed__)) ver; Loading Loading @@ -1912,7 +1904,7 @@ enum { VOLUME_FLAGS_MASK = const_cpu_to_le16(0x803f), /* To make our life easier when checking if we must mount read-only. */ VOLUME_MUST_MOUNT_RO_MASK = const_cpu_to_le16(0x8037), VOLUME_MUST_MOUNT_RO_MASK = const_cpu_to_le16(0x8027), } __attribute__ ((__packed__)); typedef le16 VOLUME_FLAGS; Loading
fs/ntfs/super.c +251 −3 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include "sysctl.h" #include "logfile.h" #include "quota.h" #include "usnjrnl.h" #include "dir.h" #include "debug.h" #include "index.h" Loading Loading @@ -497,6 +498,12 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt) NVolSetErrors(vol); return -EROFS; } if (!ntfs_stamp_usnjrnl(vol)) { ntfs_error(sb, "Failed to stamp transation log " "($UsnJrnl)%s", es); NVolSetErrors(vol); return -EROFS; } } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) { /* Remounting read-only. */ if (!NVolErrors(vol)) { Loading Loading @@ -1218,6 +1225,167 @@ static BOOL load_and_init_quota(ntfs_volume *vol) return TRUE; } /** * load_and_init_usnjrnl - load and setup the transaction log if present * @vol: ntfs super block describing device whose usnjrnl file to load * * Return TRUE on success or FALSE on error. * * If $UsnJrnl is not present or in the process of being disabled, we set * NVolUsnJrnlStamped() and return success. * * If the $UsnJrnl $DATA/$J attribute has a size equal to the lowest valid usn, * i.e. transaction logging has only just been enabled or the journal has been * stamped and nothing has been logged since, we also set NVolUsnJrnlStamped() * and return success. */ static BOOL load_and_init_usnjrnl(ntfs_volume *vol) { MFT_REF mref; struct inode *tmp_ino; ntfs_inode *tmp_ni; struct page *page; ntfs_name *name = NULL; USN_HEADER *uh; static const ntfschar UsnJrnl[9] = { const_cpu_to_le16('$'), const_cpu_to_le16('U'), const_cpu_to_le16('s'), const_cpu_to_le16('n'), const_cpu_to_le16('J'), const_cpu_to_le16('r'), const_cpu_to_le16('n'), const_cpu_to_le16('l'), 0 }; static ntfschar Max[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('M'), const_cpu_to_le16('a'), const_cpu_to_le16('x'), 0 }; static ntfschar J[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('J'), 0 }; ntfs_debug("Entering."); /* * Find the inode number for the transaction log file by looking up the * filename $UsnJrnl in the extended system files directory $Extend. */ down(&vol->extend_ino->i_sem); mref = ntfs_lookup_inode_by_name(NTFS_I(vol->extend_ino), UsnJrnl, 8, &name); up(&vol->extend_ino->i_sem); if (IS_ERR_MREF(mref)) { /* * If the file does not exist, transaction logging is disabled, * just return success. */ if (MREF_ERR(mref) == -ENOENT) { ntfs_debug("$UsnJrnl not present. Volume does not " "have transaction logging enabled."); not_enabled: /* * No need to try to stamp the transaction log if * transaction logging is not enabled. */ NVolSetUsnJrnlStamped(vol); return TRUE; } /* A real error occured. */ ntfs_error(vol->sb, "Failed to find inode number for " "$UsnJrnl."); return FALSE; } /* We do not care for the type of match that was found. */ kfree(name); /* Get the inode. */ tmp_ino = ntfs_iget(vol->sb, MREF(mref)); if (unlikely(IS_ERR(tmp_ino) || is_bad_inode(tmp_ino))) { if (!IS_ERR(tmp_ino)) iput(tmp_ino); ntfs_error(vol->sb, "Failed to load $UsnJrnl."); return FALSE; } vol->usnjrnl_ino = tmp_ino; /* * If the transaction log is in the process of being deleted, we can * ignore it. */ if (unlikely(vol->vol_flags & VOLUME_DELETE_USN_UNDERWAY)) { ntfs_debug("$UsnJrnl in the process of being disabled. " "Volume does not have transaction logging " "enabled."); goto not_enabled; } /* Get the $DATA/$Max attribute. */ tmp_ino = ntfs_attr_iget(vol->usnjrnl_ino, AT_DATA, Max, 4); if (IS_ERR(tmp_ino)) { ntfs_error(vol->sb, "Failed to load $UsnJrnl/$DATA/$Max " "attribute."); return FALSE; } vol->usnjrnl_max_ino = tmp_ino; if (unlikely(i_size_read(tmp_ino) < sizeof(USN_HEADER))) { ntfs_error(vol->sb, "Found corrupt $UsnJrnl/$DATA/$Max " "attribute (size is 0x%llx but should be at " "least 0x%x bytes).", i_size_read(tmp_ino), sizeof(USN_HEADER)); return FALSE; } /* Get the $DATA/$J attribute. */ tmp_ino = ntfs_attr_iget(vol->usnjrnl_ino, AT_DATA, J, 2); if (IS_ERR(tmp_ino)) { ntfs_error(vol->sb, "Failed to load $UsnJrnl/$DATA/$J " "attribute."); return FALSE; } vol->usnjrnl_j_ino = tmp_ino; /* Verify $J is non-resident and sparse. */ tmp_ni = NTFS_I(vol->usnjrnl_j_ino); if (unlikely(!NInoNonResident(tmp_ni) || !NInoSparse(tmp_ni))) { ntfs_error(vol->sb, "$UsnJrnl/$DATA/$J attribute is resident " "and/or not sparse."); return FALSE; } /* Read the USN_HEADER from $DATA/$Max. */ page = ntfs_map_page(vol->usnjrnl_max_ino->i_mapping, 0); if (IS_ERR(page)) { ntfs_error(vol->sb, "Failed to read from $UsnJrnl/$DATA/$Max " "attribute."); return FALSE; } uh = (USN_HEADER*)page_address(page); /* Sanity check the $Max. */ if (unlikely(sle64_to_cpu(uh->allocation_delta) > sle64_to_cpu(uh->maximum_size))) { ntfs_error(vol->sb, "Allocation delta (0x%llx) exceeds " "maximum size (0x%llx). $UsnJrnl is corrupt.", (long long)sle64_to_cpu(uh->allocation_delta), (long long)sle64_to_cpu(uh->maximum_size)); ntfs_unmap_page(page); return FALSE; } /* * If the transaction log has been stamped and nothing has been written * to it since, we do not need to stamp it. */ if (unlikely(sle64_to_cpu(uh->lowest_valid_usn) >= i_size_read(vol->usnjrnl_j_ino))) { if (likely(sle64_to_cpu(uh->lowest_valid_usn) == i_size_read(vol->usnjrnl_j_ino))) { ntfs_unmap_page(page); ntfs_debug("$UsnJrnl is enabled but nothing has been " "logged since it was last stamped. " "Treating this as if the volume does " "not have transaction logging " "enabled."); goto not_enabled; } ntfs_error(vol->sb, "$UsnJrnl has lowest valid usn (0x%llx) " "which is out of bounds (0x%llx). $UsnJrnl " "is corrupt.", (long long)sle64_to_cpu(uh->lowest_valid_usn), i_size_read(vol->usnjrnl_j_ino)); ntfs_unmap_page(page); return FALSE; } ntfs_unmap_page(page); ntfs_debug("Done."); return TRUE; } /** * load_and_init_attrdef - load the attribute definitions table for a volume * @vol: ntfs super block describing device whose attrdef to load Loading Loading @@ -1653,7 +1821,7 @@ get_ctx_vol_failed: goto iput_logfile_err_out; } /* If on NTFS versions before 3.0, we are done. */ if (vol->major_ver < 3) if (unlikely(vol->major_ver < 3)) return TRUE; /* NTFS 3.0+ specific initialization. */ /* Get the security descriptors inode. */ Loading @@ -1664,7 +1832,7 @@ get_ctx_vol_failed: ntfs_error(sb, "Failed to load $Secure."); goto iput_root_err_out; } // FIXME: Initialize security. // TODO: Initialize security. /* Get the extended system files' directory inode. */ vol->extend_ino = ntfs_iget(sb, FILE_Extend); if (IS_ERR(vol->extend_ino) || is_bad_inode(vol->extend_ino)) { Loading Loading @@ -1715,10 +1883,60 @@ get_ctx_vol_failed: sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME; NVolSetErrors(vol); } // TODO: Delete or checkpoint the $UsnJrnl if it exists. /* * Find the transaction log file ($UsnJrnl), load it if present, check * it, and set it up. */ if (!load_and_init_usnjrnl(vol)) { static const char *es1 = "Failed to load $UsnJrnl"; static const char *es2 = ". Run 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", es1, es2); goto iput_usnjrnl_err_out; } sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME; ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); } else ntfs_warning(sb, "%s. Will not be able to remount " "read-write%s", es1, es2); /* This will prevent a read-write remount. */ NVolSetErrors(vol); } /* If (still) a read-write mount, stamp the transaction log. */ if (!(sb->s_flags & MS_RDONLY) && !ntfs_stamp_usnjrnl(vol)) { static const char *es1 = "Failed to stamp transaction log " "($UsnJrnl)"; static const char *es2 = ". Run chkdsk."; /* Convert to a read-only mount. */ 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", es1, es2); goto iput_usnjrnl_err_out; } ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME; NVolSetErrors(vol); } #endif /* NTFS_RW */ return TRUE; #ifdef NTFS_RW iput_usnjrnl_err_out: if (vol->usnjrnl_j_ino) iput(vol->usnjrnl_j_ino); if (vol->usnjrnl_max_ino) iput(vol->usnjrnl_max_ino); if (vol->usnjrnl_ino) iput(vol->usnjrnl_ino); iput_quota_err_out: if (vol->quota_q_ino) iput(vol->quota_q_ino); Loading Loading @@ -1792,6 +2010,12 @@ static void ntfs_put_super(struct super_block *sb) /* NTFS 3.0+ specific. */ if (vol->major_ver >= 3) { if (vol->usnjrnl_j_ino) ntfs_commit_inode(vol->usnjrnl_j_ino); if (vol->usnjrnl_max_ino) ntfs_commit_inode(vol->usnjrnl_max_ino); if (vol->usnjrnl_ino) ntfs_commit_inode(vol->usnjrnl_ino); if (vol->quota_q_ino) ntfs_commit_inode(vol->quota_q_ino); if (vol->quota_ino) Loading Loading @@ -1847,6 +2071,18 @@ static void ntfs_put_super(struct super_block *sb) /* NTFS 3.0+ specific clean up. */ if (vol->major_ver >= 3) { #ifdef NTFS_RW if (vol->usnjrnl_j_ino) { iput(vol->usnjrnl_j_ino); vol->usnjrnl_j_ino = NULL; } if (vol->usnjrnl_max_ino) { iput(vol->usnjrnl_max_ino); vol->usnjrnl_max_ino = NULL; } if (vol->usnjrnl_ino) { iput(vol->usnjrnl_ino); vol->usnjrnl_ino = NULL; } if (vol->quota_q_ino) { iput(vol->quota_q_ino); vol->quota_q_ino = NULL; Loading Loading @@ -2463,6 +2699,18 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) /* NTFS 3.0+ specific clean up. */ if (vol->major_ver >= 3) { #ifdef NTFS_RW if (vol->usnjrnl_j_ino) { iput(vol->usnjrnl_j_ino); vol->usnjrnl_j_ino = NULL; } if (vol->usnjrnl_max_ino) { iput(vol->usnjrnl_max_ino); vol->usnjrnl_max_ino = NULL; } if (vol->usnjrnl_ino) { iput(vol->usnjrnl_ino); vol->usnjrnl_ino = NULL; } if (vol->quota_q_ino) { iput(vol->quota_q_ino); vol->quota_q_ino = NULL; Loading
fs/ntfs/types.h +9 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ * types.h - Defines for NTFS Linux kernel driver specific types. * Part of the Linux-NTFS project. * * Copyright (c) 2001-2004 Anton Altaparmakov * Copyright (c) 2001-2005 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 Loading Loading @@ -53,6 +53,14 @@ typedef sle64 leLCN; typedef s64 LSN; typedef sle64 leLSN; /* * The NTFS transaction log $UsnJrnl uses usn which are signed 64-bit values. * We define our own type USN, to allow for type checking and better code * readability. */ typedef s64 USN; typedef sle64 leUSN; typedef enum { FALSE = 0, TRUE = 1 Loading