summaryrefslogtreecommitdiff
path: root/fs/ntfs
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-05-21 15:02:54 -0700
committerJakub Kicinski <kuba@kernel.org>2026-05-21 15:09:02 -0700
commit6a20b34fe3b31b292078bc79ec18a2ab0d9f7719 (patch)
tree3d691b402ee221c67875b04f4cef738b0d2ef7cb /fs/ntfs
parent73366893d1d58d247bef70406280f71030495424 (diff)
parent68993ced0f618e36cf33388f1e50223e5e6e78cc (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR (net-7.1-rc5). No conflicts, adjacent changes: drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c cc199cd1b912 ("net/mlx5e: Reduce branches in napi poll") c326f9c68921 ("net/mlx5e: xsk: Fix unlocked writing to ICOSQ") drivers/net/ethernet/mellanox/mlx5/core/eswitch.c c6df9a65cbb0 ("net/mlx5: Skip disabled vports when setting max TX speed") 1fba57c91416 ("net/mlx5: Add VHCA_ID page management mode support") net/mac80211/mlme.c a6e6ccd5bd07 ("wifi: mac80211: consume only present negotiated TTLM maps") 49e62ec6eb06 ("wifi: mac80211: move frame RX handling to type files") Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'fs/ntfs')
-rw-r--r--fs/ntfs/attrib.c46
-rw-r--r--fs/ntfs/attrlist.c7
-rw-r--r--fs/ntfs/bdev-io.c7
-rw-r--r--fs/ntfs/index.c17
-rw-r--r--fs/ntfs/inode.c6
-rw-r--r--fs/ntfs/logfile.c5
-rw-r--r--fs/ntfs/mft.c93
-rw-r--r--fs/ntfs/namei.c4
-rw-r--r--fs/ntfs/runlist.c9
-rw-r--r--fs/ntfs/super.c35
10 files changed, 149 insertions, 80 deletions
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index 97b660eaa00c..421c6cdcbb53 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -583,24 +583,13 @@ static u32 ntfs_resident_attr_min_value_length(const __le32 type)
case AT_STANDARD_INFORMATION:
return offsetof(struct standard_information, ver) +
sizeof(((struct standard_information *)0)->ver.v1.reserved12);
- case AT_ATTRIBUTE_LIST:
- return offsetof(struct attr_list_entry, name);
case AT_FILE_NAME:
- return offsetof(struct file_name_attr, file_name);
- case AT_OBJECT_ID:
- return sizeof(struct guid);
- case AT_SECURITY_DESCRIPTOR:
- return sizeof(struct security_descriptor_relative);
+ return offsetof(struct file_name_attr, file_name) +
+ sizeof(__le16) * 1;
case AT_VOLUME_INFORMATION:
return sizeof(struct volume_information);
- case AT_INDEX_ROOT:
- return sizeof(struct index_root);
- case AT_REPARSE_POINT:
- return offsetof(struct reparse_point, reparse_data);
case AT_EA_INFORMATION:
return sizeof(struct ea_information);
- case AT_EA:
- return offsetof(struct ea_attr, ea_name) + 1;
default:
return 0;
}
@@ -672,6 +661,9 @@ static int ntfs_attr_find(const __le32 type, const __le16 *name,
__le16 *upcase = vol->upcase;
u32 upcase_len = vol->upcase_len;
unsigned int space;
+ u16 name_offset;
+ u32 attr_len;
+ u32 name_size;
/*
* Iterate over attributes in mft record starting at @ctx->attr, or the
@@ -699,6 +691,20 @@ static int ntfs_attr_find(const __le32 type, const __le16 *name,
return -ENOENT;
if (unlikely(!a->length))
break;
+ if (a->name_length) {
+ name_offset = le16_to_cpu(a->name_offset);
+ attr_len = le32_to_cpu(a->length);
+ name_size = a->name_length * sizeof(__le16);
+
+ if (name_offset > attr_len ||
+ attr_len - name_offset < name_size) {
+ ntfs_error(vol->sb,
+ "Corrupt attribute name in MFT record %llu\n",
+ ctx->ntfs_ino->mft_no);
+ break;
+ }
+ }
+
if (type == AT_UNUSED)
return 0;
if (a->type != type)
@@ -712,14 +718,6 @@ static int ntfs_attr_find(const __le32 type, const __le16 *name,
if (a->name_length)
return -ENOENT;
} else {
- if (a->name_length && ((le16_to_cpu(a->name_offset) +
- a->name_length * sizeof(__le16)) >
- le32_to_cpu(a->length))) {
- ntfs_error(vol->sb, "Corrupt attribute name in MFT record %llu\n",
- ctx->ntfs_ino->mft_no);
- break;
- }
-
if (!ntfs_are_names_equal(name, name_len,
(__le16 *)((u8 *)a + le16_to_cpu(a->name_offset)),
a->name_length, ic, upcase, upcase_len)) {
@@ -2924,12 +2922,12 @@ int ntfs_attr_open(struct ntfs_inode *ni, const __le32 type,
struct ntfs_inode *base_ni;
int err;
- ntfs_debug("Entering for inode %lld, attr 0x%x.\n",
- (unsigned long long)ni->mft_no, type);
-
if (!ni || !ni->vol)
return -EINVAL;
+ ntfs_debug("Entering for inode %lld, attr 0x%x.\n",
+ ni->mft_no, type);
+
if (NInoAttr(ni))
base_ni = ni->ext.base_ntfs_ino;
else
diff --git a/fs/ntfs/attrlist.c b/fs/ntfs/attrlist.c
index bd501e8a628c..c2594d4c83b0 100644
--- a/fs/ntfs/attrlist.c
+++ b/fs/ntfs/attrlist.c
@@ -119,15 +119,14 @@ int ntfs_attrlist_entry_add(struct ntfs_inode *ni, struct attr_record *attr)
struct mft_record *ni_mrec;
u8 *old_al;
- ntfs_debug("Entering for inode 0x%llx, attr 0x%x.\n",
- (long long) ni->mft_no,
- (unsigned int) le32_to_cpu(attr->type));
-
if (!ni || !attr) {
ntfs_debug("Invalid arguments.\n");
return -EINVAL;
}
+ ntfs_debug("Entering for inode 0x%llx, attr 0x%x.\n",
+ ni->mft_no, (unsigned int) le32_to_cpu(attr->type));
+
ni_mrec = map_mft_record(ni);
if (IS_ERR(ni_mrec)) {
ntfs_debug("Invalid arguments.\n");
diff --git a/fs/ntfs/bdev-io.c b/fs/ntfs/bdev-io.c
index 67e65c88d681..27d7c2767a33 100644
--- a/fs/ntfs/bdev-io.c
+++ b/fs/ntfs/bdev-io.c
@@ -97,6 +97,8 @@ int ntfs_bdev_write(struct super_block *sb, void *buf, loff_t start, size_t size
idx_end++;
for (; idx < idx_end; idx++, from = 0) {
+ u32 len;
+
folio = read_mapping_folio(sb->s_bdev->bd_mapping, idx, NULL);
if (IS_ERR(folio)) {
ntfs_error(sb, "Unable to read %ld page", idx);
@@ -105,9 +107,10 @@ int ntfs_bdev_write(struct super_block *sb, void *buf, loff_t start, size_t size
offset = (loff_t)idx << PAGE_SHIFT;
to = min_t(u32, end - offset, PAGE_SIZE);
+ len = to - from;
- memcpy_to_folio(folio, from, buf + buf_off, to);
- buf_off += to;
+ memcpy_to_folio(folio, from, buf + buf_off, len);
+ buf_off += len;
folio_mark_uptodate(folio);
folio_mark_dirty(folio);
folio_put(folio);
diff --git a/fs/ntfs/index.c b/fs/ntfs/index.c
index a547bdcfa456..146e011c1a41 100644
--- a/fs/ntfs/index.c
+++ b/fs/ntfs/index.c
@@ -677,11 +677,11 @@ static int ntfs_ib_read(struct ntfs_index_context *icx, s64 vcn, struct index_bl
static int ntfs_icx_parent_inc(struct ntfs_index_context *icx)
{
- icx->pindex++;
- if (icx->pindex >= MAX_PARENT_VCN) {
+ if (icx->pindex >= MAX_PARENT_VCN - 1) {
ntfs_error(icx->idx_ni->vol->sb, "Index is over %d level deep", MAX_PARENT_VCN);
return -EOPNOTSUPP;
}
+ icx->pindex++;
return 0;
}
@@ -1970,6 +1970,7 @@ struct index_entry *ntfs_index_walk_down(struct index_entry *ie, struct ntfs_ind
{
struct index_entry *entry;
struct index_block *ib;
+ int err;
s64 vcn;
entry = ie;
@@ -1979,14 +1980,20 @@ struct index_entry *ntfs_index_walk_down(struct index_entry *ie, struct ntfs_ind
ib = kvzalloc(ictx->block_size, GFP_NOFS);
if (!ib)
return ERR_PTR(-ENOMEM);
- /* down from level zero */
+ /*
+ * Descending from root index (level 0) to the first
+ * child level. is_in_root == true implies pindex == 0,
+ * so advance to level 1.
+ */
+ ictx->pindex = 1;
ictx->ir = NULL;
ictx->ib = ib;
- ictx->pindex = 1;
ictx->is_in_root = false;
} else {
/* down from non-zero level */
- ictx->pindex++;
+ err = ntfs_icx_parent_inc(ictx);
+ if (err)
+ return ERR_PTR(err);
}
ictx->parent_pos[ictx->pindex] = 0;
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 16890d411194..360bebd1ee3f 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -2582,8 +2582,8 @@ int ntfs_inode_sync_filename(struct ntfs_inode *ni)
mutex_lock_nested(&index_ni->mrec_lock, NTFS_INODE_MUTEX_PARENT);
if (NInoBeingDeleted(ni)) {
- iput(index_vi);
mutex_unlock(&index_ni->mrec_lock);
+ iput(index_vi);
continue;
}
@@ -2591,8 +2591,8 @@ int ntfs_inode_sync_filename(struct ntfs_inode *ni)
if (!ictx) {
ntfs_error(sb, "Failed to get index ctx, inode %llu",
index_ni->mft_no);
- iput(index_vi);
mutex_unlock(&index_ni->mrec_lock);
+ iput(index_vi);
continue;
}
@@ -2601,8 +2601,8 @@ int ntfs_inode_sync_filename(struct ntfs_inode *ni)
ntfs_debug("Index lookup failed, inode %llu",
index_ni->mft_no);
ntfs_index_ctx_put(ictx);
- iput(index_vi);
mutex_unlock(&index_ni->mrec_lock);
+ iput(index_vi);
continue;
}
/* Update flags and file size. */
diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c
index 3f8d1640f1d5..d3f25d8e29f9 100644
--- a/fs/ntfs/logfile.c
+++ b/fs/ntfs/logfile.c
@@ -710,6 +710,9 @@ map_vcn:
if (unlikely(lcn == LCN_RL_NOT_MAPPED)) {
vcn = rl->vcn;
kvfree(empty_buf);
+ empty_buf = NULL;
+ kfree(ra);
+ ra = NULL;
goto map_vcn;
}
/* If this run is not valid abort with an error. */
@@ -753,7 +756,7 @@ map_vcn:
} while (start < end);
} while ((++rl)->vcn < end_vcn);
up_write(&log_ni->runlist.lock);
- kfree(empty_buf);
+ kvfree(empty_buf);
kfree(ra);
truncate_inode_pages(log_vi->i_mapping, 0);
/* Set the flag so we do not have to do it again on remount. */
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
index 7d989267a82b..a7d10ee41b34 100644
--- a/fs/ntfs/mft.c
+++ b/fs/ntfs/mft.c
@@ -30,6 +30,8 @@ int ntfs_mft_record_check(const struct ntfs_volume *vol, struct mft_record *m,
{
struct attr_record *a;
struct super_block *sb = vol->sb;
+ u16 attrs_offset;
+ u32 bytes_in_use;
if (!ntfs_is_file_record(m->magic)) {
ntfs_error(sb, "Record %llu has no FILE magic (0x%x)\n",
@@ -65,7 +67,16 @@ int ntfs_mft_record_check(const struct ntfs_volume *vol, struct mft_record *m,
goto err_out;
}
- a = (struct attr_record *)((char *)m + le16_to_cpu(m->attrs_offset));
+ attrs_offset = le16_to_cpu(m->attrs_offset);
+ bytes_in_use = le32_to_cpu(m->bytes_in_use);
+
+ if (attrs_offset > bytes_in_use ||
+ bytes_in_use - attrs_offset < sizeof_field(struct attr_record, type)) {
+ ntfs_error(sb, "Record %llu has corrupt attribute offset\n", mft_no);
+ goto err_out;
+ }
+
+ a = (struct attr_record *)((char *)m + attrs_offset);
if ((char *)a < (char *)m || (char *)a > (char *)m + vol->mft_record_size) {
ntfs_error(sb, "Record %llu is corrupt\n", mft_no);
goto err_out;
@@ -449,7 +460,7 @@ static void ntfs_bio_end_io(struct bio *bio)
int ntfs_sync_mft_mirror(struct ntfs_volume *vol, const u64 mft_no,
struct mft_record *m)
{
- u8 *kmirr = NULL;
+ u8 *kmirr;
struct folio *folio;
unsigned int folio_ofs, lcn_folio_off = 0;
int err = 0;
@@ -479,6 +490,7 @@ int ntfs_sync_mft_mirror(struct ntfs_volume *vol, const u64 mft_no,
kmirr = kmap_local_folio(folio, 0) + folio_ofs;
/* Copy the mst protected mft record to the mirror. */
memcpy(kmirr, m, vol->mft_record_size);
+ kunmap_local(kmirr);
if (vol->cluster_size_bits > PAGE_SHIFT) {
lcn_folio_off = folio->index << PAGE_SHIFT;
@@ -490,20 +502,22 @@ int ntfs_sync_mft_mirror(struct ntfs_volume *vol, const u64 mft_no,
NTFS_B_TO_SECTOR(vol, NTFS_CLU_TO_B(vol, vol->mftmirr_lcn) +
lcn_folio_off + folio_ofs);
- if (!bio_add_folio(bio, folio, vol->mft_record_size, folio_ofs)) {
+ if (bio_add_folio(bio, folio, vol->mft_record_size, folio_ofs))
+ err = submit_bio_wait(bio);
+ else
err = -EIO;
- bio_put(bio);
- goto unlock_folio;
- }
+ bio_put(bio);
- bio->bi_end_io = ntfs_bio_end_io;
- submit_bio(bio);
- /* Current state: all buffers are clean, unlocked, and uptodate. */
+ /*
+ * The in-memory mirror is now valid because we just memcpy()'d the
+ * mst-protected mft record into it. Mark the folio uptodate even on
+ * write error so a subsequent read_mapping_folio() does not refetch
+ * the stale on-disk mirror and overwrite this copy. The error is
+ * propagated to the caller via @err.
+ */
folio_mark_uptodate(folio);
-unlock_folio:
folio_unlock(folio);
- kunmap_local(kmirr);
folio_put(folio);
if (likely(!err)) {
ntfs_debug("Done.");
@@ -588,20 +602,36 @@ int write_mft_record_nolock(struct ntfs_inode *ni, struct mft_record *m, int syn
}
/* Synchronize the mft mirror now if not @sync. */
- if (!sync && ni->mft_no < vol->mftmirr_size)
- ntfs_sync_mft_mirror(vol, ni->mft_no, fixup_m);
+ if (!sync && ni->mft_no < vol->mftmirr_size) {
+ int sub_err = ntfs_sync_mft_mirror(vol, ni->mft_no,
+ fixup_m);
+ if (unlikely(sub_err) && !err)
+ err = sub_err;
+ }
- folio_get(folio);
- bio->bi_private = folio;
- bio->bi_end_io = ntfs_bio_end_io;
- submit_bio(bio);
+ if (sync) {
+ int sub_err = submit_bio_wait(bio);
+
+ bio_put(bio);
+ if (unlikely(sub_err) && !err)
+ err = sub_err;
+ } else {
+ folio_get(folio);
+ bio->bi_private = folio;
+ bio->bi_end_io = ntfs_bio_end_io;
+ submit_bio(bio);
+ }
offset += vol->cluster_size;
i++;
}
/* If @sync, now synchronize the mft mirror. */
- if (sync && ni->mft_no < vol->mftmirr_size)
- ntfs_sync_mft_mirror(vol, ni->mft_no, fixup_m);
+ if (sync && ni->mft_no < vol->mftmirr_size) {
+ int sub_err = ntfs_sync_mft_mirror(vol, ni->mft_no, fixup_m);
+
+ if (unlikely(sub_err) && !err)
+ err = sub_err;
+ }
kunmap_local(kaddr);
if (unlikely(err)) {
/* I/O error during writing. This is really bad! */
@@ -617,10 +647,10 @@ put_bio_out:
bio_put(bio);
err_out:
/*
- * Current state: all buffers are clean, unlocked, and uptodate.
- * The caller should mark the base inode as bad so that no more i/o
- * happens. ->drop_inode() will still be invoked so all extent inodes
- * and other allocated memory will be freed.
+ * The caller should mark the base inode as bad so no more I/O
+ * happens. ->drop_inode() will still be invoked so all extent inodes
+ * and other allocated memory will be freed. ENOMEM is retried by
+ * redirtying the mft record below.
*/
if (err == -ENOMEM) {
ntfs_error(vol->sb,
@@ -833,7 +863,7 @@ static bool ntfs_may_write_mft_record(struct ntfs_volume *vol, const u64 mft_no,
vi = igrab(mft_vi);
WARN_ON(vi != mft_vi);
} else {
- vi = find_inode_nowait(sb, mft_no, ntfs_test_inode_wb, &na);
+ vi = find_inode_nowait(sb, na.mft_no, ntfs_test_inode_wb, &na);
if (na.state == NI_BeingDeleted || na.state == NI_BeingCreated)
return false;
}
@@ -1034,7 +1064,7 @@ static s64 ntfs_mft_bitmap_find_and_alloc_free_rec_nolock(struct ntfs_volume *vo
b = ffz((unsigned long)*byte);
if (b < 8 && b >= (bit & 7)) {
ll = data_pos + (bit & ~7ull) + b;
- if (unlikely(ll > (1ll << 32))) {
+ if (unlikely(ll >= (1ll << 32))) {
folio_unlock(folio);
kunmap_local(buf);
folio_put(folio);
@@ -2721,8 +2751,11 @@ static int ntfs_write_mft_block(struct folio *folio, struct writeback_control *w
ntfs_debug("Entering for inode 0x%llx, attribute type 0x%x, folio index 0x%lx.",
ni->mft_no, ni->type, folio->index);
- if (!locked_nis || !ref_inos)
+ if (!locked_nis || !ref_inos) {
+ folio_redirty_for_writepage(wbc, folio);
+ folio_unlock(folio);
return -ENOMEM;
+ }
/* We have to zero every time due to mmap-at-end-of-file. */
if (folio->index >= (i_size >> folio_shift(folio)))
@@ -2840,9 +2873,13 @@ flush_bio:
}
prev_mft_ofs = mft_ofs;
- if (mft_no < vol->mftmirr_size)
- ntfs_sync_mft_mirror(vol, mft_no,
+ if (mft_no < vol->mftmirr_size) {
+ int sub_err = ntfs_sync_mft_mirror(vol, mft_no,
(struct mft_record *)(kaddr + mft_ofs));
+
+ if (unlikely(sub_err) && !err)
+ err = sub_err;
+ }
} else if (ref_inos[nr_ref_inos])
nr_ref_inos++;
}
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index 96c450e62efc..c4f82846c58c 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -344,9 +344,9 @@ static int ntfs_sd_add_everyone(struct ntfs_inode *ni)
sd_len = sizeof(struct security_descriptor_relative) + 2 *
(sizeof(struct ntfs_sid) + 8) + sizeof(struct ntfs_acl) +
sizeof(struct ntfs_ace) + 4;
- sd = kmalloc(sd_len, GFP_NOFS);
+ sd = kzalloc(sd_len, GFP_NOFS);
if (!sd)
- return -1;
+ return -ENOMEM;
sd->revision = 1;
sd->control = SE_DACL_PRESENT | SE_SELF_RELATIVE;
diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c
index da21dbeaaf66..e7de3d01257e 100644
--- a/fs/ntfs/runlist.c
+++ b/fs/ntfs/runlist.c
@@ -2056,10 +2056,11 @@ struct runlist_element *ntfs_rl_collapse_range(struct runlist_element *dst_rl, i
* consists of holes.
*/
merge_cnt = 0;
- i = new_1st_cnt == 0 ? 1 : new_1st_cnt;
- if (ntfs_rle_lcn_contiguous(&new_rl[i - 1], &new_rl[i])) {
- /* Merge right and left */
- s_rl = &new_rl[new_1st_cnt - 1];
+ if (new_1st_cnt > 0 &&
+ ntfs_rle_lcn_contiguous(&new_rl[new_1st_cnt - 1],
+ &new_rl[new_1st_cnt])) {
+ /* Merge right and left. */
+ s_rl = &new_rl[new_1st_cnt - 1];
s_rl->length += s_rl[1].length;
merge_cnt = 1;
}
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 22dc7865eca7..9e321cc2febe 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -413,6 +413,7 @@ int ntfs_write_volume_label(struct ntfs_volume *vol, char *label)
{
struct ntfs_inode *vol_ni = NTFS_I(vol->vol_ino);
struct ntfs_attr_search_ctx *ctx;
+ char *new_label;
__le16 *uname;
int uname_len, ret;
@@ -425,7 +426,7 @@ int ntfs_write_volume_label(struct ntfs_volume *vol, char *label)
return uname_len;
}
- if (uname_len > NTFS_MAX_LABEL_LEN) {
+ if (uname_len > NTFS_MAX_LABEL_LEN) {
ntfs_error(vol->sb,
"Volume label is too long (max %d characters).",
NTFS_MAX_LABEL_LEN);
@@ -433,11 +434,22 @@ int ntfs_write_volume_label(struct ntfs_volume *vol, char *label)
return -EINVAL;
}
+ /*
+ * Allocate the in-memory label copy up front. If kstrdup() fails we
+ * bail out before touching on-disk metadata, so the in-memory label
+ * and the on-disk label stay in sync.
+ */
+ new_label = kstrdup(label, GFP_KERNEL);
+ if (!new_label) {
+ kvfree(uname);
+ return -ENOMEM;
+ }
+
mutex_lock(&vol_ni->mrec_lock);
ctx = ntfs_attr_get_search_ctx(vol_ni, NULL);
if (!ctx) {
ret = -ENOMEM;
- goto out;
+ goto out;
}
if (!ntfs_attr_lookup(AT_VOLUME_NAME, NULL, 0, 0, 0, NULL, 0,
@@ -450,12 +462,14 @@ int ntfs_write_volume_label(struct ntfs_volume *vol, char *label)
out:
mutex_unlock(&vol_ni->mrec_lock);
kvfree(uname);
- mark_inode_dirty_sync(vol->vol_ino);
if (ret >= 0) {
kfree(vol->volume_label);
- vol->volume_label = kstrdup(label, GFP_KERNEL);
+ vol->volume_label = new_label;
+ mark_inode_dirty_sync(vol->vol_ino);
ret = 0;
+ } else {
+ kfree(new_label);
}
return ret;
}
@@ -979,6 +993,13 @@ mft_unmap_out:
ntfs_is_baad_recordp((__le32 *)kmirr))
bytes = vol->mft_record_size;
}
+ /* Compare the two records. */
+ if (memcmp(kmft, kmirr, bytes)) {
+ ntfs_error(sb,
+ "$MFT and $MFTMirr record %i do not match. Run chkdsk.",
+ i);
+ goto mm_unmap_out;
+ }
kmft += vol->mft_record_size;
kmirr += vol->mft_record_size;
} while (++i < vol->mftmirr_size);
@@ -1671,7 +1692,7 @@ iput_attrdef_err_out:
iput_upcase_err_out:
vol->upcase_len = 0;
mutex_lock(&ntfs_lock);
- if (vol->upcase == default_upcase) {
+ if (vol->upcase && vol->upcase == default_upcase) {
ntfs_nr_upcase_users--;
vol->upcase = NULL;
}
@@ -1701,7 +1722,7 @@ static void ntfs_volume_free(struct ntfs_volume *vol)
* the number of upcase users if we are a user.
*/
mutex_lock(&ntfs_lock);
- if (vol->upcase == default_upcase) {
+ if (vol->upcase && vol->upcase == default_upcase) {
ntfs_nr_upcase_users--;
vol->upcase = NULL;
}
@@ -2494,7 +2515,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
}
vol->upcase_len = 0;
mutex_lock(&ntfs_lock);
- if (vol->upcase == default_upcase) {
+ if (vol->upcase && vol->upcase == default_upcase) {
ntfs_nr_upcase_users--;
vol->upcase = NULL;
}