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 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.