aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
authorMark Brown <broonie@kernel.org>2026-05-29 13:41:16 +0100
committerMark Brown <broonie@kernel.org>2026-05-29 13:41:16 +0100
commit3e654038ed430fa1d8dbb5161c5c45a4a3bea478 (patch)
tree2e42a8d3b18ff619c1743f91eed2246180d4e5c4 /fs
parentc50ad36cd988b822ace4370c2d0431cd3488092b (diff)
parent47a20013412ac44a71be899c206a2dc71c7a5dd9 (diff)
downloadlinux-next-history-3e654038ed430fa1d8dbb5161c5c45a4a3bea478.tar.gz
Merge branch 'ntfs-next' of https://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/ntfs.git
Diffstat (limited to 'fs')
-rw-r--r--fs/ntfs/Makefile2
-rw-r--r--fs/ntfs/attrib.c3
-rw-r--r--fs/ntfs/dir.c64
-rw-r--r--fs/ntfs/ea.c16
-rw-r--r--fs/ntfs/index.c197
-rw-r--r--fs/ntfs/index.h12
-rw-r--r--fs/ntfs/inode.c15
-rw-r--r--fs/ntfs/logfile.c3
-rw-r--r--fs/ntfs/mft.c129
-rw-r--r--fs/ntfs/namei.c5
-rw-r--r--fs/ntfs/quota.c95
-rw-r--r--fs/ntfs/quota.h15
-rw-r--r--fs/ntfs/runlist.c12
-rw-r--r--fs/ntfs/super.c153
-rw-r--r--fs/ntfs/volume.h7
15 files changed, 196 insertions, 532 deletions
diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile
index 0ce4d9a9388af..e120c2e69862a 100644
--- a/fs/ntfs/Makefile
+++ b/fs/ntfs/Makefile
@@ -5,6 +5,6 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o
ntfs-y := aops.o attrib.o collate.o dir.o file.o index.o inode.o \
mft.o mst.o namei.o runlist.o super.o unistr.o attrlist.o ea.o \
upcase.o bitmap.o lcnalloc.o logfile.o reparse.o compress.o \
- iomap.o debug.o sysctl.o quota.o object_id.o bdev-io.o
+ iomap.o debug.o sysctl.o object_id.o bdev-io.o
ccflags-$(CONFIG_NTFS_DEBUG) += -DDEBUG
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index 421c6cdcbb530..9d676375f25cb 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -16,6 +16,7 @@
* Copyright (c) 2010 Erik Larsson
*/
+#include <linux/string_choices.h>
#include <linux/writeback.h>
#include <linux/iomap.h>
@@ -1855,7 +1856,7 @@ int ntfs_attr_make_non_resident(struct ntfs_inode *ni, const u32 data_size)
if (IS_ERR(rl)) {
err = PTR_ERR(rl);
ntfs_debug("Failed to allocate cluster%s, error code %i.",
- ntfs_bytes_to_cluster(vol, new_size) > 1 ? "s" : "",
+ str_plural(ntfs_bytes_to_cluster(vol, new_size)),
err);
goto folio_err_out;
}
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c
index 20f5c7074bdd1..4b6bd5f30c65e 100644
--- a/fs/ntfs/dir.c
+++ b/fs/ntfs/dir.c
@@ -135,10 +135,6 @@ u64 ntfs_lookup_inode_by_name(struct ntfs_inode *dir_ni, const __le16 *uname,
/* Key length should not be zero if it is not last entry. */
if (!ie->key_length)
goto dir_err_out;
- /* Check the consistency of an index entry */
- if (ntfs_index_entry_inconsistent(NULL, vol, ie, COLLATION_FILE_NAME,
- dir_ni->mft_no))
- goto dir_err_out;
/*
* We perform a case sensitive comparison and if that matches
* we are done and return the mft reference of the inode (i.e.
@@ -342,43 +338,20 @@ fast_descend_into_child_node:
dir_ni->mft_no);
goto unm_err_out;
}
- /* Catch multi sector transfer fixup errors. */
- if (unlikely(!ntfs_is_indx_record(ia->magic))) {
- ntfs_error(sb,
- "Directory index record with vcn 0x%llx is corrupt. Corrupt inode 0x%llx. Run chkdsk.",
- vcn, dir_ni->mft_no);
- goto unm_err_out;
- }
- if (le64_to_cpu(ia->index_block_vcn) != vcn) {
- ntfs_error(sb,
- "Actual VCN (0x%llx) of index buffer is different from expected VCN (0x%llx). Directory inode 0x%llx is corrupt or driver bug.",
- le64_to_cpu(ia->index_block_vcn),
- vcn, dir_ni->mft_no);
- goto unm_err_out;
- }
- if (le32_to_cpu(ia->index.allocated_size) + 0x18 !=
- dir_ni->itype.index.block_size) {
- ntfs_error(sb,
- "Index buffer (VCN 0x%llx) of directory inode 0x%llx has a size (%u) differing from the directory specified size (%u). Directory inode is corrupt or driver bug.",
- vcn, dir_ni->mft_no,
- le32_to_cpu(ia->index.allocated_size) + 0x18,
- dir_ni->itype.index.block_size);
- goto unm_err_out;
- }
index_end = (u8 *)ia + dir_ni->itype.index.block_size;
if (index_end > kaddr + PAGE_SIZE) {
ntfs_error(sb,
- "Index buffer (VCN 0x%llx) of directory inode 0x%llx crosses page boundary. Impossible! Cannot access! This is probably a bug in the driver.",
- vcn, dir_ni->mft_no);
+ "Index buffer (VCN 0x%llx) of directory inode 0x%llx crosses page boundary. Impossible! Cannot access! This is probably a bug in the driver.",
+ vcn, dir_ni->mft_no);
goto unm_err_out;
}
- index_end = (u8 *)&ia->index + le32_to_cpu(ia->index.index_length);
- if (index_end > (u8 *)ia + dir_ni->itype.index.block_size) {
- ntfs_error(sb,
- "Size of index buffer (VCN 0x%llx) of directory inode 0x%llx exceeds maximum size.",
- vcn, dir_ni->mft_no);
+ err = ntfs_index_block_inconsistent(vol, ia,
+ dir_ni->itype.index.block_size,
+ vcn, COLLATION_FILE_NAME,
+ dir_ni->mft_no);
+ if (err)
goto unm_err_out;
- }
+ index_end = (u8 *)&ia->index + le32_to_cpu(ia->index.index_length);
/* The first index entry. */
ie = (struct index_entry *)((u8 *)&ia->index +
le32_to_cpu(ia->index.entries_offset));
@@ -388,15 +361,6 @@ fast_descend_into_child_node:
* reach the last entry.
*/
for (;; ie = (struct index_entry *)((u8 *)ie + le16_to_cpu(ie->length))) {
- /* Bounds checks. */
- if ((u8 *)ie < (u8 *)ia ||
- (u8 *)ie + sizeof(struct index_entry_header) > index_end ||
- (u8 *)ie + sizeof(struct index_entry_header) + le16_to_cpu(ie->key_length) >
- index_end || (u8 *)ie + le16_to_cpu(ie->length) > index_end) {
- ntfs_error(sb, "Index entry out of bounds in directory inode 0x%llx.",
- dir_ni->mft_no);
- goto unm_err_out;
- }
/*
* The last entry cannot contain a name. It can however contain
* a pointer to a child node in the B+tree so we just break out.
@@ -406,10 +370,6 @@ fast_descend_into_child_node:
/* Key length should not be zero if it is not last entry. */
if (!ie->key_length)
goto unm_err_out;
- /* Check the consistency of an index entry */
- if (ntfs_index_entry_inconsistent(NULL, vol, ie, COLLATION_FILE_NAME,
- dir_ni->mft_no))
- goto unm_err_out;
/*
* We perform a case sensitive comparison and if that matches
* we are done and return the mft reference of the inode (i.e.
@@ -892,6 +852,7 @@ static int ntfs_readdir(struct file *file, struct dir_context *actor)
ictx->vcn_size_bits = vol->cluster_size_bits;
else
ictx->vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
+ ictx->cr = ir->collation_rule;
/* The first index entry. */
next = (struct index_entry *)((u8 *)&ir->index +
@@ -929,13 +890,6 @@ static int ntfs_readdir(struct file *file, struct dir_context *actor)
if (!next)
break;
nextdir:
- /* Check the consistency of an index entry */
- if (ntfs_index_entry_inconsistent(ictx, vol, next, COLLATION_FILE_NAME,
- ndir->mft_no)) {
- err = -EIO;
- goto out;
- }
-
if (ie_pos < actor->pos) {
ie_pos += le16_to_cpu(next->length);
continue;
diff --git a/fs/ntfs/ea.c b/fs/ntfs/ea.c
index c4a4a3e3e5996..0cd192752b7cd 100644
--- a/fs/ntfs/ea.c
+++ b/fs/ntfs/ea.c
@@ -53,11 +53,11 @@ static int ntfs_ea_lookup(char *ea_buf, s64 ea_buf_size, const char *name,
loff_t offset, p_ea_size;
unsigned int next;
- if (ea_buf_size < sizeof(struct ea_attr))
- goto out;
-
offset = 0;
do {
+ if (ea_buf_size - offset < sizeof(struct ea_attr))
+ break;
+
p_ea = (const struct ea_attr *)&ea_buf[offset];
next = le32_to_cpu(p_ea->next_entry_offset);
p_ea_size = next ? next : (ea_buf_size - offset);
@@ -479,13 +479,13 @@ ssize_t ntfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
if (ea_info_qsize > ea_buf_size || ea_info_qsize == 0)
goto out;
- if (ea_info_qsize < sizeof(struct ea_attr)) {
- err = -EIO;
- goto out;
- }
-
offset = 0;
do {
+ if (ea_info_qsize - offset < sizeof(struct ea_attr)) {
+ err = -EIO;
+ goto out;
+ }
+
p_ea = (const struct ea_attr *)&ea_buf[offset];
next = le32_to_cpu(p_ea->next_entry_offset);
ea_size = next ? next : (ea_info_qsize - offset);
diff --git a/fs/ntfs/index.c b/fs/ntfs/index.c
index 146e011c1a418..8371ff4303e70 100644
--- a/fs/ntfs/index.c
+++ b/fs/ntfs/index.c
@@ -28,41 +28,10 @@
* length must have been checked beforehand to not overflow from the
* index record.
*/
-int ntfs_index_entry_inconsistent(struct ntfs_index_context *icx,
- struct ntfs_volume *vol, const struct index_entry *ie,
- __le32 collation_rule, u64 inum)
+static int ntfs_index_entry_inconsistent(const struct ntfs_volume *vol,
+ const struct index_entry *ie,
+ __le32 collation_rule, u64 inum)
{
- if (icx) {
- struct index_header *ih;
- u8 *ie_start, *ie_end;
-
- if (icx->is_in_root)
- ih = &icx->ir->index;
- else
- ih = &icx->ib->index;
-
- if ((le32_to_cpu(ih->index_length) > le32_to_cpu(ih->allocated_size)) ||
- (le32_to_cpu(ih->index_length) > icx->block_size)) {
- ntfs_error(vol->sb, "%s Index entry(0x%p)'s length is too big.",
- icx->is_in_root ? "Index root" : "Index block",
- (u8 *)icx->entry);
- return -EINVAL;
- }
-
- ie_start = (u8 *)ih + le32_to_cpu(ih->entries_offset);
- ie_end = (u8 *)ih + le32_to_cpu(ih->index_length);
-
- if (ie_start > (u8 *)ie ||
- ie_end <= (u8 *)ie + le16_to_cpu(ie->length) ||
- le16_to_cpu(ie->length) > le32_to_cpu(ih->allocated_size) ||
- le16_to_cpu(ie->length) > icx->block_size) {
- ntfs_error(vol->sb, "Index entry(0x%p) is out of range from %s",
- (u8 *)icx->entry,
- icx->is_in_root ? "index root" : "index block");
- return -EIO;
- }
- }
-
if (ie->key_length &&
((le16_to_cpu(ie->key_length) + offsetof(struct index_entry, key)) >
le16_to_cpu(ie->length))) {
@@ -303,6 +272,93 @@ static int ntfs_ie_end(struct index_entry *ie)
return ie->flags & INDEX_ENTRY_END || !ie->length;
}
+static int ntfs_index_header_inconsistent(struct ntfs_volume *vol,
+ const struct index_header *ih,
+ u32 bytes_available, u64 inum)
+{
+ u32 entries_offset, index_length, allocated_size;
+
+ if (bytes_available < sizeof(struct index_header)) {
+ ntfs_error(vol->sb,
+ "index block in inode %llu is smaller than an index header.",
+ (unsigned long long)inum);
+ return -EIO;
+ }
+
+ entries_offset = le32_to_cpu(ih->entries_offset);
+ index_length = le32_to_cpu(ih->index_length);
+ allocated_size = le32_to_cpu(ih->allocated_size);
+
+ if (entries_offset < sizeof(struct index_header) ||
+ entries_offset > bytes_available) {
+ ntfs_error(vol->sb,
+ "Invalid index entry offset in inode %llu.",
+ (unsigned long long)inum);
+ return -EIO;
+ }
+
+ if (index_length <= entries_offset) {
+ ntfs_error(vol->sb,
+ "No space for index entries in inode %llu.",
+ (unsigned long long)inum);
+ return -EIO;
+ }
+
+ if (allocated_size < index_length) {
+ ntfs_error(vol->sb,
+ "Index entries overflow in inode %llu.",
+ (unsigned long long)inum);
+ return -EIO;
+ }
+
+ if (allocated_size > bytes_available || index_length > bytes_available) {
+ ntfs_error(vol->sb,
+ "Index entries in inode %llu exceed the available buffer.",
+ (unsigned long long)inum);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int ntfs_index_entries_inconsistent(const struct ntfs_volume *vol,
+ const struct index_header *ih,
+ __le32 collation_rule, u64 inum)
+{
+ struct index_entry *ie;
+ u8 *index_end = (u8 *)ih + le32_to_cpu(ih->index_length);
+
+ for (ie = ntfs_ie_get_first((struct index_header *)ih);
+ ; ie = ntfs_ie_get_next(ie)) {
+ if ((u8 *)ie + sizeof(struct index_entry_header) > index_end ||
+ (u8 *)ie + le16_to_cpu(ie->length) > index_end) {
+ ntfs_error(vol->sb,
+ "Index entry out of bounds in inode %llu.",
+ (unsigned long long)inum);
+ return -EIO;
+ }
+
+ if (le16_to_cpu(ie->length) < sizeof(struct index_entry_header)) {
+ ntfs_error(vol->sb,
+ "Index entry too small in inode %llu.",
+ inum);
+ return -EIO;
+ }
+
+ if (ntfs_ie_end(ie))
+ break;
+
+ if (!ie->key_length)
+ return -EIO;
+
+ if (ntfs_index_entry_inconsistent(vol, ie,
+ collation_rule, inum))
+ return -EIO;
+ }
+
+ return 0;
+}
+
/*
* Find the last entry in the index block
*/
@@ -437,7 +493,7 @@ static struct index_entry *ntfs_ie_dup_novcn(struct index_entry *ie)
* The size of block is assumed to have been checked to be what is
* defined in the index root.
*
- * Returns 0 if no error was found -1 otherwise (with errno unchanged)
+ * Returns 0 if no error was found, -EIO otherwise
*
* |<--->| offsetof(struct index_block, index)
* | |<--->| sizeof(struct index_header)
@@ -452,21 +508,21 @@ static struct index_entry *ntfs_ie_dup_novcn(struct index_entry *ie)
*
* size(struct index_header) <= ent_offset < ind_length <= alloc_size < bk_size
*/
-static int ntfs_index_block_inconsistent(struct ntfs_index_context *icx,
- struct index_block *ib, s64 vcn)
+int ntfs_index_block_inconsistent(struct ntfs_volume *vol,
+ const struct index_block *ib,
+ u32 block_size, s64 vcn, __le32 cr,
+ u64 inum)
{
u32 ib_size = (unsigned int)le32_to_cpu(ib->index.allocated_size) +
offsetof(struct index_block, index);
- struct super_block *sb = icx->idx_ni->vol->sb;
- unsigned long long inum = icx->idx_ni->mft_no;
+ struct super_block *sb = vol->sb;
ntfs_debug("Entering\n");
if (!ntfs_is_indx_record(ib->magic)) {
-
ntfs_error(sb, "Corrupt index block signature: vcn %lld inode %llu\n",
- vcn, (unsigned long long)icx->idx_ni->mft_no);
- return -1;
+ vcn, (unsigned long long)inum);
+ return -EIO;
}
if (le64_to_cpu(ib->index_block_vcn) != vcn) {
@@ -474,32 +530,42 @@ static int ntfs_index_block_inconsistent(struct ntfs_index_context *icx,
"Corrupt index block: s64 (%lld) is different from expected s64 (%lld) in inode %llu\n",
(long long)le64_to_cpu(ib->index_block_vcn),
vcn, inum);
- return -1;
+ return -EIO;
}
- if (ib_size != icx->block_size) {
+ if (ib_size != block_size) {
ntfs_error(sb,
- "Corrupt index block : s64 (%lld) of inode %llu has a size (%u) differing from the index specified size (%u)\n",
- vcn, inum, ib_size, icx->block_size);
- return -1;
+ "Corrupt index block : s64 (%lld) of inode %llu has a size (%u) differing from the index specified size (%u)\n",
+ vcn, inum, ib_size, block_size);
+ return -EIO;
}
- if (le32_to_cpu(ib->index.entries_offset) < sizeof(struct index_header)) {
- ntfs_error(sb, "Invalid index entry offset in inode %lld\n", inum);
- return -1;
- }
- if (le32_to_cpu(ib->index.index_length) <=
- le32_to_cpu(ib->index.entries_offset)) {
- ntfs_error(sb, "No space for index entries in inode %lld\n", inum);
- return -1;
- }
- if (le32_to_cpu(ib->index.allocated_size) <
- le32_to_cpu(ib->index.index_length)) {
- ntfs_error(sb, "Index entries overflow in inode %lld\n", inum);
- return -1;
+ if (ntfs_index_header_inconsistent(vol, &ib->index,
+ block_size -
+ offsetof(struct index_block, index),
+ inum))
+ return -EIO;
+ if (ntfs_index_entries_inconsistent(vol, &ib->index, cr, inum))
+ return -EIO;
+ return 0;
+}
+
+int ntfs_index_root_inconsistent(struct ntfs_volume *vol,
+ const struct attr_record *a,
+ const struct index_root *ir, u64 inum)
+{
+ u32 value_length = le32_to_cpu(a->data.resident.value_length);
+
+ if (value_length < offsetof(struct index_root, index)) {
+ ntfs_error(vol->sb, "$INDEX_ROOT in inode %llu is too small.",
+ (unsigned long long)inum);
+ return -EIO;
}
- return 0;
+ return ntfs_index_header_inconsistent(vol, &ir->index,
+ value_length -
+ offsetof(struct index_root, index),
+ inum);
}
static struct index_root *ntfs_ir_lookup(struct ntfs_inode *ni, __le16 *name,
@@ -665,13 +731,14 @@ static int ntfs_ib_read(struct ntfs_index_context *icx, s64 vcn, struct index_bl
else
ntfs_error(icx->idx_ni->vol->sb,
"Failed to read full index block at %lld\n", pos);
- return -1;
+ return -EIO;
}
post_read_mst_fixup((struct ntfs_record *)((u8 *)dst), icx->block_size);
- if (ntfs_index_block_inconsistent(icx, dst, vcn))
- return -1;
-
+ if (ntfs_index_block_inconsistent(icx->idx_ni->vol, dst,
+ icx->block_size, vcn, icx->cr,
+ icx->idx_ni->mft_no))
+ return -EIO;
return 0;
}
diff --git a/fs/ntfs/index.h b/fs/ntfs/index.h
index e68d6fabaf9f1..9a03f53bba479 100644
--- a/fs/ntfs/index.h
+++ b/fs/ntfs/index.h
@@ -89,8 +89,16 @@ struct ntfs_index_context {
bool sync_write;
};
-int ntfs_index_entry_inconsistent(struct ntfs_index_context *icx, struct ntfs_volume *vol,
- const struct index_entry *ie, __le32 collation_rule, u64 inum);
+int ntfs_index_root_inconsistent(struct ntfs_volume *vol,
+ const struct attr_record *a,
+ const struct index_root *ir, u64 inum);
+int ntfs_index_block_inconsistent(struct ntfs_volume *vol,
+ const struct index_block *ib,
+ u32 block_size, s64 vcn,
+ __le32 cr, u64 inum);
+int ntfs_index_entries_inconsistent(const struct ntfs_volume *vol,
+ const struct index_header *ih,
+ __le32 collation_rule, u64 inum);
struct ntfs_index_context *ntfs_index_ctx_get(struct ntfs_inode *ni, __le16 *name,
u32 name_len);
void ntfs_index_ctx_put(struct ntfs_index_context *ictx);
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 360bebd1ee3fe..9717fb5b47097 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -890,7 +890,6 @@ skip_attr_list_load:
*/
if (S_ISDIR(vi->i_mode)) {
struct index_root *ir;
- u8 *ir_end, *index_end;
view_index_meta:
/* It is a directory, find index root attribute. */
@@ -940,10 +939,9 @@ view_index_meta:
}
ir = (struct index_root *)((u8 *)a +
le16_to_cpu(a->data.resident.value_offset));
- ir_end = (u8 *)ir + le32_to_cpu(a->data.resident.value_length);
- index_end = (u8 *)&ir->index +
- le32_to_cpu(ir->index.index_length);
- if (index_end > ir_end) {
+ if (ntfs_index_root_inconsistent(ni->vol, a, ir, ni->mft_no) ||
+ ntfs_index_entries_inconsistent(ni->vol, &ir->index,
+ ir->collation_rule, ni->mft_no)) {
ntfs_error(vi->i_sb, "Directory index is corrupt.");
goto unm_err_out;
}
@@ -1483,7 +1481,6 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
struct attr_record *a;
struct ntfs_attr_search_ctx *ctx;
struct index_root *ir;
- u8 *ir_end, *index_end;
int err = 0;
ntfs_debug("Entering for i_ino 0x%llx.", ni->mft_no);
@@ -1534,9 +1531,9 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
}
ir = (struct index_root *)((u8 *)a + le16_to_cpu(a->data.resident.value_offset));
- ir_end = (u8 *)ir + le32_to_cpu(a->data.resident.value_length);
- index_end = (u8 *)&ir->index + le32_to_cpu(ir->index.index_length);
- if (index_end > ir_end) {
+ if (ntfs_index_root_inconsistent(vol, a, ir, ni->mft_no) ||
+ ntfs_index_entries_inconsistent(vol, &ir->index,
+ ir->collation_rule, ni->mft_no)) {
ntfs_error(vi->i_sb, "Index is corrupt.");
goto unm_err_out;
}
diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c
index d3f25d8e29f9d..9df8c3095ca48 100644
--- a/fs/ntfs/logfile.c
+++ b/fs/ntfs/logfile.c
@@ -622,8 +622,7 @@ is_empty:
ntfs_debug("Done.");
return true;
err_out:
- if (rstr1_ph)
- kvfree(rstr1_ph);
+ kvfree(rstr1_ph);
return false;
}
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
index a7d10ee41b344..a5019e80951b8 100644
--- a/fs/ntfs/mft.c
+++ b/fs/ntfs/mft.c
@@ -743,23 +743,6 @@ static int ntfs_test_inode_wb(struct inode *vi, u64 ino, void *data)
*
* If the mft record is not a FILE record or it is a base mft record, we can
* safely write it and return 'true'.
- *
- * We now know the mft record is an extent mft record. We check if the inode
- * corresponding to its base mft record is in icache. If it is not, we cannot
- * safely determine the state of the extent inode, so we return 'false'.
- *
- * We now have the base inode for the extent mft record. We check if it has an
- * ntfs inode for the extent mft record attached. If not, it is safe to write
- * the extent mft record and we return 'true'.
- *
- * If the extent inode is attached, we check if it is dirty. If so, we return
- * 'false' (letting the standard write_inode path handle it).
- *
- * If it is not dirty, we attempt to lock the extent mft record. If the lock
- * was already taken, it is not safe to write and we return 'false'.
- *
- * If we manage to obtain the lock we have exclusive access to the extent mft
- * record. We set @locked_ni to the now locked ntfs inode and return 'true'.
*/
static bool ntfs_may_write_mft_record(struct ntfs_volume *vol, const u64 mft_no,
const struct mft_record *m, struct ntfs_inode **locked_ni,
@@ -768,8 +751,7 @@ static bool ntfs_may_write_mft_record(struct ntfs_volume *vol, const u64 mft_no,
struct super_block *sb = vol->sb;
struct inode *mft_vi = vol->mft_ino;
struct inode *vi;
- struct ntfs_inode *ni, *eni, **extent_nis;
- int i;
+ struct ntfs_inode *ni;
struct ntfs_attr na = {0};
ntfs_debug("Entering for inode 0x%llx.", mft_no);
@@ -849,100 +831,10 @@ static bool ntfs_may_write_mft_record(struct ntfs_volume *vol, const u64 mft_no,
mft_no);
return true;
}
- /*
- * This is an extent mft record. Check if the inode corresponding to
- * its base mft record is in icache and obtain a reference to it if it
- * is.
- */
- na.mft_no = MREF_LE(m->base_mft_record);
- na.state = 0;
- ntfs_debug("Mft record 0x%llx is an extent record. Looking for base inode 0x%llx in icache.",
- mft_no, na.mft_no);
- if (!na.mft_no) {
- /* Balance the below iput(). */
- vi = igrab(mft_vi);
- WARN_ON(vi != mft_vi);
- } else {
- vi = find_inode_nowait(sb, na.mft_no, ntfs_test_inode_wb, &na);
- if (na.state == NI_BeingDeleted || na.state == NI_BeingCreated)
- return false;
- }
- if (!vi)
- return false;
- ntfs_debug("Base inode 0x%llx is in icache.", na.mft_no);
- /*
- * The base inode is in icache. Check if it has the extent inode
- * corresponding to this extent mft record attached.
- */
- ni = NTFS_I(vi);
- mutex_lock(&ni->extent_lock);
- if (ni->nr_extents <= 0) {
- /*
- * The base inode has no attached extent inodes, write this
- * extent mft record.
- */
- mutex_unlock(&ni->extent_lock);
- *ref_vi = vi;
- ntfs_debug("Base inode 0x%llx has no attached extent inodes, write the extent record.",
- na.mft_no);
- return true;
- }
- /* Iterate over the attached extent inodes. */
- extent_nis = ni->ext.extent_ntfs_inos;
- for (eni = NULL, i = 0; i < ni->nr_extents; ++i) {
- if (mft_no == extent_nis[i]->mft_no) {
- /*
- * Found the extent inode corresponding to this extent
- * mft record.
- */
- eni = extent_nis[i];
- break;
- }
- }
- /*
- * If the extent inode was not attached to the base inode, write this
- * extent mft record.
- */
- if (!eni) {
- mutex_unlock(&ni->extent_lock);
- *ref_vi = vi;
- ntfs_debug("Extent inode 0x%llx is not attached to its base inode 0x%llx, write the extent record.",
- mft_no, na.mft_no);
- return true;
- }
- ntfs_debug("Extent inode 0x%llx is attached to its base inode 0x%llx.",
- mft_no, na.mft_no);
- /* Take a reference to the extent ntfs inode. */
- atomic_inc(&eni->count);
- mutex_unlock(&ni->extent_lock);
-
- /* if extent inode is dirty, write_inode will write it */
- if (NInoDirty(eni)) {
- atomic_dec(&eni->count);
- *ref_vi = vi;
- return false;
- }
-
- /*
- * Found the extent inode coresponding to this extent mft record.
- * Try to take the mft record lock.
- */
- if (unlikely(!mutex_trylock(&eni->mrec_lock))) {
- atomic_dec(&eni->count);
- *ref_vi = vi;
- ntfs_debug("Extent mft record 0x%llx is already locked, do not write it.",
- mft_no);
- return false;
- }
- ntfs_debug("Managed to lock extent mft record 0x%llx, write it.",
- mft_no);
- /*
- * The write has to occur while we hold the mft record lock so return
- * the locked extent ntfs inode.
- */
- *locked_ni = eni;
- return true;
+ ntfs_debug("Mft record 0x%llx is an extent record, skip it.",
+ mft_no);
+ return false;
}
static const char *es = " Leaving inconsistent metadata. Unmount and run chkdsk.";
@@ -2792,19 +2684,6 @@ static int ntfs_write_mft_block(struct folio *folio, struct writeback_control *w
s64 vcn_off = vcn;
/*
- * Skip $MFT extent mft records and let them being written
- * by writeback to avioid deadlocks. the $MFT runlist
- * lock must be taken before $MFT extent mrec_lock is taken.
- */
- if (tni && tni->nr_extents < 0 &&
- tni->ext.base_ntfs_ino == NTFS_I(vol->mft_ino)) {
- mutex_unlock(&tni->mrec_lock);
- atomic_dec(&tni->count);
- iput(vol->mft_ino);
- continue;
- }
-
- /*
* The record should be written. If a locked ntfs
* inode was returned, add it to the array of locked
* ntfs inodes.
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index c4f82846c58c3..9c1c36acfad24 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -1532,8 +1532,7 @@ static int ntfs_link(struct dentry *old_dentry, struct inode *dir,
if (uname_len < 0) {
if (uname_len != -ENAMETOOLONG)
ntfs_error(sb, "Failed to convert name to unicode.");
- err = -ENOMEM;
- goto out;
+ return -ENOMEM;
}
if (!(vol->vol_flags & VOLUME_IS_DIRTY))
@@ -1563,7 +1562,7 @@ static int ntfs_link(struct dentry *old_dentry, struct inode *dir,
mutex_unlock(&ni->mrec_lock);
out:
- kfree(uname);
+ kmem_cache_free(ntfs_name_cache, uname);
return err;
}
diff --git a/fs/ntfs/quota.c b/fs/ntfs/quota.c
deleted file mode 100644
index b443243b58fbf..0000000000000
--- a/fs/ntfs/quota.c
+++ /dev/null
@@ -1,95 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * NTFS kernel quota ($Quota) handling.
- *
- * Copyright (c) 2004 Anton Altaparmakov
- */
-
-#include "index.h"
-#include "quota.h"
-#include "debug.h"
-#include "ntfs.h"
-
-/*
- * ntfs_mark_quotas_out_of_date - mark the quotas out of date on an ntfs volume
- * @vol: ntfs volume on which to mark the quotas out of date
- *
- * Mark the quotas out of date on the ntfs volume @vol and return 'true' on
- * success and 'false' on error.
- */
-bool ntfs_mark_quotas_out_of_date(struct ntfs_volume *vol)
-{
- struct ntfs_index_context *ictx;
- struct quota_control_entry *qce;
- const __le32 qid = QUOTA_DEFAULTS_ID;
- int err;
-
- ntfs_debug("Entering.");
- if (NVolQuotaOutOfDate(vol))
- goto done;
- if (!vol->quota_ino || !vol->quota_q_ino) {
- ntfs_error(vol->sb, "Quota inodes are not open.");
- return false;
- }
- inode_lock(vol->quota_q_ino);
- ictx = ntfs_index_ctx_get(NTFS_I(vol->quota_q_ino), I30, 4);
- if (!ictx) {
- ntfs_error(vol->sb, "Failed to get index context.");
- goto err_out;
- }
- err = ntfs_index_lookup(&qid, sizeof(qid), ictx);
- if (err) {
- if (err == -ENOENT)
- ntfs_error(vol->sb, "Quota defaults entry is not present.");
- else
- ntfs_error(vol->sb, "Lookup of quota defaults entry failed.");
- goto err_out;
- }
- if (ictx->data_len < offsetof(struct quota_control_entry, sid)) {
- ntfs_error(vol->sb, "Quota defaults entry size is invalid. Run chkdsk.");
- goto err_out;
- }
- qce = (struct quota_control_entry *)ictx->data;
- if (le32_to_cpu(qce->version) != QUOTA_VERSION) {
- ntfs_error(vol->sb,
- "Quota defaults entry version 0x%x is not supported.",
- le32_to_cpu(qce->version));
- goto err_out;
- }
- ntfs_debug("Quota defaults flags = 0x%x.", le32_to_cpu(qce->flags));
- /* If quotas are already marked out of date, no need to do anything. */
- if (qce->flags & QUOTA_FLAG_OUT_OF_DATE)
- goto set_done;
- /*
- * If quota tracking is neither requested, nor enabled and there are no
- * pending deletes, no need to mark the quotas out of date.
- */
- if (!(qce->flags & (QUOTA_FLAG_TRACKING_ENABLED |
- QUOTA_FLAG_TRACKING_REQUESTED |
- QUOTA_FLAG_PENDING_DELETES)))
- goto set_done;
- /*
- * Set the QUOTA_FLAG_OUT_OF_DATE bit thus marking quotas out of date.
- * This is verified on WinXP to be sufficient to cause windows to
- * rescan the volume on boot and update all quota entries.
- */
- qce->flags |= QUOTA_FLAG_OUT_OF_DATE;
- /* Ensure the modified flags are written to disk. */
- ntfs_index_entry_mark_dirty(ictx);
-set_done:
- ntfs_index_ctx_put(ictx);
- inode_unlock(vol->quota_q_ino);
- /*
- * We set the flag so we do not try to mark the quotas out of date
- * again on remount.
- */
- NVolSetQuotaOutOfDate(vol);
-done:
- ntfs_debug("Done.");
- return true;
-err_out:
- if (ictx)
- ntfs_index_ctx_put(ictx);
- inode_unlock(vol->quota_q_ino);
- return false;
-}
diff --git a/fs/ntfs/quota.h b/fs/ntfs/quota.h
deleted file mode 100644
index 4b7322661a326..0000000000000
--- a/fs/ntfs/quota.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Defines for NTFS kernel quota ($Quota) handling.
- *
- * Copyright (c) 2004 Anton Altaparmakov
- */
-
-#ifndef _LINUX_NTFS_QUOTA_H
-#define _LINUX_NTFS_QUOTA_H
-
-#include "volume.h"
-
-bool ntfs_mark_quotas_out_of_date(struct ntfs_volume *vol);
-
-#endif /* _LINUX_NTFS_QUOTA_H */
diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c
index e7de3d01257e7..f27d78013856e 100644
--- a/fs/ntfs/runlist.c
+++ b/fs/ntfs/runlist.c
@@ -1817,7 +1817,7 @@ struct runlist_element *ntfs_rl_punch_hole(struct runlist_element *dst_rl, int d
!ntfs_rle_contain(s_rl, start_vcn))
return ERR_PTR(-EINVAL);
- begin_split = s_rl->vcn != start_vcn ? true : false;
+ begin_split = s_rl->vcn != start_vcn;
e_rl = ntfs_rl_find_vcn_nolock(dst_rl, end_vcn);
if (!e_rl ||
@@ -1825,10 +1825,10 @@ struct runlist_element *ntfs_rl_punch_hole(struct runlist_element *dst_rl, int d
!ntfs_rle_contain(e_rl, end_vcn))
return ERR_PTR(-EINVAL);
- end_split = e_rl->vcn + e_rl->length - 1 != end_vcn ? true : false;
+ end_split = e_rl->vcn + e_rl->length - 1 != end_vcn;
/* @s_rl has to be split into left, punched hole, and right */
- one_split_3 = e_rl == s_rl && begin_split && end_split ? true : false;
+ one_split_3 = e_rl == s_rl && begin_split && end_split;
punch_cnt = (int)(e_rl - s_rl) + 1;
@@ -1968,7 +1968,7 @@ struct runlist_element *ntfs_rl_collapse_range(struct runlist_element *dst_rl, i
!ntfs_rle_contain(s_rl, start_vcn))
return ERR_PTR(-EINVAL);
- begin_split = s_rl->vcn != start_vcn ? true : false;
+ begin_split = s_rl->vcn != start_vcn;
e_rl = ntfs_rl_find_vcn_nolock(dst_rl, end_vcn);
if (!e_rl ||
@@ -1976,10 +1976,10 @@ struct runlist_element *ntfs_rl_collapse_range(struct runlist_element *dst_rl, i
!ntfs_rle_contain(e_rl, end_vcn))
return ERR_PTR(-EINVAL);
- end_split = e_rl->vcn + e_rl->length - 1 != end_vcn ? true : false;
+ end_split = e_rl->vcn + e_rl->length - 1 != end_vcn;
/* @s_rl has to be split into left, collapsed, and right */
- one_split_3 = e_rl == s_rl && begin_split && end_split ? true : false;
+ one_split_3 = e_rl == s_rl && begin_split && end_split;
punch_cnt = (int)(e_rl - s_rl) + 1;
*punch_rl = kvcalloc(punch_cnt + 1, sizeof(struct runlist_element),
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 9e321cc2febe7..2a5ad7d56bc26 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -17,7 +17,6 @@
#include "sysctl.h"
#include "logfile.h"
-#include "quota.h"
#include "index.h"
#include "ntfs.h"
#include "ea.h"
@@ -240,8 +239,7 @@ static int ntfs_reconfigure(struct fs_context *fc)
* flags are set. Also, empty the logfile journal as it would become
* stale as soon as something is written to the volume and mark the
* volume dirty so that chkdsk is run if the volume is not umounted
- * cleanly. Finally, mark the quotas out of date so Windows rescans
- * the volume on boot and updates them.
+ * cleanly.
*
* When remounting read-only, mark the volume clean if no volume errors
* have occurred.
@@ -274,12 +272,6 @@ static int ntfs_reconfigure(struct fs_context *fc)
NVolSetErrors(vol);
return -EROFS;
}
- if (!ntfs_mark_quotas_out_of_date(vol)) {
- ntfs_error(sb, "Failed to mark quotas out of date%s",
- es);
- NVolSetErrors(vol);
- return -EROFS;
- }
} else if (!sb_rdonly(sb) && (fc->sb_flags & SB_RDONLY)) {
/* Remounting read-only. */
if (!NVolErrors(vol)) {
@@ -1176,73 +1168,6 @@ iput_out:
}
/*
- * load_and_init_quota - load and setup the quota file for a volume if present
- * @vol: ntfs super block describing device whose quota file to load
- *
- * Return 'true' on success or 'false' on error. If $Quota is not present, we
- * leave vol->quota_ino as NULL and return success.
- */
-static bool load_and_init_quota(struct ntfs_volume *vol)
-{
- static const __le16 Quota[7] = { cpu_to_le16('$'),
- cpu_to_le16('Q'), cpu_to_le16('u'),
- cpu_to_le16('o'), cpu_to_le16('t'),
- cpu_to_le16('a'), 0 };
- static __le16 Q[3] = { cpu_to_le16('$'),
- cpu_to_le16('Q'), 0 };
- struct ntfs_name *name = NULL;
- u64 mref;
- struct inode *tmp_ino;
-
- ntfs_debug("Entering.");
- /*
- * Find the inode number for the quota file by looking up the filename
- * $Quota in the extended system files directory $Extend.
- */
- inode_lock(vol->extend_ino);
- mref = ntfs_lookup_inode_by_name(NTFS_I(vol->extend_ino), Quota, 6,
- &name);
- inode_unlock(vol->extend_ino);
- kfree(name);
- if (IS_ERR_MREF(mref)) {
- /*
- * If the file does not exist, quotas are disabled and have
- * never been enabled on this volume, just return success.
- */
- if (MREF_ERR(mref) == -ENOENT) {
- ntfs_debug("$Quota not present. Volume does not have quotas enabled.");
- /*
- * No need to try to set quotas out of date if they are
- * not enabled.
- */
- NVolSetQuotaOutOfDate(vol);
- return true;
- }
- /* A real error occurred. */
- ntfs_error(vol->sb, "Failed to find inode number for $Quota.");
- return false;
- }
- /* Get the inode. */
- tmp_ino = ntfs_iget(vol->sb, MREF(mref));
- if (IS_ERR(tmp_ino)) {
- if (!IS_ERR(tmp_ino))
- iput(tmp_ino);
- ntfs_error(vol->sb, "Failed to load $Quota.");
- return false;
- }
- vol->quota_ino = tmp_ino;
- /* Get the $Q index allocation attribute. */
- tmp_ino = ntfs_index_iget(vol->quota_ino, Q, 2);
- if (IS_ERR(tmp_ino)) {
- ntfs_error(vol->sb, "Failed to load $Quota/$Q index.");
- return false;
- }
- vol->quota_q_ino = tmp_ino;
- 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
*
@@ -1323,7 +1248,6 @@ static bool load_and_init_upcase(struct ntfs_volume *vol)
u8 *addr;
pgoff_t index, max_index;
unsigned int size;
- int i, max;
ntfs_debug("Entering.");
/* Read upcase table and setup vol->upcase and vol->upcase_len. */
@@ -1374,16 +1298,11 @@ read_partial_upcase_page:
mutex_unlock(&ntfs_lock);
return true;
}
- max = default_upcase_len;
- if (max > vol->upcase_len)
- max = vol->upcase_len;
- for (i = 0; i < max; i++)
- if (vol->upcase[i] != default_upcase[i])
- break;
- if (i == max) {
+ if (default_upcase_len == vol->upcase_len &&
+ !memcmp(vol->upcase, default_upcase,
+ default_upcase_len * sizeof(*default_upcase))) {
kvfree(vol->upcase);
vol->upcase = default_upcase;
- vol->upcase_len = max;
ntfs_nr_upcase_users++;
mutex_unlock(&ntfs_lock);
ntfs_debug("Volume specified $UpCase matches default. Using default.");
@@ -1659,18 +1578,6 @@ get_ctx_vol_failed:
ntfs_error(sb, "Failed to load $Extend.");
goto iput_sec_err_out;
}
- /* Find the quota file, load it if present, and set it up. */
- if (!load_and_init_quota(vol) &&
- vol->on_errors == ON_ERRORS_REMOUNT_RO) {
- static const char *es1 = "Failed to load $Quota";
- static const char *es2 = ". Run chkdsk.";
-
- sb->s_flags |= SB_RDONLY;
- ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
- /* This will prevent a read-write remount. */
- NVolSetErrors(vol);
- }
-
return true;
iput_sec_err_out:
@@ -1727,7 +1634,7 @@ static void ntfs_volume_free(struct ntfs_volume *vol)
vol->upcase = NULL;
}
- if (!ntfs_nr_upcase_users && default_upcase) {
+ if (!ntfs_nr_upcase_users) {
kvfree(default_upcase);
default_upcase = NULL;
}
@@ -1742,8 +1649,7 @@ static void ntfs_volume_free(struct ntfs_volume *vol)
unload_nls(vol->nls_map);
- if (vol->lcn_empty_bits_per_page)
- kvfree(vol->lcn_empty_bits_per_page);
+ kvfree(vol->lcn_empty_bits_per_page);
kfree(vol->volume_label);
kfree(vol);
}
@@ -1768,10 +1674,6 @@ static void ntfs_put_super(struct super_block *sb)
/* NTFS 3.0+ specific. */
if (vol->major_ver >= 3) {
- if (vol->quota_q_ino)
- ntfs_commit_inode(vol->quota_q_ino);
- if (vol->quota_ino)
- ntfs_commit_inode(vol->quota_ino);
if (vol->extend_ino)
ntfs_commit_inode(vol->extend_ino);
if (vol->secure_ino)
@@ -1820,14 +1722,6 @@ static void ntfs_put_super(struct super_block *sb)
/* NTFS 3.0+ specific clean up. */
if (vol->major_ver >= 3) {
- if (vol->quota_q_ino) {
- iput(vol->quota_q_ino);
- vol->quota_q_ino = NULL;
- }
- if (vol->quota_ino) {
- iput(vol->quota_ino);
- vol->quota_ino = NULL;
- }
if (vol->extend_ino) {
iput(vol->extend_ino);
vol->extend_ino = NULL;
@@ -1954,7 +1848,7 @@ s64 get_nr_free_clusters(struct ntfs_volume *vol)
struct address_space *mapping = vol->lcnbmp_ino->i_mapping;
struct folio *folio;
pgoff_t index, max_index;
- struct file_ra_state *ra;
+ struct file_ra_state ra = { 0 };
ntfs_debug("Entering.");
/* Serialize accesses to the cluster bitmap. */
@@ -1962,11 +1856,7 @@ s64 get_nr_free_clusters(struct ntfs_volume *vol)
if (NVolFreeClusterKnown(vol))
return atomic64_read(&vol->free_clusters);
- ra = kzalloc(sizeof(*ra), GFP_NOFS);
- if (!ra)
- return 0;
-
- file_ra_state_init(ra, mapping);
+ file_ra_state_init(&ra, mapping);
/*
* Convert the number of bits into bytes rounded up, then convert into
@@ -1985,7 +1875,7 @@ s64 get_nr_free_clusters(struct ntfs_volume *vol)
* Get folio from page cache, getting it from backing store
* if necessary, and increment the use count.
*/
- folio = ntfs_get_locked_folio(mapping, index, max_index, ra);
+ folio = ntfs_get_locked_folio(mapping, index, max_index, &ra);
/* Ignore pages which errored synchronously. */
if (IS_ERR(folio)) {
@@ -2024,7 +1914,6 @@ s64 get_nr_free_clusters(struct ntfs_volume *vol)
else
atomic64_set(&vol->free_clusters, nr_free);
- kfree(ra);
NVolSetFreeClusterKnown(vol);
wake_up_all(&vol->free_waitq);
ntfs_debug("Exiting.");
@@ -2079,15 +1968,11 @@ static unsigned long __get_nr_free_mft_records(struct ntfs_volume *vol,
struct address_space *mapping = vol->mftbmp_ino->i_mapping;
struct folio *folio;
pgoff_t index;
- struct file_ra_state *ra;
+ struct file_ra_state ra = { 0 };
ntfs_debug("Entering.");
- ra = kzalloc(sizeof(*ra), GFP_NOFS);
- if (!ra)
- return 0;
-
- file_ra_state_init(ra, mapping);
+ file_ra_state_init(&ra, mapping);
/* Use multiples of 4 bytes, thus max_size is PAGE_SIZE / 4. */
ntfs_debug("Reading $MFT/$BITMAP, max_index = 0x%lx, max_size = 0x%lx.",
@@ -2099,7 +1984,7 @@ static unsigned long __get_nr_free_mft_records(struct ntfs_volume *vol,
* Get folio from page cache, getting it from backing store
* if necessary, and increment the use count.
*/
- folio = ntfs_get_locked_folio(mapping, index, max_index, ra);
+ folio = ntfs_get_locked_folio(mapping, index, max_index, &ra);
/* Ignore pages which errored synchronously. */
if (IS_ERR(folio)) {
@@ -2131,7 +2016,6 @@ static unsigned long __get_nr_free_mft_records(struct ntfs_volume *vol,
else
atomic64_set(&vol->free_mft_records, nr_free);
- kfree(ra);
ntfs_debug("Exiting.");
return nr_free;
}
@@ -2476,14 +2360,6 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
vol->vol_ino = NULL;
/* NTFS 3.0+ specific clean up. */
if (vol->major_ver >= 3) {
- if (vol->quota_q_ino) {
- iput(vol->quota_q_ino);
- vol->quota_q_ino = NULL;
- }
- if (vol->quota_ino) {
- iput(vol->quota_ino);
- vol->quota_ino = NULL;
- }
if (vol->extend_ino) {
iput(vol->extend_ino);
vol->extend_ino = NULL;
@@ -2530,8 +2406,6 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
}
/* Error exit code path. */
unl_upcase_iput_tmp_ino_err_out_now:
- if (vol->lcn_empty_bits_per_page)
- kvfree(vol->lcn_empty_bits_per_page);
/*
* Decrease the number of upcase users and destroy the global default
* upcase table if necessary.
@@ -2551,6 +2425,9 @@ iput_tmp_ino_err_out_now:
/* Errors at this stage are irrelevant. */
err_out_now:
sb->s_fs_info = NULL;
+ kvfree(vol->lcn_empty_bits_per_page);
+ kfree(vol->volume_label);
+ unload_nls(vol->nls_map);
kfree(vol);
ntfs_debug("Failed, returning -EINVAL.");
lockdep_on();
diff --git a/fs/ntfs/volume.h b/fs/ntfs/volume.h
index af41427ec622c..e13e1423b2a92 100644
--- a/fs/ntfs/volume.h
+++ b/fs/ntfs/volume.h
@@ -76,8 +76,6 @@
* @root_ino: The VFS inode of the root directory.
* @secure_ino: The VFS inode of $Secure (NTFS3.0+ only, otherwise NULL).
* @extend_ino: The VFS inode of $Extend (NTFS3.0+ only, otherwise NULL).
- * @quota_ino: The VFS inode of $Quota.
- * @quota_q_ino: Attribute inode for $Quota/$Q.
* @nls_map: NLS (National Language Support) table.
* @nls_utf8: NLS table for UTF-8.
* @free_waitq: Wait queue for threads waiting for free clusters or MFT records.
@@ -141,8 +139,6 @@ struct ntfs_volume {
struct inode *root_ino;
struct inode *secure_ino;
struct inode *extend_ino;
- struct inode *quota_ino;
- struct inode *quota_q_ino;
struct nls_table *nls_map;
bool nls_utf8;
wait_queue_head_t free_waitq;
@@ -165,7 +161,6 @@ struct ntfs_volume {
* Otherwise be case insensitive but still
* create file names in POSIX namespace.
* NV_LogFileEmpty LogFile journal is empty.
- * NV_QuotaOutOfDate Quota is out of date.
* NV_UsnJrnlStamped UsnJrnl has been stamped.
* NV_ReadOnly Volume is mounted read-only.
* NV_Compression Volume supports compression.
@@ -186,7 +181,6 @@ enum {
NV_ShowSystemFiles,
NV_CaseSensitive,
NV_LogFileEmpty,
- NV_QuotaOutOfDate,
NV_UsnJrnlStamped,
NV_ReadOnly,
NV_Compression,
@@ -223,7 +217,6 @@ DEFINE_NVOL_BIT_OPS(Errors)
DEFINE_NVOL_BIT_OPS(ShowSystemFiles)
DEFINE_NVOL_BIT_OPS(CaseSensitive)
DEFINE_NVOL_BIT_OPS(LogFileEmpty)
-DEFINE_NVOL_BIT_OPS(QuotaOutOfDate)
DEFINE_NVOL_BIT_OPS(UsnJrnlStamped)
DEFINE_NVOL_BIT_OPS(ReadOnly)
DEFINE_NVOL_BIT_OPS(Compression)