Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a0646a1f authored by Anton Altaparmakov's avatar Anton Altaparmakov
Browse files

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

parent 949763b2
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -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.


+17 −8
Original line number Original line Diff line number Diff line
@@ -1695,6 +1695,8 @@ 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 = 0;
		if (NInoCompressed(ni) || vol->major_ver < 3)
			a->data.non_resident.compression_unit = 4;
			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;
@@ -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.
					non_resident.compression_unit +
					vol->cluster_size_bits);
					vol->cluster_size_bits);
			ni->itype.compressed.block_size_bits =
			ni->itype.compressed.block_size_bits =
				ffs(ni->itype.compressed.block_size) - 1;
					ffs(ni->itype.compressed.block_size) -
					1;
			ni->itype.compressed.block_clusters = 1U <<
			ni->itype.compressed.block_clusters = 1U <<
					a->data.non_resident.compression_unit;
					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;
+45 −23
Original line number Original line Diff line number Diff line
/**
/**
 * 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 @@ 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)
					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 << (
						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.
							ffs(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);
		}
		}
+12 −7
Original line number Original line Diff line number Diff line
@@ -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 {