^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2000-2005 Silicon Graphics, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "xfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "xfs_fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "xfs_shared.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "xfs_format.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "xfs_log_format.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "xfs_trans_resv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "xfs_mount.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "xfs_inode.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "xfs_rtalloc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "xfs_iwalk.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "xfs_itable.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "xfs_error.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "xfs_attr.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "xfs_bmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "xfs_bmap_util.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "xfs_fsops.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "xfs_discard.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "xfs_quota.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "xfs_export.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "xfs_trace.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "xfs_icache.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "xfs_trans.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "xfs_acl.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "xfs_btree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/fsmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "xfs_fsmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "scrub/xfs_scrub.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include "xfs_sb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include "xfs_ag.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include "xfs_health.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include "xfs_reflink.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include "xfs_ioctl.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include "xfs_da_format.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include "xfs_da_btree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * a file or fs handle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * XFS_IOC_PATH_TO_FSHANDLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * returns fs handle for a mount point or path within that mount point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * XFS_IOC_FD_TO_HANDLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * returns full handle for a FD opened in user space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * XFS_IOC_PATH_TO_HANDLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * returns full handle for a path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) xfs_find_handle(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) xfs_fsop_handlereq_t *hreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int hsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) xfs_handle_t handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct fd f = {NULL};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct path path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct xfs_inode *ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (cmd == XFS_IOC_FD_TO_HANDLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) f = fdget(hreq->fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (!f.file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) inode = file_inode(f.file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) error = user_path_at(AT_FDCWD, hreq->path, 0, &path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) inode = d_inode(path.dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) ip = XFS_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * We can only generate handles for inodes residing on a XFS filesystem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * and only for regular files, directories or symbolic links.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (inode->i_sb->s_magic != XFS_SB_MAGIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) goto out_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) error = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (!S_ISREG(inode->i_mode) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) !S_ISDIR(inode->i_mode) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) !S_ISLNK(inode->i_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) goto out_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) memcpy(&handle.ha_fsid, ip->i_mount->m_fixedfsid, sizeof(xfs_fsid_t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (cmd == XFS_IOC_PATH_TO_FSHANDLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * This handle only contains an fsid, zero the rest.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) memset(&handle.ha_fid, 0, sizeof(handle.ha_fid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) hsize = sizeof(xfs_fsid_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) sizeof(handle.ha_fid.fid_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) handle.ha_fid.fid_pad = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) handle.ha_fid.fid_gen = inode->i_generation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) handle.ha_fid.fid_ino = ip->i_ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) hsize = sizeof(xfs_handle_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (copy_to_user(hreq->ohandle, &handle, hsize) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) goto out_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) out_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (cmd == XFS_IOC_FD_TO_HANDLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) fdput(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) path_put(&path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * No need to do permission checks on the various pathname components
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * as the handle operations are privileged.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) xfs_handle_acceptable(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) void *context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * Convert userspace handle data into a dentry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct dentry *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) xfs_handle_to_dentry(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct file *parfilp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) void __user *uhandle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) u32 hlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) xfs_handle_t handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct xfs_fid64 fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * Only allow handle opens under a directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (!S_ISDIR(file_inode(parfilp)->i_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return ERR_PTR(-ENOTDIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (hlen != sizeof(xfs_handle_t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (copy_from_user(&handle, uhandle, hlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return ERR_PTR(-EFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (handle.ha_fid.fid_len !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) sizeof(handle.ha_fid) - sizeof(handle.ha_fid.fid_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) memset(&fid, 0, sizeof(struct fid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) fid.ino = handle.ha_fid.fid_ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) fid.gen = handle.ha_fid.fid_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return exportfs_decode_fh(parfilp->f_path.mnt, (struct fid *)&fid, 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) xfs_handle_acceptable, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) STATIC struct dentry *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) xfs_handlereq_to_dentry(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct file *parfilp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) xfs_fsop_handlereq_t *hreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return xfs_handle_to_dentry(parfilp, hreq->ihandle, hreq->ihandlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) xfs_open_by_handle(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct file *parfilp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) xfs_fsop_handlereq_t *hreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) const struct cred *cred = current_cred();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) int fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) int permflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct file *filp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) fmode_t fmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct path path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) dentry = xfs_handlereq_to_dentry(parfilp, hreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (IS_ERR(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return PTR_ERR(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /* Restrict xfs_open_by_handle to directories & regular files. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) goto out_dput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) #if BITS_PER_LONG != 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) hreq->oflags |= O_LARGEFILE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) permflag = hreq->oflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) fmode = OPEN_FMODE(permflag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) (fmode & FMODE_WRITE) && IS_APPEND(inode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) goto out_dput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if ((fmode & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) goto out_dput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* Can't write directories. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (S_ISDIR(inode->i_mode) && (fmode & FMODE_WRITE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) error = -EISDIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) goto out_dput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) fd = get_unused_fd_flags(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) error = fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) goto out_dput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) path.mnt = parfilp->f_path.mnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) path.dentry = dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) filp = dentry_open(&path, hreq->oflags, cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (IS_ERR(filp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) put_unused_fd(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return PTR_ERR(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (S_ISREG(inode->i_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) filp->f_flags |= O_NOATIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) filp->f_mode |= FMODE_NOCMTIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) fd_install(fd, filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) out_dput:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) xfs_readlink_by_handle(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) struct file *parfilp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) xfs_fsop_handlereq_t *hreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) __u32 olen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) dentry = xfs_handlereq_to_dentry(parfilp, hreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (IS_ERR(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return PTR_ERR(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* Restrict this handle operation to symlinks only. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (!d_is_symlink(dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) goto out_dput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) goto out_dput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) error = vfs_readlink(dentry, hreq->ohandle, olen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) out_dput:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * Format an attribute and copy it out to the user's buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * Take care to check values and protect against them changing later,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * we may be reading them directly out of a user buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) xfs_ioc_attr_put_listent(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) struct xfs_attr_list_context *context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) unsigned char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) int namelen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) int valuelen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct xfs_attrlist *alist = context->buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct xfs_attrlist_ent *aep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) int arraytop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) ASSERT(!context->seen_enough);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) ASSERT(context->count >= 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) ASSERT(context->firstu >= sizeof(*alist));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) ASSERT(context->firstu <= context->bufsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * Only list entries in the right namespace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (context->attr_filter != (flags & XFS_ATTR_NSP_ONDISK_MASK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) arraytop = sizeof(*alist) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) context->count * sizeof(alist->al_offset[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* decrement by the actual bytes used by the attr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) context->firstu -= round_up(offsetof(struct xfs_attrlist_ent, a_name) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) namelen + 1, sizeof(uint32_t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (context->firstu < arraytop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) trace_xfs_attr_list_full(context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) alist->al_more = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) context->seen_enough = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) aep = context->buffer + context->firstu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) aep->a_valuelen = valuelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) memcpy(aep->a_name, name, namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) aep->a_name[namelen] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) alist->al_offset[context->count++] = context->firstu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) alist->al_count = context->count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) trace_xfs_attr_list_add(context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) xfs_attr_filter(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) u32 ioc_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (ioc_flags & XFS_IOC_ATTR_ROOT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return XFS_ATTR_ROOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (ioc_flags & XFS_IOC_ATTR_SECURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return XFS_ATTR_SECURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) xfs_attr_flags(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) u32 ioc_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (ioc_flags & XFS_IOC_ATTR_CREATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return XATTR_CREATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (ioc_flags & XFS_IOC_ATTR_REPLACE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return XATTR_REPLACE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) xfs_ioc_attr_list(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct xfs_inode *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) void __user *ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) int bufsize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct xfs_attrlist_cursor __user *ucursor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct xfs_attr_list_context context = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) struct xfs_attrlist *alist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) void *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (bufsize < sizeof(struct xfs_attrlist) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) bufsize > XFS_XATTR_LIST_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * Reject flags, only allow namespaces.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (flags & ~(XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (flags == (XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * Validate the cursor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (copy_from_user(&context.cursor, ucursor, sizeof(context.cursor)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (context.cursor.pad1 || context.cursor.pad2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (!context.cursor.initted &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) (context.cursor.hashval || context.cursor.blkno ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) context.cursor.offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) buffer = kvzalloc(bufsize, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (!buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * Initialize the output buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) context.dp = dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) context.resynch = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) context.attr_filter = xfs_attr_filter(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) context.buffer = buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) context.bufsize = round_down(bufsize, sizeof(uint32_t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) context.firstu = context.bufsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) context.put_listent = xfs_ioc_attr_put_listent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) alist = context.buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) alist->al_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) alist->al_more = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) alist->al_offset[0] = context.bufsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) error = xfs_attr_list(&context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (copy_to_user(ubuf, buffer, bufsize) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) copy_to_user(ucursor, &context.cursor, sizeof(context.cursor)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) kmem_free(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) xfs_attrlist_by_handle(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct file *parfilp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct xfs_fsop_attrlist_handlereq __user *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct xfs_fsop_attrlist_handlereq al_hreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) int error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (copy_from_user(&al_hreq, p, sizeof(al_hreq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) dentry = xfs_handlereq_to_dentry(parfilp, &al_hreq.hreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (IS_ERR(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) return PTR_ERR(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) error = xfs_ioc_attr_list(XFS_I(d_inode(dentry)), al_hreq.buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) al_hreq.buflen, al_hreq.flags, &p->pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) xfs_attrmulti_attr_get(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) unsigned char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) unsigned char __user *ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) uint32_t *len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) uint32_t flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct xfs_da_args args = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) .dp = XFS_I(inode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) .attr_filter = xfs_attr_filter(flags),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) .attr_flags = xfs_attr_flags(flags),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) .name = name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) .namelen = strlen(name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) .valuelen = *len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (*len > XFS_XATTR_SIZE_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) error = xfs_attr_get(&args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) goto out_kfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) *len = args.valuelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (copy_to_user(ubuf, args.value, args.valuelen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) out_kfree:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) kmem_free(args.value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) xfs_attrmulti_attr_set(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) unsigned char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) const unsigned char __user *ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) uint32_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) uint32_t flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) struct xfs_da_args args = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) .dp = XFS_I(inode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) .attr_filter = xfs_attr_filter(flags),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) .attr_flags = xfs_attr_flags(flags),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) .name = name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) .namelen = strlen(name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (ubuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (len > XFS_XATTR_SIZE_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) args.value = memdup_user(ubuf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (IS_ERR(args.value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return PTR_ERR(args.value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) args.valuelen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) error = xfs_attr_set(&args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (!error && (flags & XFS_IOC_ATTR_ROOT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) xfs_forget_acl(inode, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) kfree(args.value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) xfs_ioc_attrmulti_one(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct file *parfilp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) uint32_t opcode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) void __user *uname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) void __user *value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) uint32_t *len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) uint32_t flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) unsigned char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if ((flags & XFS_IOC_ATTR_ROOT) && (flags & XFS_IOC_ATTR_SECURE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) name = strndup_user(uname, MAXNAMELEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (IS_ERR(name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return PTR_ERR(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) switch (opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) case ATTR_OP_GET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) error = xfs_attrmulti_attr_get(inode, name, value, len, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) case ATTR_OP_REMOVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) value = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) *len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) case ATTR_OP_SET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) error = mnt_want_write_file(parfilp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) error = xfs_attrmulti_attr_set(inode, name, value, *len, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) mnt_drop_write_file(parfilp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) kfree(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) xfs_attrmulti_by_handle(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) struct file *parfilp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) xfs_attr_multiop_t *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) xfs_fsop_attrmulti_handlereq_t am_hreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) unsigned int i, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) /* overflow check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (am_hreq.opcount >= INT_MAX / sizeof(xfs_attr_multiop_t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) dentry = xfs_handlereq_to_dentry(parfilp, &am_hreq.hreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (IS_ERR(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return PTR_ERR(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) error = -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) size = am_hreq.opcount * sizeof(xfs_attr_multiop_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (!size || size > 16 * PAGE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) goto out_dput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) ops = memdup_user(am_hreq.ops, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (IS_ERR(ops)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) error = PTR_ERR(ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) goto out_dput;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) for (i = 0; i < am_hreq.opcount; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) ops[i].am_error = xfs_ioc_attrmulti_one(parfilp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) d_inode(dentry), ops[i].am_opcode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) ops[i].am_attrname, ops[i].am_attrvalue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) &ops[i].am_length, ops[i].am_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (copy_to_user(am_hreq.ops, ops, size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) kfree(ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) out_dput:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) xfs_ioc_space(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) struct file *filp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) xfs_flock64_t *bf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct inode *inode = file_inode(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) struct xfs_inode *ip = XFS_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) struct iattr iattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) enum xfs_prealloc_flags flags = XFS_PREALLOC_CLEAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) uint iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (inode->i_flags & (S_IMMUTABLE|S_APPEND))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (!(filp->f_mode & FMODE_WRITE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (!S_ISREG(inode->i_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (xfs_is_always_cow_inode(ip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (filp->f_flags & O_DSYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) flags |= XFS_PREALLOC_SYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (filp->f_mode & FMODE_NOCMTIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) flags |= XFS_PREALLOC_INVISIBLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) error = mnt_want_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) xfs_ilock(ip, iolock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) error = xfs_break_layouts(inode, &iolock, BREAK_UNMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) inode_dio_wait(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) switch (bf->l_whence) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) case 0: /*SEEK_SET*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) case 1: /*SEEK_CUR*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) bf->l_start += filp->f_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) case 2: /*SEEK_END*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) bf->l_start += XFS_ISIZE(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (bf->l_start < 0 || bf->l_start > inode->i_sb->s_maxbytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (bf->l_start > XFS_ISIZE(ip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) error = xfs_alloc_file_space(ip, XFS_ISIZE(ip),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) bf->l_start - XFS_ISIZE(ip),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) XFS_BMAPI_PREALLOC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) iattr.ia_valid = ATTR_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) iattr.ia_size = bf->l_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) error = xfs_vn_setattr_size(file_dentry(filp), &iattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) error = xfs_update_prealloc_flags(ip, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) xfs_iunlock(ip, iolock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) mnt_drop_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /* Return 0 on success or positive error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) xfs_fsbulkstat_one_fmt(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct xfs_ibulk *breq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) const struct xfs_bulkstat *bstat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) struct xfs_bstat bs1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) xfs_bulkstat_to_bstat(breq->mp, &bs1, bstat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if (copy_to_user(breq->ubuffer, &bs1, sizeof(bs1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return xfs_ibulk_advance(breq, sizeof(struct xfs_bstat));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) xfs_fsinumbers_fmt(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct xfs_ibulk *breq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) const struct xfs_inumbers *igrp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) struct xfs_inogrp ig1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) xfs_inumbers_to_inogrp(&ig1, igrp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (copy_to_user(breq->ubuffer, &ig1, sizeof(struct xfs_inogrp)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return xfs_ibulk_advance(breq, sizeof(struct xfs_inogrp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) xfs_ioc_fsbulkstat(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) xfs_mount_t *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) struct xfs_fsop_bulkreq bulkreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) struct xfs_ibulk breq = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) .mp = mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) .ocount = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) xfs_ino_t lastino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) /* done = 1 if there are more stats to get and if bulkstat */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) /* should be called again (unused here, but used in dmapi) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (XFS_FORCED_SHUTDOWN(mp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (copy_from_user(&bulkreq, arg, sizeof(struct xfs_fsop_bulkreq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (copy_from_user(&lastino, bulkreq.lastip, sizeof(__s64)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (bulkreq.icount <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (bulkreq.ubuffer == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) breq.ubuffer = bulkreq.ubuffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) breq.icount = bulkreq.icount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) * FSBULKSTAT_SINGLE expects that *lastip contains the inode number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) * that we want to stat. However, FSINUMBERS and FSBULKSTAT expect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) * that *lastip contains either zero or the number of the last inode to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) * be examined by the previous call and return results starting with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) * the next inode after that. The new bulk request back end functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) * take the inode to start with, so we have to compute the startino
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) * parameter from lastino to maintain correct function. lastino == 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) * is a special case because it has traditionally meant "first inode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) * in filesystem".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (cmd == XFS_IOC_FSINUMBERS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) breq.startino = lastino ? lastino + 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) error = xfs_inumbers(&breq, xfs_fsinumbers_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) lastino = breq.startino - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) breq.startino = lastino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) breq.icount = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) error = xfs_bulkstat_one(&breq, xfs_fsbulkstat_one_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) } else { /* XFS_IOC_FSBULKSTAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) breq.startino = lastino ? lastino + 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) error = xfs_bulkstat(&breq, xfs_fsbulkstat_one_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) lastino = breq.startino - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (bulkreq.lastip != NULL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) copy_to_user(bulkreq.lastip, &lastino, sizeof(xfs_ino_t)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (bulkreq.ocount != NULL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) copy_to_user(bulkreq.ocount, &breq.ocount, sizeof(__s32)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) /* Return 0 on success or positive error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) xfs_bulkstat_fmt(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) struct xfs_ibulk *breq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) const struct xfs_bulkstat *bstat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (copy_to_user(breq->ubuffer, bstat, sizeof(struct xfs_bulkstat)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) return xfs_ibulk_advance(breq, sizeof(struct xfs_bulkstat));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) * Check the incoming bulk request @hdr from userspace and initialize the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) * internal @breq bulk request appropriately. Returns 0 if the bulk request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) * should proceed; -ECANCELED if there's nothing to do; or the usual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) xfs_bulk_ireq_setup(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) struct xfs_bulk_ireq *hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) struct xfs_ibulk *breq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) void __user *ubuffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (hdr->icount == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) (hdr->flags & ~XFS_BULK_IREQ_FLAGS_ALL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) breq->startino = hdr->ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) breq->ubuffer = ubuffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) breq->icount = hdr->icount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) breq->ocount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) breq->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * The @ino parameter is a special value, so we must look it up here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * We're not allowed to have IREQ_AGNO, and we only return one inode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * worth of data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (hdr->flags & XFS_BULK_IREQ_SPECIAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (hdr->flags & XFS_BULK_IREQ_AGNO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) switch (hdr->ino) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) case XFS_BULK_IREQ_SPECIAL_ROOT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) hdr->ino = mp->m_sb.sb_rootino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) breq->icount = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) * The IREQ_AGNO flag means that we only want results from a given AG.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) * If @hdr->ino is zero, we start iterating in that AG. If @hdr->ino is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) * beyond the specified AG then we return no results.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (hdr->flags & XFS_BULK_IREQ_AGNO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (hdr->agno >= mp->m_sb.sb_agcount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (breq->startino == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) breq->startino = XFS_AGINO_TO_INO(mp, hdr->agno, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) else if (XFS_INO_TO_AGNO(mp, breq->startino) < hdr->agno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) breq->flags |= XFS_IBULK_SAME_AG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) /* Asking for an inode past the end of the AG? We're done! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (XFS_INO_TO_AGNO(mp, breq->startino) > hdr->agno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) return -ECANCELED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) } else if (hdr->agno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) /* Asking for an inode past the end of the FS? We're done! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (XFS_INO_TO_AGNO(mp, breq->startino) >= mp->m_sb.sb_agcount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) return -ECANCELED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) * Update the userspace bulk request @hdr to reflect the end state of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * internal bulk request @breq.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) xfs_bulk_ireq_teardown(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) struct xfs_bulk_ireq *hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) struct xfs_ibulk *breq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) hdr->ino = breq->startino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) hdr->ocount = breq->ocount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) /* Handle the v5 bulkstat ioctl. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) xfs_ioc_bulkstat(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) struct xfs_bulkstat_req __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) struct xfs_bulk_ireq hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) struct xfs_ibulk breq = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) .mp = mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (XFS_FORCED_SHUTDOWN(mp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) error = xfs_bulk_ireq_setup(mp, &hdr, &breq, arg->bulkstat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (error == -ECANCELED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) goto out_teardown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (error < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) error = xfs_bulkstat(&breq, xfs_bulkstat_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) out_teardown:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) xfs_bulk_ireq_teardown(&hdr, &breq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) xfs_inumbers_fmt(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) struct xfs_ibulk *breq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) const struct xfs_inumbers *igrp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) if (copy_to_user(breq->ubuffer, igrp, sizeof(struct xfs_inumbers)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) return xfs_ibulk_advance(breq, sizeof(struct xfs_inumbers));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) /* Handle the v5 inumbers ioctl. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) xfs_ioc_inumbers(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) struct xfs_inumbers_req __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) struct xfs_bulk_ireq hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) struct xfs_ibulk breq = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) .mp = mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if (XFS_FORCED_SHUTDOWN(mp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) error = xfs_bulk_ireq_setup(mp, &hdr, &breq, arg->inumbers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (error == -ECANCELED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) goto out_teardown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (error < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) error = xfs_inumbers(&breq, xfs_inumbers_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) out_teardown:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) xfs_bulk_ireq_teardown(&hdr, &breq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) xfs_ioc_fsgeometry(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) void __user *arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) int struct_version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) struct xfs_fsop_geom fsgeo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) xfs_fs_geometry(&mp->m_sb, &fsgeo, struct_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) if (struct_version <= 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) len = sizeof(struct xfs_fsop_geom_v1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) else if (struct_version == 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) len = sizeof(struct xfs_fsop_geom_v4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) xfs_fsop_geom_health(mp, &fsgeo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) len = sizeof(fsgeo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (copy_to_user(arg, &fsgeo, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) xfs_ioc_ag_geometry(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) struct xfs_ag_geometry ageo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (copy_from_user(&ageo, arg, sizeof(ageo)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (ageo.ag_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (memchr_inv(&ageo.ag_reserved, 0, sizeof(ageo.ag_reserved)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) error = xfs_ag_get_geometry(mp, ageo.ag_number, &ageo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (copy_to_user(arg, &ageo, sizeof(ageo)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) * Linux extended inode flags interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) STATIC unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) xfs_merge_ioc_xflags(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) unsigned int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) unsigned int start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) unsigned int xflags = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (flags & FS_IMMUTABLE_FL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) xflags |= FS_XFLAG_IMMUTABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) xflags &= ~FS_XFLAG_IMMUTABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if (flags & FS_APPEND_FL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) xflags |= FS_XFLAG_APPEND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) xflags &= ~FS_XFLAG_APPEND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (flags & FS_SYNC_FL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) xflags |= FS_XFLAG_SYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) xflags &= ~FS_XFLAG_SYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (flags & FS_NOATIME_FL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) xflags |= FS_XFLAG_NOATIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) xflags &= ~FS_XFLAG_NOATIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (flags & FS_NODUMP_FL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) xflags |= FS_XFLAG_NODUMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) xflags &= ~FS_XFLAG_NODUMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) if (flags & FS_DAX_FL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) xflags |= FS_XFLAG_DAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) xflags &= ~FS_XFLAG_DAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) return xflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) STATIC unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) xfs_di2lxflags(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) uint16_t di_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) uint64_t di_flags2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) unsigned int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if (di_flags & XFS_DIFLAG_IMMUTABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) flags |= FS_IMMUTABLE_FL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (di_flags & XFS_DIFLAG_APPEND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) flags |= FS_APPEND_FL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (di_flags & XFS_DIFLAG_SYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) flags |= FS_SYNC_FL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if (di_flags & XFS_DIFLAG_NOATIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) flags |= FS_NOATIME_FL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (di_flags & XFS_DIFLAG_NODUMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) flags |= FS_NODUMP_FL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (di_flags2 & XFS_DIFLAG2_DAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) flags |= FS_DAX_FL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) return flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) xfs_fill_fsxattr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) struct xfs_inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) bool attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) struct fsxattr *fa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) struct xfs_ifork *ifp = attr ? ip->i_afp : &ip->i_df;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) simple_fill_fsxattr(fa, xfs_ip2xflags(ip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) fa->fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) fa->fsx_cowextsize = ip->i_d.di_cowextsize <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) ip->i_mount->m_sb.sb_blocklog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) fa->fsx_projid = ip->i_d.di_projid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) if (ifp && (ifp->if_flags & XFS_IFEXTENTS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) fa->fsx_nextents = xfs_iext_count(ifp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) fa->fsx_nextents = xfs_ifork_nextents(ifp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) xfs_ioc_fsgetxattr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) xfs_inode_t *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) int attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) struct fsxattr fa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) xfs_ilock(ip, XFS_ILOCK_SHARED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) xfs_fill_fsxattr(ip, attr, &fa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) xfs_iunlock(ip, XFS_ILOCK_SHARED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) if (copy_to_user(arg, &fa, sizeof(fa)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) STATIC uint16_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) xfs_flags2diflags(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) struct xfs_inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) unsigned int xflags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) /* can't set PREALLOC this way, just preserve it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) uint16_t di_flags =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) if (xflags & FS_XFLAG_IMMUTABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) di_flags |= XFS_DIFLAG_IMMUTABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) if (xflags & FS_XFLAG_APPEND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) di_flags |= XFS_DIFLAG_APPEND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) if (xflags & FS_XFLAG_SYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) di_flags |= XFS_DIFLAG_SYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (xflags & FS_XFLAG_NOATIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) di_flags |= XFS_DIFLAG_NOATIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) if (xflags & FS_XFLAG_NODUMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) di_flags |= XFS_DIFLAG_NODUMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if (xflags & FS_XFLAG_NODEFRAG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) di_flags |= XFS_DIFLAG_NODEFRAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if (xflags & FS_XFLAG_FILESTREAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) di_flags |= XFS_DIFLAG_FILESTREAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) if (S_ISDIR(VFS_I(ip)->i_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) if (xflags & FS_XFLAG_RTINHERIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) di_flags |= XFS_DIFLAG_RTINHERIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) if (xflags & FS_XFLAG_NOSYMLINKS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) di_flags |= XFS_DIFLAG_NOSYMLINKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) if (xflags & FS_XFLAG_EXTSZINHERIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) di_flags |= XFS_DIFLAG_EXTSZINHERIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (xflags & FS_XFLAG_PROJINHERIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) di_flags |= XFS_DIFLAG_PROJINHERIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) } else if (S_ISREG(VFS_I(ip)->i_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) if (xflags & FS_XFLAG_REALTIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) di_flags |= XFS_DIFLAG_REALTIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (xflags & FS_XFLAG_EXTSIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) di_flags |= XFS_DIFLAG_EXTSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) return di_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) STATIC uint64_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) xfs_flags2diflags2(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) struct xfs_inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) unsigned int xflags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) uint64_t di_flags2 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) (ip->i_d.di_flags2 & (XFS_DIFLAG2_REFLINK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) XFS_DIFLAG2_BIGTIME));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) if (xflags & FS_XFLAG_DAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) di_flags2 |= XFS_DIFLAG2_DAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (xflags & FS_XFLAG_COWEXTSIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) di_flags2 |= XFS_DIFLAG2_COWEXTSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) return di_flags2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) xfs_ioctl_setattr_xflags(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) struct xfs_inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) struct fsxattr *fa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) struct xfs_mount *mp = ip->i_mount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) uint64_t di_flags2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) /* Can't change realtime flag if any extents are allocated. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if ((ip->i_df.if_nextents || ip->i_delayed_blks) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) /* If realtime flag is set then must have realtime device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) if (fa->fsx_xflags & FS_XFLAG_REALTIME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) (ip->i_d.di_extsize % mp->m_sb.sb_rextsize))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) /* Clear reflink if we are actually able to set the rt flag. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) if ((fa->fsx_xflags & FS_XFLAG_REALTIME) && xfs_is_reflink_inode(ip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) /* Don't allow us to set DAX mode for a reflinked file for now. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) if ((fa->fsx_xflags & FS_XFLAG_DAX) && xfs_is_reflink_inode(ip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) /* diflags2 only valid for v3 inodes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) di_flags2 = xfs_flags2diflags2(ip, fa->fsx_xflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) if (di_flags2 && !xfs_sb_version_has_v3inode(&mp->m_sb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) ip->i_d.di_flags = xfs_flags2diflags(ip, fa->fsx_xflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) ip->i_d.di_flags2 = di_flags2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) xfs_diflags_to_iflags(ip, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) XFS_STATS_INC(mp, xs_ig_attrchg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) xfs_ioctl_setattr_prepare_dax(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) struct xfs_inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) struct fsxattr *fa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) struct xfs_mount *mp = ip->i_mount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) struct inode *inode = VFS_I(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if (S_ISDIR(inode->i_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if ((mp->m_flags & XFS_MOUNT_DAX_ALWAYS) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) (mp->m_flags & XFS_MOUNT_DAX_NEVER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) if (((fa->fsx_xflags & FS_XFLAG_DAX) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) !(ip->i_d.di_flags2 & XFS_DIFLAG2_DAX)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) (!(fa->fsx_xflags & FS_XFLAG_DAX) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) (ip->i_d.di_flags2 & XFS_DIFLAG2_DAX)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) d_mark_dontcache(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) * Set up the transaction structure for the setattr operation, checking that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) * have permission to do so. On success, return a clean transaction and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) * inode locked exclusively ready for further operation specific checks. On
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) * failure, return an error without modifying or locking the inode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) static struct xfs_trans *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) xfs_ioctl_setattr_get_trans(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) struct xfs_inode *ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) struct xfs_mount *mp = ip->i_mount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) struct xfs_trans *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) int error = -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) if (mp->m_flags & XFS_MOUNT_RDONLY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) error = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (XFS_FORCED_SHUTDOWN(mp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) xfs_ilock(ip, XFS_ILOCK_EXCL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) * CAP_FOWNER overrides the following restrictions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) * The user ID of the calling process must be equal to the file owner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) * ID, except in cases where the CAP_FSETID capability is applicable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) if (!inode_owner_or_capable(VFS_I(ip))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) goto out_cancel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) if (mp->m_flags & XFS_MOUNT_WSYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) xfs_trans_set_sync(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) return tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) out_cancel:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) xfs_trans_cancel(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) return ERR_PTR(error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) * extent size hint validation is somewhat cumbersome. Rules are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) * 1. extent size hint is only valid for directories and regular files
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) * 2. FS_XFLAG_EXTSIZE is only valid for regular files
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) * 3. FS_XFLAG_EXTSZINHERIT is only valid for directories.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) * 4. can only be changed on regular files if no extents are allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) * 5. can be changed on directories at any time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) * 6. extsize hint of 0 turns off hints, clears inode flags.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) * 7. Extent size must be a multiple of the appropriate block size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) * 8. for non-realtime files, the extent size hint must be limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) * to half the AG size to avoid alignment extending the extent beyond the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) * limits of the AG.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) * Please keep this function in sync with xfs_scrub_inode_extsize.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) xfs_ioctl_setattr_check_extsize(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) struct xfs_inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) struct fsxattr *fa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) struct xfs_mount *mp = ip->i_mount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) xfs_extlen_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) xfs_fsblock_t extsize_fsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_df.if_nextents &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != fa->fsx_extsize))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) if (fa->fsx_extsize == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) if (extsize_fsb > MAXEXTLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) if (XFS_IS_REALTIME_INODE(ip) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) (fa->fsx_xflags & FS_XFLAG_REALTIME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) size = mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) size = mp->m_sb.sb_blocksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) if (extsize_fsb > mp->m_sb.sb_agblocks / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) if (fa->fsx_extsize % size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) * CoW extent size hint validation rules are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) * 1. CoW extent size hint can only be set if reflink is enabled on the fs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) * The inode does not have to have any shared blocks, but it must be a v3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) * 2. FS_XFLAG_COWEXTSIZE is only valid for directories and regular files;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) * for a directory, the hint is propagated to new files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) * 3. Can be changed on files & directories at any time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) * 4. CoW extsize hint of 0 turns off hints, clears inode flags.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) * 5. Extent size must be a multiple of the appropriate block size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) * 6. The extent size hint must be limited to half the AG size to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) * alignment extending the extent beyond the limits of the AG.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) * Please keep this function in sync with xfs_scrub_inode_cowextsize.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) xfs_ioctl_setattr_check_cowextsize(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) struct xfs_inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) struct fsxattr *fa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) struct xfs_mount *mp = ip->i_mount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) xfs_extlen_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) xfs_fsblock_t cowextsize_fsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) if (!(fa->fsx_xflags & FS_XFLAG_COWEXTSIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) if (!xfs_sb_version_hasreflink(&ip->i_mount->m_sb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) if (fa->fsx_cowextsize == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) cowextsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_cowextsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) if (cowextsize_fsb > MAXEXTLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) size = mp->m_sb.sb_blocksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) if (cowextsize_fsb > mp->m_sb.sb_agblocks / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) if (fa->fsx_cowextsize % size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) xfs_ioctl_setattr_check_projid(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) struct xfs_inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) struct fsxattr *fa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) /* Disallow 32bit project ids if projid32bit feature is not enabled. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) if (fa->fsx_projid > (uint16_t)-1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) xfs_ioctl_setattr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) xfs_inode_t *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) struct fsxattr *fa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) struct fsxattr old_fa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) struct xfs_mount *mp = ip->i_mount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) struct xfs_trans *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) struct xfs_dquot *pdqp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) struct xfs_dquot *olddquot = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) int code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) trace_xfs_ioctl_setattr(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) code = xfs_ioctl_setattr_check_projid(ip, fa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) if (code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) return code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) * If disk quotas is on, we make sure that the dquots do exist on disk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) * before we start any other transactions. Trying to do this later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) * is messy. We don't care to take a readlock to look at the ids
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) * in inode here, because we can't hold it across the trans_reserve.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) * If the IDs do change before we take the ilock, we're covered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) * because the i_*dquot fields will get updated anyway.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) if (XFS_IS_QUOTA_ON(mp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) code = xfs_qm_vop_dqalloc(ip, VFS_I(ip)->i_uid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) VFS_I(ip)->i_gid, fa->fsx_projid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) XFS_QMOPT_PQUOTA, NULL, NULL, &pdqp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) if (code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) return code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) xfs_ioctl_setattr_prepare_dax(ip, fa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) tp = xfs_ioctl_setattr_get_trans(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) if (IS_ERR(tp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) code = PTR_ERR(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) goto error_free_dquots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) ip->i_d.di_projid != fa->fsx_projid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) code = xfs_qm_vop_chown_reserve(tp, ip, NULL, NULL, pdqp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) capable(CAP_FOWNER) ? XFS_QMOPT_FORCE_RES : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) if (code) /* out of quota */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) goto error_trans_cancel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) xfs_fill_fsxattr(ip, false, &old_fa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) code = vfs_ioc_fssetxattr_check(VFS_I(ip), &old_fa, fa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) if (code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) goto error_trans_cancel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) code = xfs_ioctl_setattr_check_extsize(ip, fa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) if (code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) goto error_trans_cancel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) code = xfs_ioctl_setattr_check_cowextsize(ip, fa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) if (code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) goto error_trans_cancel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) code = xfs_ioctl_setattr_xflags(tp, ip, fa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) if (code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) goto error_trans_cancel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) * Change file ownership. Must be the owner or privileged. CAP_FSETID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) * overrides the following restrictions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) * The set-user-ID and set-group-ID bits of a file will be cleared upon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) * successful return from chown()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) if ((VFS_I(ip)->i_mode & (S_ISUID|S_ISGID)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) !capable_wrt_inode_uidgid(VFS_I(ip), CAP_FSETID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) VFS_I(ip)->i_mode &= ~(S_ISUID|S_ISGID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) /* Change the ownerships and register project quota modifications */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) if (ip->i_d.di_projid != fa->fsx_projid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) olddquot = xfs_qm_vop_chown(tp, ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) &ip->i_pdquot, pdqp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) ip->i_d.di_projid = fa->fsx_projid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) * Only set the extent size hint if we've already determined that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) * extent size hint should be set on the inode. If no extent size flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) * are set on the inode then unconditionally clear the extent size hint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) if (ip->i_d.di_flags & (XFS_DIFLAG_EXTSIZE | XFS_DIFLAG_EXTSZINHERIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) ip->i_d.di_extsize = fa->fsx_extsize >> mp->m_sb.sb_blocklog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) ip->i_d.di_extsize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) if (xfs_sb_version_has_v3inode(&mp->m_sb) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) (ip->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) ip->i_d.di_cowextsize = fa->fsx_cowextsize >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) mp->m_sb.sb_blocklog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) ip->i_d.di_cowextsize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) code = xfs_trans_commit(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) * Release any dquot(s) the inode had kept before chown.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) xfs_qm_dqrele(olddquot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) xfs_qm_dqrele(pdqp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) return code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) error_trans_cancel:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) xfs_trans_cancel(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) error_free_dquots:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) xfs_qm_dqrele(pdqp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) return code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) xfs_ioc_fssetxattr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) xfs_inode_t *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) struct file *filp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) struct fsxattr fa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) if (copy_from_user(&fa, arg, sizeof(fa)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) error = mnt_want_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) error = xfs_ioctl_setattr(ip, &fa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) mnt_drop_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) xfs_ioc_getxflags(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) xfs_inode_t *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) unsigned int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) flags = xfs_di2lxflags(ip->i_d.di_flags, ip->i_d.di_flags2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) if (copy_to_user(arg, &flags, sizeof(flags)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) xfs_ioc_setxflags(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) struct xfs_inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) struct file *filp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) struct xfs_trans *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) struct fsxattr fa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) struct fsxattr old_fa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) unsigned int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) if (copy_from_user(&flags, arg, sizeof(flags)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) FS_NOATIME_FL | FS_NODUMP_FL | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) FS_SYNC_FL | FS_DAX_FL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) error = mnt_want_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) xfs_ioctl_setattr_prepare_dax(ip, &fa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) tp = xfs_ioctl_setattr_get_trans(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) if (IS_ERR(tp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) error = PTR_ERR(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) goto out_drop_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) xfs_fill_fsxattr(ip, false, &old_fa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) error = vfs_ioc_fssetxattr_check(VFS_I(ip), &old_fa, &fa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) xfs_trans_cancel(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) goto out_drop_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) error = xfs_ioctl_setattr_xflags(tp, ip, &fa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) xfs_trans_cancel(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) goto out_drop_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) error = xfs_trans_commit(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) out_drop_write:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) mnt_drop_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) xfs_getbmap_format(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) struct kgetbmap *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) struct getbmapx __user *u,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) size_t recsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) if (put_user(p->bmv_offset, &u->bmv_offset) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) put_user(p->bmv_block, &u->bmv_block) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) put_user(p->bmv_length, &u->bmv_length) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) put_user(0, &u->bmv_count) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) put_user(0, &u->bmv_entries))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) if (recsize < sizeof(struct getbmapx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) if (put_user(0, &u->bmv_iflags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) put_user(p->bmv_oflags, &u->bmv_oflags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) put_user(0, &u->bmv_unused1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) put_user(0, &u->bmv_unused2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) xfs_ioc_getbmap(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) struct getbmapx bmx = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) struct kgetbmap *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) size_t recsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) int error, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) case XFS_IOC_GETBMAPA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) bmx.bmv_iflags = BMV_IF_ATTRFORK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) /*FALLTHRU*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) case XFS_IOC_GETBMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) if (file->f_mode & FMODE_NOCMTIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) bmx.bmv_iflags |= BMV_IF_NO_DMAPI_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) /* struct getbmap is a strict subset of struct getbmapx. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) recsize = sizeof(struct getbmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) case XFS_IOC_GETBMAPX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) recsize = sizeof(struct getbmapx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) if (copy_from_user(&bmx, arg, recsize))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) if (bmx.bmv_count < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) if (bmx.bmv_count > ULONG_MAX / recsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) buf = kvzalloc(bmx.bmv_count * sizeof(*buf), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) error = xfs_getbmap(XFS_I(file_inode(file)), &bmx, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) if (copy_to_user(arg, &bmx, recsize))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) arg += recsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) for (i = 0; i < bmx.bmv_entries; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) if (!xfs_getbmap_format(buf + i, arg, recsize))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) arg += recsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) out_free_buf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) kmem_free(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) xfs_ioc_getfsmap(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) struct xfs_inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) struct fsmap_head __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) struct xfs_fsmap_head xhead = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) struct fsmap_head head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) struct fsmap *recs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) unsigned int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) __u32 last_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) bool done = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) if (copy_from_user(&head, arg, sizeof(struct fsmap_head)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) if (memchr_inv(head.fmh_reserved, 0, sizeof(head.fmh_reserved)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) memchr_inv(head.fmh_keys[0].fmr_reserved, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) sizeof(head.fmh_keys[0].fmr_reserved)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) memchr_inv(head.fmh_keys[1].fmr_reserved, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) sizeof(head.fmh_keys[1].fmr_reserved)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) * Use an internal memory buffer so that we don't have to copy fsmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) * data to userspace while holding locks. Start by trying to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) * up to 128k for the buffer, but fall back to a single page if needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) count = min_t(unsigned int, head.fmh_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) 131072 / sizeof(struct fsmap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) recs = kvzalloc(count * sizeof(struct fsmap), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) if (!recs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) count = min_t(unsigned int, head.fmh_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) PAGE_SIZE / sizeof(struct fsmap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) recs = kvzalloc(count * sizeof(struct fsmap), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) if (!recs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) xhead.fmh_iflags = head.fmh_iflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) xfs_fsmap_to_internal(&xhead.fmh_keys[0], &head.fmh_keys[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) xfs_fsmap_to_internal(&xhead.fmh_keys[1], &head.fmh_keys[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) trace_xfs_getfsmap_low_key(ip->i_mount, &xhead.fmh_keys[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) trace_xfs_getfsmap_high_key(ip->i_mount, &xhead.fmh_keys[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) head.fmh_entries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) struct fsmap __user *user_recs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) struct fsmap *last_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) user_recs = &arg->fmh_recs[head.fmh_entries];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) xhead.fmh_entries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) xhead.fmh_count = min_t(unsigned int, count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) head.fmh_count - head.fmh_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) /* Run query, record how many entries we got. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) error = xfs_getfsmap(ip->i_mount, &xhead, recs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) switch (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) * There are no more records in the result set. Copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) * whatever we got to userspace and break out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) done = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) case -ECANCELED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) * The internal memory buffer is full. Copy whatever
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) * records we got to userspace and go again if we have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) * not yet filled the userspace buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) head.fmh_entries += xhead.fmh_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) head.fmh_oflags = xhead.fmh_oflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) * If the caller wanted a record count or there aren't any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) * new records to return, we're done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) if (head.fmh_count == 0 || xhead.fmh_entries == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) /* Copy all the records we got out to userspace. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) if (copy_to_user(user_recs, recs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) xhead.fmh_entries * sizeof(struct fsmap))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) /* Remember the last record flags we copied to userspace. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) last_rec = &recs[xhead.fmh_entries - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) last_flags = last_rec->fmr_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) /* Set up the low key for the next iteration. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) xfs_fsmap_to_internal(&xhead.fmh_keys[0], last_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) trace_xfs_getfsmap_low_key(ip->i_mount, &xhead.fmh_keys[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) } while (!done && head.fmh_entries < head.fmh_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) * If there are no more records in the query result set and we're not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) * in counting mode, mark the last record returned with the LAST flag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) if (done && head.fmh_count > 0 && head.fmh_entries > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) struct fsmap __user *user_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) last_flags |= FMR_OF_LAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) user_rec = &arg->fmh_recs[head.fmh_entries - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) if (copy_to_user(&user_rec->fmr_flags, &last_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) sizeof(last_flags))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) /* copy back header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) if (copy_to_user(arg, &head, sizeof(struct fsmap_head))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) kmem_free(recs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) xfs_ioc_scrub_metadata(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) struct xfs_inode *ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) struct xfs_scrub_metadata scrub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) if (copy_from_user(&scrub, arg, sizeof(scrub)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) error = xfs_scrub_metadata(ip, &scrub);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) if (copy_to_user(arg, &scrub, sizeof(scrub)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) xfs_ioc_swapext(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) xfs_swapext_t *sxp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) xfs_inode_t *ip, *tip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) struct fd f, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) /* Pull information for the target fd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) f = fdget((int)sxp->sx_fdtarget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) if (!f.file) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) if (!(f.file->f_mode & FMODE_WRITE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) !(f.file->f_mode & FMODE_READ) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) (f.file->f_flags & O_APPEND)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) error = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) goto out_put_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) tmp = fdget((int)sxp->sx_fdtmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) if (!tmp.file) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) goto out_put_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) if (!(tmp.file->f_mode & FMODE_WRITE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) !(tmp.file->f_mode & FMODE_READ) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) (tmp.file->f_flags & O_APPEND)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) error = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) goto out_put_tmp_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) if (IS_SWAPFILE(file_inode(f.file)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) IS_SWAPFILE(file_inode(tmp.file))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) goto out_put_tmp_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) * We need to ensure that the fds passed in point to XFS inodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) * before we cast and access them as XFS structures as we have no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) * control over what the user passes us here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) if (f.file->f_op != &xfs_file_operations ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) tmp.file->f_op != &xfs_file_operations) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) goto out_put_tmp_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) ip = XFS_I(file_inode(f.file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) tip = XFS_I(file_inode(tmp.file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) if (ip->i_mount != tip->i_mount) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) goto out_put_tmp_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) if (ip->i_ino == tip->i_ino) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) goto out_put_tmp_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) error = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) goto out_put_tmp_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) error = xfs_swap_extents(ip, tip, sxp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) out_put_tmp_file:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) fdput(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) out_put_file:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) fdput(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) xfs_ioc_getlabel(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) char __user *user_label)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) struct xfs_sb *sbp = &mp->m_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) char label[XFSLABEL_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) /* Paranoia */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) BUILD_BUG_ON(sizeof(sbp->sb_fname) > FSLABEL_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) /* 1 larger than sb_fname, so this ensures a trailing NUL char */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) memset(label, 0, sizeof(label));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) spin_lock(&mp->m_sb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) strncpy(label, sbp->sb_fname, XFSLABEL_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) spin_unlock(&mp->m_sb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) if (copy_to_user(user_label, label, sizeof(label)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) xfs_ioc_setlabel(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) struct file *filp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) char __user *newlabel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) struct xfs_sb *sbp = &mp->m_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) char label[XFSLABEL_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) * The generic ioctl allows up to FSLABEL_MAX chars, but XFS is much
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) * smaller, at 12 bytes. We copy one more to be sure we find the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) * (required) NULL character to test the incoming label length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) * NB: The on disk label doesn't need to be null terminated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) if (copy_from_user(label, newlabel, XFSLABEL_MAX + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) len = strnlen(label, XFSLABEL_MAX + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) if (len > sizeof(sbp->sb_fname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) error = mnt_want_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) spin_lock(&mp->m_sb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) memset(sbp->sb_fname, 0, sizeof(sbp->sb_fname));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) memcpy(sbp->sb_fname, label, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) spin_unlock(&mp->m_sb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) * Now we do several things to satisfy userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) * In addition to normal logging of the primary superblock, we also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) * immediately write these changes to sector zero for the primary, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) * update all backup supers (as xfs_db does for a label change), then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) * invalidate the block device page cache. This is so that any prior
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) * buffered reads from userspace (i.e. from blkid) are invalidated,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) * and userspace will see the newly-written label.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) error = xfs_sync_sb_buf(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) * growfs also updates backup supers so lock against that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) mutex_lock(&mp->m_growlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) error = xfs_update_secondary_sbs(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) mutex_unlock(&mp->m_growlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) invalidate_bdev(mp->m_ddev_targp->bt_bdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) mnt_drop_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) xfs_fs_eofblocks_from_user(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) struct xfs_fs_eofblocks *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) struct xfs_eofblocks *dst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) if (src->eof_version != XFS_EOFBLOCKS_VERSION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) if (src->eof_flags & ~XFS_EOF_FLAGS_VALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) if (memchr_inv(&src->pad32, 0, sizeof(src->pad32)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) memchr_inv(src->pad64, 0, sizeof(src->pad64)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) dst->eof_flags = src->eof_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) dst->eof_prid = src->eof_prid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) dst->eof_min_file_size = src->eof_min_file_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) dst->eof_uid = INVALID_UID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) if (src->eof_flags & XFS_EOF_FLAGS_UID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) dst->eof_uid = make_kuid(current_user_ns(), src->eof_uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) if (!uid_valid(dst->eof_uid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) dst->eof_gid = INVALID_GID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) if (src->eof_flags & XFS_EOF_FLAGS_GID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) dst->eof_gid = make_kgid(current_user_ns(), src->eof_gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) if (!gid_valid(dst->eof_gid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) * Note: some of the ioctl's return positive numbers as a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) * byte count indicating success, such as readlink_by_handle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) * So we don't "sign flip" like most other routines. This means
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) * true errors need to be returned as a negative value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) xfs_file_ioctl(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) struct file *filp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) unsigned long p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) struct inode *inode = file_inode(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) struct xfs_inode *ip = XFS_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) struct xfs_mount *mp = ip->i_mount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) void __user *arg = (void __user *)p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) trace_xfs_file_ioctl(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) case FITRIM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) return xfs_ioc_trim(mp, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) case FS_IOC_GETFSLABEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) return xfs_ioc_getlabel(mp, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) case FS_IOC_SETFSLABEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) return xfs_ioc_setlabel(filp, mp, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) case XFS_IOC_ALLOCSP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) case XFS_IOC_FREESP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) case XFS_IOC_ALLOCSP64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) case XFS_IOC_FREESP64: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) xfs_flock64_t bf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) if (copy_from_user(&bf, arg, sizeof(bf)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) return xfs_ioc_space(filp, &bf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) case XFS_IOC_DIOINFO: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) struct xfs_buftarg *target = xfs_inode_buftarg(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) struct dioattr da;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) da.d_mem = da.d_miniosz = target->bt_logical_sectorsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) if (copy_to_user(arg, &da, sizeof(da)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) case XFS_IOC_FSBULKSTAT_SINGLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) case XFS_IOC_FSBULKSTAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) case XFS_IOC_FSINUMBERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) return xfs_ioc_fsbulkstat(mp, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) case XFS_IOC_BULKSTAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) return xfs_ioc_bulkstat(mp, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) case XFS_IOC_INUMBERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) return xfs_ioc_inumbers(mp, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) case XFS_IOC_FSGEOMETRY_V1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) return xfs_ioc_fsgeometry(mp, arg, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) case XFS_IOC_FSGEOMETRY_V4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) return xfs_ioc_fsgeometry(mp, arg, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) case XFS_IOC_FSGEOMETRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) return xfs_ioc_fsgeometry(mp, arg, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) case XFS_IOC_AG_GEOMETRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) return xfs_ioc_ag_geometry(mp, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) case XFS_IOC_GETVERSION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) return put_user(inode->i_generation, (int __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) case XFS_IOC_FSGETXATTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) return xfs_ioc_fsgetxattr(ip, 0, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) case XFS_IOC_FSGETXATTRA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) return xfs_ioc_fsgetxattr(ip, 1, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) case XFS_IOC_FSSETXATTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) return xfs_ioc_fssetxattr(ip, filp, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) case XFS_IOC_GETXFLAGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) return xfs_ioc_getxflags(ip, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) case XFS_IOC_SETXFLAGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) return xfs_ioc_setxflags(ip, filp, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) case XFS_IOC_GETBMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) case XFS_IOC_GETBMAPA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) case XFS_IOC_GETBMAPX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) return xfs_ioc_getbmap(filp, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) case FS_IOC_GETFSMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) return xfs_ioc_getfsmap(ip, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) case XFS_IOC_SCRUB_METADATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) return xfs_ioc_scrub_metadata(ip, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) case XFS_IOC_FD_TO_HANDLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) case XFS_IOC_PATH_TO_HANDLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) case XFS_IOC_PATH_TO_FSHANDLE: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) xfs_fsop_handlereq_t hreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) if (copy_from_user(&hreq, arg, sizeof(hreq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) return xfs_find_handle(cmd, &hreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) case XFS_IOC_OPEN_BY_HANDLE: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) xfs_fsop_handlereq_t hreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) return xfs_open_by_handle(filp, &hreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) case XFS_IOC_READLINK_BY_HANDLE: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) xfs_fsop_handlereq_t hreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) return xfs_readlink_by_handle(filp, &hreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) case XFS_IOC_ATTRLIST_BY_HANDLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) return xfs_attrlist_by_handle(filp, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) case XFS_IOC_ATTRMULTI_BY_HANDLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) return xfs_attrmulti_by_handle(filp, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) case XFS_IOC_SWAPEXT: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) struct xfs_swapext sxp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) error = mnt_want_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) error = xfs_ioc_swapext(&sxp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) mnt_drop_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) case XFS_IOC_FSCOUNTS: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) xfs_fsop_counts_t out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) xfs_fs_counts(mp, &out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) if (copy_to_user(arg, &out, sizeof(out)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) case XFS_IOC_SET_RESBLKS: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) xfs_fsop_resblks_t inout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) uint64_t in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) if (mp->m_flags & XFS_MOUNT_RDONLY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) return -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) if (copy_from_user(&inout, arg, sizeof(inout)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) error = mnt_want_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) /* input parameter is passed in resblks field of structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) in = inout.resblks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) error = xfs_reserve_blocks(mp, &in, &inout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) mnt_drop_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) if (copy_to_user(arg, &inout, sizeof(inout)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) case XFS_IOC_GET_RESBLKS: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) xfs_fsop_resblks_t out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) error = xfs_reserve_blocks(mp, NULL, &out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) if (copy_to_user(arg, &out, sizeof(out)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) case XFS_IOC_FSGROWFSDATA: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) xfs_growfs_data_t in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) if (copy_from_user(&in, arg, sizeof(in)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) error = mnt_want_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) error = xfs_growfs_data(mp, &in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) mnt_drop_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) case XFS_IOC_FSGROWFSLOG: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) xfs_growfs_log_t in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) if (copy_from_user(&in, arg, sizeof(in)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) error = mnt_want_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) error = xfs_growfs_log(mp, &in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) mnt_drop_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) case XFS_IOC_FSGROWFSRT: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) xfs_growfs_rt_t in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) if (copy_from_user(&in, arg, sizeof(in)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) error = mnt_want_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) error = xfs_growfs_rt(mp, &in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) mnt_drop_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) case XFS_IOC_GOINGDOWN: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) uint32_t in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) if (get_user(in, (uint32_t __user *)arg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) return xfs_fs_goingdown(mp, in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) case XFS_IOC_ERROR_INJECTION: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) xfs_error_injection_t in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) if (copy_from_user(&in, arg, sizeof(in)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) return xfs_errortag_add(mp, in.errtag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) case XFS_IOC_ERROR_CLEARALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) return xfs_errortag_clearall(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) case XFS_IOC_FREE_EOFBLOCKS: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) struct xfs_fs_eofblocks eofb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) struct xfs_eofblocks keofb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) if (mp->m_flags & XFS_MOUNT_RDONLY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) return -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) if (copy_from_user(&eofb, arg, sizeof(eofb)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) error = xfs_fs_eofblocks_from_user(&eofb, &keofb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) sb_start_write(mp->m_super);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) error = xfs_icache_free_eofblocks(mp, &keofb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) sb_end_write(mp->m_super);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) }