From: "Darrick J. Wong" <djwong@kernel.org>
To: djwong@kernel.org
Cc: catherine.hoang@oracle.com, hch@lst.de,
allison.henderson@oracle.com, linux-xfs@vger.kernel.org
Subject: [PATCH 25/32] xfs: move handle ioctl code to xfs_handle.c
Date: Tue, 09 Apr 2024 18:00:01 -0700 [thread overview]
Message-ID: <171270969974.3631889.581031520799249475.stgit@frogsfrogsfrogs> (raw)
In-Reply-To: <171270969477.3631889.12488500941186994317.stgit@frogsfrogsfrogs>
From: Darrick J. Wong <djwong@kernel.org>
Move the handle managemnet code (and the attrmulti code that uses it) to
xfs_handle.c.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
fs/xfs/Makefile | 1
fs/xfs/xfs_handle.c | 617 ++++++++++++++++++++++++++++++++++++++++++++++++++
fs/xfs/xfs_handle.h | 28 ++
fs/xfs/xfs_ioctl.c | 591 ------------------------------------------------
fs/xfs/xfs_ioctl.h | 28 --
fs/xfs/xfs_ioctl32.c | 1
6 files changed, 648 insertions(+), 618 deletions(-)
create mode 100644 fs/xfs/xfs_handle.c
create mode 100644 fs/xfs/xfs_handle.h
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 0c1a0b67af93c..c969b11ce0f47 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -78,6 +78,7 @@ xfs-y += xfs_aops.o \
xfs_fsmap.o \
xfs_fsops.o \
xfs_globals.o \
+ xfs_handle.o \
xfs_health.o \
xfs_icache.o \
xfs_ioctl.o \
diff --git a/fs/xfs/xfs_handle.c b/fs/xfs/xfs_handle.c
new file mode 100644
index 0000000000000..a0015dc8cff1a
--- /dev/null
+++ b/fs/xfs/xfs_handle.c
@@ -0,0 +1,617 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * All rights reserved.
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_format.h"
+#include "xfs_log_format.h"
+#include "xfs_shared.h"
+#include "xfs_trans_resv.h"
+#include "xfs_mount.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_inode.h"
+#include "xfs_error.h"
+#include "xfs_trace.h"
+#include "xfs_trans.h"
+#include "xfs_da_format.h"
+#include "xfs_da_btree.h"
+#include "xfs_attr.h"
+#include "xfs_ioctl.h"
+#include "xfs_parent.h"
+#include "xfs_da_btree.h"
+#include "xfs_handle.h"
+#include "xfs_health.h"
+#include "xfs_icache.h"
+#include "xfs_export.h"
+#include "xfs_xattr.h"
+#include "xfs_acl.h"
+
+#include <linux/namei.h>
+
+/*
+ * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
+ * a file or fs handle.
+ *
+ * XFS_IOC_PATH_TO_FSHANDLE
+ * returns fs handle for a mount point or path within that mount point
+ * XFS_IOC_FD_TO_HANDLE
+ * returns full handle for a FD opened in user space
+ * XFS_IOC_PATH_TO_HANDLE
+ * returns full handle for a path
+ */
+int
+xfs_find_handle(
+ unsigned int cmd,
+ xfs_fsop_handlereq_t *hreq)
+{
+ int hsize;
+ xfs_handle_t handle;
+ struct inode *inode;
+ struct fd f = {NULL};
+ struct path path;
+ int error;
+ struct xfs_inode *ip;
+
+ if (cmd == XFS_IOC_FD_TO_HANDLE) {
+ f = fdget(hreq->fd);
+ if (!f.file)
+ return -EBADF;
+ inode = file_inode(f.file);
+ } else {
+ error = user_path_at(AT_FDCWD, hreq->path, 0, &path);
+ if (error)
+ return error;
+ inode = d_inode(path.dentry);
+ }
+ ip = XFS_I(inode);
+
+ /*
+ * We can only generate handles for inodes residing on a XFS filesystem,
+ * and only for regular files, directories or symbolic links.
+ */
+ error = -EINVAL;
+ if (inode->i_sb->s_magic != XFS_SB_MAGIC)
+ goto out_put;
+
+ error = -EBADF;
+ if (!S_ISREG(inode->i_mode) &&
+ !S_ISDIR(inode->i_mode) &&
+ !S_ISLNK(inode->i_mode))
+ goto out_put;
+
+
+ memcpy(&handle.ha_fsid, ip->i_mount->m_fixedfsid, sizeof(xfs_fsid_t));
+
+ if (cmd == XFS_IOC_PATH_TO_FSHANDLE) {
+ /*
+ * This handle only contains an fsid, zero the rest.
+ */
+ memset(&handle.ha_fid, 0, sizeof(handle.ha_fid));
+ hsize = sizeof(xfs_fsid_t);
+ } else {
+ handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
+ sizeof(handle.ha_fid.fid_len);
+ handle.ha_fid.fid_pad = 0;
+ handle.ha_fid.fid_gen = inode->i_generation;
+ handle.ha_fid.fid_ino = ip->i_ino;
+ hsize = sizeof(xfs_handle_t);
+ }
+
+ error = -EFAULT;
+ if (copy_to_user(hreq->ohandle, &handle, hsize) ||
+ copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32)))
+ goto out_put;
+
+ error = 0;
+
+ out_put:
+ if (cmd == XFS_IOC_FD_TO_HANDLE)
+ fdput(f);
+ else
+ path_put(&path);
+ return error;
+}
+
+/*
+ * No need to do permission checks on the various pathname components
+ * as the handle operations are privileged.
+ */
+STATIC int
+xfs_handle_acceptable(
+ void *context,
+ struct dentry *dentry)
+{
+ return 1;
+}
+
+/*
+ * Convert userspace handle data into a dentry.
+ */
+struct dentry *
+xfs_handle_to_dentry(
+ struct file *parfilp,
+ void __user *uhandle,
+ u32 hlen)
+{
+ xfs_handle_t handle;
+ struct xfs_fid64 fid;
+
+ /*
+ * Only allow handle opens under a directory.
+ */
+ if (!S_ISDIR(file_inode(parfilp)->i_mode))
+ return ERR_PTR(-ENOTDIR);
+
+ if (hlen != sizeof(xfs_handle_t))
+ return ERR_PTR(-EINVAL);
+ if (copy_from_user(&handle, uhandle, hlen))
+ return ERR_PTR(-EFAULT);
+ if (handle.ha_fid.fid_len !=
+ sizeof(handle.ha_fid) - sizeof(handle.ha_fid.fid_len))
+ return ERR_PTR(-EINVAL);
+
+ memset(&fid, 0, sizeof(struct fid));
+ fid.ino = handle.ha_fid.fid_ino;
+ fid.gen = handle.ha_fid.fid_gen;
+
+ return exportfs_decode_fh(parfilp->f_path.mnt, (struct fid *)&fid, 3,
+ FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG,
+ xfs_handle_acceptable, NULL);
+}
+
+STATIC struct dentry *
+xfs_handlereq_to_dentry(
+ struct file *parfilp,
+ xfs_fsop_handlereq_t *hreq)
+{
+ return xfs_handle_to_dentry(parfilp, hreq->ihandle, hreq->ihandlen);
+}
+
+int
+xfs_open_by_handle(
+ struct file *parfilp,
+ xfs_fsop_handlereq_t *hreq)
+{
+ const struct cred *cred = current_cred();
+ int error;
+ int fd;
+ int permflag;
+ struct file *filp;
+ struct inode *inode;
+ struct dentry *dentry;
+ fmode_t fmode;
+ struct path path;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ dentry = xfs_handlereq_to_dentry(parfilp, hreq);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+ inode = d_inode(dentry);
+
+ /* Restrict xfs_open_by_handle to directories & regular files. */
+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
+ error = -EPERM;
+ goto out_dput;
+ }
+
+#if BITS_PER_LONG != 32
+ hreq->oflags |= O_LARGEFILE;
+#endif
+
+ permflag = hreq->oflags;
+ fmode = OPEN_FMODE(permflag);
+ if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
+ (fmode & FMODE_WRITE) && IS_APPEND(inode)) {
+ error = -EPERM;
+ goto out_dput;
+ }
+
+ if ((fmode & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
+ error = -EPERM;
+ goto out_dput;
+ }
+
+ /* Can't write directories. */
+ if (S_ISDIR(inode->i_mode) && (fmode & FMODE_WRITE)) {
+ error = -EISDIR;
+ goto out_dput;
+ }
+
+ fd = get_unused_fd_flags(0);
+ if (fd < 0) {
+ error = fd;
+ goto out_dput;
+ }
+
+ path.mnt = parfilp->f_path.mnt;
+ path.dentry = dentry;
+ filp = dentry_open(&path, hreq->oflags, cred);
+ dput(dentry);
+ if (IS_ERR(filp)) {
+ put_unused_fd(fd);
+ return PTR_ERR(filp);
+ }
+
+ if (S_ISREG(inode->i_mode)) {
+ filp->f_flags |= O_NOATIME;
+ filp->f_mode |= FMODE_NOCMTIME;
+ }
+
+ fd_install(fd, filp);
+ return fd;
+
+ out_dput:
+ dput(dentry);
+ return error;
+}
+
+int
+xfs_readlink_by_handle(
+ struct file *parfilp,
+ xfs_fsop_handlereq_t *hreq)
+{
+ struct dentry *dentry;
+ __u32 olen;
+ int error;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ dentry = xfs_handlereq_to_dentry(parfilp, hreq);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+ /* Restrict this handle operation to symlinks only. */
+ if (!d_is_symlink(dentry)) {
+ error = -EINVAL;
+ goto out_dput;
+ }
+
+ if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) {
+ error = -EFAULT;
+ goto out_dput;
+ }
+
+ error = vfs_readlink(dentry, hreq->ohandle, olen);
+
+ out_dput:
+ dput(dentry);
+ return error;
+}
+
+/*
+ * Format an attribute and copy it out to the user's buffer.
+ * Take care to check values and protect against them changing later,
+ * we may be reading them directly out of a user buffer.
+ */
+static void
+xfs_ioc_attr_put_listent(
+ struct xfs_attr_list_context *context,
+ int flags,
+ unsigned char *name,
+ int namelen,
+ void *value,
+ int valuelen)
+{
+ struct xfs_attrlist *alist = context->buffer;
+ struct xfs_attrlist_ent *aep;
+ int arraytop;
+
+ ASSERT(!context->seen_enough);
+ ASSERT(context->count >= 0);
+ ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
+ ASSERT(context->firstu >= sizeof(*alist));
+ ASSERT(context->firstu <= context->bufsize);
+
+ /*
+ * Only list entries in the right namespace.
+ */
+ if (context->attr_filter != (flags & XFS_ATTR_NSP_ONDISK_MASK))
+ return;
+
+ arraytop = sizeof(*alist) +
+ context->count * sizeof(alist->al_offset[0]);
+
+ /* decrement by the actual bytes used by the attr */
+ context->firstu -= round_up(offsetof(struct xfs_attrlist_ent, a_name) +
+ namelen + 1, sizeof(uint32_t));
+ if (context->firstu < arraytop) {
+ trace_xfs_attr_list_full(context);
+ alist->al_more = 1;
+ context->seen_enough = 1;
+ return;
+ }
+
+ aep = context->buffer + context->firstu;
+ aep->a_valuelen = valuelen;
+ memcpy(aep->a_name, name, namelen);
+ aep->a_name[namelen] = 0;
+ alist->al_offset[context->count++] = context->firstu;
+ alist->al_count = context->count;
+ trace_xfs_attr_list_add(context);
+}
+
+static unsigned int
+xfs_attr_filter(
+ u32 ioc_flags)
+{
+ if (ioc_flags & XFS_IOC_ATTR_ROOT)
+ return XFS_ATTR_ROOT;
+ if (ioc_flags & XFS_IOC_ATTR_SECURE)
+ return XFS_ATTR_SECURE;
+ return 0;
+}
+
+static unsigned int
+xfs_xattr_flags(
+ u32 ioc_flags)
+{
+ if (ioc_flags & XFS_IOC_ATTR_CREATE)
+ return XATTR_CREATE;
+ if (ioc_flags & XFS_IOC_ATTR_REPLACE)
+ return XATTR_REPLACE;
+ return 0;
+}
+
+int
+xfs_ioc_attr_list(
+ struct xfs_inode *dp,
+ void __user *ubuf,
+ size_t bufsize,
+ int flags,
+ struct xfs_attrlist_cursor __user *ucursor)
+{
+ struct xfs_attr_list_context context = { };
+ struct xfs_attrlist *alist;
+ void *buffer;
+ int error;
+
+ if (bufsize < sizeof(struct xfs_attrlist) ||
+ bufsize > XFS_XATTR_LIST_MAX)
+ return -EINVAL;
+
+ /*
+ * Reject flags, only allow namespaces.
+ */
+ if (flags & ~(XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
+ return -EINVAL;
+ if (flags == (XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
+ return -EINVAL;
+
+ /*
+ * Validate the cursor.
+ */
+ if (copy_from_user(&context.cursor, ucursor, sizeof(context.cursor)))
+ return -EFAULT;
+ if (context.cursor.pad1 || context.cursor.pad2)
+ return -EINVAL;
+ if (!context.cursor.initted &&
+ (context.cursor.hashval || context.cursor.blkno ||
+ context.cursor.offset))
+ return -EINVAL;
+
+ buffer = kvzalloc(bufsize, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ /*
+ * Initialize the output buffer.
+ */
+ context.dp = dp;
+ context.resynch = 1;
+ context.attr_filter = xfs_attr_filter(flags);
+ context.buffer = buffer;
+ context.bufsize = round_down(bufsize, sizeof(uint32_t));
+ context.firstu = context.bufsize;
+ context.put_listent = xfs_ioc_attr_put_listent;
+
+ alist = context.buffer;
+ alist->al_count = 0;
+ alist->al_more = 0;
+ alist->al_offset[0] = context.bufsize;
+
+ error = xfs_attr_list(&context);
+ if (error)
+ goto out_free;
+
+ if (copy_to_user(ubuf, buffer, bufsize) ||
+ copy_to_user(ucursor, &context.cursor, sizeof(context.cursor)))
+ error = -EFAULT;
+out_free:
+ kvfree(buffer);
+ return error;
+}
+
+int
+xfs_attrlist_by_handle(
+ struct file *parfilp,
+ struct xfs_fsop_attrlist_handlereq __user *p)
+{
+ struct xfs_fsop_attrlist_handlereq al_hreq;
+ struct dentry *dentry;
+ int error = -ENOMEM;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (copy_from_user(&al_hreq, p, sizeof(al_hreq)))
+ return -EFAULT;
+
+ dentry = xfs_handlereq_to_dentry(parfilp, &al_hreq.hreq);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+ error = xfs_ioc_attr_list(XFS_I(d_inode(dentry)), al_hreq.buffer,
+ al_hreq.buflen, al_hreq.flags, &p->pos);
+ dput(dentry);
+ return error;
+}
+
+static int
+xfs_attrmulti_attr_get(
+ struct inode *inode,
+ unsigned char *name,
+ unsigned char __user *ubuf,
+ uint32_t *len,
+ uint32_t flags)
+{
+ struct xfs_da_args args = {
+ .dp = XFS_I(inode),
+ .attr_filter = xfs_attr_filter(flags),
+ .xattr_flags = xfs_xattr_flags(flags),
+ .name = name,
+ .namelen = strlen(name),
+ .valuelen = *len,
+ };
+ int error;
+
+ if (*len > XFS_XATTR_SIZE_MAX)
+ return -EINVAL;
+
+ error = xfs_attr_get(&args);
+ if (error)
+ goto out_kfree;
+
+ *len = args.valuelen;
+ if (copy_to_user(ubuf, args.value, args.valuelen))
+ error = -EFAULT;
+
+out_kfree:
+ kvfree(args.value);
+ return error;
+}
+
+static int
+xfs_attrmulti_attr_set(
+ struct inode *inode,
+ unsigned char *name,
+ const unsigned char __user *ubuf,
+ uint32_t len,
+ uint32_t flags)
+{
+ struct xfs_da_args args = {
+ .dp = XFS_I(inode),
+ .attr_filter = xfs_attr_filter(flags),
+ .xattr_flags = xfs_xattr_flags(flags),
+ .name = name,
+ .namelen = strlen(name),
+ };
+ int error;
+
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ return -EPERM;
+
+ if (ubuf) {
+ if (len > XFS_XATTR_SIZE_MAX)
+ return -EINVAL;
+ args.value = memdup_user(ubuf, len);
+ if (IS_ERR(args.value))
+ return PTR_ERR(args.value);
+ args.valuelen = len;
+ }
+
+ error = xfs_attr_change(&args);
+ if (!error && (flags & XFS_IOC_ATTR_ROOT))
+ xfs_forget_acl(inode, name);
+ kfree(args.value);
+ return error;
+}
+
+int
+xfs_ioc_attrmulti_one(
+ struct file *parfilp,
+ struct inode *inode,
+ uint32_t opcode,
+ void __user *uname,
+ void __user *value,
+ uint32_t *len,
+ uint32_t flags)
+{
+ unsigned char *name;
+ int error;
+
+ if ((flags & XFS_IOC_ATTR_ROOT) && (flags & XFS_IOC_ATTR_SECURE))
+ return -EINVAL;
+
+ name = strndup_user(uname, MAXNAMELEN);
+ if (IS_ERR(name))
+ return PTR_ERR(name);
+
+ switch (opcode) {
+ case ATTR_OP_GET:
+ error = xfs_attrmulti_attr_get(inode, name, value, len, flags);
+ break;
+ case ATTR_OP_REMOVE:
+ value = NULL;
+ *len = 0;
+ fallthrough;
+ case ATTR_OP_SET:
+ error = mnt_want_write_file(parfilp);
+ if (error)
+ break;
+ error = xfs_attrmulti_attr_set(inode, name, value, *len, flags);
+ mnt_drop_write_file(parfilp);
+ break;
+ default:
+ error = -EINVAL;
+ break;
+ }
+
+ kfree(name);
+ return error;
+}
+
+int
+xfs_attrmulti_by_handle(
+ struct file *parfilp,
+ void __user *arg)
+{
+ int error;
+ xfs_attr_multiop_t *ops;
+ xfs_fsop_attrmulti_handlereq_t am_hreq;
+ struct dentry *dentry;
+ unsigned int i, size;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t)))
+ return -EFAULT;
+
+ /* overflow check */
+ if (am_hreq.opcount >= INT_MAX / sizeof(xfs_attr_multiop_t))
+ return -E2BIG;
+
+ dentry = xfs_handlereq_to_dentry(parfilp, &am_hreq.hreq);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+ error = -E2BIG;
+ size = am_hreq.opcount * sizeof(xfs_attr_multiop_t);
+ if (!size || size > 16 * PAGE_SIZE)
+ goto out_dput;
+
+ ops = memdup_user(am_hreq.ops, size);
+ if (IS_ERR(ops)) {
+ error = PTR_ERR(ops);
+ goto out_dput;
+ }
+
+ error = 0;
+ for (i = 0; i < am_hreq.opcount; i++) {
+ ops[i].am_error = xfs_ioc_attrmulti_one(parfilp,
+ d_inode(dentry), ops[i].am_opcode,
+ ops[i].am_attrname, ops[i].am_attrvalue,
+ &ops[i].am_length, ops[i].am_flags);
+ }
+
+ if (copy_to_user(am_hreq.ops, ops, size))
+ error = -EFAULT;
+
+ kfree(ops);
+ out_dput:
+ dput(dentry);
+ return error;
+}
diff --git a/fs/xfs/xfs_handle.h b/fs/xfs/xfs_handle.h
new file mode 100644
index 0000000000000..e39eaf4689da9
--- /dev/null
+++ b/fs/xfs/xfs_handle.h
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * All rights reserved.
+ */
+#ifndef __XFS_HANDLE_H__
+#define __XFS_HANDLE_H__
+
+int xfs_attrlist_by_handle(struct file *parfilp,
+ struct xfs_fsop_attrlist_handlereq __user *p);
+int xfs_attrmulti_by_handle(struct file *parfilp, void __user *arg);
+
+int xfs_find_handle(unsigned int cmd, struct xfs_fsop_handlereq *hreq);
+int xfs_open_by_handle(struct file *parfilp, struct xfs_fsop_handlereq *hreq);
+int xfs_readlink_by_handle(struct file *parfilp,
+ struct xfs_fsop_handlereq *hreq);
+
+int xfs_ioc_attrmulti_one(struct file *parfilp, struct inode *inode,
+ uint32_t opcode, void __user *uname, void __user *value,
+ uint32_t *len, uint32_t flags);
+int xfs_ioc_attr_list(struct xfs_inode *dp, void __user *ubuf,
+ size_t bufsize, int flags,
+ struct xfs_attrlist_cursor __user *ucursor);
+
+struct dentry *xfs_handle_to_dentry(struct file *parfilp, void __user *uhandle,
+ u32 hlen);
+
+#endif /* __XFS_HANDLE_H__ */
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index d56e5c6876eee..7b347cdd28785 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -23,11 +23,9 @@
#include "xfs_fsops.h"
#include "xfs_discard.h"
#include "xfs_quota.h"
-#include "xfs_export.h"
#include "xfs_trace.h"
#include "xfs_icache.h"
#include "xfs_trans.h"
-#include "xfs_acl.h"
#include "xfs_btree.h"
#include <linux/fsmap.h>
#include "xfs_fsmap.h"
@@ -37,601 +35,14 @@
#include "xfs_health.h"
#include "xfs_reflink.h"
#include "xfs_ioctl.h"
-#include "xfs_xattr.h"
#include "xfs_rtbitmap.h"
#include "xfs_file.h"
#include "xfs_exchrange.h"
+#include "xfs_handle.h"
#include <linux/mount.h>
-#include <linux/namei.h>
#include <linux/fileattr.h>
-/*
- * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
- * a file or fs handle.
- *
- * XFS_IOC_PATH_TO_FSHANDLE
- * returns fs handle for a mount point or path within that mount point
- * XFS_IOC_FD_TO_HANDLE
- * returns full handle for a FD opened in user space
- * XFS_IOC_PATH_TO_HANDLE
- * returns full handle for a path
- */
-int
-xfs_find_handle(
- unsigned int cmd,
- xfs_fsop_handlereq_t *hreq)
-{
- int hsize;
- xfs_handle_t handle;
- struct inode *inode;
- struct fd f = {NULL};
- struct path path;
- int error;
- struct xfs_inode *ip;
-
- if (cmd == XFS_IOC_FD_TO_HANDLE) {
- f = fdget(hreq->fd);
- if (!f.file)
- return -EBADF;
- inode = file_inode(f.file);
- } else {
- error = user_path_at(AT_FDCWD, hreq->path, 0, &path);
- if (error)
- return error;
- inode = d_inode(path.dentry);
- }
- ip = XFS_I(inode);
-
- /*
- * We can only generate handles for inodes residing on a XFS filesystem,
- * and only for regular files, directories or symbolic links.
- */
- error = -EINVAL;
- if (inode->i_sb->s_magic != XFS_SB_MAGIC)
- goto out_put;
-
- error = -EBADF;
- if (!S_ISREG(inode->i_mode) &&
- !S_ISDIR(inode->i_mode) &&
- !S_ISLNK(inode->i_mode))
- goto out_put;
-
-
- memcpy(&handle.ha_fsid, ip->i_mount->m_fixedfsid, sizeof(xfs_fsid_t));
-
- if (cmd == XFS_IOC_PATH_TO_FSHANDLE) {
- /*
- * This handle only contains an fsid, zero the rest.
- */
- memset(&handle.ha_fid, 0, sizeof(handle.ha_fid));
- hsize = sizeof(xfs_fsid_t);
- } else {
- handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
- sizeof(handle.ha_fid.fid_len);
- handle.ha_fid.fid_pad = 0;
- handle.ha_fid.fid_gen = inode->i_generation;
- handle.ha_fid.fid_ino = ip->i_ino;
- hsize = sizeof(xfs_handle_t);
- }
-
- error = -EFAULT;
- if (copy_to_user(hreq->ohandle, &handle, hsize) ||
- copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32)))
- goto out_put;
-
- error = 0;
-
- out_put:
- if (cmd == XFS_IOC_FD_TO_HANDLE)
- fdput(f);
- else
- path_put(&path);
- return error;
-}
-
-/*
- * No need to do permission checks on the various pathname components
- * as the handle operations are privileged.
- */
-STATIC int
-xfs_handle_acceptable(
- void *context,
- struct dentry *dentry)
-{
- return 1;
-}
-
-/*
- * Convert userspace handle data into a dentry.
- */
-struct dentry *
-xfs_handle_to_dentry(
- struct file *parfilp,
- void __user *uhandle,
- u32 hlen)
-{
- xfs_handle_t handle;
- struct xfs_fid64 fid;
-
- /*
- * Only allow handle opens under a directory.
- */
- if (!S_ISDIR(file_inode(parfilp)->i_mode))
- return ERR_PTR(-ENOTDIR);
-
- if (hlen != sizeof(xfs_handle_t))
- return ERR_PTR(-EINVAL);
- if (copy_from_user(&handle, uhandle, hlen))
- return ERR_PTR(-EFAULT);
- if (handle.ha_fid.fid_len !=
- sizeof(handle.ha_fid) - sizeof(handle.ha_fid.fid_len))
- return ERR_PTR(-EINVAL);
-
- memset(&fid, 0, sizeof(struct fid));
- fid.ino = handle.ha_fid.fid_ino;
- fid.gen = handle.ha_fid.fid_gen;
-
- return exportfs_decode_fh(parfilp->f_path.mnt, (struct fid *)&fid, 3,
- FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG,
- xfs_handle_acceptable, NULL);
-}
-
-STATIC struct dentry *
-xfs_handlereq_to_dentry(
- struct file *parfilp,
- xfs_fsop_handlereq_t *hreq)
-{
- return xfs_handle_to_dentry(parfilp, hreq->ihandle, hreq->ihandlen);
-}
-
-int
-xfs_open_by_handle(
- struct file *parfilp,
- xfs_fsop_handlereq_t *hreq)
-{
- const struct cred *cred = current_cred();
- int error;
- int fd;
- int permflag;
- struct file *filp;
- struct inode *inode;
- struct dentry *dentry;
- fmode_t fmode;
- struct path path;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- dentry = xfs_handlereq_to_dentry(parfilp, hreq);
- if (IS_ERR(dentry))
- return PTR_ERR(dentry);
- inode = d_inode(dentry);
-
- /* Restrict xfs_open_by_handle to directories & regular files. */
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
- error = -EPERM;
- goto out_dput;
- }
-
-#if BITS_PER_LONG != 32
- hreq->oflags |= O_LARGEFILE;
-#endif
-
- permflag = hreq->oflags;
- fmode = OPEN_FMODE(permflag);
- if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
- (fmode & FMODE_WRITE) && IS_APPEND(inode)) {
- error = -EPERM;
- goto out_dput;
- }
-
- if ((fmode & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
- error = -EPERM;
- goto out_dput;
- }
-
- /* Can't write directories. */
- if (S_ISDIR(inode->i_mode) && (fmode & FMODE_WRITE)) {
- error = -EISDIR;
- goto out_dput;
- }
-
- fd = get_unused_fd_flags(0);
- if (fd < 0) {
- error = fd;
- goto out_dput;
- }
-
- path.mnt = parfilp->f_path.mnt;
- path.dentry = dentry;
- filp = dentry_open(&path, hreq->oflags, cred);
- dput(dentry);
- if (IS_ERR(filp)) {
- put_unused_fd(fd);
- return PTR_ERR(filp);
- }
-
- if (S_ISREG(inode->i_mode)) {
- filp->f_flags |= O_NOATIME;
- filp->f_mode |= FMODE_NOCMTIME;
- }
-
- fd_install(fd, filp);
- return fd;
-
- out_dput:
- dput(dentry);
- return error;
-}
-
-int
-xfs_readlink_by_handle(
- struct file *parfilp,
- xfs_fsop_handlereq_t *hreq)
-{
- struct dentry *dentry;
- __u32 olen;
- int error;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- dentry = xfs_handlereq_to_dentry(parfilp, hreq);
- if (IS_ERR(dentry))
- return PTR_ERR(dentry);
-
- /* Restrict this handle operation to symlinks only. */
- if (!d_is_symlink(dentry)) {
- error = -EINVAL;
- goto out_dput;
- }
-
- if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) {
- error = -EFAULT;
- goto out_dput;
- }
-
- error = vfs_readlink(dentry, hreq->ohandle, olen);
-
- out_dput:
- dput(dentry);
- return error;
-}
-
-/*
- * Format an attribute and copy it out to the user's buffer.
- * Take care to check values and protect against them changing later,
- * we may be reading them directly out of a user buffer.
- */
-static void
-xfs_ioc_attr_put_listent(
- struct xfs_attr_list_context *context,
- int flags,
- unsigned char *name,
- int namelen,
- void *value,
- int valuelen)
-{
- struct xfs_attrlist *alist = context->buffer;
- struct xfs_attrlist_ent *aep;
- int arraytop;
-
- ASSERT(!context->seen_enough);
- ASSERT(context->count >= 0);
- ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
- ASSERT(context->firstu >= sizeof(*alist));
- ASSERT(context->firstu <= context->bufsize);
-
- /*
- * Only list entries in the right namespace.
- */
- if (context->attr_filter != (flags & XFS_ATTR_NSP_ONDISK_MASK))
- return;
-
- arraytop = sizeof(*alist) +
- context->count * sizeof(alist->al_offset[0]);
-
- /* decrement by the actual bytes used by the attr */
- context->firstu -= round_up(offsetof(struct xfs_attrlist_ent, a_name) +
- namelen + 1, sizeof(uint32_t));
- if (context->firstu < arraytop) {
- trace_xfs_attr_list_full(context);
- alist->al_more = 1;
- context->seen_enough = 1;
- return;
- }
-
- aep = context->buffer + context->firstu;
- aep->a_valuelen = valuelen;
- memcpy(aep->a_name, name, namelen);
- aep->a_name[namelen] = 0;
- alist->al_offset[context->count++] = context->firstu;
- alist->al_count = context->count;
- trace_xfs_attr_list_add(context);
-}
-
-static unsigned int
-xfs_attr_filter(
- u32 ioc_flags)
-{
- if (ioc_flags & XFS_IOC_ATTR_ROOT)
- return XFS_ATTR_ROOT;
- if (ioc_flags & XFS_IOC_ATTR_SECURE)
- return XFS_ATTR_SECURE;
- return 0;
-}
-
-static unsigned int
-xfs_xattr_flags(
- u32 ioc_flags)
-{
- if (ioc_flags & XFS_IOC_ATTR_CREATE)
- return XATTR_CREATE;
- if (ioc_flags & XFS_IOC_ATTR_REPLACE)
- return XATTR_REPLACE;
- return 0;
-}
-
-int
-xfs_ioc_attr_list(
- struct xfs_inode *dp,
- void __user *ubuf,
- size_t bufsize,
- int flags,
- struct xfs_attrlist_cursor __user *ucursor)
-{
- struct xfs_attr_list_context context = { };
- struct xfs_attrlist *alist;
- void *buffer;
- int error;
-
- if (bufsize < sizeof(struct xfs_attrlist) ||
- bufsize > XFS_XATTR_LIST_MAX)
- return -EINVAL;
-
- /*
- * Reject flags, only allow namespaces.
- */
- if (flags & ~(XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
- return -EINVAL;
- if (flags == (XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
- return -EINVAL;
-
- /*
- * Validate the cursor.
- */
- if (copy_from_user(&context.cursor, ucursor, sizeof(context.cursor)))
- return -EFAULT;
- if (context.cursor.pad1 || context.cursor.pad2)
- return -EINVAL;
- if (!context.cursor.initted &&
- (context.cursor.hashval || context.cursor.blkno ||
- context.cursor.offset))
- return -EINVAL;
-
- buffer = kvzalloc(bufsize, GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
-
- /*
- * Initialize the output buffer.
- */
- context.dp = dp;
- context.resynch = 1;
- context.attr_filter = xfs_attr_filter(flags);
- context.buffer = buffer;
- context.bufsize = round_down(bufsize, sizeof(uint32_t));
- context.firstu = context.bufsize;
- context.put_listent = xfs_ioc_attr_put_listent;
-
- alist = context.buffer;
- alist->al_count = 0;
- alist->al_more = 0;
- alist->al_offset[0] = context.bufsize;
-
- error = xfs_attr_list(&context);
- if (error)
- goto out_free;
-
- if (copy_to_user(ubuf, buffer, bufsize) ||
- copy_to_user(ucursor, &context.cursor, sizeof(context.cursor)))
- error = -EFAULT;
-out_free:
- kvfree(buffer);
- return error;
-}
-
-STATIC int
-xfs_attrlist_by_handle(
- struct file *parfilp,
- struct xfs_fsop_attrlist_handlereq __user *p)
-{
- struct xfs_fsop_attrlist_handlereq al_hreq;
- struct dentry *dentry;
- int error = -ENOMEM;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (copy_from_user(&al_hreq, p, sizeof(al_hreq)))
- return -EFAULT;
-
- dentry = xfs_handlereq_to_dentry(parfilp, &al_hreq.hreq);
- if (IS_ERR(dentry))
- return PTR_ERR(dentry);
-
- error = xfs_ioc_attr_list(XFS_I(d_inode(dentry)), al_hreq.buffer,
- al_hreq.buflen, al_hreq.flags, &p->pos);
- dput(dentry);
- return error;
-}
-
-static int
-xfs_attrmulti_attr_get(
- struct inode *inode,
- unsigned char *name,
- unsigned char __user *ubuf,
- uint32_t *len,
- uint32_t flags)
-{
- struct xfs_da_args args = {
- .dp = XFS_I(inode),
- .attr_filter = xfs_attr_filter(flags),
- .xattr_flags = xfs_xattr_flags(flags),
- .name = name,
- .namelen = strlen(name),
- .valuelen = *len,
- };
- int error;
-
- if (*len > XFS_XATTR_SIZE_MAX)
- return -EINVAL;
-
- error = xfs_attr_get(&args);
- if (error)
- goto out_kfree;
-
- *len = args.valuelen;
- if (copy_to_user(ubuf, args.value, args.valuelen))
- error = -EFAULT;
-
-out_kfree:
- kvfree(args.value);
- return error;
-}
-
-static int
-xfs_attrmulti_attr_set(
- struct inode *inode,
- unsigned char *name,
- const unsigned char __user *ubuf,
- uint32_t len,
- uint32_t flags)
-{
- struct xfs_da_args args = {
- .dp = XFS_I(inode),
- .attr_filter = xfs_attr_filter(flags),
- .xattr_flags = xfs_xattr_flags(flags),
- .name = name,
- .namelen = strlen(name),
- };
- int error;
-
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- return -EPERM;
-
- if (ubuf) {
- if (len > XFS_XATTR_SIZE_MAX)
- return -EINVAL;
- args.value = memdup_user(ubuf, len);
- if (IS_ERR(args.value))
- return PTR_ERR(args.value);
- args.valuelen = len;
- }
-
- error = xfs_attr_change(&args);
- if (!error && (flags & XFS_IOC_ATTR_ROOT))
- xfs_forget_acl(inode, name);
- kfree(args.value);
- return error;
-}
-
-int
-xfs_ioc_attrmulti_one(
- struct file *parfilp,
- struct inode *inode,
- uint32_t opcode,
- void __user *uname,
- void __user *value,
- uint32_t *len,
- uint32_t flags)
-{
- unsigned char *name;
- int error;
-
- if ((flags & XFS_IOC_ATTR_ROOT) && (flags & XFS_IOC_ATTR_SECURE))
- return -EINVAL;
-
- name = strndup_user(uname, MAXNAMELEN);
- if (IS_ERR(name))
- return PTR_ERR(name);
-
- switch (opcode) {
- case ATTR_OP_GET:
- error = xfs_attrmulti_attr_get(inode, name, value, len, flags);
- break;
- case ATTR_OP_REMOVE:
- value = NULL;
- *len = 0;
- fallthrough;
- case ATTR_OP_SET:
- error = mnt_want_write_file(parfilp);
- if (error)
- break;
- error = xfs_attrmulti_attr_set(inode, name, value, *len, flags);
- mnt_drop_write_file(parfilp);
- break;
- default:
- error = -EINVAL;
- break;
- }
-
- kfree(name);
- return error;
-}
-
-STATIC int
-xfs_attrmulti_by_handle(
- struct file *parfilp,
- void __user *arg)
-{
- int error;
- xfs_attr_multiop_t *ops;
- xfs_fsop_attrmulti_handlereq_t am_hreq;
- struct dentry *dentry;
- unsigned int i, size;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t)))
- return -EFAULT;
-
- /* overflow check */
- if (am_hreq.opcount >= INT_MAX / sizeof(xfs_attr_multiop_t))
- return -E2BIG;
-
- dentry = xfs_handlereq_to_dentry(parfilp, &am_hreq.hreq);
- if (IS_ERR(dentry))
- return PTR_ERR(dentry);
-
- error = -E2BIG;
- size = am_hreq.opcount * sizeof(xfs_attr_multiop_t);
- if (!size || size > 16 * PAGE_SIZE)
- goto out_dput;
-
- ops = memdup_user(am_hreq.ops, size);
- if (IS_ERR(ops)) {
- error = PTR_ERR(ops);
- goto out_dput;
- }
-
- error = 0;
- for (i = 0; i < am_hreq.opcount; i++) {
- ops[i].am_error = xfs_ioc_attrmulti_one(parfilp,
- d_inode(dentry), ops[i].am_opcode,
- ops[i].am_attrname, ops[i].am_attrvalue,
- &ops[i].am_length, ops[i].am_flags);
- }
-
- if (copy_to_user(am_hreq.ops, ops, size))
- error = -EFAULT;
-
- kfree(ops);
- out_dput:
- dput(dentry);
- return error;
-}
-
/* Return 0 on success or positive error */
int
xfs_fsbulkstat_one_fmt(
diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h
index 38be600b5e1e8..12124946f347e 100644
--- a/fs/xfs/xfs_ioctl.h
+++ b/fs/xfs/xfs_ioctl.h
@@ -14,34 +14,6 @@ int
xfs_ioc_swapext(
xfs_swapext_t *sxp);
-extern int
-xfs_find_handle(
- unsigned int cmd,
- xfs_fsop_handlereq_t *hreq);
-
-extern int
-xfs_open_by_handle(
- struct file *parfilp,
- xfs_fsop_handlereq_t *hreq);
-
-extern int
-xfs_readlink_by_handle(
- struct file *parfilp,
- xfs_fsop_handlereq_t *hreq);
-
-int xfs_ioc_attrmulti_one(struct file *parfilp, struct inode *inode,
- uint32_t opcode, void __user *uname, void __user *value,
- uint32_t *len, uint32_t flags);
-int xfs_ioc_attr_list(struct xfs_inode *dp, void __user *ubuf,
- size_t bufsize, int flags,
- struct xfs_attrlist_cursor __user *ucursor);
-
-extern struct dentry *
-xfs_handle_to_dentry(
- struct file *parfilp,
- void __user *uhandle,
- u32 hlen);
-
extern int
xfs_fileattr_get(
struct dentry *dentry,
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index ee35eea1ecce6..b64785dc4354e 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -24,6 +24,7 @@
#include "xfs_ioctl32.h"
#include "xfs_trace.h"
#include "xfs_sb.h"
+#include "xfs_handle.h"
#define _NATIVE_IOC(cmd, type) \
_IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type))
next prev parent reply other threads:[~2024-04-10 1:00 UTC|newest]
Thread overview: 234+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-10 0:36 [PATCHBOMB v13.1] xfs: directory parent pointers Darrick J. Wong
2024-04-10 0:44 ` [PATCHSET v13.1 1/9] xfs: design documentation for online fsck, part 2 Darrick J. Wong
2024-04-10 0:46 ` [PATCH 1/4] docs: update the parent pointers documentation to the final version Darrick J. Wong
2024-04-10 4:40 ` Christoph Hellwig
2024-04-10 0:46 ` [PATCH 2/4] docs: update online directory and parent pointer repair sections Darrick J. Wong
2024-04-10 4:40 ` Christoph Hellwig
2024-04-10 0:47 ` [PATCH 3/4] docs: update offline parent pointer repair strategy Darrick J. Wong
2024-04-10 4:40 ` Christoph Hellwig
2024-04-10 0:47 ` [PATCH 4/4] docs: describe xfs directory tree online fsck Darrick J. Wong
2024-04-10 4:40 ` Christoph Hellwig
2024-04-10 0:44 ` [PATCHSET v13.1 2/9] xfs: retain ILOCK during directory updates Darrick J. Wong
2024-04-10 0:47 ` [PATCH 1/7] xfs: Increase XFS_DEFER_OPS_NR_INODES to 5 Darrick J. Wong
2024-04-10 4:41 ` Christoph Hellwig
2024-04-10 0:48 ` [PATCH 2/7] xfs: Increase XFS_QM_TRANS_MAXDQS " Darrick J. Wong
2024-04-10 4:41 ` Christoph Hellwig
2024-04-10 0:48 ` [PATCH 3/7] xfs: Hold inode locks in xfs_ialloc Darrick J. Wong
2024-04-10 4:41 ` Christoph Hellwig
2024-04-10 0:48 ` [PATCH 4/7] xfs: Hold inode locks in xfs_trans_alloc_dir Darrick J. Wong
2024-04-10 4:41 ` Christoph Hellwig
2024-04-10 0:48 ` [PATCH 5/7] xfs: Hold inode locks in xfs_rename Darrick J. Wong
2024-04-10 4:42 ` Christoph Hellwig
2024-04-10 0:49 ` [PATCH 6/7] xfs: don't pick up IOLOCK during rmapbt repair scan Darrick J. Wong
2024-04-10 4:42 ` Christoph Hellwig
2024-04-10 0:49 ` [PATCH 7/7] xfs: unlock new repair tempfiles after creation Darrick J. Wong
2024-04-10 4:42 ` Christoph Hellwig
2024-04-10 0:44 ` [PATCHSET v13.1 3/9] xfs: shrink struct xfs_da_args Darrick J. Wong
2024-04-10 0:49 ` [PATCH 1/4] xfs: remove XFS_DA_OP_REMOVE Darrick J. Wong
2024-04-10 4:43 ` Christoph Hellwig
2024-04-10 0:49 ` [PATCH 2/4] xfs: remove XFS_DA_OP_NOTIME Darrick J. Wong
2024-04-10 4:44 ` Christoph Hellwig
2024-04-10 0:50 ` [PATCH 3/4] xfs: rename xfs_da_args.attr_flags Darrick J. Wong
2024-04-10 5:01 ` Christoph Hellwig
2024-04-10 20:55 ` Darrick J. Wong
2024-04-11 0:00 ` Darrick J. Wong
2024-04-11 3:26 ` Christoph Hellwig
2024-04-11 4:15 ` Darrick J. Wong
2024-04-10 0:50 ` [PATCH 4/4] xfs: rearrange xfs_da_args a bit to use less space Darrick J. Wong
2024-04-10 5:02 ` Christoph Hellwig
2024-04-10 20:56 ` Darrick J. Wong
2024-04-10 0:45 ` [PATCHSET v13.1 4/9] xfs: improve extended attribute validation Darrick J. Wong
2024-04-10 0:50 ` [PATCH 01/12] xfs: attr fork iext must be loaded before calling xfs_attr_is_leaf Darrick J. Wong
2024-04-10 5:04 ` Christoph Hellwig
2024-04-10 20:58 ` Darrick J. Wong
2024-04-10 0:50 ` [PATCH 02/12] xfs: require XFS_SB_FEAT_INCOMPAT_LOG_XATTRS for attr log intent item recovery Darrick J. Wong
2024-04-10 5:04 ` Christoph Hellwig
2024-04-10 0:51 ` [PATCH 03/12] xfs: use an XFS_OPSTATE_ flag for detecting if logged xattrs are available Darrick J. Wong
2024-04-10 5:05 ` Christoph Hellwig
2024-04-10 0:51 ` [PATCH 04/12] xfs: check opcode and iovec count match in xlog_recover_attri_commit_pass2 Darrick J. Wong
2024-04-10 5:05 ` Christoph Hellwig
2024-04-10 0:51 ` [PATCH 05/12] xfs: fix missing check for invalid attr flags Darrick J. Wong
2024-04-10 5:07 ` Christoph Hellwig
2024-04-10 21:04 ` Darrick J. Wong
2024-04-10 0:51 ` [PATCH 06/12] xfs: restructure xfs_attr_complete_op a bit Darrick J. Wong
2024-04-10 5:07 ` Christoph Hellwig
2024-04-10 0:52 ` [PATCH 07/12] xfs: use helpers to extract xattr op from opflags Darrick J. Wong
2024-04-10 5:07 ` Christoph Hellwig
2024-04-10 0:52 ` [PATCH 08/12] xfs: validate recovered name buffers when recovering xattr items Darrick J. Wong
2024-04-10 5:08 ` Christoph Hellwig
2024-04-10 0:52 ` [PATCH 09/12] xfs: always set args->value in xfs_attri_item_recover Darrick J. Wong
2024-04-10 5:08 ` Christoph Hellwig
2024-04-10 0:52 ` [PATCH 10/12] xfs: use local variables for name and value length in _attri_commit_pass2 Darrick J. Wong
2024-04-10 5:08 ` Christoph Hellwig
2024-04-10 0:53 ` [PATCH 11/12] xfs: refactor name/length checks in xfs_attri_validate Darrick J. Wong
2024-04-10 5:09 ` Christoph Hellwig
2024-04-10 0:53 ` [PATCH 12/12] xfs: enforce one namespace per attribute Darrick J. Wong
2024-04-10 5:09 ` Christoph Hellwig
2024-04-10 0:45 ` [PATCHSET v13.1 5/9] xfs: Parent Pointers Darrick J. Wong
2024-04-10 0:53 ` [PATCH 01/32] xfs: rearrange xfs_attr_match parameters Darrick J. Wong
2024-04-10 5:10 ` Christoph Hellwig
2024-04-10 0:54 ` [PATCH 02/32] xfs: check the flags earlier in xfs_attr_match Darrick J. Wong
2024-04-10 0:54 ` [PATCH 03/32] xfs: move xfs_attr_defer_add to xfs_attr_item.c Darrick J. Wong
2024-04-10 5:11 ` Christoph Hellwig
2024-04-10 0:54 ` [PATCH 04/32] xfs: create a separate hashname function for extended attributes Darrick J. Wong
2024-04-10 5:11 ` Christoph Hellwig
2024-04-10 0:54 ` [PATCH 05/32] xfs: add parent pointer support to attribute code Darrick J. Wong
2024-04-10 5:11 ` Christoph Hellwig
2024-04-10 0:55 ` [PATCH 06/32] xfs: define parent pointer ondisk extended attribute format Darrick J. Wong
2024-04-10 5:12 ` Christoph Hellwig
2024-04-10 0:55 ` [PATCH 07/32] xfs: allow xattr matching on name and value for local/sf attrs Darrick J. Wong
2024-04-10 5:16 ` Christoph Hellwig
2024-04-10 21:13 ` Darrick J. Wong
2024-04-11 3:28 ` Christoph Hellwig
2024-04-10 0:55 ` [PATCH 08/32] xfs: allow logged xattr operations if parent pointers are enabled Darrick J. Wong
2024-04-10 5:18 ` Christoph Hellwig
2024-04-10 21:18 ` Darrick J. Wong
2024-04-10 0:55 ` [PATCH 09/32] xfs: log parent pointer xattr removal operations Darrick J. Wong
2024-04-10 5:18 ` Christoph Hellwig
2024-04-10 0:56 ` [PATCH 10/32] xfs: log parent pointer xattr setting operations Darrick J. Wong
2024-04-10 0:56 ` [PATCH 11/32] xfs: log parent pointer xattr replace operations Darrick J. Wong
2024-04-10 5:26 ` Christoph Hellwig
2024-04-10 23:07 ` Darrick J. Wong
2024-04-11 3:35 ` Christoph Hellwig
2024-04-10 0:56 ` [PATCH 12/32] xfs: record inode generation in xattr update log intent items Darrick J. Wong
2024-04-10 5:27 ` Christoph Hellwig
2024-04-10 0:56 ` [PATCH 13/32] xfs: Expose init_xattrs in xfs_create_tmpfile Darrick J. Wong
2024-04-10 5:28 ` Christoph Hellwig
2024-04-10 0:57 ` [PATCH 14/32] xfs: add parent pointer validator functions Darrick J. Wong
2024-04-10 5:31 ` Christoph Hellwig
2024-04-10 18:53 ` Darrick J. Wong
2024-04-11 3:25 ` Christoph Hellwig
2024-04-10 0:57 ` [PATCH 15/32] xfs: extend transaction reservations for parent attributes Darrick J. Wong
2024-04-10 5:31 ` Christoph Hellwig
2024-04-10 0:57 ` [PATCH 16/32] xfs: create a hashname function for parent pointers Darrick J. Wong
2024-04-10 5:33 ` Christoph Hellwig
2024-04-10 21:39 ` Darrick J. Wong
2024-04-10 0:57 ` [PATCH 17/32] xfs: parent pointer attribute creation Darrick J. Wong
2024-04-10 5:44 ` Christoph Hellwig
2024-04-10 21:50 ` Darrick J. Wong
2024-04-10 0:58 ` [PATCH 18/32] xfs: add parent attributes to link Darrick J. Wong
2024-04-10 5:45 ` Christoph Hellwig
2024-04-10 0:58 ` [PATCH 19/32] xfs: add parent attributes to symlink Darrick J. Wong
2024-04-10 5:45 ` Christoph Hellwig
2024-04-10 0:58 ` [PATCH 20/32] xfs: remove parent pointers in unlink Darrick J. Wong
2024-04-10 5:45 ` Christoph Hellwig
2024-04-10 0:58 ` [PATCH 21/32] xfs: Add parent pointers to rename Darrick J. Wong
2024-04-10 5:46 ` Christoph Hellwig
2024-04-10 0:59 ` [PATCH 22/32] xfs: Add parent pointers to xfs_cross_rename Darrick J. Wong
2024-04-10 5:46 ` Christoph Hellwig
2024-04-10 0:59 ` [PATCH 23/32] xfs: Filter XFS_ATTR_PARENT for getfattr Darrick J. Wong
2024-04-10 5:51 ` Christoph Hellwig
2024-04-10 21:58 ` Darrick J. Wong
2024-04-11 3:29 ` Christoph Hellwig
2024-04-10 0:59 ` [PATCH 24/32] xfs: pass the attr value to put_listent when possible Darrick J. Wong
2024-04-10 5:51 ` Christoph Hellwig
2024-04-10 1:00 ` Darrick J. Wong [this message]
2024-04-10 5:52 ` [PATCH 25/32] xfs: move handle ioctl code to xfs_handle.c Christoph Hellwig
2024-04-10 1:00 ` [PATCH 26/32] xfs: split out handle management helpers a bit Darrick J. Wong
2024-04-10 5:56 ` Christoph Hellwig
2024-04-10 22:01 ` Darrick J. Wong
2024-04-10 1:00 ` [PATCH 27/32] xfs: Add parent pointer ioctls Darrick J. Wong
2024-04-10 6:04 ` Christoph Hellwig
2024-04-10 23:34 ` Darrick J. Wong
2024-04-12 17:39 ` Darrick J. Wong
2024-04-14 5:18 ` Christoph Hellwig
2024-04-15 19:40 ` Darrick J. Wong
2024-04-16 4:47 ` Christoph Hellwig
2024-04-16 16:50 ` Darrick J. Wong
2024-04-16 16:54 ` Christoph Hellwig
2024-04-16 18:52 ` Darrick J. Wong
2024-04-16 19:01 ` Christoph Hellwig
2024-04-16 19:07 ` Darrick J. Wong
2024-04-16 19:14 ` Christoph Hellwig
2024-04-17 5:22 ` Darrick J. Wong
2024-04-17 5:29 ` Christoph Hellwig
2024-04-17 5:55 ` Darrick J. Wong
2024-04-10 1:00 ` [PATCH 28/32] xfs: don't remove the attr fork when parent pointers are enabled Darrick J. Wong
2024-04-10 6:04 ` Christoph Hellwig
2024-04-10 1:01 ` [PATCH 29/32] xfs: Add the parent pointer support to the superblock version 5 Darrick J. Wong
2024-04-10 6:05 ` Christoph Hellwig
2024-04-10 22:06 ` Darrick J. Wong
2024-04-10 1:01 ` [PATCH 30/32] xfs: fix unit conversion error in xfs_log_calc_max_attrsetm_res Darrick J. Wong
2024-04-10 6:05 ` Christoph Hellwig
2024-04-10 1:01 ` [PATCH 31/32] xfs: drop compatibility minimum log size computations for reflink Darrick J. Wong
2024-04-10 6:06 ` Christoph Hellwig
2024-04-10 1:01 ` [PATCH 32/32] xfs: enable parent pointers Darrick J. Wong
2024-04-10 6:06 ` Christoph Hellwig
2024-04-10 22:11 ` Darrick J. Wong
2024-04-10 0:45 ` [PATCHSET v13.1 6/9] xfs: scrubbing for " Darrick J. Wong
2024-04-10 1:02 ` [PATCH 1/7] xfs: check dirents have " Darrick J. Wong
2024-04-10 6:12 ` Christoph Hellwig
2024-04-10 1:02 ` [PATCH 2/7] xfs: deferred scrub of dirents Darrick J. Wong
2024-04-10 6:13 ` Christoph Hellwig
2024-04-10 1:02 ` [PATCH 3/7] xfs: scrub parent pointers Darrick J. Wong
2024-04-10 6:13 ` Christoph Hellwig
2024-04-10 1:02 ` [PATCH 4/7] xfs: deferred scrub of " Darrick J. Wong
2024-04-10 6:14 ` Christoph Hellwig
2024-04-10 1:03 ` [PATCH 5/7] xfs: walk directory parent pointers to determine backref count Darrick J. Wong
2024-04-10 6:14 ` Christoph Hellwig
2024-04-10 1:03 ` [PATCH 6/7] xfs: check parent pointer xattrs when scrubbing Darrick J. Wong
2024-04-10 6:14 ` Christoph Hellwig
2024-04-10 1:03 ` [PATCH 7/7] xfs: salvage parent pointers when rebuilding xattr structures Darrick J. Wong
2024-04-10 6:15 ` Christoph Hellwig
2024-04-10 0:45 ` [PATCHSET v13.1 7/9] xfs: online repair for parent pointers Darrick J. Wong
2024-04-10 1:03 ` [PATCH 01/14] xfs: add xattr setname and removename functions for internal users Darrick J. Wong
2024-04-10 6:18 ` Christoph Hellwig
2024-04-10 22:18 ` Darrick J. Wong
2024-04-11 3:32 ` Christoph Hellwig
2024-04-11 4:30 ` Darrick J. Wong
2024-04-11 4:50 ` Christoph Hellwig
2024-04-10 1:04 ` [PATCH 02/14] xfs: add raw parent pointer apis to support repair Darrick J. Wong
2024-04-10 6:18 ` Christoph Hellwig
2024-04-10 1:04 ` [PATCH 03/14] xfs: repair directories by scanning directory parent pointers Darrick J. Wong
2024-04-10 6:19 ` Christoph Hellwig
2024-04-10 1:04 ` [PATCH 04/14] xfs: implement live updates for directory repairs Darrick J. Wong
2024-04-10 6:19 ` Christoph Hellwig
2024-04-10 1:04 ` [PATCH 05/14] xfs: replay unlocked parent pointer updates that accrue during xattr repair Darrick J. Wong
2024-04-10 6:19 ` Christoph Hellwig
2024-04-10 1:05 ` [PATCH 06/14] xfs: repair directory parent pointers by scanning for dirents Darrick J. Wong
2024-04-10 6:20 ` Christoph Hellwig
2024-04-10 1:05 ` [PATCH 07/14] xfs: implement live updates for parent pointer repairs Darrick J. Wong
2024-04-10 6:20 ` Christoph Hellwig
2024-04-10 1:05 ` [PATCH 08/14] xfs: remove pointless unlocked assertion Darrick J. Wong
2024-04-10 6:20 ` Christoph Hellwig
2024-04-10 1:06 ` [PATCH 09/14] xfs: split xfs_bmap_add_attrfork into two pieces Darrick J. Wong
2024-04-10 6:21 ` Christoph Hellwig
2024-04-10 1:06 ` [PATCH 10/14] xfs: add a per-leaf block callback to xchk_xattr_walk Darrick J. Wong
2024-04-10 6:22 ` Christoph Hellwig
2024-04-10 1:06 ` [PATCH 11/14] xfs: actually rebuild the parent pointer xattrs Darrick J. Wong
2024-04-10 6:22 ` Christoph Hellwig
2024-04-10 1:06 ` [PATCH 12/14] xfs: adapt the orphanage code to handle parent pointers Darrick J. Wong
2024-04-10 6:23 ` Christoph Hellwig
2024-04-10 1:07 ` [PATCH 13/14] xfs: repair link count of nondirectories after rebuilding " Darrick J. Wong
2024-04-10 6:22 ` Christoph Hellwig
2024-04-10 1:07 ` [PATCH 14/14] xfs: inode repair should ensure there's an attr fork to store " Darrick J. Wong
2024-04-10 6:24 ` Christoph Hellwig
2024-04-10 0:46 ` [PATCHSET v13.1 8/9] xfs: detect and correct directory tree problems Darrick J. Wong
2024-04-10 1:07 ` [PATCH 1/4] xfs: teach online scrub to find directory tree structure problems Darrick J. Wong
2024-04-10 7:21 ` Christoph Hellwig
2024-04-10 1:07 ` [PATCH 2/4] xfs: invalidate dirloop scrub path data when concurrent updates happen Darrick J. Wong
2024-04-10 7:21 ` Christoph Hellwig
2024-04-10 1:08 ` [PATCH 3/4] xfs: report directory tree corruption in the health information Darrick J. Wong
2024-04-10 7:23 ` Christoph Hellwig
2024-04-10 1:08 ` [PATCH 4/4] xfs: fix corruptions in the directory tree Darrick J. Wong
2024-04-10 7:23 ` Christoph Hellwig
2024-04-10 0:46 ` [PATCHSET v13.1 9/9] xfs: vectorize scrub kernel calls Darrick J. Wong
2024-04-10 1:08 ` [PATCH 1/3] xfs: reduce the rate of cond_resched calls inside scrub Darrick J. Wong
2024-04-10 14:55 ` Christoph Hellwig
2024-04-10 22:19 ` Darrick J. Wong
2024-04-10 1:08 ` [PATCH 2/3] xfs: introduce vectored scrub mode Darrick J. Wong
2024-04-10 15:00 ` Christoph Hellwig
2024-04-11 0:59 ` Darrick J. Wong
2024-04-11 3:38 ` Christoph Hellwig
2024-04-11 4:31 ` Darrick J. Wong
2024-04-10 1:09 ` [PATCH 3/3] xfs: only iget the file once when doing vectored scrub-by-handle Darrick J. Wong
2024-04-10 15:12 ` Christoph Hellwig
2024-04-11 1:15 ` Darrick J. Wong
2024-04-11 3:49 ` Christoph Hellwig
2024-04-11 4:41 ` Darrick J. Wong
2024-04-11 4:52 ` Christoph Hellwig
2024-04-11 4:56 ` Darrick J. Wong
2024-04-11 5:02 ` Christoph Hellwig
2024-04-11 5:21 ` Darrick J. Wong
2024-04-11 14:02 ` Christoph Hellwig
2024-04-12 0:21 ` Darrick J. Wong
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=171270969974.3631889.581031520799249475.stgit@frogsfrogsfrogs \
--to=djwong@kernel.org \
--cc=allison.henderson@oracle.com \
--cc=catherine.hoang@oracle.com \
--cc=hch@lst.de \
--cc=linux-xfs@vger.kernel.org \
/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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).