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