NTFS: Add support for sparse files which have a compression unit of 0.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
This commit is contained in:
parent
949763b2b8
commit
a0646a1f04
4 changed files with 75 additions and 38 deletions
|
@ -31,6 +31,7 @@ ToDo/Notes:
|
||||||
- Fix comparison of $MFT and $MFTMirr to not bail out when there are
|
- Fix comparison of $MFT and $MFTMirr to not bail out when there are
|
||||||
unused, invalid mft records which are the same in both $MFT and
|
unused, invalid mft records which are the same in both $MFT and
|
||||||
$MFTMirr.
|
$MFTMirr.
|
||||||
|
- Add support for sparse files which have a compression unit of 0.
|
||||||
|
|
||||||
2.1.26 - Minor bug fixes and updates.
|
2.1.26 - Minor bug fixes and updates.
|
||||||
|
|
||||||
|
|
|
@ -1695,7 +1695,9 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size)
|
||||||
a->data.non_resident.initialized_size =
|
a->data.non_resident.initialized_size =
|
||||||
cpu_to_sle64(attr_size);
|
cpu_to_sle64(attr_size);
|
||||||
if (NInoSparse(ni) || NInoCompressed(ni)) {
|
if (NInoSparse(ni) || NInoCompressed(ni)) {
|
||||||
a->data.non_resident.compression_unit = 4;
|
a->data.non_resident.compression_unit = 0;
|
||||||
|
if (NInoCompressed(ni) || vol->major_ver < 3)
|
||||||
|
a->data.non_resident.compression_unit = 4;
|
||||||
a->data.non_resident.compressed_size =
|
a->data.non_resident.compressed_size =
|
||||||
a->data.non_resident.allocated_size;
|
a->data.non_resident.allocated_size;
|
||||||
} else
|
} else
|
||||||
|
@ -1714,13 +1716,20 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size)
|
||||||
ni->allocated_size = new_size;
|
ni->allocated_size = new_size;
|
||||||
if (NInoSparse(ni) || NInoCompressed(ni)) {
|
if (NInoSparse(ni) || NInoCompressed(ni)) {
|
||||||
ni->itype.compressed.size = ni->allocated_size;
|
ni->itype.compressed.size = ni->allocated_size;
|
||||||
ni->itype.compressed.block_size = 1U <<
|
if (a->data.non_resident.compression_unit) {
|
||||||
(a->data.non_resident.compression_unit +
|
ni->itype.compressed.block_size = 1U << (a->data.
|
||||||
vol->cluster_size_bits);
|
non_resident.compression_unit +
|
||||||
ni->itype.compressed.block_size_bits =
|
vol->cluster_size_bits);
|
||||||
ffs(ni->itype.compressed.block_size) - 1;
|
ni->itype.compressed.block_size_bits =
|
||||||
ni->itype.compressed.block_clusters = 1U <<
|
ffs(ni->itype.compressed.block_size) -
|
||||||
a->data.non_resident.compression_unit;
|
1;
|
||||||
|
ni->itype.compressed.block_clusters = 1U <<
|
||||||
|
a->data.non_resident.compression_unit;
|
||||||
|
} else {
|
||||||
|
ni->itype.compressed.block_size = 0;
|
||||||
|
ni->itype.compressed.block_size_bits = 0;
|
||||||
|
ni->itype.compressed.block_clusters = 0;
|
||||||
|
}
|
||||||
vi->i_blocks = ni->itype.compressed.size >> 9;
|
vi->i_blocks = ni->itype.compressed.size >> 9;
|
||||||
} else
|
} else
|
||||||
vi->i_blocks = ni->allocated_size >> 9;
|
vi->i_blocks = ni->allocated_size >> 9;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project.
|
* inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2001-2005 Anton Altaparmakov
|
* Copyright (c) 2001-2006 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
|
||||||
|
@ -24,8 +24,10 @@
|
||||||
#include <linux/smp_lock.h>
|
#include <linux/smp_lock.h>
|
||||||
#include <linux/quotaops.h>
|
#include <linux/quotaops.h>
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
|
||||||
#include "aops.h"
|
#include "aops.h"
|
||||||
|
#include "attrib.h"
|
||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "inode.h"
|
#include "inode.h"
|
||||||
|
@ -1064,10 +1066,10 @@ skip_large_dir_stuff:
|
||||||
if (a->non_resident) {
|
if (a->non_resident) {
|
||||||
NInoSetNonResident(ni);
|
NInoSetNonResident(ni);
|
||||||
if (NInoCompressed(ni) || NInoSparse(ni)) {
|
if (NInoCompressed(ni) || NInoSparse(ni)) {
|
||||||
if (a->data.non_resident.compression_unit !=
|
if (NInoCompressed(ni) && a->data.non_resident.
|
||||||
4) {
|
compression_unit != 4) {
|
||||||
ntfs_error(vi->i_sb, "Found "
|
ntfs_error(vi->i_sb, "Found "
|
||||||
"nonstandard "
|
"non-standard "
|
||||||
"compression unit (%u "
|
"compression unit (%u "
|
||||||
"instead of 4). "
|
"instead of 4). "
|
||||||
"Cannot handle this.",
|
"Cannot handle this.",
|
||||||
|
@ -1076,16 +1078,26 @@ skip_large_dir_stuff:
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
goto unm_err_out;
|
goto unm_err_out;
|
||||||
}
|
}
|
||||||
ni->itype.compressed.block_clusters = 1U <<
|
if (a->data.non_resident.compression_unit) {
|
||||||
a->data.non_resident.
|
ni->itype.compressed.block_size = 1U <<
|
||||||
compression_unit;
|
(a->data.non_resident.
|
||||||
ni->itype.compressed.block_size = 1U << (
|
compression_unit +
|
||||||
a->data.non_resident.
|
vol->cluster_size_bits);
|
||||||
compression_unit +
|
ni->itype.compressed.block_size_bits =
|
||||||
vol->cluster_size_bits);
|
ffs(ni->itype.
|
||||||
ni->itype.compressed.block_size_bits = ffs(
|
compressed.
|
||||||
ni->itype.compressed.
|
block_size) - 1;
|
||||||
block_size) - 1;
|
ni->itype.compressed.block_clusters =
|
||||||
|
1U << a->data.
|
||||||
|
non_resident.
|
||||||
|
compression_unit;
|
||||||
|
} else {
|
||||||
|
ni->itype.compressed.block_size = 0;
|
||||||
|
ni->itype.compressed.block_size_bits =
|
||||||
|
0;
|
||||||
|
ni->itype.compressed.block_clusters =
|
||||||
|
0;
|
||||||
|
}
|
||||||
ni->itype.compressed.size = sle64_to_cpu(
|
ni->itype.compressed.size = sle64_to_cpu(
|
||||||
a->data.non_resident.
|
a->data.non_resident.
|
||||||
compressed_size);
|
compressed_size);
|
||||||
|
@ -1338,8 +1350,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
|
||||||
goto unm_err_out;
|
goto unm_err_out;
|
||||||
}
|
}
|
||||||
if (NInoCompressed(ni) || NInoSparse(ni)) {
|
if (NInoCompressed(ni) || NInoSparse(ni)) {
|
||||||
if (a->data.non_resident.compression_unit != 4) {
|
if (NInoCompressed(ni) && a->data.non_resident.
|
||||||
ntfs_error(vi->i_sb, "Found nonstandard "
|
compression_unit != 4) {
|
||||||
|
ntfs_error(vi->i_sb, "Found non-standard "
|
||||||
"compression unit (%u instead "
|
"compression unit (%u instead "
|
||||||
"of 4). Cannot handle this.",
|
"of 4). Cannot handle this.",
|
||||||
a->data.non_resident.
|
a->data.non_resident.
|
||||||
|
@ -1347,13 +1360,22 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
goto unm_err_out;
|
goto unm_err_out;
|
||||||
}
|
}
|
||||||
ni->itype.compressed.block_clusters = 1U <<
|
if (a->data.non_resident.compression_unit) {
|
||||||
a->data.non_resident.compression_unit;
|
ni->itype.compressed.block_size = 1U <<
|
||||||
ni->itype.compressed.block_size = 1U << (
|
(a->data.non_resident.
|
||||||
a->data.non_resident.compression_unit +
|
compression_unit +
|
||||||
vol->cluster_size_bits);
|
vol->cluster_size_bits);
|
||||||
ni->itype.compressed.block_size_bits = ffs(
|
ni->itype.compressed.block_size_bits =
|
||||||
ni->itype.compressed.block_size) - 1;
|
ffs(ni->itype.compressed.
|
||||||
|
block_size) - 1;
|
||||||
|
ni->itype.compressed.block_clusters = 1U <<
|
||||||
|
a->data.non_resident.
|
||||||
|
compression_unit;
|
||||||
|
} else {
|
||||||
|
ni->itype.compressed.block_size = 0;
|
||||||
|
ni->itype.compressed.block_size_bits = 0;
|
||||||
|
ni->itype.compressed.block_clusters = 0;
|
||||||
|
}
|
||||||
ni->itype.compressed.size = sle64_to_cpu(
|
ni->itype.compressed.size = sle64_to_cpu(
|
||||||
a->data.non_resident.compressed_size);
|
a->data.non_resident.compressed_size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -769,7 +769,7 @@ typedef struct {
|
||||||
compressed. (This effectively limits the
|
compressed. (This effectively limits the
|
||||||
compression unit size to be a power of two
|
compression unit size to be a power of two
|
||||||
clusters.) WinNT4 only uses a value of 4.
|
clusters.) WinNT4 only uses a value of 4.
|
||||||
Sparse files also have this set to 4. */
|
Sparse files have this set to 0 on XPSP2. */
|
||||||
/* 35*/ u8 reserved[5]; /* Align to 8-byte boundary. */
|
/* 35*/ u8 reserved[5]; /* Align to 8-byte boundary. */
|
||||||
/* The sizes below are only used when lowest_vcn is zero, as otherwise it would
|
/* The sizes below are only used when lowest_vcn is zero, as otherwise it would
|
||||||
be difficult to keep them up-to-date.*/
|
be difficult to keep them up-to-date.*/
|
||||||
|
@ -1076,16 +1076,21 @@ typedef struct {
|
||||||
/* 20*/ sle64 last_access_time; /* Time this mft record was last
|
/* 20*/ sle64 last_access_time; /* Time this mft record was last
|
||||||
accessed. */
|
accessed. */
|
||||||
/* 28*/ sle64 allocated_size; /* Byte size of on-disk allocated space
|
/* 28*/ sle64 allocated_size; /* Byte size of on-disk allocated space
|
||||||
for the data attribute. So for
|
for the unnamed data attribute. So
|
||||||
normal $DATA, this is the
|
for normal $DATA, this is the
|
||||||
allocated_size from the unnamed
|
allocated_size from the unnamed
|
||||||
$DATA attribute and for compressed
|
$DATA attribute and for compressed
|
||||||
and/or sparse $DATA, this is the
|
and/or sparse $DATA, this is the
|
||||||
compressed_size from the unnamed
|
compressed_size from the unnamed
|
||||||
$DATA attribute. NOTE: This is a
|
$DATA attribute. For a directory or
|
||||||
multiple of the cluster size. */
|
other inode without an unnamed $DATA
|
||||||
/* 30*/ sle64 data_size; /* Byte size of actual data in data
|
attribute, this is always 0. NOTE:
|
||||||
attribute. */
|
This is a multiple of the cluster
|
||||||
|
size. */
|
||||||
|
/* 30*/ sle64 data_size; /* Byte size of actual data in unnamed
|
||||||
|
data attribute. For a directory or
|
||||||
|
other inode without an unnamed $DATA
|
||||||
|
attribute, this is always 0. */
|
||||||
/* 38*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */
|
/* 38*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */
|
||||||
/* 3c*/ union {
|
/* 3c*/ union {
|
||||||
/* 3c*/ struct {
|
/* 3c*/ struct {
|
||||||
|
|
Loading…
Reference in a new issue