Skip to content

Commit 110b24e

Browse files
fs/ntfs3: Taking DOS names into account during link counting
When counting and checking hard links in an ntfs file record, struct MFT_REC { struct NTFS_RECORD_HEADER rhdr; // 'FILE' __le16 seq; // 0x10: Sequence number for this record. >> __le16 hard_links; // 0x12: The number of hard links to record. __le16 attr_off; // 0x14: Offset to attributes. ... the ntfs3 driver ignored short names (DOS names), causing the link count to be reduced by 1 and messages to be output to dmesg. For Windows, such a situation is a minor error, meaning chkdsk does not report errors on such a volume, and in the case of using the /f switch, it silently corrects them, reporting that no errors were found. This does not affect the consistency of the file system. Nevertheless, the behavior in the ntfs3 driver is incorrect and changes the content of the file system. This patch should fix that. PS: most likely, there has been a confusion of concepts MFT_REC::hard_links and inode::__i_nlink. Fixes: 82cae26 ("fs/ntfs3: Add initialization of super block") Signed-off-by: Konstantin Komarov <[email protected]> Cc: [email protected]
1 parent 93b4d70 commit 110b24e

File tree

2 files changed

+6
-12
lines changed

2 files changed

+6
-12
lines changed

fs/ntfs3/inode.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ static struct inode *ntfs_read_mft(struct inode *inode,
3737
bool is_dir;
3838
unsigned long ino = inode->i_ino;
3939
u32 rp_fa = 0, asize, t32;
40-
u16 roff, rsize, names = 0;
40+
u16 roff, rsize, names = 0, links = 0;
4141
const struct ATTR_FILE_NAME *fname = NULL;
4242
const struct INDEX_ROOT *root;
4343
struct REPARSE_DATA_BUFFER rp; // 0x18 bytes
@@ -200,11 +200,12 @@ static struct inode *ntfs_read_mft(struct inode *inode,
200200
rsize < SIZEOF_ATTRIBUTE_FILENAME)
201201
goto out;
202202

203+
names += 1;
203204
fname = Add2Ptr(attr, roff);
204205
if (fname->type == FILE_NAME_DOS)
205206
goto next_attr;
206207

207-
names += 1;
208+
links += 1;
208209
if (name && name->len == fname->name_len &&
209210
!ntfs_cmp_names_cpu(name, (struct le_str *)&fname->name_len,
210211
NULL, false))
@@ -429,7 +430,7 @@ static struct inode *ntfs_read_mft(struct inode *inode,
429430
ni->mi.dirty = true;
430431
}
431432

432-
set_nlink(inode, names);
433+
set_nlink(inode, links);
433434

434435
if (S_ISDIR(mode)) {
435436
ni->std_fa |= FILE_ATTRIBUTE_DIRECTORY;

fs/ntfs3/record.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -534,16 +534,9 @@ bool mi_remove_attr(struct ntfs_inode *ni, struct mft_inode *mi,
534534
if (aoff + asize > used)
535535
return false;
536536

537-
if (ni && is_attr_indexed(attr)) {
537+
if (ni && is_attr_indexed(attr) && attr->type == ATTR_NAME) {
538538
u16 links = le16_to_cpu(ni->mi.mrec->hard_links);
539-
struct ATTR_FILE_NAME *fname =
540-
attr->type != ATTR_NAME ?
541-
NULL :
542-
resident_data_ex(attr,
543-
SIZEOF_ATTRIBUTE_FILENAME);
544-
if (fname && fname->type == FILE_NAME_DOS) {
545-
/* Do not decrease links count deleting DOS name. */
546-
} else if (!links) {
539+
if (!links) {
547540
/* minor error. Not critical. */
548541
} else {
549542
ni->mi.mrec->hard_links = cpu_to_le16(links - 1);

0 commit comments

Comments
 (0)