Commit 8faccfef authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'mm-hotfixes-stable-2024-07-03-22-23' of...

Merge tag 'mm-hotfixes-stable-2024-07-03-22-23' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm

Pull misc fixes from, Andrew Morton:
 "6 hotfies, all cc:stable. Some fixes for longstanding nilfs2 issues
  and three unrelated MM fixes"

* tag 'mm-hotfixes-stable-2024-07-03-22-23' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm:
  nilfs2: fix incorrect inode allocation from reserved inodes
  nilfs2: add missing check for inode numbers on directory entries
  nilfs2: fix inode number range checks
  mm: avoid overflows in dirty throttling logic
  Revert "mm/writeback: fix possible divide-by-zero in wb_dirty_limits(), again"
  mm: optimize the redundant loop of mm_update_owner_next()
parents 795c58e4 93aef9ed
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -377,11 +377,12 @@ void *nilfs_palloc_block_get_entry(const struct inode *inode, __u64 nr,
 * @target: offset number of an entry in the group (start point)
 * @bsize: size in bits
 * @lock: spin lock protecting @bitmap
 * @wrap: whether to wrap around
 */
static int nilfs_palloc_find_available_slot(unsigned char *bitmap,
					    unsigned long target,
					    unsigned int bsize,
					    spinlock_t *lock)
					    spinlock_t *lock, bool wrap)
{
	int pos, end = bsize;

@@ -397,6 +398,8 @@ static int nilfs_palloc_find_available_slot(unsigned char *bitmap,

		end = target;
	}
	if (!wrap)
		return -ENOSPC;

	/* wrap around */
	for (pos = 0; pos < end; pos++) {
@@ -495,9 +498,10 @@ int nilfs_palloc_count_max_entries(struct inode *inode, u64 nused, u64 *nmaxp)
 * nilfs_palloc_prepare_alloc_entry - prepare to allocate a persistent object
 * @inode: inode of metadata file using this allocator
 * @req: nilfs_palloc_req structure exchanged for the allocation
 * @wrap: whether to wrap around
 */
int nilfs_palloc_prepare_alloc_entry(struct inode *inode,
				     struct nilfs_palloc_req *req)
				     struct nilfs_palloc_req *req, bool wrap)
{
	struct buffer_head *desc_bh, *bitmap_bh;
	struct nilfs_palloc_group_desc *desc;
@@ -516,7 +520,7 @@ int nilfs_palloc_prepare_alloc_entry(struct inode *inode,
	entries_per_group = nilfs_palloc_entries_per_group(inode);

	for (i = 0; i < ngroups; i += n) {
		if (group >= ngroups) {
		if (group >= ngroups && wrap) {
			/* wrap around */
			group = 0;
			maxgroup = nilfs_palloc_group(inode, req->pr_entry_nr,
@@ -550,7 +554,14 @@ int nilfs_palloc_prepare_alloc_entry(struct inode *inode,
			bitmap_kaddr = kmap_local_page(bitmap_bh->b_page);
			bitmap = bitmap_kaddr + bh_offset(bitmap_bh);
			pos = nilfs_palloc_find_available_slot(
				bitmap, group_offset, entries_per_group, lock);
				bitmap, group_offset, entries_per_group, lock,
				wrap);
			/*
			 * Since the search for a free slot in the second and
			 * subsequent bitmap blocks always starts from the
			 * beginning, the wrap flag only has an effect on the
			 * first search.
			 */
			kunmap_local(bitmap_kaddr);
			if (pos >= 0)
				goto found;
+2 −2
Original line number Diff line number Diff line
@@ -50,8 +50,8 @@ struct nilfs_palloc_req {
	struct buffer_head *pr_entry_bh;
};

int nilfs_palloc_prepare_alloc_entry(struct inode *,
				     struct nilfs_palloc_req *);
int nilfs_palloc_prepare_alloc_entry(struct inode *inode,
				     struct nilfs_palloc_req *req, bool wrap);
void nilfs_palloc_commit_alloc_entry(struct inode *,
				     struct nilfs_palloc_req *);
void nilfs_palloc_abort_alloc_entry(struct inode *, struct nilfs_palloc_req *);
+1 −1
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ int nilfs_dat_prepare_alloc(struct inode *dat, struct nilfs_palloc_req *req)
{
	int ret;

	ret = nilfs_palloc_prepare_alloc_entry(dat, req);
	ret = nilfs_palloc_prepare_alloc_entry(dat, req, true);
	if (ret < 0)
		return ret;

+6 −0
Original line number Diff line number Diff line
@@ -135,6 +135,9 @@ static bool nilfs_check_folio(struct folio *folio, char *kaddr)
			goto Enamelen;
		if (((offs + rec_len - 1) ^ offs) & ~(chunk_size-1))
			goto Espan;
		if (unlikely(p->inode &&
			     NILFS_PRIVATE_INODE(le64_to_cpu(p->inode))))
			goto Einumber;
	}
	if (offs != limit)
		goto Eend;
@@ -160,6 +163,9 @@ static bool nilfs_check_folio(struct folio *folio, char *kaddr)
	goto bad_entry;
Espan:
	error = "directory entry across blocks";
	goto bad_entry;
Einumber:
	error = "disallowed inode number";
bad_entry:
	nilfs_error(sb,
		    "bad entry in directory #%lu: %s - offset=%lu, inode=%lu, rec_len=%zd, name_len=%d",
+2 −5
Original line number Diff line number Diff line
@@ -56,13 +56,10 @@ int nilfs_ifile_create_inode(struct inode *ifile, ino_t *out_ino,
	struct nilfs_palloc_req req;
	int ret;

	req.pr_entry_nr = 0;  /*
			       * 0 says find free inode from beginning
			       * of a group. dull code!!
			       */
	req.pr_entry_nr = NILFS_FIRST_INO(ifile->i_sb);
	req.pr_entry_bh = NULL;

	ret = nilfs_palloc_prepare_alloc_entry(ifile, &req);
	ret = nilfs_palloc_prepare_alloc_entry(ifile, &req, false);
	if (!ret) {
		ret = nilfs_palloc_get_entry_block(ifile, req.pr_entry_nr, 1,
						   &req.pr_entry_bh);
Loading