Skip to content

Commit 52034ca

Browse files
committed
Merge tag 'vfs-6.9-rc6.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs fixes from Christian Brauner: "This contains a few small fixes for this merge window and the attempt to handle the ntfs removal regression that was reported a little while ago: - After the removal of the legacy ntfs driver we received reports about regressions for some people that do mount "ntfs" explicitly and expect the driver to be available. Since ntfs3 is a drop-in for legacy ntfs we alias legacy ntfs to ntfs3 just like ext3 is aliased to ext4. We also enforce legacy ntfs is always mounted read-only and give it custom file operations to ensure that ioctl()'s can't be abused to perform write operations. - Fix an unbalanced module_get() in bdev_open(). - Two smaller fixes for the netfs work done earlier in this cycle. - Fix the errno returned from the new FS_IOC_GETUUID and FS_IOC_GETFSSYSFSPATH ioctls. Both commands just pull information out of the superblock so there's no need to call into the actual ioctl handlers. So instead of returning ENOIOCTLCMD to indicate to fallback we just return ENOTTY directly avoiding that indirection" * tag 'vfs-6.9-rc6.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: netfs: Fix the pre-flush when appending to a file in writethrough mode netfs: Fix writethrough-mode error handling ntfs3: add legacy ntfs file operations ntfs3: enforce read-only when used as legacy ntfs driver ntfs3: serve as alias for the legacy ntfs driver block: fix module reference leakage from bdev_open_by_dev error path fs: Return ENOTTY directly if FS_IOC_GETUUID or FS_IOC_GETFSSYSFSPATH fail
2 parents 09ef295 + c97f59e commit 52034ca

File tree

9 files changed

+121
-21
lines changed

9 files changed

+121
-21
lines changed

block/bdev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder,
882882
goto abort_claiming;
883883
ret = -EBUSY;
884884
if (!bdev_may_open(bdev, mode))
885-
goto abort_claiming;
885+
goto put_module;
886886
if (bdev_is_partition(bdev))
887887
ret = blkdev_get_part(bdev, mode);
888888
else

fs/ioctl.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ static int ioctl_getfsuuid(struct file *file, void __user *argp)
769769
struct fsuuid2 u = { .len = sb->s_uuid_len, };
770770

771771
if (!sb->s_uuid_len)
772-
return -ENOIOCTLCMD;
772+
return -ENOTTY;
773773

774774
memcpy(&u.uuid[0], &sb->s_uuid, sb->s_uuid_len);
775775

@@ -781,7 +781,7 @@ static int ioctl_get_fs_sysfs_path(struct file *file, void __user *argp)
781781
struct super_block *sb = file_inode(file)->i_sb;
782782

783783
if (!strlen(sb->s_sysfs_name))
784-
return -ENOIOCTLCMD;
784+
return -ENOTTY;
785785

786786
struct fs_sysfs_path u = {};
787787

fs/netfs/buffered_write.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -164,23 +164,22 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
164164
enum netfs_how_to_modify howto;
165165
enum netfs_folio_trace trace;
166166
unsigned int bdp_flags = (iocb->ki_flags & IOCB_SYNC) ? 0: BDP_ASYNC;
167-
ssize_t written = 0, ret;
167+
ssize_t written = 0, ret, ret2;
168168
loff_t i_size, pos = iocb->ki_pos, from, to;
169169
size_t max_chunk = PAGE_SIZE << MAX_PAGECACHE_ORDER;
170170
bool maybe_trouble = false;
171171

172172
if (unlikely(test_bit(NETFS_ICTX_WRITETHROUGH, &ctx->flags) ||
173173
iocb->ki_flags & (IOCB_DSYNC | IOCB_SYNC))
174174
) {
175-
if (pos < i_size_read(inode)) {
176-
ret = filemap_write_and_wait_range(mapping, pos, pos + iter->count);
177-
if (ret < 0) {
178-
goto out;
179-
}
180-
}
181-
182175
wbc_attach_fdatawrite_inode(&wbc, mapping->host);
183176

177+
ret = filemap_write_and_wait_range(mapping, pos, pos + iter->count);
178+
if (ret < 0) {
179+
wbc_detach_inode(&wbc);
180+
goto out;
181+
}
182+
184183
wreq = netfs_begin_writethrough(iocb, iter->count);
185184
if (IS_ERR(wreq)) {
186185
wbc_detach_inode(&wbc);
@@ -395,10 +394,12 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
395394

396395
out:
397396
if (unlikely(wreq)) {
398-
ret = netfs_end_writethrough(wreq, iocb);
397+
ret2 = netfs_end_writethrough(wreq, iocb);
399398
wbc_detach_inode(&wbc);
400-
if (ret == -EIOCBQUEUED)
401-
return ret;
399+
if (ret2 == -EIOCBQUEUED)
400+
return ret2;
401+
if (ret == 0)
402+
ret = ret2;
402403
}
403404

404405
iocb->ki_pos += written;

fs/ntfs3/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,12 @@ config NTFS3_FS_POSIX_ACL
4646
NOTE: this is linux only feature. Windows will ignore these ACLs.
4747

4848
If you don't know what Access Control Lists are, say N.
49+
50+
config NTFS_FS
51+
tristate "NTFS file system support"
52+
select NTFS3_FS
53+
select BUFFER_HEAD
54+
select NLS
55+
help
56+
This config option is here only for backward compatibility. NTFS
57+
filesystem is now handled by the NTFS3 driver.

fs/ntfs3/dir.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,4 +616,11 @@ const struct file_operations ntfs_dir_operations = {
616616
.compat_ioctl = ntfs_compat_ioctl,
617617
#endif
618618
};
619+
620+
const struct file_operations ntfs_legacy_dir_operations = {
621+
.llseek = generic_file_llseek,
622+
.read = generic_read_dir,
623+
.iterate_shared = ntfs_readdir,
624+
.open = ntfs_file_open,
625+
};
619626
// clang-format on

fs/ntfs3/file.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,4 +1236,12 @@ const struct file_operations ntfs_file_operations = {
12361236
.fallocate = ntfs_fallocate,
12371237
.release = ntfs_file_release,
12381238
};
1239+
1240+
const struct file_operations ntfs_legacy_file_operations = {
1241+
.llseek = generic_file_llseek,
1242+
.read_iter = ntfs_file_read_iter,
1243+
.splice_read = ntfs_file_splice_read,
1244+
.open = ntfs_file_open,
1245+
.release = ntfs_file_release,
1246+
};
12391247
// clang-format on

fs/ntfs3/inode.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,10 @@ static struct inode *ntfs_read_mft(struct inode *inode,
440440
* Usually a hard links to directories are disabled.
441441
*/
442442
inode->i_op = &ntfs_dir_inode_operations;
443-
inode->i_fop = &ntfs_dir_operations;
443+
if (is_legacy_ntfs(inode->i_sb))
444+
inode->i_fop = &ntfs_legacy_dir_operations;
445+
else
446+
inode->i_fop = &ntfs_dir_operations;
444447
ni->i_valid = 0;
445448
} else if (S_ISLNK(mode)) {
446449
ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY;
@@ -450,7 +453,10 @@ static struct inode *ntfs_read_mft(struct inode *inode,
450453
} else if (S_ISREG(mode)) {
451454
ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY;
452455
inode->i_op = &ntfs_file_inode_operations;
453-
inode->i_fop = &ntfs_file_operations;
456+
if (is_legacy_ntfs(inode->i_sb))
457+
inode->i_fop = &ntfs_legacy_file_operations;
458+
else
459+
inode->i_fop = &ntfs_file_operations;
454460
inode->i_mapping->a_ops = is_compressed(ni) ? &ntfs_aops_cmpr :
455461
&ntfs_aops;
456462
if (ino != MFT_REC_MFT)
@@ -1614,7 +1620,10 @@ struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
16141620

16151621
if (S_ISDIR(mode)) {
16161622
inode->i_op = &ntfs_dir_inode_operations;
1617-
inode->i_fop = &ntfs_dir_operations;
1623+
if (is_legacy_ntfs(inode->i_sb))
1624+
inode->i_fop = &ntfs_legacy_dir_operations;
1625+
else
1626+
inode->i_fop = &ntfs_dir_operations;
16181627
} else if (S_ISLNK(mode)) {
16191628
inode->i_op = &ntfs_link_inode_operations;
16201629
inode->i_fop = NULL;
@@ -1623,7 +1632,10 @@ struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
16231632
inode_nohighmem(inode);
16241633
} else if (S_ISREG(mode)) {
16251634
inode->i_op = &ntfs_file_inode_operations;
1626-
inode->i_fop = &ntfs_file_operations;
1635+
if (is_legacy_ntfs(inode->i_sb))
1636+
inode->i_fop = &ntfs_legacy_file_operations;
1637+
else
1638+
inode->i_fop = &ntfs_file_operations;
16271639
inode->i_mapping->a_ops = is_compressed(ni) ? &ntfs_aops_cmpr :
16281640
&ntfs_aops;
16291641
init_rwsem(&ni->file.run_lock);

fs/ntfs3/ntfs_fs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ struct inode *dir_search_u(struct inode *dir, const struct cpu_str *uni,
493493
struct ntfs_fnd *fnd);
494494
bool dir_is_empty(struct inode *dir);
495495
extern const struct file_operations ntfs_dir_operations;
496+
extern const struct file_operations ntfs_legacy_dir_operations;
496497

497498
/* Globals from file.c */
498499
int ntfs_getattr(struct mnt_idmap *idmap, const struct path *path,
@@ -507,6 +508,7 @@ long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg);
507508
extern const struct inode_operations ntfs_special_inode_operations;
508509
extern const struct inode_operations ntfs_file_inode_operations;
509510
extern const struct file_operations ntfs_file_operations;
511+
extern const struct file_operations ntfs_legacy_file_operations;
510512

511513
/* Globals from frecord.c */
512514
void ni_remove_mi(struct ntfs_inode *ni, struct mft_inode *mi);
@@ -1154,4 +1156,6 @@ static inline void le64_sub_cpu(__le64 *var, u64 val)
11541156
*var = cpu_to_le64(le64_to_cpu(*var) - val);
11551157
}
11561158

1159+
bool is_legacy_ntfs(struct super_block *sb);
1160+
11571161
#endif /* _LINUX_NTFS3_NTFS_FS_H */

fs/ntfs3/super.c

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,12 @@ static int ntfs_fs_reconfigure(struct fs_context *fc)
408408
struct ntfs_mount_options *new_opts = fc->fs_private;
409409
int ro_rw;
410410

411+
/* If ntfs3 is used as legacy ntfs enforce read-only mode. */
412+
if (is_legacy_ntfs(sb)) {
413+
fc->sb_flags |= SB_RDONLY;
414+
goto out;
415+
}
416+
411417
ro_rw = sb_rdonly(sb) && !(fc->sb_flags & SB_RDONLY);
412418
if (ro_rw && (sbi->flags & NTFS_FLAGS_NEED_REPLAY)) {
413419
errorf(fc,
@@ -427,15 +433,15 @@ static int ntfs_fs_reconfigure(struct fs_context *fc)
427433
fc,
428434
"ntfs3: Cannot use different iocharset when remounting!");
429435

430-
sync_filesystem(sb);
431-
432436
if (ro_rw && (sbi->volume.flags & VOLUME_FLAG_DIRTY) &&
433437
!new_opts->force) {
434438
errorf(fc,
435439
"ntfs3: Volume is dirty and \"force\" flag is not set!");
436440
return -EINVAL;
437441
}
438442

443+
out:
444+
sync_filesystem(sb);
439445
swap(sbi->options, fc->fs_private);
440446

441447
return 0;
@@ -1613,6 +1619,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
16131619
}
16141620
#endif
16151621

1622+
if (is_legacy_ntfs(sb))
1623+
sb->s_flags |= SB_RDONLY;
16161624
return 0;
16171625

16181626
put_inode_out:
@@ -1730,7 +1738,7 @@ static const struct fs_context_operations ntfs_context_ops = {
17301738
* This will called when mount/remount. We will first initialize
17311739
* options so that if remount we can use just that.
17321740
*/
1733-
static int ntfs_init_fs_context(struct fs_context *fc)
1741+
static int __ntfs_init_fs_context(struct fs_context *fc)
17341742
{
17351743
struct ntfs_mount_options *opts;
17361744
struct ntfs_sb_info *sbi;
@@ -1778,6 +1786,11 @@ static int ntfs_init_fs_context(struct fs_context *fc)
17781786
return -ENOMEM;
17791787
}
17801788

1789+
static int ntfs_init_fs_context(struct fs_context *fc)
1790+
{
1791+
return __ntfs_init_fs_context(fc);
1792+
}
1793+
17811794
static void ntfs3_kill_sb(struct super_block *sb)
17821795
{
17831796
struct ntfs_sb_info *sbi = sb->s_fs_info;
@@ -1798,6 +1811,50 @@ static struct file_system_type ntfs_fs_type = {
17981811
.kill_sb = ntfs3_kill_sb,
17991812
.fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
18001813
};
1814+
1815+
#if IS_ENABLED(CONFIG_NTFS_FS)
1816+
static int ntfs_legacy_init_fs_context(struct fs_context *fc)
1817+
{
1818+
int ret;
1819+
1820+
ret = __ntfs_init_fs_context(fc);
1821+
/* If ntfs3 is used as legacy ntfs enforce read-only mode. */
1822+
fc->sb_flags |= SB_RDONLY;
1823+
return ret;
1824+
}
1825+
1826+
static struct file_system_type ntfs_legacy_fs_type = {
1827+
.owner = THIS_MODULE,
1828+
.name = "ntfs",
1829+
.init_fs_context = ntfs_legacy_init_fs_context,
1830+
.parameters = ntfs_fs_parameters,
1831+
.kill_sb = ntfs3_kill_sb,
1832+
.fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
1833+
};
1834+
MODULE_ALIAS_FS("ntfs");
1835+
1836+
static inline void register_as_ntfs_legacy(void)
1837+
{
1838+
int err = register_filesystem(&ntfs_legacy_fs_type);
1839+
if (err)
1840+
pr_warn("ntfs3: Failed to register legacy ntfs filesystem driver: %d\n", err);
1841+
}
1842+
1843+
static inline void unregister_as_ntfs_legacy(void)
1844+
{
1845+
unregister_filesystem(&ntfs_legacy_fs_type);
1846+
}
1847+
bool is_legacy_ntfs(struct super_block *sb)
1848+
{
1849+
return sb->s_type == &ntfs_legacy_fs_type;
1850+
}
1851+
#else
1852+
static inline void register_as_ntfs_legacy(void) {}
1853+
static inline void unregister_as_ntfs_legacy(void) {}
1854+
bool is_legacy_ntfs(struct super_block *sb) { return false; }
1855+
#endif
1856+
1857+
18011858
// clang-format on
18021859

18031860
static int __init init_ntfs_fs(void)
@@ -1832,6 +1889,7 @@ static int __init init_ntfs_fs(void)
18321889
goto out1;
18331890
}
18341891

1892+
register_as_ntfs_legacy();
18351893
err = register_filesystem(&ntfs_fs_type);
18361894
if (err)
18371895
goto out;
@@ -1849,6 +1907,7 @@ static void __exit exit_ntfs_fs(void)
18491907
rcu_barrier();
18501908
kmem_cache_destroy(ntfs_inode_cachep);
18511909
unregister_filesystem(&ntfs_fs_type);
1910+
unregister_as_ntfs_legacy();
18521911
ntfs3_exit_bitmap();
18531912

18541913
#ifdef CONFIG_PROC_FS

0 commit comments

Comments
 (0)