Commit 0aba4860 authored by Jan Kara's avatar Jan Kara
Browse files

udf: Allocate name buffer in directory iterator on heap

Currently we allocate name buffer in directory iterators (struct
udf_fileident_iter) on stack. These structures are relatively large
(some 360 bytes on 64-bit architectures). For udf_rename() which needs
to keep three of these structures in parallel the stack usage becomes
rather heavy - 1536 bytes in total. Allocate the name buffer in the
iterator from heap to avoid excessive stack usage.

Link: https://lore.kernel.org/all/202212200558.lK9x1KW0-lkp@intel.com


Reported-by: default avatarkernel test robot <lkp@intel.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 19fd80de
Loading
Loading
Loading
Loading
+15 −8
Original line number Diff line number Diff line
@@ -248,9 +248,14 @@ int udf_fiiter_init(struct udf_fileident_iter *iter, struct inode *dir,
	iter->elen = 0;
	iter->epos.bh = NULL;
	iter->name = NULL;
	iter->namebuf = kmalloc(UDF_NAME_LEN_CS0, GFP_KERNEL);
	if (!iter->namebuf)
		return -ENOMEM;

	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
		return udf_copy_fi(iter);
	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
		err = udf_copy_fi(iter);
		goto out;
	}

	if (inode_bmap(dir, iter->pos >> dir->i_blkbits, &iter->epos,
		       &iter->eloc, &iter->elen, &iter->loffset) !=
@@ -260,18 +265,18 @@ int udf_fiiter_init(struct udf_fileident_iter *iter, struct inode *dir,
		udf_err(dir->i_sb,
			"position %llu not allocated in directory (ino %lu)\n",
			(unsigned long long)pos, dir->i_ino);
		return -EFSCORRUPTED;
		err = -EFSCORRUPTED;
		goto out;
	}
	err = udf_fiiter_load_bhs(iter);
	if (err < 0)
		return err;
		goto out;
	err = udf_copy_fi(iter);
	if (err < 0) {
out:
	if (err < 0)
		udf_fiiter_release(iter);
	return err;
}
	return 0;
}

int udf_fiiter_advance(struct udf_fileident_iter *iter)
{
@@ -307,6 +312,8 @@ void udf_fiiter_release(struct udf_fileident_iter *iter)
	brelse(iter->bh[0]);
	brelse(iter->bh[1]);
	iter->bh[0] = iter->bh[1] = NULL;
	kfree(iter->namebuf);
	iter->namebuf = NULL;
}

static void udf_copy_to_bufs(void *buf1, int len1, void *buf2, int len2,
+1 −1
Original line number Diff line number Diff line
@@ -99,7 +99,7 @@ struct udf_fileident_iter {
	struct extent_position epos;	/* Position after the above extent */
	struct fileIdentDesc fi;	/* Copied directory entry */
	uint8_t *name;			/* Pointer to entry name */
	uint8_t namebuf[UDF_NAME_LEN_CS0]; /* Storage for entry name in case
	uint8_t *namebuf;		/* Storage for entry name in case
					 * the name is split between two blocks
					 */
};