Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 9299
b: refs/heads/master
c: e8c2cd9
h: refs/heads/master
i:
  9297: 568b643
  9295: e4a486b
v: v3
  • Loading branch information
Anton Altaparmakov committed Sep 26, 2005
1 parent e33bddc commit 145d560
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 45 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8ddec7460d2f5db3ac35812c03676b1473d1d668
refs/heads/master: e8c2cd99a3933d93413910bc93cbd5b53177110b
10 changes: 9 additions & 1 deletion trunk/fs/ntfs/ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ ToDo/Notes:
The Windows boot will run chkdsk and then reboot. The user can then
immediately boot into Linux rather than having to do a full Windows
boot first before rebooting into Linux and we will recognize such a
journal and empty it as it is clean by definition.
journal and empty it as it is clean by definition. Note, this only
works if chkdsk left the journal in an obviously clean state.
- Support journals ($LogFile) with only one restart page as well as
journals with two different restart pages. We sanity check both and
either use the only sane one or the more recent one of the two in the
Expand Down Expand Up @@ -94,6 +95,13 @@ ToDo/Notes:
my ways.
- Fix various bugs in the runlist merging code. (Based on libntfs
changes by Richard Russon.)
- Fix sparse warnings that have crept in over time.
- Change ntfs_cluster_free() to require a write locked runlist on entry
since we otherwise get into a lock reversal deadlock if a read locked
runlist is passed in. In the process also change it to take an ntfs
inode instead of a vfs inode as parameter.
- Fix the definition of the CHKD ntfs record magic. It had an off by
two error causing it to be CHKB instead of CHKD.

2.1.23 - Implement extension of resident files and make writing safe as well as
many bug fixes, cleanups, and enhancements...
Expand Down
9 changes: 5 additions & 4 deletions trunk/fs/ntfs/layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ enum {
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. */
magic_CHKD = const_cpu_to_le32(0x444b4843), /* Modified by chkdsk. */

/* Found in all ntfs record containing records. */
magic_BAAD = const_cpu_to_le32(0x44414142), /* Failed multi sector
Expand Down Expand Up @@ -317,12 +317,13 @@ typedef u64 MFT_REF;
typedef le64 leMFT_REF;

#define MK_MREF(m, s) ((MFT_REF)(((MFT_REF)(s) << 48) | \
((MFT_REF)(m) & MFT_REF_MASK_CPU)))
((MFT_REF)(m) & (u64)MFT_REF_MASK_CPU)))
#define MK_LE_MREF(m, s) cpu_to_le64(MK_MREF(m, s))

#define MREF(x) ((unsigned long)((x) & MFT_REF_MASK_CPU))
#define MREF(x) ((unsigned long)((x) & (u64)MFT_REF_MASK_CPU))
#define MSEQNO(x) ((u16)(((x) >> 48) & 0xffff))
#define MREF_LE(x) ((unsigned long)(le64_to_cpu(x) & MFT_REF_MASK_CPU))
#define MREF_LE(x) ((unsigned long)(le64_to_cpu(x) & \
(u64)MFT_REF_MASK_CPU))
#define MSEQNO_LE(x) ((u16)((le64_to_cpu(x) >> 48) & 0xffff))

#define IS_ERR_MREF(x) (((x) & 0x0000800000000000ULL) ? 1 : 0)
Expand Down
31 changes: 13 additions & 18 deletions trunk/fs/ntfs/lcnalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -779,14 +779,13 @@ switch_to_data1_zone: search_zone = 2;

/**
* __ntfs_cluster_free - free clusters on an ntfs volume
* @vi: vfs inode whose runlist describes the clusters to free
* @start_vcn: vcn in the runlist of @vi at which to start freeing clusters
* @ni: ntfs inode whose runlist describes the clusters to free
* @start_vcn: vcn in the runlist of @ni at which to start freeing clusters
* @count: number of clusters to free or -1 for all clusters
* @write_locked: true if the runlist is locked for writing
* @is_rollback: true if this is a rollback operation
*
* Free @count clusters starting at the cluster @start_vcn in the runlist
* described by the vfs inode @vi.
* described by the vfs inode @ni.
*
* If @count is -1, all clusters from @start_vcn to the end of the runlist are
* deallocated. Thus, to completely free all clusters in a runlist, use
Expand All @@ -801,31 +800,28 @@ switch_to_data1_zone: search_zone = 2;
* Return the number of deallocated clusters (not counting sparse ones) on
* success and -errno on error.
*
* Locking: - The runlist described by @vi must be locked on entry and is
* locked on return. Note if the runlist is locked for reading the
* lock may be dropped and reacquired. Note the runlist may be
* modified when needed runlist fragments need to be mapped.
* Locking: - The runlist described by @ni must be locked for writing on entry
* and is locked on return. Note the runlist may be modified when
* needed runlist fragments need to be mapped.
* - The volume lcn bitmap must be unlocked on entry and is unlocked
* on return.
* - This function takes the volume lcn bitmap lock for writing and
* modifies the bitmap contents.
*/
s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
const BOOL write_locked, const BOOL is_rollback)
s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count,
const BOOL is_rollback)
{
s64 delta, to_free, total_freed, real_freed;
ntfs_inode *ni;
ntfs_volume *vol;
struct inode *lcnbmp_vi;
runlist_element *rl;
int err;

BUG_ON(!vi);
BUG_ON(!ni);
ntfs_debug("Entering for i_ino 0x%lx, start_vcn 0x%llx, count "
"0x%llx.%s", vi->i_ino, (unsigned long long)start_vcn,
"0x%llx.%s", ni->mft_no, (unsigned long long)start_vcn,
(unsigned long long)count,
is_rollback ? " (rollback)" : "");
ni = NTFS_I(vi);
vol = ni->vol;
lcnbmp_vi = vol->lcnbmp_ino;
BUG_ON(!lcnbmp_vi);
Expand All @@ -843,7 +839,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,

total_freed = real_freed = 0;

rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, write_locked);
rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, TRUE);
if (IS_ERR(rl)) {
if (!is_rollback)
ntfs_error(vol->sb, "Failed to find first runlist "
Expand Down Expand Up @@ -897,7 +893,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,

/* Attempt to map runlist. */
vcn = rl->vcn;
rl = ntfs_attr_find_vcn_nolock(ni, vcn, write_locked);
rl = ntfs_attr_find_vcn_nolock(ni, vcn, TRUE);
if (IS_ERR(rl)) {
err = PTR_ERR(rl);
if (!is_rollback)
Expand Down Expand Up @@ -965,8 +961,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
* If rollback fails, set the volume errors flag, emit an error
* message, and return the error code.
*/
delta = __ntfs_cluster_free(vi, start_vcn, total_freed, write_locked,
TRUE);
delta = __ntfs_cluster_free(ni, start_vcn, total_freed, TRUE);
if (delta < 0) {
ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving "
"inconsistent metadata! Unmount and run "
Expand Down
27 changes: 13 additions & 14 deletions trunk/fs/ntfs/lcnalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* lcnalloc.h - Exports for NTFS kernel cluster (de)allocation. Part of the
* Linux-NTFS project.
*
* Copyright (c) 2004 Anton Altaparmakov
* Copyright (c) 2004-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
Expand All @@ -28,6 +28,7 @@
#include <linux/fs.h>

#include "types.h"
#include "inode.h"
#include "runlist.h"
#include "volume.h"

Expand All @@ -42,18 +43,17 @@ extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol,
const VCN start_vcn, const s64 count, const LCN start_lcn,
const NTFS_CLUSTER_ALLOCATION_ZONES zone);

extern s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn,
s64 count, const BOOL write_locked, const BOOL is_rollback);
extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
s64 count, const BOOL is_rollback);

/**
* ntfs_cluster_free - free clusters on an ntfs volume
* @vi: vfs inode whose runlist describes the clusters to free
* @start_vcn: vcn in the runlist of @vi at which to start freeing clusters
* @ni: ntfs inode whose runlist describes the clusters to free
* @start_vcn: vcn in the runlist of @ni at which to start freeing clusters
* @count: number of clusters to free or -1 for all clusters
* @write_locked: true if the runlist is locked for writing
*
* Free @count clusters starting at the cluster @start_vcn in the runlist
* described by the vfs inode @vi.
* described by the ntfs inode @ni.
*
* If @count is -1, all clusters from @start_vcn to the end of the runlist are
* deallocated. Thus, to completely free all clusters in a runlist, use
Expand All @@ -65,19 +65,18 @@ extern s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn,
* Return the number of deallocated clusters (not counting sparse ones) on
* success and -errno on error.
*
* Locking: - The runlist described by @vi must be locked on entry and is
* locked on return. Note if the runlist is locked for reading the
* lock may be dropped and reacquired. Note the runlist may be
* modified when needed runlist fragments need to be mapped.
* Locking: - The runlist described by @ni must be locked for writing on entry
* and is locked on return. Note the runlist may be modified when
* needed runlist fragments need to be mapped.
* - The volume lcn bitmap must be unlocked on entry and is unlocked
* on return.
* - This function takes the volume lcn bitmap lock for writing and
* modifies the bitmap contents.
*/
static inline s64 ntfs_cluster_free(struct inode *vi, const VCN start_vcn,
s64 count, const BOOL write_locked)
static inline s64 ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
s64 count)
{
return __ntfs_cluster_free(vi, start_vcn, count, write_locked, FALSE);
return __ntfs_cluster_free(ni, start_vcn, count, FALSE);
}

extern int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
Expand Down
30 changes: 25 additions & 5 deletions trunk/fs/ntfs/logfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi,
RESTART_PAGE_HEADER *rp, s64 pos)
{
u32 logfile_system_page_size, logfile_log_page_size;
u16 usa_count, usa_ofs, usa_end, ra_ofs;
u16 ra_ofs, usa_count, usa_ofs, usa_end = 0;
BOOL have_usa = TRUE;

ntfs_debug("Entering.");
/*
Expand Down Expand Up @@ -86,6 +87,14 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi,
(int)sle16_to_cpu(rp->minor_ver));
return FALSE;
}
/*
* If chkdsk has been run the restart page may not be protected by an
* update sequence array.
*/
if (ntfs_is_chkd_record(rp->magic) && !le16_to_cpu(rp->usa_count)) {
have_usa = FALSE;
goto skip_usa_checks;
}
/* Verify the size of the update sequence array. */
usa_count = 1 + (logfile_system_page_size >> NTFS_BLOCK_SIZE_BITS);
if (usa_count != le16_to_cpu(rp->usa_count)) {
Expand All @@ -102,14 +111,16 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi,
"inconsistent update sequence array offset.");
return FALSE;
}
skip_usa_checks:
/*
* Verify the position of the restart area. It must be:
* - aligned to 8-byte boundary,
* - after the update sequence array, and
* - within the system page size.
*/
ra_ofs = le16_to_cpu(rp->restart_area_offset);
if (ra_ofs & 7 || ra_ofs < usa_end ||
if (ra_ofs & 7 || (have_usa ? ra_ofs < usa_end :
ra_ofs < sizeof(RESTART_PAGE_HEADER)) ||
ra_ofs > logfile_system_page_size) {
ntfs_error(vi->i_sb, "$LogFile restart page specifies "
"inconsistent restart area offset.");
Expand Down Expand Up @@ -402,8 +413,12 @@ static int ntfs_check_and_load_restart_page(struct inode *vi,
idx++;
} while (to_read > 0);
}
/* Perform the multi sector transfer deprotection on the buffer. */
if (post_read_mst_fixup((NTFS_RECORD*)trp,
/*
* Perform the multi sector transfer deprotection on the buffer if the
* restart page is protected.
*/
if ((!ntfs_is_chkd_record(trp->magic) || le16_to_cpu(trp->usa_count))
&& post_read_mst_fixup((NTFS_RECORD*)trp,
le32_to_cpu(rp->system_page_size))) {
/*
* A multi sector tranfer error was detected. We only need to
Expand Down Expand Up @@ -615,11 +630,16 @@ BOOL ntfs_check_logfile(struct inode *log_vi, RESTART_PAGE_HEADER **rp)
* Otherwise just throw it away.
*/
if (rstr2_lsn > rstr1_lsn) {
ntfs_debug("Using second restart page as it is more "
"recent.");
ntfs_free(rstr1_ph);
rstr1_ph = rstr2_ph;
/* rstr1_lsn = rstr2_lsn; */
} else
} else {
ntfs_debug("Using first restart page as it is more "
"recent.");
ntfs_free(rstr2_ph);
}
rstr2_ph = NULL;
}
/* All consistency checks passed. */
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/ntfs/logfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ typedef struct {
*/
enum {
RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16(0x0002),
RESTART_SPACE_FILLER = 0xffff, /* gcc: Force enum bit width to 16. */
RESTART_SPACE_FILLER = const_cpu_to_le16(0xffff), /* gcc: Force enum bit width to 16. */
} __attribute__ ((__packed__));

typedef le16 RESTART_AREA_FLAGS;
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/ntfs/mft.c
Original file line number Diff line number Diff line change
Expand Up @@ -1953,7 +1953,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol)
a = ctx->attr;
a->data.non_resident.highest_vcn = cpu_to_sle64(old_last_vcn - 1);
undo_alloc:
if (ntfs_cluster_free(vol->mft_ino, old_last_vcn, -1, TRUE) < 0) {
if (ntfs_cluster_free(mft_ni, old_last_vcn, -1) < 0) {
ntfs_error(vol->sb, "Failed to free clusters from mft data "
"attribute.%s", es);
NVolSetErrors(vol);
Expand Down

0 comments on commit 145d560

Please sign in to comment.