Skip to content

Commit 89b61ca

Browse files
committed
Pull ntfs3 updates from Konstantin Komarov: "Fixes: - reusing of the file index (could cause the file to be trimmed) - infinite dir enumeration - taking DOS names into account during link counting - le32_to_cpu conversion, 32 bit overflow, NULL check - some code was refactored Changes: - removed max link count info display during driver init Remove: - atomic_open has been removed for lack of use" * tag 'ntfs3_for_6.10' of https://github.com/Paragon-Software-Group/linux-ntfs3: fs/ntfs3: Break dir enumeration if directory contents error fs/ntfs3: Fix case when index is reused during tree transformation fs/ntfs3: Mark volume as dirty if xattr is broken fs/ntfs3: Always make file nonresident on fallocate call fs/ntfs3: Redesign ntfs_create_inode to return error code instead of inode fs/ntfs3: Use variable length array instead of fixed size fs/ntfs3: Use 64 bit variable to avoid 32 bit overflow fs/ntfs3: Check 'folio' pointer for NULL fs/ntfs3: Missed le32_to_cpu conversion fs/ntfs3: Remove max link count info display during driver init fs/ntfs3: Taking DOS names into account during link counting fs/ntfs3: remove atomic_open fs/ntfs3: use kcalloc() instead of kzalloc()
2 parents 6c8b1a2 + 302e9dc commit 89b61ca

File tree

13 files changed

+98
-154
lines changed

13 files changed

+98
-154
lines changed

fs/ntfs3/attrib.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2558,3 +2558,35 @@ int attr_insert_range(struct ntfs_inode *ni, u64 vbo, u64 bytes)
25582558

25592559
goto out;
25602560
}
2561+
2562+
/*
2563+
* attr_force_nonresident
2564+
*
2565+
* Convert default data attribute into non resident form.
2566+
*/
2567+
int attr_force_nonresident(struct ntfs_inode *ni)
2568+
{
2569+
int err;
2570+
struct ATTRIB *attr;
2571+
struct ATTR_LIST_ENTRY *le = NULL;
2572+
struct mft_inode *mi;
2573+
2574+
attr = ni_find_attr(ni, NULL, &le, ATTR_DATA, NULL, 0, NULL, &mi);
2575+
if (!attr) {
2576+
ntfs_bad_inode(&ni->vfs_inode, "no data attribute");
2577+
return -ENOENT;
2578+
}
2579+
2580+
if (attr->non_res) {
2581+
/* Already non resident. */
2582+
return 0;
2583+
}
2584+
2585+
down_write(&ni->file.run_lock);
2586+
err = attr_make_nonresident(ni, attr, le, mi,
2587+
le32_to_cpu(attr->res.data_size),
2588+
&ni->file.run, &attr, NULL);
2589+
up_write(&ni->file.run_lock);
2590+
2591+
return err;
2592+
}

fs/ntfs3/dir.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@ static int ntfs_readdir(struct file *file, struct dir_context *ctx)
475475
vbo = (u64)bit << index_bits;
476476
if (vbo >= i_size) {
477477
ntfs_inode_err(dir, "Looks like your dir is corrupt");
478+
ctx->pos = eod;
478479
err = -EINVAL;
479480
goto out;
480481
}

fs/ntfs3/file.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,15 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
578578
/* Check new size. */
579579
u8 cluster_bits = sbi->cluster_bits;
580580

581+
/* Be sure file is non resident. */
582+
if (is_resident(ni)) {
583+
ni_lock(ni);
584+
err = attr_force_nonresident(ni);
585+
ni_unlock(ni);
586+
if (err)
587+
goto out;
588+
}
589+
581590
/* generic/213: expected -ENOSPC instead of -EFBIG. */
582591
if (!is_supported_holes) {
583592
loff_t to_alloc = new_size - inode_get_bytes(inode);

fs/ntfs3/frecord.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2636,7 +2636,7 @@ int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages,
26362636
goto out1;
26372637
}
26382638

2639-
pages_disk = kzalloc(npages_disk * sizeof(struct page *), GFP_NOFS);
2639+
pages_disk = kcalloc(npages_disk, sizeof(*pages_disk), GFP_NOFS);
26402640
if (!pages_disk) {
26412641
err = -ENOMEM;
26422642
goto out2;

fs/ntfs3/fslog.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ static inline bool is_rst_area_valid(const struct RESTART_HDR *rhdr)
517517
seq_bits -= 1;
518518
}
519519

520-
if (seq_bits != ra->seq_num_bits)
520+
if (seq_bits != le32_to_cpu(ra->seq_num_bits))
521521
return false;
522522

523523
/* The log page data offset and record header length must be quad-aligned. */
@@ -1184,7 +1184,8 @@ static int read_log_page(struct ntfs_log *log, u32 vbo,
11841184
static int log_read_rst(struct ntfs_log *log, bool first,
11851185
struct restart_info *info)
11861186
{
1187-
u32 skip, vbo;
1187+
u32 skip;
1188+
u64 vbo;
11881189
struct RESTART_HDR *r_page = NULL;
11891190

11901191
/* Determine which restart area we are looking for. */

fs/ntfs3/index.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,11 @@ static int indx_add_allocate(struct ntfs_index *indx, struct ntfs_inode *ni,
15341534
goto out1;
15351535
}
15361536

1537+
if (data_size <= le64_to_cpu(alloc->nres.data_size)) {
1538+
/* Reuse index. */
1539+
goto out;
1540+
}
1541+
15371542
/* Increase allocation. */
15381543
err = attr_set_size(ni, ATTR_ALLOC, in->name, in->name_len,
15391544
&indx->alloc_run, data_size, &data_size, true,
@@ -1547,6 +1552,7 @@ static int indx_add_allocate(struct ntfs_index *indx, struct ntfs_inode *ni,
15471552
if (in->name == I30_NAME)
15481553
i_size_write(&ni->vfs_inode, data_size);
15491554

1555+
out:
15501556
*vbn = bit << indx->idx2vbn_bits;
15511557

15521558
return 0;

fs/ntfs3/inode.c

Lines changed: 26 additions & 20 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;
@@ -576,13 +577,18 @@ static noinline int ntfs_get_block_vbo(struct inode *inode, u64 vbo,
576577
clear_buffer_uptodate(bh);
577578

578579
if (is_resident(ni)) {
579-
ni_lock(ni);
580-
err = attr_data_read_resident(ni, &folio->page);
581-
ni_unlock(ni);
582-
583-
if (!err)
584-
set_buffer_uptodate(bh);
580+
bh->b_blocknr = RESIDENT_LCN;
585581
bh->b_size = block_size;
582+
if (!folio) {
583+
err = 0;
584+
} else {
585+
ni_lock(ni);
586+
err = attr_data_read_resident(ni, &folio->page);
587+
ni_unlock(ni);
588+
589+
if (!err)
590+
set_buffer_uptodate(bh);
591+
}
586592
return err;
587593
}
588594

@@ -1216,11 +1222,10 @@ ntfs_create_reparse_buffer(struct ntfs_sb_info *sbi, const char *symname,
12161222
*
12171223
* NOTE: if fnd != NULL (ntfs_atomic_open) then @dir is locked
12181224
*/
1219-
struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
1220-
struct dentry *dentry,
1221-
const struct cpu_str *uni, umode_t mode,
1222-
dev_t dev, const char *symname, u32 size,
1223-
struct ntfs_fnd *fnd)
1225+
int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
1226+
struct dentry *dentry, const struct cpu_str *uni,
1227+
umode_t mode, dev_t dev, const char *symname, u32 size,
1228+
struct ntfs_fnd *fnd)
12241229
{
12251230
int err;
12261231
struct super_block *sb = dir->i_sb;
@@ -1245,6 +1250,9 @@ struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
12451250
struct REPARSE_DATA_BUFFER *rp = NULL;
12461251
bool rp_inserted = false;
12471252

1253+
/* New file will be resident or non resident. */
1254+
const bool new_file_resident = 1;
1255+
12481256
if (!fnd)
12491257
ni_lock_dir(dir_ni);
12501258

@@ -1484,7 +1492,7 @@ struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
14841492
attr->size = cpu_to_le32(SIZEOF_RESIDENT);
14851493
attr->name_off = SIZEOF_RESIDENT_LE;
14861494
attr->res.data_off = SIZEOF_RESIDENT_LE;
1487-
} else if (S_ISREG(mode)) {
1495+
} else if (!new_file_resident && S_ISREG(mode)) {
14881496
/*
14891497
* Regular file. Create empty non resident data attribute.
14901498
*/
@@ -1727,12 +1735,10 @@ struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
17271735
if (!fnd)
17281736
ni_unlock(dir_ni);
17291737

1730-
if (err)
1731-
return ERR_PTR(err);
1732-
1733-
unlock_new_inode(inode);
1738+
if (!err)
1739+
unlock_new_inode(inode);
17341740

1735-
return inode;
1741+
return err;
17361742
}
17371743

17381744
int ntfs_link_inode(struct inode *inode, struct dentry *dentry)

fs/ntfs3/namei.c

Lines changed: 8 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,8 @@ static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *dentry,
107107
static int ntfs_create(struct mnt_idmap *idmap, struct inode *dir,
108108
struct dentry *dentry, umode_t mode, bool excl)
109109
{
110-
struct inode *inode;
111-
112-
inode = ntfs_create_inode(idmap, dir, dentry, NULL, S_IFREG | mode, 0,
113-
NULL, 0, NULL);
114-
115-
return IS_ERR(inode) ? PTR_ERR(inode) : 0;
110+
return ntfs_create_inode(idmap, dir, dentry, NULL, S_IFREG | mode, 0,
111+
NULL, 0, NULL);
116112
}
117113

118114
/*
@@ -123,12 +119,8 @@ static int ntfs_create(struct mnt_idmap *idmap, struct inode *dir,
123119
static int ntfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
124120
struct dentry *dentry, umode_t mode, dev_t rdev)
125121
{
126-
struct inode *inode;
127-
128-
inode = ntfs_create_inode(idmap, dir, dentry, NULL, mode, rdev, NULL, 0,
129-
NULL);
130-
131-
return IS_ERR(inode) ? PTR_ERR(inode) : 0;
122+
return ntfs_create_inode(idmap, dir, dentry, NULL, mode, rdev, NULL, 0,
123+
NULL);
132124
}
133125

134126
/*
@@ -200,15 +192,12 @@ static int ntfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
200192
struct dentry *dentry, const char *symname)
201193
{
202194
u32 size = strlen(symname);
203-
struct inode *inode;
204195

205196
if (unlikely(ntfs3_forced_shutdown(dir->i_sb)))
206197
return -EIO;
207198

208-
inode = ntfs_create_inode(idmap, dir, dentry, NULL, S_IFLNK | 0777, 0,
209-
symname, size, NULL);
210-
211-
return IS_ERR(inode) ? PTR_ERR(inode) : 0;
199+
return ntfs_create_inode(idmap, dir, dentry, NULL, S_IFLNK | 0777, 0,
200+
symname, size, NULL);
212201
}
213202

214203
/*
@@ -217,12 +206,8 @@ static int ntfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
217206
static int ntfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
218207
struct dentry *dentry, umode_t mode)
219208
{
220-
struct inode *inode;
221-
222-
inode = ntfs_create_inode(idmap, dir, dentry, NULL, S_IFDIR | mode, 0,
223-
NULL, 0, NULL);
224-
225-
return IS_ERR(inode) ? PTR_ERR(inode) : 0;
209+
return ntfs_create_inode(idmap, dir, dentry, NULL, S_IFDIR | mode, 0,
210+
NULL, 0, NULL);
226211
}
227212

228213
/*
@@ -358,95 +343,6 @@ static int ntfs_rename(struct mnt_idmap *idmap, struct inode *dir,
358343
return err;
359344
}
360345

361-
/*
362-
* ntfs_atomic_open
363-
*
364-
* inode_operations::atomic_open
365-
*/
366-
static int ntfs_atomic_open(struct inode *dir, struct dentry *dentry,
367-
struct file *file, u32 flags, umode_t mode)
368-
{
369-
int err;
370-
struct inode *inode;
371-
struct ntfs_fnd *fnd = NULL;
372-
struct ntfs_inode *ni = ntfs_i(dir);
373-
struct dentry *d = NULL;
374-
struct cpu_str *uni = __getname();
375-
bool locked = false;
376-
377-
if (!uni)
378-
return -ENOMEM;
379-
380-
err = ntfs_nls_to_utf16(ni->mi.sbi, dentry->d_name.name,
381-
dentry->d_name.len, uni, NTFS_NAME_LEN,
382-
UTF16_HOST_ENDIAN);
383-
if (err < 0)
384-
goto out;
385-
386-
#ifdef CONFIG_NTFS3_FS_POSIX_ACL
387-
if (IS_POSIXACL(dir)) {
388-
/*
389-
* Load in cache current acl to avoid ni_lock(dir):
390-
* ntfs_create_inode -> ntfs_init_acl -> posix_acl_create ->
391-
* ntfs_get_acl -> ntfs_get_acl_ex -> ni_lock
392-
*/
393-
struct posix_acl *p = get_inode_acl(dir, ACL_TYPE_DEFAULT);
394-
395-
if (IS_ERR(p)) {
396-
err = PTR_ERR(p);
397-
goto out;
398-
}
399-
posix_acl_release(p);
400-
}
401-
#endif
402-
403-
if (d_in_lookup(dentry)) {
404-
ni_lock_dir(ni);
405-
locked = true;
406-
fnd = fnd_get();
407-
if (!fnd) {
408-
err = -ENOMEM;
409-
goto out1;
410-
}
411-
412-
d = d_splice_alias(dir_search_u(dir, uni, fnd), dentry);
413-
if (IS_ERR(d)) {
414-
err = PTR_ERR(d);
415-
d = NULL;
416-
goto out2;
417-
}
418-
419-
if (d)
420-
dentry = d;
421-
}
422-
423-
if (!(flags & O_CREAT) || d_really_is_positive(dentry)) {
424-
err = finish_no_open(file, d);
425-
goto out2;
426-
}
427-
428-
file->f_mode |= FMODE_CREATED;
429-
430-
/*
431-
* fnd contains tree's path to insert to.
432-
* If fnd is not NULL then dir is locked.
433-
*/
434-
inode = ntfs_create_inode(file_mnt_idmap(file), dir, dentry, uni,
435-
mode, 0, NULL, 0, fnd);
436-
err = IS_ERR(inode) ? PTR_ERR(inode) :
437-
finish_open(file, dentry, ntfs_file_open);
438-
dput(d);
439-
440-
out2:
441-
fnd_put(fnd);
442-
out1:
443-
if (locked)
444-
ni_unlock(ni);
445-
out:
446-
__putname(uni);
447-
return err;
448-
}
449-
450346
struct dentry *ntfs3_get_parent(struct dentry *child)
451347
{
452348
struct inode *inode = d_inode(child);
@@ -612,7 +508,6 @@ const struct inode_operations ntfs_dir_inode_operations = {
612508
.setattr = ntfs3_setattr,
613509
.getattr = ntfs_getattr,
614510
.listxattr = ntfs_listxattr,
615-
.atomic_open = ntfs_atomic_open,
616511
.fiemap = ntfs_fiemap,
617512
};
618513

fs/ntfs3/ntfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ struct GUID {
5959
struct cpu_str {
6060
u8 len;
6161
u8 unused;
62-
u16 name[10];
62+
u16 name[];
6363
};
6464

6565
struct le_str {

0 commit comments

Comments
 (0)