Skip to content

Commit ce33580

Browse files
committed
Pull ntfs3 fixes from Konstantin Komarov: - unify inode corruption marking and mark them as bad immediately upon detection of an error in attribute enumeration - folio cleanup * tag 'ntfs3_for_6.14' of https://github.com/Paragon-Software-Group/linux-ntfs3: fs/ntfs3: Unify inode corruption marking with _ntfs_bad_inode() fs/ntfs3: Mark inode as bad as soon as error detected in mi_enum_attr() ntfs3: Remove an access to page->index
2 parents 8080ff5 + 55ad333 commit ce33580

File tree

8 files changed

+112
-94
lines changed

8 files changed

+112
-94
lines changed

fs/ntfs3/attrib.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,8 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type,
787787
if (err)
788788
goto out;
789789

790-
attr = mi_find_attr(mi, NULL, type, name, name_len, &le->id);
790+
attr = mi_find_attr(ni, mi, NULL, type, name, name_len,
791+
&le->id);
791792
if (!attr) {
792793
err = -EINVAL;
793794
goto bad_inode;
@@ -1181,7 +1182,7 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
11811182
goto out;
11821183
}
11831184

1184-
attr = mi_find_attr(mi, NULL, ATTR_DATA, NULL, 0, &le->id);
1185+
attr = mi_find_attr(ni, mi, NULL, ATTR_DATA, NULL, 0, &le->id);
11851186
if (!attr) {
11861187
err = -EINVAL;
11871188
goto out;
@@ -1406,7 +1407,7 @@ int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr,
14061407
*/
14071408
if (!attr->non_res) {
14081409
if (vbo[1] + bytes_per_off > le32_to_cpu(attr->res.data_size)) {
1409-
ntfs_inode_err(&ni->vfs_inode, "is corrupted");
1410+
_ntfs_bad_inode(&ni->vfs_inode);
14101411
return -EINVAL;
14111412
}
14121413
addr = resident_data(attr);
@@ -1796,7 +1797,7 @@ int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size,
17961797
goto out;
17971798
}
17981799

1799-
attr = mi_find_attr(mi, NULL, ATTR_DATA, NULL, 0,
1800+
attr = mi_find_attr(ni, mi, NULL, ATTR_DATA, NULL, 0,
18001801
&le->id);
18011802
if (!attr) {
18021803
err = -EINVAL;
@@ -2041,8 +2042,8 @@ int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes)
20412042
}
20422043

20432044
/* Look for required attribute. */
2044-
attr = mi_find_attr(mi, NULL, ATTR_DATA, NULL,
2045-
0, &le->id);
2045+
attr = mi_find_attr(ni, mi, NULL, ATTR_DATA,
2046+
NULL, 0, &le->id);
20462047
if (!attr) {
20472048
err = -EINVAL;
20482049
goto out;
@@ -2587,7 +2588,7 @@ int attr_force_nonresident(struct ntfs_inode *ni)
25872588

25882589
attr = ni_find_attr(ni, NULL, &le, ATTR_DATA, NULL, 0, NULL, &mi);
25892590
if (!attr) {
2590-
ntfs_bad_inode(&ni->vfs_inode, "no data attribute");
2591+
_ntfs_bad_inode(&ni->vfs_inode);
25912592
return -ENOENT;
25922593
}
25932594

fs/ntfs3/dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ static int ntfs_readdir(struct file *file, struct dir_context *ctx)
512512
ctx->pos = pos;
513513
} else if (err < 0) {
514514
if (err == -EINVAL)
515-
ntfs_inode_err(dir, "directory corrupted");
515+
_ntfs_bad_inode(dir);
516516
ctx->pos = eod;
517517
}
518518

fs/ntfs3/frecord.c

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ struct ATTR_STD_INFO *ni_std(struct ntfs_inode *ni)
7575
{
7676
const struct ATTRIB *attr;
7777

78-
attr = mi_find_attr(&ni->mi, NULL, ATTR_STD, NULL, 0, NULL);
78+
attr = mi_find_attr(ni, &ni->mi, NULL, ATTR_STD, NULL, 0, NULL);
7979
return attr ? resident_data_ex(attr, sizeof(struct ATTR_STD_INFO)) :
8080
NULL;
8181
}
@@ -89,7 +89,7 @@ struct ATTR_STD_INFO5 *ni_std5(struct ntfs_inode *ni)
8989
{
9090
const struct ATTRIB *attr;
9191

92-
attr = mi_find_attr(&ni->mi, NULL, ATTR_STD, NULL, 0, NULL);
92+
attr = mi_find_attr(ni, &ni->mi, NULL, ATTR_STD, NULL, 0, NULL);
9393

9494
return attr ? resident_data_ex(attr, sizeof(struct ATTR_STD_INFO5)) :
9595
NULL;
@@ -148,8 +148,10 @@ int ni_load_mi_ex(struct ntfs_inode *ni, CLST rno, struct mft_inode **mi)
148148
goto out;
149149

150150
err = mi_get(ni->mi.sbi, rno, &r);
151-
if (err)
151+
if (err) {
152+
_ntfs_bad_inode(&ni->vfs_inode);
152153
return err;
154+
}
153155

154156
ni_add_mi(ni, r);
155157

@@ -201,7 +203,8 @@ struct ATTRIB *ni_find_attr(struct ntfs_inode *ni, struct ATTRIB *attr,
201203
*mi = &ni->mi;
202204

203205
/* Look for required attribute in primary record. */
204-
return mi_find_attr(&ni->mi, attr, type, name, name_len, NULL);
206+
return mi_find_attr(ni, &ni->mi, attr, type, name, name_len,
207+
NULL);
205208
}
206209

207210
/* First look for list entry of required type. */
@@ -217,7 +220,7 @@ struct ATTRIB *ni_find_attr(struct ntfs_inode *ni, struct ATTRIB *attr,
217220
return NULL;
218221

219222
/* Look for required attribute. */
220-
attr = mi_find_attr(m, NULL, type, name, name_len, &le->id);
223+
attr = mi_find_attr(ni, m, NULL, type, name, name_len, &le->id);
221224

222225
if (!attr)
223226
goto out;
@@ -238,8 +241,7 @@ struct ATTRIB *ni_find_attr(struct ntfs_inode *ni, struct ATTRIB *attr,
238241
return attr;
239242

240243
out:
241-
ntfs_inode_err(&ni->vfs_inode, "failed to parse mft record");
242-
ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_ERROR);
244+
_ntfs_bad_inode(&ni->vfs_inode);
243245
return NULL;
244246
}
245247

@@ -259,7 +261,7 @@ struct ATTRIB *ni_enum_attr_ex(struct ntfs_inode *ni, struct ATTRIB *attr,
259261
if (mi)
260262
*mi = &ni->mi;
261263
/* Enum attributes in primary record. */
262-
return mi_enum_attr(&ni->mi, attr);
264+
return mi_enum_attr(ni, &ni->mi, attr);
263265
}
264266

265267
/* Get next list entry. */
@@ -275,7 +277,7 @@ struct ATTRIB *ni_enum_attr_ex(struct ntfs_inode *ni, struct ATTRIB *attr,
275277
*mi = mi2;
276278

277279
/* Find attribute in loaded record. */
278-
return rec_find_attr_le(mi2, le2);
280+
return rec_find_attr_le(ni, mi2, le2);
279281
}
280282

281283
/*
@@ -293,7 +295,8 @@ struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
293295
if (!ni->attr_list.size) {
294296
if (pmi)
295297
*pmi = &ni->mi;
296-
return mi_find_attr(&ni->mi, NULL, type, name, name_len, NULL);
298+
return mi_find_attr(ni, &ni->mi, NULL, type, name, name_len,
299+
NULL);
297300
}
298301

299302
le = al_find_ex(ni, NULL, type, name, name_len, NULL);
@@ -319,7 +322,7 @@ struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
319322
if (pmi)
320323
*pmi = mi;
321324

322-
attr = mi_find_attr(mi, NULL, type, name, name_len, &le->id);
325+
attr = mi_find_attr(ni, mi, NULL, type, name, name_len, &le->id);
323326
if (!attr)
324327
return NULL;
325328

@@ -330,6 +333,7 @@ struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
330333
vcn <= le64_to_cpu(attr->nres.evcn))
331334
return attr;
332335

336+
_ntfs_bad_inode(&ni->vfs_inode);
333337
return NULL;
334338
}
335339

@@ -398,7 +402,8 @@ int ni_remove_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
398402
int diff;
399403

400404
if (base_only || type == ATTR_LIST || !ni->attr_list.size) {
401-
attr = mi_find_attr(&ni->mi, NULL, type, name, name_len, id);
405+
attr = mi_find_attr(ni, &ni->mi, NULL, type, name, name_len,
406+
id);
402407
if (!attr)
403408
return -ENOENT;
404409

@@ -437,7 +442,7 @@ int ni_remove_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
437442

438443
al_remove_le(ni, le);
439444

440-
attr = mi_find_attr(mi, NULL, type, name, name_len, id);
445+
attr = mi_find_attr(ni, mi, NULL, type, name, name_len, id);
441446
if (!attr)
442447
return -ENOENT;
443448

@@ -485,7 +490,7 @@ ni_ins_new_attr(struct ntfs_inode *ni, struct mft_inode *mi,
485490
name = le->name;
486491
}
487492

488-
attr = mi_insert_attr(mi, type, name, name_len, asize, name_off);
493+
attr = mi_insert_attr(ni, mi, type, name, name_len, asize, name_off);
489494
if (!attr) {
490495
if (le_added)
491496
al_remove_le(ni, le);
@@ -673,7 +678,7 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni)
673678
if (err)
674679
return err;
675680

676-
attr_list = mi_find_attr(&ni->mi, NULL, ATTR_LIST, NULL, 0, NULL);
681+
attr_list = mi_find_attr(ni, &ni->mi, NULL, ATTR_LIST, NULL, 0, NULL);
677682
if (!attr_list)
678683
return 0;
679684

@@ -695,7 +700,7 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni)
695700
if (!mi)
696701
return 0;
697702

698-
attr = mi_find_attr(mi, NULL, le->type, le_name(le),
703+
attr = mi_find_attr(ni, mi, NULL, le->type, le_name(le),
699704
le->name_len, &le->id);
700705
if (!attr)
701706
return 0;
@@ -731,7 +736,7 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni)
731736
goto out;
732737
}
733738

734-
attr = mi_find_attr(mi, NULL, le->type, le_name(le),
739+
attr = mi_find_attr(ni, mi, NULL, le->type, le_name(le),
735740
le->name_len, &le->id);
736741
if (!attr) {
737742
/* Should never happened, 'cause already checked. */
@@ -740,7 +745,7 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni)
740745
asize = le32_to_cpu(attr->size);
741746

742747
/* Insert into primary record. */
743-
attr_ins = mi_insert_attr(&ni->mi, le->type, le_name(le),
748+
attr_ins = mi_insert_attr(ni, &ni->mi, le->type, le_name(le),
744749
le->name_len, asize,
745750
le16_to_cpu(attr->name_off));
746751
if (!attr_ins) {
@@ -768,7 +773,7 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni)
768773
if (!mi)
769774
continue;
770775

771-
attr = mi_find_attr(mi, NULL, le->type, le_name(le),
776+
attr = mi_find_attr(ni, mi, NULL, le->type, le_name(le),
772777
le->name_len, &le->id);
773778
if (!attr)
774779
continue;
@@ -831,7 +836,7 @@ int ni_create_attr_list(struct ntfs_inode *ni)
831836
free_b = 0;
832837
attr = NULL;
833838

834-
for (; (attr = mi_enum_attr(&ni->mi, attr)); le = Add2Ptr(le, sz)) {
839+
for (; (attr = mi_enum_attr(ni, &ni->mi, attr)); le = Add2Ptr(le, sz)) {
835840
sz = le_size(attr->name_len);
836841
le->type = attr->type;
837842
le->size = cpu_to_le16(sz);
@@ -886,7 +891,7 @@ int ni_create_attr_list(struct ntfs_inode *ni)
886891
u32 asize = le32_to_cpu(b->size);
887892
u16 name_off = le16_to_cpu(b->name_off);
888893

889-
attr = mi_insert_attr(mi, b->type, Add2Ptr(b, name_off),
894+
attr = mi_insert_attr(ni, mi, b->type, Add2Ptr(b, name_off),
890895
b->name_len, asize, name_off);
891896
if (!attr)
892897
goto out;
@@ -909,7 +914,7 @@ int ni_create_attr_list(struct ntfs_inode *ni)
909914
goto out;
910915
}
911916

912-
attr = mi_insert_attr(&ni->mi, ATTR_LIST, NULL, 0,
917+
attr = mi_insert_attr(ni, &ni->mi, ATTR_LIST, NULL, 0,
913918
lsize + SIZEOF_RESIDENT, SIZEOF_RESIDENT);
914919
if (!attr)
915920
goto out;
@@ -993,13 +998,13 @@ static int ni_ins_attr_ext(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le,
993998
mi = rb_entry(node, struct mft_inode, node);
994999

9951000
if (is_mft_data &&
996-
(mi_enum_attr(mi, NULL) ||
1001+
(mi_enum_attr(ni, mi, NULL) ||
9971002
vbo <= ((u64)mi->rno << sbi->record_bits))) {
9981003
/* We can't accept this record 'cause MFT's bootstrapping. */
9991004
continue;
10001005
}
10011006
if (is_mft &&
1002-
mi_find_attr(mi, NULL, ATTR_DATA, NULL, 0, NULL)) {
1007+
mi_find_attr(ni, mi, NULL, ATTR_DATA, NULL, 0, NULL)) {
10031008
/*
10041009
* This child record already has a ATTR_DATA.
10051010
* So it can't accept any other records.
@@ -1008,7 +1013,7 @@ static int ni_ins_attr_ext(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le,
10081013
}
10091014

10101015
if ((type != ATTR_NAME || name_len) &&
1011-
mi_find_attr(mi, NULL, type, name, name_len, NULL)) {
1016+
mi_find_attr(ni, mi, NULL, type, name, name_len, NULL)) {
10121017
/* Only indexed attributes can share same record. */
10131018
continue;
10141019
}
@@ -1157,7 +1162,7 @@ static int ni_insert_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
11571162
/* Estimate the result of moving all possible attributes away. */
11581163
attr = NULL;
11591164

1160-
while ((attr = mi_enum_attr(&ni->mi, attr))) {
1165+
while ((attr = mi_enum_attr(ni, &ni->mi, attr))) {
11611166
if (attr->type == ATTR_STD)
11621167
continue;
11631168
if (attr->type == ATTR_LIST)
@@ -1175,7 +1180,7 @@ static int ni_insert_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
11751180
attr = NULL;
11761181

11771182
for (;;) {
1178-
attr = mi_enum_attr(&ni->mi, attr);
1183+
attr = mi_enum_attr(ni, &ni->mi, attr);
11791184
if (!attr) {
11801185
/* We should never be here 'cause we have already check this case. */
11811186
err = -EINVAL;
@@ -1259,7 +1264,7 @@ static int ni_expand_mft_list(struct ntfs_inode *ni)
12591264
for (node = rb_first(&ni->mi_tree); node; node = rb_next(node)) {
12601265
mi = rb_entry(node, struct mft_inode, node);
12611266

1262-
attr = mi_enum_attr(mi, NULL);
1267+
attr = mi_enum_attr(ni, mi, NULL);
12631268

12641269
if (!attr) {
12651270
mft_min = mi->rno;
@@ -1280,7 +1285,7 @@ static int ni_expand_mft_list(struct ntfs_inode *ni)
12801285
ni_remove_mi(ni, mi_new);
12811286
}
12821287

1283-
attr = mi_find_attr(&ni->mi, NULL, ATTR_DATA, NULL, 0, NULL);
1288+
attr = mi_find_attr(ni, &ni->mi, NULL, ATTR_DATA, NULL, 0, NULL);
12841289
if (!attr) {
12851290
err = -EINVAL;
12861291
goto out;
@@ -1397,7 +1402,7 @@ int ni_expand_list(struct ntfs_inode *ni)
13971402
continue;
13981403

13991404
/* Find attribute in primary record. */
1400-
attr = rec_find_attr_le(&ni->mi, le);
1405+
attr = rec_find_attr_le(ni, &ni->mi, le);
14011406
if (!attr) {
14021407
err = -EINVAL;
14031408
goto out;
@@ -1604,8 +1609,8 @@ int ni_delete_all(struct ntfs_inode *ni)
16041609
roff = le16_to_cpu(attr->nres.run_off);
16051610

16061611
if (roff > asize) {
1607-
_ntfs_bad_inode(&ni->vfs_inode);
1608-
return -EINVAL;
1612+
/* ni_enum_attr_ex checks this case. */
1613+
continue;
16091614
}
16101615

16111616
/* run==1 means unpack and deallocate. */
@@ -2726,9 +2731,10 @@ int ni_write_frame(struct ntfs_inode *ni, struct page **pages,
27262731
{
27272732
int err;
27282733
struct ntfs_sb_info *sbi = ni->mi.sbi;
2734+
struct folio *folio = page_folio(pages[0]);
27292735
u8 frame_bits = NTFS_LZNT_CUNIT + sbi->cluster_bits;
27302736
u32 frame_size = sbi->cluster_size << NTFS_LZNT_CUNIT;
2731-
u64 frame_vbo = (u64)pages[0]->index << PAGE_SHIFT;
2737+
u64 frame_vbo = folio_pos(folio);
27322738
CLST frame = frame_vbo >> frame_bits;
27332739
char *frame_ondisk = NULL;
27342740
struct page **pages_disk = NULL;
@@ -3343,7 +3349,7 @@ int ni_write_inode(struct inode *inode, int sync, const char *hint)
33433349
if (!mi->dirty)
33443350
continue;
33453351

3346-
is_empty = !mi_enum_attr(mi, NULL);
3352+
is_empty = !mi_enum_attr(ni, mi, NULL);
33473353

33483354
if (is_empty)
33493355
clear_rec_inuse(mi->mrec);

fs/ntfs3/fsntfs.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -908,7 +908,11 @@ void ntfs_bad_inode(struct inode *inode, const char *hint)
908908

909909
ntfs_inode_err(inode, "%s", hint);
910910
make_bad_inode(inode);
911-
ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
911+
/* Avoid recursion if bad inode is $Volume. */
912+
if (inode->i_ino != MFT_REC_VOL &&
913+
!(sbi->flags & NTFS_FLAGS_LOG_REPLAYING)) {
914+
ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
915+
}
912916
}
913917

914918
/*

0 commit comments

Comments
 (0)