All of lore.kernel.org
 help / color / mirror / Atom feed
From: kernel test robot <lkp@intel.com>
To: Artem Blagodarenko <artem.blagodarenko@gmail.com>,
	linux-ext4@vger.kernel.org
Cc: oe-kbuild-all@lists.linux.dev, tytso@mit.edu, jack@suse.cz,
	adilger.kernel@dilger.ca, ablagodarenko@thelustrecollective.com,
	Artem Blagodarenko <artem.blagodarenko@gmail.com>,
	Andreas Dilger <adilger@dilger.ca>
Subject: Re: [PATCH v13 11/11] ext4: Add EXT4_IOC_SET_LUFID ioctl for setting LUFID on directory entries
Date: Fri, 30 Oct 2026 20:21:59 +0800	[thread overview]
Message-ID: <202610302057.dZ9WDGS4-lkp@intel.com> (raw)
In-Reply-To: <20261029122413.230409-12-ablagodarenko@thelustrecollective.com>

Hi Artem,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 8c4f6e3376348fc3162eed86a05b933921c8f9ed]

url:    https://github.com/intel-lab-lkp/linux/commits/Artem-Blagodarenko/ext4-validate-count-against-limit-in-ext4_dx_csum_verify-_set/20261029-122400
base:   8c4f6e3376348fc3162eed86a05b933921c8f9ed
patch link:    https://lore.kernel.org/r/20261029122413.230409-12-ablagodarenko%40thelustrecollective.com
patch subject: [PATCH v13 11/11] ext4: Add EXT4_IOC_SET_LUFID ioctl for setting LUFID on directory entries
config: arm-allyesconfig (https://download.01.org/0day-ci/archive/20261030/202610302057.dZ9WDGS4-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 16.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261030/202610302057.dZ9WDGS4-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202610302057.dZ9WDGS4-lkp@intel.com/

All warnings (new ones prefixed by >>):

   fs/ext4/namei.c: In function 'ext4_dirdata_set_lufid':
>> fs/ext4/namei.c:5097:1: warning: the frame size of 1344 bytes is larger than 1280 bytes [-Wframe-larger-than=]
    5097 | }
         | ^


vim +5097 fs/ext4/namei.c

  4838	
  4839	/*
  4840	 * ext4_dirdata_set_lufid() - Set LUFID data on an existing directory entry
  4841	 * @dir:        parent directory inode
  4842	 * @filename:   name of the file in the directory
  4843	 * @namelen:    length of filename
  4844	 * @edp:        pointer to initialized dentry param with LUFID data
  4845	 *
  4846	 * This function finds an existing directory entry, deletes it, and re-creates it
  4847	 * with LUFID data attached. Used by the EXT4_IOC_SET_LUFID ioctl.
  4848	 *
  4849	 * Returns 0 on success, negative error code on failure.
  4850	 */
  4851	int ext4_dirdata_set_lufid(struct mnt_idmap *idmap, struct inode *dir,
  4852				    const char *filename, int namelen,
  4853				    struct ext4_dentry_param *edp)
  4854	{
  4855		struct super_block *sb = dir->i_sb;
  4856		 /* zero-init: safe to free on any path */
  4857		struct ext4_filename fname = {};
  4858		struct ext4_dir_entry_2 *de = NULL;
  4859		struct buffer_head *bh = NULL;
  4860		struct inode *inode = NULL;
  4861		handle_t *handle = NULL;
  4862		struct ext4_lufid_snap old_snap = {};
  4863		struct qstr d_name;
  4864		/* on-disk name snapshot for non-encrypted casefolded directories: the
  4865		 * on-disk case may differ from what the caller supplied. */
  4866		char ondisk_name[EXT4_NAME_LEN];
  4867		struct qstr real_name = {};
  4868		/* name to pass to ext4_add_entry() for the re-add and rollback */
  4869		const struct qstr *add_name;
  4870		__u32 ino = 0;
  4871		bool child_locked = false;
  4872		int err = 0;
  4873	
  4874		if (!ext4_has_feature_dirdata(sb))
  4875			return -EOPNOTSUPP;
  4876	
  4877		if (namelen > EXT4_NAME_LEN)
  4878			return -ENAMETOOLONG;
  4879		if (namelen != strnlen(filename, namelen + 1))
  4880			return -EINVAL;
  4881	
  4882		d_name.name = filename;
  4883		d_name.len = namelen;
  4884	
  4885		err = ext4_fname_setup_filename(dir, &d_name, 0, &fname);
  4886		if (err)
  4887			goto out_free;
  4888	
  4889		/* Lock dir with the VFS parent-mutation subclass.  The lookup and any
  4890		 * mutation must be inside this lock to prevent TOCTOU races. */
  4891		inode_lock_nested(dir, I_MUTEX_PARENT);
  4892	
  4893		/* Phase 1: look up the entry without holding a journal handle to
  4894		 * obtain the child inode reference before taking the child lock.
  4895		 * VFS locking order requires all inode locks to be acquired before
  4896		 * starting a jbd2 transaction; starting the journal while already
  4897		 * holding the child lock would invert that order and risk deadlock
  4898		 * if jbd2 blocks waiting for a commit that the child lock holder
  4899		 * prevents from finishing. */
  4900		bh = ext4_find_entry(dir, &d_name, &de, NULL);
  4901		if (IS_ERR(bh)) {
  4902			err = PTR_ERR(bh);
  4903			bh = NULL;
  4904			goto out_unlock_dir;
  4905		}
  4906		if (!bh) {
  4907			err = -ENOENT;
  4908			goto out_unlock_dir;
  4909		}
  4910		ino = le32_to_cpu(de->inode);
  4911		brelse(bh);
  4912		bh = NULL;
  4913		de = NULL;
  4914	
  4915		inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
  4916		if (IS_ERR(inode)) {
  4917			err = PTR_ERR(inode);
  4918			inode = NULL;
  4919			goto out_unlock_dir;
  4920		}
  4921	
  4922		/* Enforce sticky-bit restriction: on a sticky directory only the
  4923		 * directory owner, the file owner, or a privileged process may
  4924		 * modify entries.  inode_permission(MAY_WRITE) alone does not cover
  4925		 * this, so check it explicitly here as may_delete() does. */
  4926		err = check_sticky(idmap, dir, inode);
  4927		if (err)
  4928			goto out_iput;
  4929	
  4930		/* The ioctl calls ext4_delete_entry() on the parent directory, which
  4931		 * bypasses the VFS may_delete() path.  inode_permission(MAY_WRITE)
  4932		 * above blocks IS_IMMUTABLE(dir) but does NOT block IS_APPEND(dir):
  4933		 * append-only directories allow new entries but forbid deletion, and
  4934		 * that restriction lives only in may_delete(), not in
  4935		 * inode_permission().  Enforce it explicitly here. */
  4936		if (IS_APPEND(dir)) {
  4937			err = -EPERM;
  4938			goto out_iput;
  4939		}
  4940	
  4941		/* The ioctl deletes and re-creates the directory entry, which
  4942		 * effectively modifies the target file's namespace presence.
  4943		 * Refuse if the target itself is immutable or append-only. */
  4944		if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
  4945			err = -EPERM;
  4946			goto out_iput;
  4947		}
  4948	
  4949		/* Lock the target inode BEFORE starting the journal (dir-then-child,
  4950		 * VFS-locks-before-journal ordering).  Use I_MUTEX_CHILD for directory
  4951		 * inodes (consistent with VFS rename/rmdir) and I_MUTEX_NONDIR2 for
  4952		 * all others; mixing subclasses on the same inode triggers lockdep
  4953		 * cycles with concurrent rename. */
  4954		if (inode != dir) {
  4955			if (S_ISDIR(inode->i_mode))
  4956				inode_lock_nested(inode, I_MUTEX_CHILD);
  4957			else
  4958				inode_lock_nested(inode, I_MUTEX_NONDIR2);
  4959			child_locked = true;
  4960		}
  4961	
  4962		handle = ext4_journal_start(dir, EXT4_HT_DIR,
  4963					    3 * EXT4_DATA_TRANS_BLOCKS(sb) +
  4964					    2 * EXT4_INDEX_EXTRA_TRANS_BLOCKS);
  4965		if (IS_ERR(handle)) {
  4966			err = PTR_ERR(handle);
  4967			handle = NULL;
  4968			goto out_unlock;
  4969		}
  4970	
  4971		/* Phase 2: re-look up the entry inside the journal to obtain a stable
  4972		 * de pointer.  Verify it still refers to the same inode (TOCTOU
  4973		 * guard: a concurrent unlink+create between phase 1 and here would
  4974		 * change the inode number). */
  4975		bh = ext4_find_entry(dir, &d_name, &de, NULL);
  4976		if (IS_ERR(bh)) {
  4977			err = PTR_ERR(bh);
  4978			bh = NULL;
  4979			goto out_journal;
  4980		}
  4981		if (!bh) {
  4982			err = -ENOENT;
  4983			goto out_journal;
  4984		}
  4985		if (le32_to_cpu(de->inode) != ino) {
  4986			err = -ENOENT;
  4987			goto out_brelse;
  4988		}
  4989	
  4990		/* Choose the name to use for re-adding the entry after deletion.
  4991		 *
  4992		 * For non-encrypted casefolded directories ext4_find_entry() matches
  4993		 * case-insensitively, so de->name may differ in case from the
  4994		 * caller-supplied filename.  Re-adding with the caller's case would
  4995		 * silently rename the entry, so preserve the on-disk bytes.
  4996		 *
  4997		 * For encrypted directories (with or without casefold) de->name holds
  4998		 * the raw ciphertext.  ext4_fname_setup_filename() deterministically
  4999		 * re-encrypts d_name (the plaintext) to the identical ciphertext, so
  5000		 * using d_name for the re-add is correct.  Passing the raw ciphertext
  5001		 * bytes would cause double-encryption and make the entry unreachable. */
  5002		if (IS_CASEFOLDED(dir) && !IS_ENCRYPTED(dir)) {
  5003			memcpy(ondisk_name, de->name, de->name_len);
  5004			real_name.name = ondisk_name;
  5005			real_name.len = de->name_len;
  5006			add_name = &real_name;
  5007		} else {
  5008			add_name = &d_name;
  5009		}
  5010	
  5011		/* Snapshot the old LUFID before deleting so we can restore it if the
  5012		 * re-add fails.  Without this the rollback path re-adds the entry
  5013		 * without any LUFID, silently orphaning the old FID-to-path mapping. */
  5014		err = ext4_lufid_snapshot(de, sb->s_blocksize, &old_snap);
  5015		if (err)
  5016			goto out_brelse;
  5017	
  5018		err = ext4_delete_entry(handle, dir, de, bh);
  5019		if (err)
  5020			goto out_brelse;
  5021	
  5022		brelse(bh);
  5023		bh = NULL;
  5024	
  5025		/* Re-add with LUFID via dentry->d_fsdata.  ext4_add_entry() resolves
  5026		 * dfid from d_fsdata into fname.dfid and passes it through to
  5027		 * add_dirent_to_buf() without touching the shared i_dirdata field,
  5028		 * eliminating the race with concurrent link() calls. */
  5029		{
  5030			struct dentry parent_dentry = { .d_inode = dir };
  5031			struct dentry new_dentry = {
  5032				.d_name = *add_name,
  5033				.d_parent = &parent_dentry,
  5034				.d_inode = inode,
  5035				.d_fsdata = edp,
  5036			};
  5037			err = ext4_add_entry(handle, &new_dentry, inode);
  5038		}
  5039	
  5040		if (err) {
  5041			/* Delete succeeded but re-add failed; try to restore so the
  5042			 * inode is not left without a directory entry.  Restore the
  5043			 * original LUFID too: without it the entry is re-added clean
  5044			 * and the old FID-to-path mapping is silently lost. */
  5045			struct dentry parent_dentry = { .d_inode = dir };
  5046			struct dentry orig_dentry = {
  5047				.d_name = *add_name,
  5048				.d_parent = &parent_dentry,
  5049				.d_inode = inode,
  5050			};
  5051			int rollback_err;
  5052	
  5053			if (old_snap.fid) {
  5054				unsigned int fid_size = old_snap.fid->df_header.ddh_length;
  5055				struct ext4_dentry_param *old_edp =
  5056					kmalloc(sizeof(*old_edp) + fid_size, GFP_NOFS);
  5057	
  5058				if (old_edp) {
  5059					old_edp->edp_magic = EXT4_LUFID_MAGIC;
  5060					memcpy(old_edp->edp_dfid, old_snap.fid, fid_size);
  5061					orig_dentry.d_fsdata = old_edp;
  5062				}
  5063			}
  5064	
  5065			rollback_err = ext4_add_entry(handle, &orig_dentry, inode);
  5066			kfree(orig_dentry.d_fsdata);
  5067	
  5068			if (rollback_err)
  5069				EXT4_ERROR_INODE(dir,
  5070					"Failed to set LUFID on '%.*s' (err=%d) and failed to restore the original directory entry (err=%d); inode %llu may be orphaned",
  5071					namelen, filename, err, rollback_err,
  5072					(unsigned long long)inode->i_ino);
  5073			goto out_journal;
  5074		}
  5075	
  5076		inode_set_ctime_current(dir);
  5077		inode_inc_iversion(dir);
  5078		ext4_mark_inode_dirty(handle, dir);
  5079	
  5080	out_brelse:
  5081		brelse(bh);
  5082	out_journal:
  5083		ext4_lufid_snap_release(&old_snap);
  5084		if (handle)
  5085			ext4_journal_stop(handle);
  5086	out_unlock:
  5087		if (child_locked)
  5088			inode_unlock(inode);
  5089	out_iput:
  5090		iput(inode);
  5091	out_unlock_dir:
  5092		inode_unlock(dir);
  5093	out_free:
  5094		ext4_fname_free_filename(&fname);
  5095	
  5096		return err;
> 5097	}
  5098	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

      parent reply	other threads:[~2026-10-30 12:22 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-29 12:23 [PATCH v13 00/11] Data in direntry (dirdata) feature Artem Blagodarenko
2026-10-29 12:24 ` [PATCH v13 01/11] ext4: validate count against limit in ext4_dx_csum_verify/_set Artem Blagodarenko
2026-10-29 12:37   ` sashiko-bot
2026-10-29 12:24 ` [PATCH v13 02/11] ext4: replace ext4_dir_entry with ext4_dir_entry_2 Artem Blagodarenko
2026-10-29 12:34   ` sashiko-bot
2026-10-29 12:24 ` [PATCH v13 03/11] ext4: add ext4_dir_entry_is_tail() Artem Blagodarenko
2026-10-29 12:31   ` sashiko-bot
2026-10-29 12:24 ` [PATCH v13 04/11] ext4: add dirdata format definitions and access helpers Artem Blagodarenko
2026-10-29 12:31   ` sashiko-bot
2026-10-29 12:24 ` [PATCH v13 05/11] ext4: refactor dx_root to support variable dirent sizes Artem Blagodarenko
2026-10-29 12:49   ` sashiko-bot
2026-10-29 12:24 ` [PATCH v13 06/11] ext4: add ext4_dir_entry_len() Artem Blagodarenko
2026-10-29 12:50   ` sashiko-bot
2026-10-29 12:24 ` [PATCH v13 07/11] ext4: rename ext4_dir_rec_len() and clarify dirdata usage Artem Blagodarenko
2026-10-29 12:50   ` sashiko-bot
2026-10-29 12:24 ` [PATCH v13 08/11] ext4: dirdata feature Artem Blagodarenko
2026-10-29 12:51   ` sashiko-bot
2026-10-30  9:29   ` kernel test robot
2026-10-29 12:24 ` [PATCH v13 09/11] ext4: add dirdata LUFID support for directory entry rename Artem Blagodarenko
2026-10-29 12:47   ` sashiko-bot
2026-10-29 12:24 ` [PATCH v13 10/11] ext4: add dirdata set/get helpers Artem Blagodarenko
2026-10-29 12:44   ` sashiko-bot
2026-10-29 12:24 ` [PATCH v13 11/11] ext4: Add EXT4_IOC_SET_LUFID ioctl for setting LUFID on directory entries Artem Blagodarenko
2026-10-29 12:58   ` sashiko-bot
2026-10-30 12:21   ` kernel test robot [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=202610302057.dZ9WDGS4-lkp@intel.com \
    --to=lkp@intel.com \
    --cc=ablagodarenko@thelustrecollective.com \
    --cc=adilger.kernel@dilger.ca \
    --cc=adilger@dilger.ca \
    --cc=artem.blagodarenko@gmail.com \
    --cc=jack@suse.cz \
    --cc=linux-ext4@vger.kernel.org \
    --cc=oe-kbuild-all@lists.linux.dev \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.