222 lines · c
1/*2 * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README3 */4 5#include <linux/capability.h>6#include <linux/fs.h>7#include <linux/mount.h>8#include "reiserfs.h"9#include <linux/time.h>10#include <linux/uaccess.h>11#include <linux/pagemap.h>12#include <linux/compat.h>13#include <linux/fileattr.h>14 15int reiserfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)16{17 struct inode *inode = d_inode(dentry);18 19 if (!reiserfs_attrs(inode->i_sb))20 return -ENOTTY;21 22 fileattr_fill_flags(fa, REISERFS_I(inode)->i_attrs);23 24 return 0;25}26 27int reiserfs_fileattr_set(struct mnt_idmap *idmap,28 struct dentry *dentry, struct fileattr *fa)29{30 struct inode *inode = d_inode(dentry);31 unsigned int flags = fa->flags;32 int err;33 34 reiserfs_write_lock(inode->i_sb);35 36 err = -ENOTTY;37 if (!reiserfs_attrs(inode->i_sb))38 goto unlock;39 40 err = -EOPNOTSUPP;41 if (fileattr_has_fsx(fa))42 goto unlock;43 44 /*45 * Is it quota file? Do not allow user to mess with it46 */47 err = -EPERM;48 if (IS_NOQUOTA(inode))49 goto unlock;50 51 if ((flags & REISERFS_NOTAIL_FL) && S_ISREG(inode->i_mode)) {52 err = reiserfs_unpack(inode);53 if (err)54 goto unlock;55 }56 sd_attrs_to_i_attrs(flags, inode);57 REISERFS_I(inode)->i_attrs = flags;58 inode_set_ctime_current(inode);59 mark_inode_dirty(inode);60 err = 0;61unlock:62 reiserfs_write_unlock(inode->i_sb);63 64 return err;65}66 67/*68 * reiserfs_ioctl - handler for ioctl for inode69 * supported commands:70 * 1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect71 * and prevent packing file (argument arg has t72 * be non-zero)73 * 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION74 * 3) That's all for a while ...75 */76long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)77{78 struct inode *inode = file_inode(filp);79 int err = 0;80 81 reiserfs_write_lock(inode->i_sb);82 83 switch (cmd) {84 case REISERFS_IOC_UNPACK:85 if (S_ISREG(inode->i_mode)) {86 if (arg)87 err = reiserfs_unpack(inode);88 } else89 err = -ENOTTY;90 break;91 /*92 * following two cases are taken from fs/ext2/ioctl.c by Remy93 * Card (card@masi.ibp.fr)94 */95 case REISERFS_IOC_GETVERSION:96 err = put_user(inode->i_generation, (int __user *)arg);97 break;98 case REISERFS_IOC_SETVERSION:99 if (!inode_owner_or_capable(&nop_mnt_idmap, inode)) {100 err = -EPERM;101 break;102 }103 err = mnt_want_write_file(filp);104 if (err)105 break;106 if (get_user(inode->i_generation, (int __user *)arg)) {107 err = -EFAULT;108 goto setversion_out;109 }110 inode_set_ctime_current(inode);111 mark_inode_dirty(inode);112setversion_out:113 mnt_drop_write_file(filp);114 break;115 default:116 err = -ENOTTY;117 }118 119 reiserfs_write_unlock(inode->i_sb);120 121 return err;122}123 124#ifdef CONFIG_COMPAT125long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,126 unsigned long arg)127{128 /*129 * These are just misnamed, they actually130 * get/put from/to user an int131 */132 switch (cmd) {133 case REISERFS_IOC32_UNPACK:134 cmd = REISERFS_IOC_UNPACK;135 break;136 case REISERFS_IOC32_GETVERSION:137 cmd = REISERFS_IOC_GETVERSION;138 break;139 case REISERFS_IOC32_SETVERSION:140 cmd = REISERFS_IOC_SETVERSION;141 break;142 default:143 return -ENOIOCTLCMD;144 }145 146 return reiserfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg));147}148#endif149 150int reiserfs_commit_write(struct file *f, struct page *page,151 unsigned from, unsigned to);152/*153 * reiserfs_unpack154 * Function try to convert tail from direct item into indirect.155 * It set up nopack attribute in the REISERFS_I(inode)->nopack156 */157int reiserfs_unpack(struct inode *inode)158{159 int retval = 0;160 int index;161 struct page *page;162 struct address_space *mapping;163 unsigned long write_from;164 unsigned long blocksize = inode->i_sb->s_blocksize;165 166 if (inode->i_size == 0) {167 REISERFS_I(inode)->i_flags |= i_nopack_mask;168 return 0;169 }170 /* ioctl already done */171 if (REISERFS_I(inode)->i_flags & i_nopack_mask) {172 return 0;173 }174 175 /* we need to make sure nobody is changing the file size beneath us */176 {177 int depth = reiserfs_write_unlock_nested(inode->i_sb);178 179 inode_lock(inode);180 reiserfs_write_lock_nested(inode->i_sb, depth);181 }182 183 reiserfs_write_lock(inode->i_sb);184 185 write_from = inode->i_size & (blocksize - 1);186 /* if we are on a block boundary, we are already unpacked. */187 if (write_from == 0) {188 REISERFS_I(inode)->i_flags |= i_nopack_mask;189 goto out;190 }191 192 /*193 * we unpack by finding the page with the tail, and calling194 * __reiserfs_write_begin on that page. This will force a195 * reiserfs_get_block to unpack the tail for us.196 */197 index = inode->i_size >> PAGE_SHIFT;198 mapping = inode->i_mapping;199 page = grab_cache_page(mapping, index);200 retval = -ENOMEM;201 if (!page) {202 goto out;203 }204 retval = __reiserfs_write_begin(page, write_from, 0);205 if (retval)206 goto out_unlock;207 208 /* conversion can change page contents, must flush */209 flush_dcache_page(page);210 retval = reiserfs_commit_write(NULL, page, write_from, write_from);211 REISERFS_I(inode)->i_flags |= i_nopack_mask;212 213out_unlock:214 unlock_page(page);215 put_page(page);216 217out:218 inode_unlock(inode);219 reiserfs_write_unlock(inode->i_sb);220 return retval;221}222