Commit a0646a1f authored by Anton Altaparmakov's avatar Anton Altaparmakov

NTFS: Add support for sparse files which have a compression unit of 0.

Signed-off-by: default avatarAnton Altaparmakov <aia21@cantab.net>
parent 949763b2
...@@ -31,6 +31,7 @@ ToDo/Notes: ...@@ -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) ...@@ -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) ...@@ -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;
......
/** /**
* 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 @@ ...@@ -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 @@ static int ntfs_read_locked_inode(struct inode *vi) ...@@ -1064,10 +1066,10 @@ static int ntfs_read_locked_inode(struct inode *vi)
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 @@ static int ntfs_read_locked_inode(struct inode *vi) ...@@ -1076,16 +1078,26 @@ static int ntfs_read_locked_inode(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. 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) ...@@ -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) ...@@ -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 { ...@@ -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 { ...@@ -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 {
......
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