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
prev 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox