ioctl.c revision 16f7e0fe2ecc30f30652e8185e1772cdebe39109
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 13static int reiserfs_unpack(struct inode *inode, struct file *filp); 14 15/* 16** reiserfs_ioctl - handler for ioctl for inode 17** supported commands: 18** 1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect 19** and prevent packing file (argument arg has to be non-zero) 20** 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION 21** 3) That's all for a while ... 22*/ 23int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, 24 unsigned long arg) 25{ 26 unsigned int flags; 27 28 switch (cmd) { 29 case REISERFS_IOC_UNPACK: 30 if (S_ISREG(inode->i_mode)) { 31 if (arg) 32 return reiserfs_unpack(inode, filp); 33 else 34 return 0; 35 } else 36 return -ENOTTY; 37 /* following two cases are taken from fs/ext2/ioctl.c by Remy 38 Card (card@masi.ibp.fr) */ 39 case REISERFS_IOC_GETFLAGS: 40 if (!reiserfs_attrs(inode->i_sb)) 41 return -ENOTTY; 42 43 flags = REISERFS_I(inode)->i_attrs; 44 i_attrs_to_sd_attrs(inode, (__u16 *) & flags); 45 return put_user(flags, (int __user *)arg); 46 case REISERFS_IOC_SETFLAGS:{ 47 if (!reiserfs_attrs(inode->i_sb)) 48 return -ENOTTY; 49 50 if (IS_RDONLY(inode)) 51 return -EROFS; 52 53 if ((current->fsuid != inode->i_uid) 54 && !capable(CAP_FOWNER)) 55 return -EPERM; 56 57 if (get_user(flags, (int __user *)arg)) 58 return -EFAULT; 59 60 if (((flags ^ REISERFS_I(inode)-> 61 i_attrs) & (REISERFS_IMMUTABLE_FL | 62 REISERFS_APPEND_FL)) 63 && !capable(CAP_LINUX_IMMUTABLE)) 64 return -EPERM; 65 66 if ((flags & REISERFS_NOTAIL_FL) && 67 S_ISREG(inode->i_mode)) { 68 int result; 69 70 result = reiserfs_unpack(inode, filp); 71 if (result) 72 return result; 73 } 74 sd_attrs_to_i_attrs(flags, inode); 75 REISERFS_I(inode)->i_attrs = flags; 76 inode->i_ctime = CURRENT_TIME_SEC; 77 mark_inode_dirty(inode); 78 return 0; 79 } 80 case REISERFS_IOC_GETVERSION: 81 return put_user(inode->i_generation, (int __user *)arg); 82 case REISERFS_IOC_SETVERSION: 83 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) 84 return -EPERM; 85 if (IS_RDONLY(inode)) 86 return -EROFS; 87 if (get_user(inode->i_generation, (int __user *)arg)) 88 return -EFAULT; 89 inode->i_ctime = CURRENT_TIME_SEC; 90 mark_inode_dirty(inode); 91 return 0; 92 default: 93 return -ENOTTY; 94 } 95} 96 97/* 98** reiserfs_unpack 99** Function try to convert tail from direct item into indirect. 100** It set up nopack attribute in the REISERFS_I(inode)->nopack 101*/ 102static int reiserfs_unpack(struct inode *inode, struct file *filp) 103{ 104 int retval = 0; 105 int index; 106 struct page *page; 107 struct address_space *mapping; 108 unsigned long write_from; 109 unsigned long blocksize = inode->i_sb->s_blocksize; 110 111 if (inode->i_size == 0) { 112 REISERFS_I(inode)->i_flags |= i_nopack_mask; 113 return 0; 114 } 115 /* ioctl already done */ 116 if (REISERFS_I(inode)->i_flags & i_nopack_mask) { 117 return 0; 118 } 119 reiserfs_write_lock(inode->i_sb); 120 121 /* we need to make sure nobody is changing the file size beneath 122 ** us 123 */ 124 mutex_lock(&inode->i_mutex); 125 126 write_from = inode->i_size & (blocksize - 1); 127 /* if we are on a block boundary, we are already unpacked. */ 128 if (write_from == 0) { 129 REISERFS_I(inode)->i_flags |= i_nopack_mask; 130 goto out; 131 } 132 133 /* we unpack by finding the page with the tail, and calling 134 ** reiserfs_prepare_write on that page. This will force a 135 ** reiserfs_get_block to unpack the tail for us. 136 */ 137 index = inode->i_size >> PAGE_CACHE_SHIFT; 138 mapping = inode->i_mapping; 139 page = grab_cache_page(mapping, index); 140 retval = -ENOMEM; 141 if (!page) { 142 goto out; 143 } 144 retval = 145 mapping->a_ops->prepare_write(NULL, page, write_from, write_from); 146 if (retval) 147 goto out_unlock; 148 149 /* conversion can change page contents, must flush */ 150 flush_dcache_page(page); 151 retval = 152 mapping->a_ops->commit_write(NULL, page, write_from, write_from); 153 REISERFS_I(inode)->i_flags |= i_nopack_mask; 154 155 out_unlock: 156 unlock_page(page); 157 page_cache_release(page); 158 159 out: 160 mutex_unlock(&inode->i_mutex); 161 reiserfs_write_unlock(inode->i_sb); 162 return retval; 163} 164