^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) * linux/fs/ocfs2/ioctl.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2006 Herbert Poetzl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * adapted from Remy Card's ext2/ioctl.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <cluster/masklog.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "ocfs2.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "alloc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "dlmglue.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "file.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "inode.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "journal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "ocfs2_fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "ioctl.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "resize.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "refcounttree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "sysfile.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "dir.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "buffer_head_io.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "suballoc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "move_extents.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define o2info_from_user(a, b) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) copy_from_user(&(a), (b), sizeof(a))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define o2info_to_user(a, b) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) copy_to_user((typeof(a) __user *)b, &(a), sizeof(a))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * This is just a best-effort to tell userspace that this request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * caused the error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static inline void o2info_set_request_error(struct ocfs2_info_request *kreq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct ocfs2_info_request __user *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) kreq->ir_flags |= OCFS2_INFO_FL_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) (void)put_user(kreq->ir_flags, (__u32 __user *)&(req->ir_flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static inline void o2info_set_request_filled(struct ocfs2_info_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) req->ir_flags |= OCFS2_INFO_FL_FILLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static inline void o2info_clear_request_filled(struct ocfs2_info_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) req->ir_flags &= ~OCFS2_INFO_FL_FILLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static inline int o2info_coherent(struct ocfs2_info_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return (!(req->ir_flags & OCFS2_INFO_FL_NON_COHERENT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) status = ocfs2_inode_lock(inode, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) mlog_errno(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) ocfs2_get_inode_flags(OCFS2_I(inode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) *flags = OCFS2_I(inode)->ip_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ocfs2_inode_unlock(inode, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct ocfs2_inode_info *ocfs2_inode = OCFS2_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) handle_t *handle = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct buffer_head *bh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) unsigned oldflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) inode_lock(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) status = ocfs2_inode_lock(inode, &bh, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) mlog_errno(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) status = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (!inode_owner_or_capable(inode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) goto bail_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (!S_ISDIR(inode->i_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) flags &= ~OCFS2_DIRSYNC_FL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) oldflags = ocfs2_inode->ip_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) flags = flags & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) flags |= oldflags & ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) status = vfs_ioc_setflags_prepare(inode, oldflags, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) goto bail_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (IS_ERR(handle)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) status = PTR_ERR(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) mlog_errno(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) goto bail_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ocfs2_inode->ip_attr = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) ocfs2_set_inode_flags(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) status = ocfs2_mark_inode_dirty(handle, inode, bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) mlog_errno(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ocfs2_commit_trans(osb, handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) bail_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ocfs2_inode_unlock(inode, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) bail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) inode_unlock(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static int ocfs2_info_handle_blocksize(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct ocfs2_info_request __user *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct ocfs2_info_blocksize oib;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (o2info_from_user(oib, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) oib.ib_blocksize = inode->i_sb->s_blocksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) o2info_set_request_filled(&oib.ib_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (o2info_to_user(oib, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static int ocfs2_info_handle_clustersize(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct ocfs2_info_request __user *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct ocfs2_info_clustersize oic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (o2info_from_user(oic, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) oic.ic_clustersize = osb->s_clustersize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) o2info_set_request_filled(&oic.ic_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (o2info_to_user(oic, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static int ocfs2_info_handle_maxslots(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct ocfs2_info_request __user *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct ocfs2_info_maxslots oim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (o2info_from_user(oim, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) oim.im_max_slots = osb->max_slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) o2info_set_request_filled(&oim.im_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (o2info_to_user(oim, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static int ocfs2_info_handle_label(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct ocfs2_info_request __user *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct ocfs2_info_label oil;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (o2info_from_user(oil, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) memcpy(oil.il_label, osb->vol_label, OCFS2_MAX_VOL_LABEL_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) o2info_set_request_filled(&oil.il_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (o2info_to_user(oil, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static int ocfs2_info_handle_uuid(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct ocfs2_info_request __user *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct ocfs2_info_uuid oiu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (o2info_from_user(oiu, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) memcpy(oiu.iu_uuid_str, osb->uuid_str, OCFS2_TEXT_UUID_LEN + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) o2info_set_request_filled(&oiu.iu_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (o2info_to_user(oiu, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static int ocfs2_info_handle_fs_features(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct ocfs2_info_request __user *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct ocfs2_info_fs_features oif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (o2info_from_user(oif, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) oif.if_compat_features = osb->s_feature_compat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) oif.if_incompat_features = osb->s_feature_incompat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) oif.if_ro_compat_features = osb->s_feature_ro_compat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) o2info_set_request_filled(&oif.if_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (o2info_to_user(oif, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static int ocfs2_info_handle_journal_size(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct ocfs2_info_request __user *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) struct ocfs2_info_journal_size oij;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (o2info_from_user(oij, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) oij.ij_journal_size = i_size_read(osb->journal->j_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) o2info_set_request_filled(&oij.ij_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (o2info_to_user(oij, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static int ocfs2_info_scan_inode_alloc(struct ocfs2_super *osb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct inode *inode_alloc, u64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct ocfs2_info_freeinode *fi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) u32 slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) int status = 0, unlock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct buffer_head *bh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct ocfs2_dinode *dinode_alloc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (inode_alloc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) inode_lock(inode_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (inode_alloc && o2info_coherent(&fi->ifi_req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) status = ocfs2_inode_lock(inode_alloc, &bh, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) mlog_errno(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) unlock = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) status = ocfs2_read_blocks_sync(osb, blkno, 1, &bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) mlog_errno(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) dinode_alloc = (struct ocfs2_dinode *)bh->b_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) fi->ifi_stat[slot].lfi_total =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) le32_to_cpu(dinode_alloc->id1.bitmap1.i_total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) fi->ifi_stat[slot].lfi_free =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) le32_to_cpu(dinode_alloc->id1.bitmap1.i_total) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) le32_to_cpu(dinode_alloc->id1.bitmap1.i_used);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) bail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (unlock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) ocfs2_inode_unlock(inode_alloc, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (inode_alloc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) inode_unlock(inode_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return status;
^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) static int ocfs2_info_handle_freeinode(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct ocfs2_info_request __user *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) u64 blkno = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) char namebuf[40];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) int status, type = INODE_ALLOC_SYSTEM_INODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct ocfs2_info_freeinode *oifi = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) struct inode *inode_alloc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) oifi = kzalloc(sizeof(struct ocfs2_info_freeinode), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (!oifi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) status = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) mlog_errno(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) goto out_err;
^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) if (o2info_from_user(*oifi, req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) status = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) oifi->ifi_slotnum = osb->max_slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) for (i = 0; i < oifi->ifi_slotnum; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (o2info_coherent(&oifi->ifi_req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) inode_alloc = ocfs2_get_system_file_inode(osb, type, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (!inode_alloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) mlog(ML_ERROR, "unable to get alloc inode in "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) "slot %u\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) status = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) ocfs2_sprintf_system_inode_name(namebuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) sizeof(namebuf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) type, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) status = ocfs2_lookup_ino_from_name(osb->sys_root_inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) namebuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) strlen(namebuf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) &blkno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) status = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) status = ocfs2_info_scan_inode_alloc(osb, inode_alloc, blkno, oifi, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) iput(inode_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) inode_alloc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) o2info_set_request_filled(&oifi->ifi_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (o2info_to_user(*oifi, req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) status = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) bail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) o2info_set_request_error(&oifi->ifi_req, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) kfree(oifi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static void o2ffg_update_histogram(struct ocfs2_info_free_chunk_list *hist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) unsigned int chunksize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) u32 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) index = __ilog2_u32(chunksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (index >= OCFS2_INFO_MAX_HIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) index = OCFS2_INFO_MAX_HIST - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) hist->fc_chunks[index]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) hist->fc_clusters[index] += chunksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static void o2ffg_update_stats(struct ocfs2_info_freefrag_stats *stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) unsigned int chunksize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (chunksize > stats->ffs_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) stats->ffs_max = chunksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (chunksize < stats->ffs_min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) stats->ffs_min = chunksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) stats->ffs_avg += chunksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) stats->ffs_free_chunks_real++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static void ocfs2_info_update_ffg(struct ocfs2_info_freefrag *ffg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) unsigned int chunksize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) o2ffg_update_histogram(&(ffg->iff_ffs.ffs_fc_hist), chunksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) o2ffg_update_stats(&(ffg->iff_ffs), chunksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static int ocfs2_info_freefrag_scan_chain(struct ocfs2_super *osb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct inode *gb_inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) struct ocfs2_dinode *gb_dinode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) struct ocfs2_chain_rec *rec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct ocfs2_info_freefrag *ffg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) u32 chunks_in_group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) int status = 0, used;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) u64 blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) struct buffer_head *bh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) struct ocfs2_group_desc *bg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) unsigned int max_bits, num_clusters;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) unsigned int offset = 0, cluster, chunk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) unsigned int chunk_free, last_chunksize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (!le32_to_cpu(rec->c_free))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (!bg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) blkno = le64_to_cpu(rec->c_blkno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) blkno = le64_to_cpu(bg->bg_next_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (bh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) bh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (o2info_coherent(&ffg->iff_req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) status = ocfs2_read_group_descriptor(gb_inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) gb_dinode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) blkno, &bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) status = ocfs2_read_blocks_sync(osb, blkno, 1, &bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) mlog(ML_ERROR, "Can't read the group descriptor # "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) "%llu from device.", (unsigned long long)blkno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) status = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) bg = (struct ocfs2_group_desc *)bh->b_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (!le16_to_cpu(bg->bg_free_bits_count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) max_bits = le16_to_cpu(bg->bg_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) for (chunk = 0; chunk < chunks_in_group; chunk++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * last chunk may be not an entire one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if ((offset + ffg->iff_chunksize) > max_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) num_clusters = max_bits - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) num_clusters = ffg->iff_chunksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) chunk_free = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) for (cluster = 0; cluster < num_clusters; cluster++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) used = ocfs2_test_bit(offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) (unsigned long *)bg->bg_bitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * - chunk_free counts free clusters in #N chunk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * - last_chunksize records the size(in) clusters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * for the last real free chunk being counted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (!used) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) last_chunksize++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) chunk_free++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (used && last_chunksize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) ocfs2_info_update_ffg(ffg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) last_chunksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) last_chunksize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) offset++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (chunk_free == ffg->iff_chunksize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) ffg->iff_ffs.ffs_free_chunks++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) * need to update the info for last free chunk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (last_chunksize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) ocfs2_info_update_ffg(ffg, last_chunksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) } while (le64_to_cpu(bg->bg_next_group));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) bail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) static int ocfs2_info_freefrag_scan_bitmap(struct ocfs2_super *osb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) struct inode *gb_inode, u64 blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) struct ocfs2_info_freefrag *ffg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) u32 chunks_in_group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int status = 0, unlock = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct buffer_head *bh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) struct ocfs2_chain_list *cl = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) struct ocfs2_chain_rec *rec = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) struct ocfs2_dinode *gb_dinode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (gb_inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) inode_lock(gb_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (o2info_coherent(&ffg->iff_req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) status = ocfs2_inode_lock(gb_inode, &bh, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) mlog_errno(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) unlock = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) status = ocfs2_read_blocks_sync(osb, blkno, 1, &bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) mlog_errno(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) gb_dinode = (struct ocfs2_dinode *)bh->b_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) cl = &(gb_dinode->id2.i_chain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) * Chunksize(in) clusters from userspace should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * less than clusters in a group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (ffg->iff_chunksize > le16_to_cpu(cl->cl_cpg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) status = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) goto bail;
^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) memset(&ffg->iff_ffs, 0, sizeof(struct ocfs2_info_freefrag_stats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) ffg->iff_ffs.ffs_min = ~0U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) ffg->iff_ffs.ffs_clusters =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) le32_to_cpu(gb_dinode->id1.bitmap1.i_total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) ffg->iff_ffs.ffs_free_clusters = ffg->iff_ffs.ffs_clusters -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) le32_to_cpu(gb_dinode->id1.bitmap1.i_used);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) chunks_in_group = le16_to_cpu(cl->cl_cpg) / ffg->iff_chunksize + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) for (i = 0; i < le16_to_cpu(cl->cl_next_free_rec); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) rec = &(cl->cl_recs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) status = ocfs2_info_freefrag_scan_chain(osb, gb_inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) gb_dinode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) rec, ffg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) chunks_in_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (ffg->iff_ffs.ffs_free_chunks_real)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) ffg->iff_ffs.ffs_avg = (ffg->iff_ffs.ffs_avg /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) ffg->iff_ffs.ffs_free_chunks_real);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) bail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (unlock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) ocfs2_inode_unlock(gb_inode, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (gb_inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) inode_unlock(gb_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) iput(gb_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static int ocfs2_info_handle_freefrag(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) struct ocfs2_info_request __user *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) u64 blkno = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) char namebuf[40];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) int status, type = GLOBAL_BITMAP_SYSTEM_INODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) struct ocfs2_info_freefrag *oiff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) struct inode *gb_inode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) oiff = kzalloc(sizeof(struct ocfs2_info_freefrag), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (!oiff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) status = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) mlog_errno(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (o2info_from_user(*oiff, req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) status = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) * chunksize from userspace should be power of 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if ((oiff->iff_chunksize & (oiff->iff_chunksize - 1)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) (!oiff->iff_chunksize)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) status = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (o2info_coherent(&oiff->iff_req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) gb_inode = ocfs2_get_system_file_inode(osb, type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) OCFS2_INVALID_SLOT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (!gb_inode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) mlog(ML_ERROR, "unable to get global_bitmap inode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) status = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ocfs2_sprintf_system_inode_name(namebuf, sizeof(namebuf), type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) OCFS2_INVALID_SLOT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) status = ocfs2_lookup_ino_from_name(osb->sys_root_inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) namebuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) strlen(namebuf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) &blkno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) status = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) status = ocfs2_info_freefrag_scan_bitmap(osb, gb_inode, blkno, oiff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) o2info_set_request_filled(&oiff->iff_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (o2info_to_user(*oiff, req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) status = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) bail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) o2info_set_request_error(&oiff->iff_req, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) kfree(oiff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) return status;
^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) static int ocfs2_info_handle_unknown(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) struct ocfs2_info_request __user *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) struct ocfs2_info_request oir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (o2info_from_user(oir, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) o2info_clear_request_filled(&oir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (o2info_to_user(oir, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * Validate and distinguish OCFS2_IOC_INFO requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * - validate the magic number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * - distinguish different requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) * - validate size of different requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) static int ocfs2_info_handle_request(struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) struct ocfs2_info_request __user *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) int status = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) struct ocfs2_info_request oir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (o2info_from_user(oir, req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) status = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (oir.ir_magic != OCFS2_INFO_MAGIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) switch (oir.ir_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) case OCFS2_INFO_BLOCKSIZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (oir.ir_size == sizeof(struct ocfs2_info_blocksize))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) status = ocfs2_info_handle_blocksize(inode, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) case OCFS2_INFO_CLUSTERSIZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (oir.ir_size == sizeof(struct ocfs2_info_clustersize))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) status = ocfs2_info_handle_clustersize(inode, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) case OCFS2_INFO_MAXSLOTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (oir.ir_size == sizeof(struct ocfs2_info_maxslots))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) status = ocfs2_info_handle_maxslots(inode, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) case OCFS2_INFO_LABEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (oir.ir_size == sizeof(struct ocfs2_info_label))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) status = ocfs2_info_handle_label(inode, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) case OCFS2_INFO_UUID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (oir.ir_size == sizeof(struct ocfs2_info_uuid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) status = ocfs2_info_handle_uuid(inode, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) case OCFS2_INFO_FS_FEATURES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (oir.ir_size == sizeof(struct ocfs2_info_fs_features))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) status = ocfs2_info_handle_fs_features(inode, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) case OCFS2_INFO_JOURNAL_SIZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (oir.ir_size == sizeof(struct ocfs2_info_journal_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) status = ocfs2_info_handle_journal_size(inode, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) case OCFS2_INFO_FREEINODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (oir.ir_size == sizeof(struct ocfs2_info_freeinode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) status = ocfs2_info_handle_freeinode(inode, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) case OCFS2_INFO_FREEFRAG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (oir.ir_size == sizeof(struct ocfs2_info_freefrag))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) status = ocfs2_info_handle_freefrag(inode, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) status = ocfs2_info_handle_unknown(inode, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) bail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) static int ocfs2_get_request_ptr(struct ocfs2_info *info, int idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) u64 *req_addr, int compat_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) int status = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) u64 __user *bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (compat_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) * pointer bp stores the base address of a pointers array,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) * which collects all addresses of separate request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) bp = (u64 __user *)(unsigned long)compat_ptr(info->oi_requests);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) bp = (u64 __user *)(unsigned long)(info->oi_requests);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (o2info_from_user(*req_addr, bp + idx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) bail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * OCFS2_IOC_INFO handles an array of requests passed from userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * ocfs2_info_handle() recevies a large info aggregation, grab and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * validate the request count from header, then break it into small
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) * pieces, later specific handlers can handle them one by one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) * Idea here is to make each separate request small enough to ensure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) * a better backward&forward compatibility, since a small piece of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * request will be less likely to be broken if disk layout get changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) static int ocfs2_info_handle(struct inode *inode, struct ocfs2_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) int compat_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) int i, status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) u64 req_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) struct ocfs2_info_request __user *reqp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if ((info->oi_count > OCFS2_INFO_MAX_REQUEST) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) (!info->oi_requests)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) status = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) for (i = 0; i < info->oi_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) status = ocfs2_get_request_ptr(info, i, &req_addr, compat_flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) reqp = (struct ocfs2_info_request __user *)(unsigned long)req_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (!reqp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) status = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) status = ocfs2_info_handle_request(inode, reqp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) bail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) struct inode *inode = file_inode(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) unsigned int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) int new_clusters;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) struct ocfs2_space_resv sr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) struct ocfs2_new_group_input input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) struct reflink_arguments args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) const char __user *old_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) const char __user *new_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) bool preserve;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) struct ocfs2_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) void __user *argp = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) case OCFS2_IOC_GETFLAGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) status = ocfs2_get_inode_attr(inode, &flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) flags &= OCFS2_FL_VISIBLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return put_user(flags, (int __user *) arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) case OCFS2_IOC_SETFLAGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (get_user(flags, (int __user *) arg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) status = mnt_want_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) status = ocfs2_set_inode_attr(inode, flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) OCFS2_FL_MODIFIABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) mnt_drop_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) case OCFS2_IOC_RESVSP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) case OCFS2_IOC_RESVSP64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) case OCFS2_IOC_UNRESVSP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) case OCFS2_IOC_UNRESVSP64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (copy_from_user(&sr, (int __user *) arg, sizeof(sr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return ocfs2_change_file_space(filp, cmd, &sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) case OCFS2_IOC_GROUP_EXTEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (!capable(CAP_SYS_RESOURCE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if (get_user(new_clusters, (int __user *)arg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) status = mnt_want_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) status = ocfs2_group_extend(inode, new_clusters);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) mnt_drop_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) case OCFS2_IOC_GROUP_ADD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) case OCFS2_IOC_GROUP_ADD64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (!capable(CAP_SYS_RESOURCE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (copy_from_user(&input, (int __user *) arg, sizeof(input)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) status = mnt_want_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) status = ocfs2_group_add(inode, &input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) mnt_drop_write_file(filp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) case OCFS2_IOC_REFLINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (copy_from_user(&args, argp, sizeof(args)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) old_path = (const char __user *)(unsigned long)args.old_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) new_path = (const char __user *)(unsigned long)args.new_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) preserve = (args.preserve != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) return ocfs2_reflink_ioctl(inode, old_path, new_path, preserve);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) case OCFS2_IOC_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (copy_from_user(&info, argp, sizeof(struct ocfs2_info)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) return ocfs2_info_handle(inode, &info, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) case FITRIM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) struct super_block *sb = inode->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) struct request_queue *q = bdev_get_queue(sb->s_bdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) struct fstrim_range range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (!blk_queue_discard(q))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (copy_from_user(&range, argp, sizeof(range)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) range.minlen = max_t(u64, q->limits.discard_granularity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) range.minlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) ret = ocfs2_trim_fs(sb, &range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (copy_to_user(argp, &range, sizeof(range)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) case OCFS2_IOC_MOVE_EXT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return ocfs2_ioctl_move_extents(filp, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) bool preserve;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) struct reflink_arguments args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct inode *inode = file_inode(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) struct ocfs2_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) void __user *argp = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) case OCFS2_IOC32_GETFLAGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) cmd = OCFS2_IOC_GETFLAGS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) case OCFS2_IOC32_SETFLAGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) cmd = OCFS2_IOC_SETFLAGS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) case OCFS2_IOC_RESVSP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) case OCFS2_IOC_RESVSP64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) case OCFS2_IOC_UNRESVSP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) case OCFS2_IOC_UNRESVSP64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) case OCFS2_IOC_GROUP_EXTEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) case OCFS2_IOC_GROUP_ADD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) case OCFS2_IOC_GROUP_ADD64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) case OCFS2_IOC_REFLINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (copy_from_user(&args, argp, sizeof(args)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) preserve = (args.preserve != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return ocfs2_reflink_ioctl(inode, compat_ptr(args.old_path),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) compat_ptr(args.new_path), preserve);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) case OCFS2_IOC_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (copy_from_user(&info, argp, sizeof(struct ocfs2_info)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return ocfs2_info_handle(inode, &info, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) case FITRIM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) case OCFS2_IOC_MOVE_EXT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) return ocfs2_ioctl(file, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) #endif