Commit 1b5dd29869b1 for kernel

commit 1b5dd29869b1e63f7e5c37d7552e2dcf22de3c26
Merge: ffbf700df204 0512bf9701f3
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date:   Mon Dec 1 17:32:07 2025 -0800

    Merge tag 'vfs-6.19-rc1.fd_prepare.fs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

    Pull fd prepare updates from Christian Brauner:
     "This adds the FD_ADD() and FD_PREPARE() primitive. They simplify the
      common pattern of get_unused_fd_flags() + create file + fd_install()
      that is used extensively throughout the kernel and currently requires
      cumbersome cleanup paths.

      FD_ADD() - For simple cases where a file is installed immediately:

          fd = FD_ADD(O_CLOEXEC, vfio_device_open_file(device));
          if (fd < 0)
              vfio_device_put_registration(device);
          return fd;

      FD_PREPARE() - For cases requiring access to the fd or file, or
      additional work before publishing:

          FD_PREPARE(fdf, O_CLOEXEC, sync_file->file);
          if (fdf.err) {
              fput(sync_file->file);
              return fdf.err;
          }

          data.fence = fd_prepare_fd(fdf);
          if (copy_to_user((void __user *)arg, &data, sizeof(data)))
              return -EFAULT;

          return fd_publish(fdf);

      The primitives are centered around struct fd_prepare. FD_PREPARE()
      encapsulates all allocation and cleanup logic and must be followed by
      a call to fd_publish() which associates the fd with the file and
      installs it into the caller's fdtable. If fd_publish() isn't called,
      both are deallocated automatically. FD_ADD() is a shorthand that does
      fd_publish() immediately and never exposes the struct to the caller.

      I've implemented this in a way that it's compatible with the cleanup
      infrastructure while also being usable separately. IOW, it's centered
      around struct fd_prepare which is aliased to class_fd_prepare_t and so
      we can make use of all the basica guard infrastructure"

    * tag 'vfs-6.19-rc1.fd_prepare.fs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (42 commits)
      io_uring: convert io_create_mock_file() to FD_PREPARE()
      file: convert replace_fd() to FD_PREPARE()
      vfio: convert vfio_group_ioctl_get_device_fd() to FD_ADD()
      tty: convert ptm_open_peer() to FD_ADD()
      ntsync: convert ntsync_obj_get_fd() to FD_PREPARE()
      media: convert media_request_alloc() to FD_PREPARE()
      hv: convert mshv_ioctl_create_partition() to FD_ADD()
      gpio: convert linehandle_create() to FD_PREPARE()
      pseries: port papr_rtas_setup_file_interface() to FD_ADD()
      pseries: convert papr_platform_dump_create_handle() to FD_ADD()
      spufs: convert spufs_gang_open() to FD_PREPARE()
      papr-hvpipe: convert papr_hvpipe_dev_create_handle() to FD_PREPARE()
      spufs: convert spufs_context_open() to FD_PREPARE()
      net/socket: convert __sys_accept4_file() to FD_ADD()
      net/socket: convert sock_map_fd() to FD_ADD()
      net/kcm: convert kcm_ioctl() to FD_PREPARE()
      net/handshake: convert handshake_nl_accept_doit() to FD_PREPARE()
      secretmem: convert memfd_secret() to FD_ADD()
      memfd: convert memfd_create() to FD_ADD()
      bpf: convert bpf_token_create() to FD_PREPARE()
      ...

diff --cc include/linux/cleanup.h
index 19c7e475d3a4,361104bcfe92..b8bd2f15f91f
--- a/include/linux/cleanup.h
+++ b/include/linux/cleanup.h
@@@ -290,16 -294,18 +294,19 @@@ static inline class_##_name##_t class_#
  	class_##_name##_t var __cleanup(class_##_name##_destructor) =	\
  		class_##_name##_constructor

+ #define CLASS_INIT(_name, _var, _init_expr)                             \
+         class_##_name##_t _var __cleanup(class_##_name##_destructor) = (_init_expr)
+
 -#define scoped_class(_name, var, args)                          \
 -	for (CLASS(_name, var)(args);                           \
 -	     __guard_ptr(_name)(&var) || !__is_cond_ptr(_name); \
 -	     ({ goto _label; }))                                \
 -		if (0) {                                        \
 -_label:                                                         \
 -			break;                                  \
 +#define __scoped_class(_name, var, _label, args...)        \
 +	for (CLASS(_name, var)(args); ; ({ goto _label; })) \
 +		if (0) {                                   \
 +_label:                                                    \
 +			break;                             \
  		} else

 +#define scoped_class(_name, var, args...) \
 +	__scoped_class(_name, var, __UNIQUE_ID(label), args)
 +
  /*
   * DEFINE_GUARD(name, type, lock, unlock):
   *	trivial wrapper around DEFINE_CLASS() above specifically
diff --cc ipc/mqueue.c
index 83d9466710d6,d3a588d0dcf6..56e811f9e5fa
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@@ -892,15 -892,36 +892,35 @@@ static int prepare_open(struct dentry *
  	return inode_permission(&nop_mnt_idmap, d_inode(dentry), acc);
  }

+ static struct file *mqueue_file_open(struct filename *name,
+ 				     struct vfsmount *mnt, int oflag, bool ro,
+ 				     umode_t mode, struct mq_attr *attr)
+ {
 -	struct path path __free(path_put) = {};
+ 	struct dentry *dentry;
++	struct file *file;
+ 	int ret;
+
 -	dentry = lookup_noperm(&QSTR(name->name), mnt->mnt_root);
++	dentry = start_creating_noperm(mnt->mnt_root, &QSTR(name->name));
+ 	if (IS_ERR(dentry))
+ 		return ERR_CAST(dentry);
+
 -	path.dentry = dentry;
 -	path.mnt = mntget(mnt);
 -
 -	ret = prepare_open(path.dentry, oflag, ro, mode, name, attr);
 -	if (ret)
 -		return ERR_PTR(ret);
++	ret = prepare_open(dentry, oflag, ro, mode, name, attr);
++	file = ERR_PTR(ret);
++	if (!ret) {
++		const struct path path = { .mnt = mnt, .dentry = dentry };
++		file = dentry_open(&path, oflag, current_cred());
++	}
+
 -	return dentry_open(&path, oflag, current_cred());
++	end_creating(dentry);
++	return file;
+ }
+
  static int do_mq_open(const char __user *u_name, int oflag, umode_t mode,
  		      struct mq_attr *attr)
  {
+ 	struct filename *name __free(putname) = NULL;;
  	struct vfsmount *mnt = current->nsproxy->ipc_ns->mq_mnt;
--	struct dentry *root = mnt->mnt_root;
- 	struct filename *name;
- 	struct path path;
- 	int fd, error;
 -	int fd;
--	int ro;
++	int fd, ro;

  	audit_mq_open(oflag, mode, attr);

@@@ -908,35 -929,12 +928,10 @@@
  	if (IS_ERR(name))
  		return PTR_ERR(name);

- 	fd = get_unused_fd_flags(O_CLOEXEC);
- 	if (fd < 0)
- 		goto out_putname;
-
  	ro = mnt_want_write(mnt);	/* we'll drop it in any case */
- 	path.dentry = start_creating_noperm(root, &QSTR(name->name));
- 	if (IS_ERR(path.dentry)) {
- 		error = PTR_ERR(path.dentry);
- 		goto out_putfd;
- 	}
- 	path.mnt = mnt;
- 	error = prepare_open(path.dentry, oflag, ro, mode, name, attr);
- 	if (!error) {
- 		struct file *file = dentry_open(&path, oflag, current_cred());
- 		if (!IS_ERR(file))
- 			fd_install(fd, file);
- 		else
- 			error = PTR_ERR(file);
- 	}
- out_putfd:
- 	if (error) {
- 		put_unused_fd(fd);
- 		fd = error;
- 	}
- 	end_creating(path.dentry);
 -	inode_lock(d_inode(root));
+ 	fd = FD_ADD(O_CLOEXEC, mqueue_file_open(name, mnt, oflag, ro, mode, attr));
 -	inode_unlock(d_inode(root));
  	if (!ro)
  		mnt_drop_write(mnt);
- out_putname:
- 	putname(name);
  	return fd;
  }