1ca4d147eSHerbert Poetzl /* 2ca4d147eSHerbert Poetzl * linux/fs/ocfs2/ioctl.c 3ca4d147eSHerbert Poetzl * 4ca4d147eSHerbert Poetzl * Copyright (C) 2006 Herbert Poetzl 5ca4d147eSHerbert Poetzl * adapted from Remy Card's ext2/ioctl.c 6ca4d147eSHerbert Poetzl */ 7ca4d147eSHerbert Poetzl 8ca4d147eSHerbert Poetzl #include <linux/fs.h> 9ca4d147eSHerbert Poetzl #include <linux/mount.h> 106953b4c0SJoel Becker #include <linux/smp_lock.h> 11ca4d147eSHerbert Poetzl 12ca4d147eSHerbert Poetzl #define MLOG_MASK_PREFIX ML_INODE 13ca4d147eSHerbert Poetzl #include <cluster/masklog.h> 14ca4d147eSHerbert Poetzl 15ca4d147eSHerbert Poetzl #include "ocfs2.h" 16ca4d147eSHerbert Poetzl #include "alloc.h" 17ca4d147eSHerbert Poetzl #include "dlmglue.h" 18b2580103SMark Fasheh #include "file.h" 19ca4d147eSHerbert Poetzl #include "inode.h" 20ca4d147eSHerbert Poetzl #include "journal.h" 21ca4d147eSHerbert Poetzl 22ca4d147eSHerbert Poetzl #include "ocfs2_fs.h" 232d562518SAdrian Bunk #include "ioctl.h" 24d659072fSTao Ma #include "resize.h" 252d562518SAdrian Bunk 26ca4d147eSHerbert Poetzl #include <linux/ext2_fs.h> 27ca4d147eSHerbert Poetzl 28ca4d147eSHerbert Poetzl static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags) 29ca4d147eSHerbert Poetzl { 30ca4d147eSHerbert Poetzl int status; 31ca4d147eSHerbert Poetzl 32e63aecb6SMark Fasheh status = ocfs2_inode_lock(inode, NULL, 0); 33ca4d147eSHerbert Poetzl if (status < 0) { 34ca4d147eSHerbert Poetzl mlog_errno(status); 35ca4d147eSHerbert Poetzl return status; 36ca4d147eSHerbert Poetzl } 376e4b0d56SJan Kara ocfs2_get_inode_flags(OCFS2_I(inode)); 38ca4d147eSHerbert Poetzl *flags = OCFS2_I(inode)->ip_attr; 39e63aecb6SMark Fasheh ocfs2_inode_unlock(inode, 0); 40ca4d147eSHerbert Poetzl 41ca4d147eSHerbert Poetzl mlog_exit(status); 42ca4d147eSHerbert Poetzl return status; 43ca4d147eSHerbert Poetzl } 44ca4d147eSHerbert Poetzl 45ca4d147eSHerbert Poetzl static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, 46ca4d147eSHerbert Poetzl unsigned mask) 47ca4d147eSHerbert Poetzl { 48ca4d147eSHerbert Poetzl struct ocfs2_inode_info *ocfs2_inode = OCFS2_I(inode); 49ca4d147eSHerbert Poetzl struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 501fabe148SMark Fasheh handle_t *handle = NULL; 51ca4d147eSHerbert Poetzl struct buffer_head *bh = NULL; 52ca4d147eSHerbert Poetzl unsigned oldflags; 53ca4d147eSHerbert Poetzl int status; 54ca4d147eSHerbert Poetzl 55ca4d147eSHerbert Poetzl mutex_lock(&inode->i_mutex); 56ca4d147eSHerbert Poetzl 57e63aecb6SMark Fasheh status = ocfs2_inode_lock(inode, &bh, 1); 58ca4d147eSHerbert Poetzl if (status < 0) { 59ca4d147eSHerbert Poetzl mlog_errno(status); 60ca4d147eSHerbert Poetzl goto bail; 61ca4d147eSHerbert Poetzl } 62ca4d147eSHerbert Poetzl 63ca4d147eSHerbert Poetzl status = -EACCES; 643bd858abSSatyam Sharma if (!is_owner_or_cap(inode)) 65ca4d147eSHerbert Poetzl goto bail_unlock; 66ca4d147eSHerbert Poetzl 67ca4d147eSHerbert Poetzl if (!S_ISDIR(inode->i_mode)) 68ca4d147eSHerbert Poetzl flags &= ~OCFS2_DIRSYNC_FL; 69ca4d147eSHerbert Poetzl 7065eff9ccSMark Fasheh handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); 71ca4d147eSHerbert Poetzl if (IS_ERR(handle)) { 72ca4d147eSHerbert Poetzl status = PTR_ERR(handle); 73ca4d147eSHerbert Poetzl mlog_errno(status); 74ca4d147eSHerbert Poetzl goto bail_unlock; 75ca4d147eSHerbert Poetzl } 76ca4d147eSHerbert Poetzl 77ca4d147eSHerbert Poetzl oldflags = ocfs2_inode->ip_attr; 78ca4d147eSHerbert Poetzl flags = flags & mask; 79ca4d147eSHerbert Poetzl flags |= oldflags & ~mask; 80ca4d147eSHerbert Poetzl 81ca4d147eSHerbert Poetzl /* 82ca4d147eSHerbert Poetzl * The IMMUTABLE and APPEND_ONLY flags can only be changed by 83ca4d147eSHerbert Poetzl * the relevant capability. 84ca4d147eSHerbert Poetzl */ 85ca4d147eSHerbert Poetzl status = -EPERM; 86ca4d147eSHerbert Poetzl if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) & 87ca4d147eSHerbert Poetzl (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) { 88ca4d147eSHerbert Poetzl if (!capable(CAP_LINUX_IMMUTABLE)) 89ca4d147eSHerbert Poetzl goto bail_unlock; 90ca4d147eSHerbert Poetzl } 91ca4d147eSHerbert Poetzl 92ca4d147eSHerbert Poetzl ocfs2_inode->ip_attr = flags; 93ca4d147eSHerbert Poetzl ocfs2_set_inode_flags(inode); 94ca4d147eSHerbert Poetzl 95ca4d147eSHerbert Poetzl status = ocfs2_mark_inode_dirty(handle, inode, bh); 96ca4d147eSHerbert Poetzl if (status < 0) 97ca4d147eSHerbert Poetzl mlog_errno(status); 98ca4d147eSHerbert Poetzl 9902dc1af4SMark Fasheh ocfs2_commit_trans(osb, handle); 100ca4d147eSHerbert Poetzl bail_unlock: 101e63aecb6SMark Fasheh ocfs2_inode_unlock(inode, 1); 102ca4d147eSHerbert Poetzl bail: 103ca4d147eSHerbert Poetzl mutex_unlock(&inode->i_mutex); 104ca4d147eSHerbert Poetzl 105ca4d147eSHerbert Poetzl if (bh) 106ca4d147eSHerbert Poetzl brelse(bh); 107ca4d147eSHerbert Poetzl 108ca4d147eSHerbert Poetzl mlog_exit(status); 109ca4d147eSHerbert Poetzl return status; 110ca4d147eSHerbert Poetzl } 111ca4d147eSHerbert Poetzl 112c9ec1488SAndi Kleen long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 113ca4d147eSHerbert Poetzl { 114c9ec1488SAndi Kleen struct inode *inode = filp->f_path.dentry->d_inode; 115ca4d147eSHerbert Poetzl unsigned int flags; 116d659072fSTao Ma int new_clusters; 117ca4d147eSHerbert Poetzl int status; 118b2580103SMark Fasheh struct ocfs2_space_resv sr; 1197909f2bfSTao Ma struct ocfs2_new_group_input input; 120ca4d147eSHerbert Poetzl 121ca4d147eSHerbert Poetzl switch (cmd) { 122ca4d147eSHerbert Poetzl case OCFS2_IOC_GETFLAGS: 123ca4d147eSHerbert Poetzl status = ocfs2_get_inode_attr(inode, &flags); 124ca4d147eSHerbert Poetzl if (status < 0) 125ca4d147eSHerbert Poetzl return status; 126ca4d147eSHerbert Poetzl 127ca4d147eSHerbert Poetzl flags &= OCFS2_FL_VISIBLE; 128ca4d147eSHerbert Poetzl return put_user(flags, (int __user *) arg); 129ca4d147eSHerbert Poetzl case OCFS2_IOC_SETFLAGS: 130ca4d147eSHerbert Poetzl if (get_user(flags, (int __user *) arg)) 131ca4d147eSHerbert Poetzl return -EFAULT; 132ca4d147eSHerbert Poetzl 133*42a74f20SDave Hansen status = mnt_want_write(filp->f_path.mnt); 134*42a74f20SDave Hansen if (status) 135*42a74f20SDave Hansen return status; 136*42a74f20SDave Hansen status = ocfs2_set_inode_attr(inode, flags, 137ca4d147eSHerbert Poetzl OCFS2_FL_MODIFIABLE); 138*42a74f20SDave Hansen mnt_drop_write(filp->f_path.mnt); 139*42a74f20SDave Hansen return status; 140b2580103SMark Fasheh case OCFS2_IOC_RESVSP: 141b2580103SMark Fasheh case OCFS2_IOC_RESVSP64: 142b2580103SMark Fasheh case OCFS2_IOC_UNRESVSP: 143b2580103SMark Fasheh case OCFS2_IOC_UNRESVSP64: 144b2580103SMark Fasheh if (copy_from_user(&sr, (int __user *) arg, sizeof(sr))) 145b2580103SMark Fasheh return -EFAULT; 146b2580103SMark Fasheh 147b2580103SMark Fasheh return ocfs2_change_file_space(filp, cmd, &sr); 148d659072fSTao Ma case OCFS2_IOC_GROUP_EXTEND: 1490957f007SMark Fasheh if (!capable(CAP_SYS_RESOURCE)) 1500957f007SMark Fasheh return -EPERM; 1510957f007SMark Fasheh 152d659072fSTao Ma if (get_user(new_clusters, (int __user *)arg)) 153d659072fSTao Ma return -EFAULT; 154d659072fSTao Ma 155d659072fSTao Ma return ocfs2_group_extend(inode, new_clusters); 1567909f2bfSTao Ma case OCFS2_IOC_GROUP_ADD: 1577909f2bfSTao Ma case OCFS2_IOC_GROUP_ADD64: 1580957f007SMark Fasheh if (!capable(CAP_SYS_RESOURCE)) 1590957f007SMark Fasheh return -EPERM; 1600957f007SMark Fasheh 1617909f2bfSTao Ma if (copy_from_user(&input, (int __user *) arg, sizeof(input))) 1627909f2bfSTao Ma return -EFAULT; 1637909f2bfSTao Ma 1647909f2bfSTao Ma return ocfs2_group_add(inode, &input); 165ca4d147eSHerbert Poetzl default: 166ca4d147eSHerbert Poetzl return -ENOTTY; 167ca4d147eSHerbert Poetzl } 168ca4d147eSHerbert Poetzl } 169ca4d147eSHerbert Poetzl 170586d232bSMark Fasheh #ifdef CONFIG_COMPAT 171586d232bSMark Fasheh long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) 172586d232bSMark Fasheh { 173586d232bSMark Fasheh switch (cmd) { 174586d232bSMark Fasheh case OCFS2_IOC32_GETFLAGS: 175586d232bSMark Fasheh cmd = OCFS2_IOC_GETFLAGS; 176586d232bSMark Fasheh break; 177586d232bSMark Fasheh case OCFS2_IOC32_SETFLAGS: 178586d232bSMark Fasheh cmd = OCFS2_IOC_SETFLAGS; 179586d232bSMark Fasheh break; 180b2580103SMark Fasheh case OCFS2_IOC_RESVSP: 181b2580103SMark Fasheh case OCFS2_IOC_RESVSP64: 182b2580103SMark Fasheh case OCFS2_IOC_UNRESVSP: 183b2580103SMark Fasheh case OCFS2_IOC_UNRESVSP64: 184d659072fSTao Ma case OCFS2_IOC_GROUP_EXTEND: 1857909f2bfSTao Ma case OCFS2_IOC_GROUP_ADD: 1867909f2bfSTao Ma case OCFS2_IOC_GROUP_ADD64: 187b2580103SMark Fasheh break; 188586d232bSMark Fasheh default: 189586d232bSMark Fasheh return -ENOIOCTLCMD; 190586d232bSMark Fasheh } 191586d232bSMark Fasheh 192c9ec1488SAndi Kleen return ocfs2_ioctl(file, cmd, arg); 193586d232bSMark Fasheh } 194586d232bSMark Fasheh #endif 195