summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-07-01 12:06:39 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2021-07-01 12:06:39 -0700
commit911a2997a5b7c16b27dfe83d8e2f614e44d90f74 (patch)
treefdad1abbe9909f8faf703c4fe27f794085d34730 /fs
parenta6ecc2a491e378e00e65e59a006d4005e1c2f4af (diff)
parent8b0ed8443ae6458786580d36b7d5f8125535c5d4 (diff)
Merge tag 'fs_for_v5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull misc fs updates from Jan Kara: "The new quotactl_fd() syscall (remake of quotactl_path() syscall that got introduced & disabled in 5.13 cycle), and couple of udf, reiserfs, isofs, and writeback fixes and cleanups" * tag 'fs_for_v5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: writeback: fix obtain a reference to a freeing memcg css quota: remove unnecessary oom message isofs: remove redundant continue statement quota: Wire up quotactl_fd syscall quota: Change quotactl_path() systcall to an fd-based one reiserfs: Remove unneed check in reiserfs_write_full_page() udf: Fix NULL pointer dereference in udf_symlink function reiserfs: add check for invalid 1st journal block
Diffstat (limited to 'fs')
-rw-r--r--fs/fs-writeback.c9
-rw-r--r--fs/isofs/dir.c2
-rw-r--r--fs/quota/quota.c28
-rw-r--r--fs/quota/quota_tree.c33
-rw-r--r--fs/reiserfs/inode.c4
-rw-r--r--fs/reiserfs/journal.c14
-rw-r--r--fs/udf/namei.c4
7 files changed, 51 insertions, 43 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 8c7e9e51a398..06d04a74ab6c 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -567,9 +567,14 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
/* find and pin the new wb */
rcu_read_lock();
memcg_css = css_from_id(new_wb_id, &memory_cgrp_subsys);
- if (memcg_css)
- isw->new_wb = wb_get_create(bdi, memcg_css, GFP_ATOMIC);
+ if (memcg_css && !css_tryget(memcg_css))
+ memcg_css = NULL;
rcu_read_unlock();
+ if (!memcg_css)
+ goto out_free;
+
+ isw->new_wb = wb_get_create(bdi, memcg_css, GFP_ATOMIC);
+ css_put(memcg_css);
if (!isw->new_wb)
goto out_free;
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index b9e6a7ec78be..eb2f8273e6f1 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -235,8 +235,6 @@ static int do_isofs_readdir(struct inode *inode, struct file *file,
break;
}
ctx->pos += de_len;
-
- continue;
}
if (bh)
brelse(bh);
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 05e4bd9ab6d6..2bcc9a6f1bfc 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -968,31 +968,30 @@ out:
return ret;
}
-SYSCALL_DEFINE4(quotactl_path, unsigned int, cmd, const char __user *,
- mountpoint, qid_t, id, void __user *, addr)
+SYSCALL_DEFINE4(quotactl_fd, unsigned int, fd, unsigned int, cmd,
+ qid_t, id, void __user *, addr)
{
struct super_block *sb;
- struct path mountpath;
unsigned int cmds = cmd >> SUBCMDSHIFT;
unsigned int type = cmd & SUBCMDMASK;
+ struct fd f;
int ret;
- if (type >= MAXQUOTAS)
- return -EINVAL;
+ f = fdget_raw(fd);
+ if (!f.file)
+ return -EBADF;
- ret = user_path_at(AT_FDCWD, mountpoint,
- LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT, &mountpath);
- if (ret)
- return ret;
-
- sb = mountpath.mnt->mnt_sb;
+ ret = -EINVAL;
+ if (type >= MAXQUOTAS)
+ goto out;
if (quotactl_cmd_write(cmds)) {
- ret = mnt_want_write(mountpath.mnt);
+ ret = mnt_want_write(f.file->f_path.mnt);
if (ret)
goto out;
}
+ sb = f.file->f_path.mnt->mnt_sb;
if (quotactl_cmd_onoff(cmds))
down_write(&sb->s_umount);
else
@@ -1006,9 +1005,8 @@ SYSCALL_DEFINE4(quotactl_path, unsigned int, cmd, const char __user *,
up_read(&sb->s_umount);
if (quotactl_cmd_write(cmds))
- mnt_drop_write(mountpath.mnt);
+ mnt_drop_write(f.file->f_path.mnt);
out:
- path_put(&mountpath);
-
+ fdput(f);
return ret;
}
diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c
index c5562c871c8b..d3e995e1046f 100644
--- a/fs/quota/quota_tree.c
+++ b/fs/quota/quota_tree.c
@@ -47,15 +47,6 @@ static int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info)
/ info->dqi_entry_size;
}
-static char *getdqbuf(size_t size)
-{
- char *buf = kmalloc(size, GFP_NOFS);
- if (!buf)
- printk(KERN_WARNING
- "VFS: Not enough memory for quota buffers.\n");
- return buf;
-}
-
static ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf)
{
struct super_block *sb = info->dqi_sb;
@@ -83,7 +74,7 @@ static ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf)
/* Remove empty block from list and return it */
static int get_free_dqblk(struct qtree_mem_dqinfo *info)
{
- char *buf = getdqbuf(info->dqi_usable_bs);
+ char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
int ret, blk;
@@ -132,7 +123,7 @@ static int put_free_dqblk(struct qtree_mem_dqinfo *info, char *buf, uint blk)
static int remove_free_dqentry(struct qtree_mem_dqinfo *info, char *buf,
uint blk)
{
- char *tmpbuf = getdqbuf(info->dqi_usable_bs);
+ char *tmpbuf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
uint nextblk = le32_to_cpu(dh->dqdh_next_free);
uint prevblk = le32_to_cpu(dh->dqdh_prev_free);
@@ -179,7 +170,7 @@ out_buf:
static int insert_free_dqentry(struct qtree_mem_dqinfo *info, char *buf,
uint blk)
{
- char *tmpbuf = getdqbuf(info->dqi_usable_bs);
+ char *tmpbuf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
int err;
@@ -227,7 +218,7 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info,
{
uint blk, i;
struct qt_disk_dqdbheader *dh;
- char *buf = getdqbuf(info->dqi_usable_bs);
+ char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
char *ddquot;
*err = 0;
@@ -298,7 +289,7 @@ out_buf:
static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
uint *treeblk, int depth)
{
- char *buf = getdqbuf(info->dqi_usable_bs);
+ char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
int ret = 0, newson = 0, newact = 0;
__le32 *ref;
uint newblk;
@@ -375,7 +366,7 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
int type = dquot->dq_id.type;
struct super_block *sb = dquot->dq_sb;
ssize_t ret;
- char *ddquot = getdqbuf(info->dqi_entry_size);
+ char *ddquot = kmalloc(info->dqi_entry_size, GFP_NOFS);
if (!ddquot)
return -ENOMEM;
@@ -414,7 +405,7 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot,
uint blk)
{
struct qt_disk_dqdbheader *dh;
- char *buf = getdqbuf(info->dqi_usable_bs);
+ char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
int ret = 0;
if (!buf)
@@ -474,7 +465,7 @@ out_buf:
static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
uint *blk, int depth)
{
- char *buf = getdqbuf(info->dqi_usable_bs);
+ char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
int ret = 0;
uint newblk;
__le32 *ref = (__le32 *)buf;
@@ -533,7 +524,7 @@ EXPORT_SYMBOL(qtree_delete_dquot);
static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info,
struct dquot *dquot, uint blk)
{
- char *buf = getdqbuf(info->dqi_usable_bs);
+ char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
loff_t ret = 0;
int i;
char *ddquot;
@@ -571,7 +562,7 @@ out_buf:
static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info,
struct dquot *dquot, uint blk, int depth)
{
- char *buf = getdqbuf(info->dqi_usable_bs);
+ char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
loff_t ret = 0;
__le32 *ref = (__le32 *)buf;
@@ -635,7 +626,7 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
}
dquot->dq_off = offset;
}
- ddquot = getdqbuf(info->dqi_entry_size);
+ ddquot = kmalloc(info->dqi_entry_size, GFP_NOFS);
if (!ddquot)
return -ENOMEM;
ret = sb->s_op->quota_read(sb, type, ddquot, info->dqi_entry_size,
@@ -679,7 +670,7 @@ EXPORT_SYMBOL(qtree_release_dquot);
static int find_next_id(struct qtree_mem_dqinfo *info, qid_t *id,
unsigned int blk, int depth)
{
- char *buf = getdqbuf(info->dqi_usable_bs);
+ char *buf = kmalloc(info->dqi_usable_bs, GFP_NOFS);
__le32 *ref = (__le32 *)buf;
ssize_t ret;
unsigned int epb = info->dqi_usable_bs >> 2;
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 780bb90c1804..f49b72ccac4c 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2584,9 +2584,7 @@ static int reiserfs_write_full_page(struct page *page,
clear_buffer_dirty(bh);
set_buffer_uptodate(bh);
} else if ((checked || buffer_dirty(bh)) &&
- (!buffer_mapped(bh) || (buffer_mapped(bh)
- && bh->b_blocknr ==
- 0))) {
+ (!buffer_mapped(bh) || bh->b_blocknr == 0)) {
/*
* not mapped yet, or it points to a direct item, search
* the btree for the mapping info, and log any direct
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 9edc8e2b154e..0834b101c316 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -2758,6 +2758,20 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
goto free_and_return;
}
+ /*
+ * Sanity check to see if journal first block is correct.
+ * If journal first block is invalid it can cause
+ * zeroing important superblock members.
+ */
+ if (!SB_ONDISK_JOURNAL_DEVICE(sb) &&
+ SB_ONDISK_JOURNAL_1st_BLOCK(sb) < SB_JOURNAL_1st_RESERVED_BLOCK(sb)) {
+ reiserfs_warning(sb, "journal-1393",
+ "journal 1st super block is invalid: 1st reserved block %d, but actual 1st block is %d",
+ SB_JOURNAL_1st_RESERVED_BLOCK(sb),
+ SB_ONDISK_JOURNAL_1st_BLOCK(sb));
+ goto free_and_return;
+ }
+
if (journal_init_dev(sb, journal, j_dev_name) != 0) {
reiserfs_warning(sb, "sh-462",
"unable to initialize journal device");
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 3ae9f1e91984..7c7c9bbbfa57 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -934,6 +934,10 @@ static int udf_symlink(struct user_namespace *mnt_userns, struct inode *dir,
iinfo->i_location.partitionReferenceNum,
0);
epos.bh = udf_tgetblk(sb, block);
+ if (unlikely(!epos.bh)) {
+ err = -ENOMEM;
+ goto out_no_entry;
+ }
lock_buffer(epos.bh);
memset(epos.bh->b_data, 0x00, bsize);
set_buffer_uptodate(epos.bh);