ioctl.c revision 1fc5adbd1916793c19d25347f484806c124d9be7
1/* 2 * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README 3 */ 4 5#include <linux/capability.h> 6#include <linux/fs.h> 7#include <linux/reiserfs_fs.h> 8#include <linux/time.h> 9#include <asm/uaccess.h> 10#include <linux/pagemap.h> 11#include <linux/smp_lock.h> 12#include <linux/compat.h> 13 14static int reiserfs_unpack(struct inode *inode, struct file *filp); 15 16/* 17** reiserfs_ioctl - handler for ioctl for inode 18** supported commands: 19** 1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect 20** and prevent packing file (argument arg has to be non-zero) 21** 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION 22** 3) That's all for a while ... 23*/ 24int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, 25 unsigned long arg) 26{ 27 unsigned int flags; 28 29 switch (cmd) { 30 case REISERFS_IOC_UNPACK: 31 if (S_ISREG(inode->i_mode)) { 32 if (arg) 33 return reiserfs_unpack(inode, filp); 34 else 35 return 0; 36 } else 37 return -ENOTTY; 38 /* following two cases are taken from fs/ext2/ioctl.c by Remy 39 Card (card@masi.ibp.fr) */ 40 case REISERFS_IOC_GETFLAGS: 41 if (!reiserfs_attrs(inode->i_sb)) 42 return -ENOTTY; 43 44 flags = REISERFS_I(inode)->i_attrs; 45 i_attrs_to_sd_attrs(inode, (__u16 *) & flags); 46 return put_user(flags, (int __user *)arg); 47 case REISERFS_IOC_SETFLAGS:{ 48 if (!reiserfs_attrs(inode->i_sb)) 49 return -ENOTTY; 50 51 if (IS_RDONLY(inode)) 52 return -EROFS; 53 54 if ((current->fsuid != inode->i_uid) 55 && !capable(CAP_FOWNER)) 56 return -EPERM; 57 58 if (get_user(flags, (int __user *)arg)) 59 return -EFAULT; 60 61 if (((flags ^ REISERFS_I(inode)-> 62 i_attrs) & (REISERFS_IMMUTABLE_FL | 63 REISERFS_APPEND_FL)) 64 && !capable(CAP_LINUX_IMMUTABLE)) 65 return -EPERM; 66 67 if ((flags & REISERFS_NOTAIL_FL) && 68 S_ISREG(inode->i_mode)) { 69 int result; 70 71 result = reiserfs_unpack(inode, filp); 72 if (result) 73 return result; 74 } 75 sd_attrs_to_i_attrs(flags, inode); 76 REISERFS_I(inode)->i_attrs = flags; 77 inode->i_ctime = CURRENT_TIME_SEC; 78 mark_inode_dirty(inode); 79 return 0; 80 } 81 case REISERFS_IOC_GETVERSION: 82 return put_user(inode->i_generation, (int __user *)arg); 83 case REISERFS_IOC_SETVERSION: 84 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) 85 return -EPERM; 86 if (IS_RDONLY(inode)) 87 return -EROFS; 88 if (get_user(inode->i_generation, (int __user *)arg)) 89 return -EFAULT; 90 inode->i_ctime = CURRENT_TIME_SEC; 91 mark_inode_dirty(inode); 92 return 0; 93 default: 94 return -ENOTTY; 95 } 96} 97 98#ifdef CONFIG_COMPAT 99long reiserfs_compat_ioctl(struct file *file, unsigned int cmd, 100 unsigned long arg) 101{ 102 struct inode *inode = file->f_path.dentry->d_inode; 103 int ret; 104 105 /* These are just misnamed, they actually get/put from/to user an int */ 106 switch (cmd) { 107 case REISERFS_IOC32_UNPACK: 108 cmd = REISERFS_IOC_UNPACK; 109 break; 110 case REISERFS_IOC32_GETFLAGS: 111 cmd = REISERFS_IOC_GETFLAGS; 112 break; 113 case REISERFS_IOC32_SETFLAGS: 114 cmd = REISERFS_IOC_SETFLAGS; 115 break; 116 case REISERFS_IOC32_GETVERSION: 117 cmd = REISERFS_IOC_GETVERSION; 118 break; 119 case REISERFS_IOC32_SETVERSION: 120 cmd = REISERFS_IOC_SETVERSION; 121 break; 122 default: 123 return -ENOIOCTLCMD; 124 } 125 lock_kernel(); 126 ret = reiserfs_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg)); 127 unlock_kernel(); 128 return ret; 129} 130#endif 131 132/* 133** reiserfs_unpack 134** Function try to convert tail from direct item into indirect. 135** It set up nopack attribute in the REISERFS_I(inode)->nopack 136*/ 137static int reiserfs_unpack(struct inode *inode, struct file *filp) 138{ 139 int retval = 0; 140 int index; 141 struct page *page; 142 struct address_space *mapping; 143 unsigned long write_from; 144 unsigned long blocksize = inode->i_sb->s_blocksize; 145 146 if (inode->i_size == 0) { 147 REISERFS_I(inode)->i_flags |= i_nopack_mask; 148 return 0; 149 } 150 /* ioctl already done */ 151 if (REISERFS_I(inode)->i_flags & i_nopack_mask) { 152 return 0; 153 } 154 155 /* we need to make sure nobody is changing the file size beneath 156 ** us 157 */ 158 mutex_lock(&inode->i_mutex); 159 reiserfs_write_lock(inode->i_sb); 160 161 write_from = inode->i_size & (blocksize - 1); 162 /* if we are on a block boundary, we are already unpacked. */ 163 if (write_from == 0) { 164 REISERFS_I(inode)->i_flags |= i_nopack_mask; 165 goto out; 166 } 167 168 /* we unpack by finding the page with the tail, and calling 169 ** reiserfs_prepare_write on that page. This will force a 170 ** reiserfs_get_block to unpack the tail for us. 171 */ 172 index = inode->i_size >> PAGE_CACHE_SHIFT; 173 mapping = inode->i_mapping; 174 page = grab_cache_page(mapping, index); 175 retval = -ENOMEM; 176 if (!page) { 177 goto out; 178 } 179 retval = 180 mapping->a_ops->prepare_write(NULL, page, write_from, write_from); 181 if (retval) 182 goto out_unlock; 183 184 /* conversion can change page contents, must flush */ 185 flush_dcache_page(page); 186 retval = 187 mapping->a_ops->commit_write(NULL, page, write_from, write_from); 188 REISERFS_I(inode)->i_flags |= i_nopack_mask; 189 190 out_unlock: 191 unlock_page(page); 192 page_cache_release(page); 193 194 out: 195 mutex_unlock(&inode->i_mutex); 196 reiserfs_write_unlock(inode->i_sb); 197 return retval; 198} 199