root/fs/reiserfs/ioctl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. reiserfs_ioctl
  2. reiserfs_compat_ioctl
  3. reiserfs_unpack

   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/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 
  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 t
  19  *                            be non-zero)
  20  *  2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION
  21  *  3) That's all for a while ...
  22  */
  23 long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  24 {
  25         struct inode *inode = file_inode(filp);
  26         unsigned int flags;
  27         int err = 0;
  28 
  29         reiserfs_write_lock(inode->i_sb);
  30 
  31         switch (cmd) {
  32         case REISERFS_IOC_UNPACK:
  33                 if (S_ISREG(inode->i_mode)) {
  34                         if (arg)
  35                                 err = reiserfs_unpack(inode, filp);
  36                 } else
  37                         err = -ENOTTY;
  38                 break;
  39                 /*
  40                  * following two cases are taken from fs/ext2/ioctl.c by Remy
  41                  * Card (card@masi.ibp.fr)
  42                  */
  43         case REISERFS_IOC_GETFLAGS:
  44                 if (!reiserfs_attrs(inode->i_sb)) {
  45                         err = -ENOTTY;
  46                         break;
  47                 }
  48 
  49                 flags = REISERFS_I(inode)->i_attrs;
  50                 err = put_user(flags, (int __user *)arg);
  51                 break;
  52         case REISERFS_IOC_SETFLAGS:{
  53                         if (!reiserfs_attrs(inode->i_sb)) {
  54                                 err = -ENOTTY;
  55                                 break;
  56                         }
  57 
  58                         err = mnt_want_write_file(filp);
  59                         if (err)
  60                                 break;
  61 
  62                         if (!inode_owner_or_capable(inode)) {
  63                                 err = -EPERM;
  64                                 goto setflags_out;
  65                         }
  66                         if (get_user(flags, (int __user *)arg)) {
  67                                 err = -EFAULT;
  68                                 goto setflags_out;
  69                         }
  70                         /*
  71                          * Is it quota file? Do not allow user to mess with it
  72                          */
  73                         if (IS_NOQUOTA(inode)) {
  74                                 err = -EPERM;
  75                                 goto setflags_out;
  76                         }
  77                         err = vfs_ioc_setflags_prepare(inode,
  78                                                      REISERFS_I(inode)->i_attrs,
  79                                                      flags);
  80                         if (err)
  81                                 goto setflags_out;
  82                         if ((flags & REISERFS_NOTAIL_FL) &&
  83                             S_ISREG(inode->i_mode)) {
  84                                 int result;
  85 
  86                                 result = reiserfs_unpack(inode, filp);
  87                                 if (result) {
  88                                         err = result;
  89                                         goto setflags_out;
  90                                 }
  91                         }
  92                         sd_attrs_to_i_attrs(flags, inode);
  93                         REISERFS_I(inode)->i_attrs = flags;
  94                         inode->i_ctime = current_time(inode);
  95                         mark_inode_dirty(inode);
  96 setflags_out:
  97                         mnt_drop_write_file(filp);
  98                         break;
  99                 }
 100         case REISERFS_IOC_GETVERSION:
 101                 err = put_user(inode->i_generation, (int __user *)arg);
 102                 break;
 103         case REISERFS_IOC_SETVERSION:
 104                 if (!inode_owner_or_capable(inode)) {
 105                         err = -EPERM;
 106                         break;
 107                 }
 108                 err = mnt_want_write_file(filp);
 109                 if (err)
 110                         break;
 111                 if (get_user(inode->i_generation, (int __user *)arg)) {
 112                         err = -EFAULT;
 113                         goto setversion_out;
 114                 }
 115                 inode->i_ctime = current_time(inode);
 116                 mark_inode_dirty(inode);
 117 setversion_out:
 118                 mnt_drop_write_file(filp);
 119                 break;
 120         default:
 121                 err = -ENOTTY;
 122         }
 123 
 124         reiserfs_write_unlock(inode->i_sb);
 125 
 126         return err;
 127 }
 128 
 129 #ifdef CONFIG_COMPAT
 130 long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
 131                                 unsigned long arg)
 132 {
 133         /*
 134          * These are just misnamed, they actually
 135          * get/put from/to user an int
 136          */
 137         switch (cmd) {
 138         case REISERFS_IOC32_UNPACK:
 139                 cmd = REISERFS_IOC_UNPACK;
 140                 break;
 141         case REISERFS_IOC32_GETFLAGS:
 142                 cmd = REISERFS_IOC_GETFLAGS;
 143                 break;
 144         case REISERFS_IOC32_SETFLAGS:
 145                 cmd = REISERFS_IOC_SETFLAGS;
 146                 break;
 147         case REISERFS_IOC32_GETVERSION:
 148                 cmd = REISERFS_IOC_GETVERSION;
 149                 break;
 150         case REISERFS_IOC32_SETVERSION:
 151                 cmd = REISERFS_IOC_SETVERSION;
 152                 break;
 153         default:
 154                 return -ENOIOCTLCMD;
 155         }
 156 
 157         return reiserfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
 158 }
 159 #endif
 160 
 161 int reiserfs_commit_write(struct file *f, struct page *page,
 162                           unsigned from, unsigned to);
 163 /*
 164  * reiserfs_unpack
 165  * Function try to convert tail from direct item into indirect.
 166  * It set up nopack attribute in the REISERFS_I(inode)->nopack
 167  */
 168 int reiserfs_unpack(struct inode *inode, struct file *filp)
 169 {
 170         int retval = 0;
 171         int index;
 172         struct page *page;
 173         struct address_space *mapping;
 174         unsigned long write_from;
 175         unsigned long blocksize = inode->i_sb->s_blocksize;
 176 
 177         if (inode->i_size == 0) {
 178                 REISERFS_I(inode)->i_flags |= i_nopack_mask;
 179                 return 0;
 180         }
 181         /* ioctl already done */
 182         if (REISERFS_I(inode)->i_flags & i_nopack_mask) {
 183                 return 0;
 184         }
 185 
 186         /* we need to make sure nobody is changing the file size beneath us */
 187 {
 188         int depth = reiserfs_write_unlock_nested(inode->i_sb);
 189         inode_lock(inode);
 190         reiserfs_write_lock_nested(inode->i_sb, depth);
 191 }
 192 
 193         reiserfs_write_lock(inode->i_sb);
 194 
 195         write_from = inode->i_size & (blocksize - 1);
 196         /* if we are on a block boundary, we are already unpacked.  */
 197         if (write_from == 0) {
 198                 REISERFS_I(inode)->i_flags |= i_nopack_mask;
 199                 goto out;
 200         }
 201 
 202         /*
 203          * we unpack by finding the page with the tail, and calling
 204          * __reiserfs_write_begin on that page.  This will force a
 205          * reiserfs_get_block to unpack the tail for us.
 206          */
 207         index = inode->i_size >> PAGE_SHIFT;
 208         mapping = inode->i_mapping;
 209         page = grab_cache_page(mapping, index);
 210         retval = -ENOMEM;
 211         if (!page) {
 212                 goto out;
 213         }
 214         retval = __reiserfs_write_begin(page, write_from, 0);
 215         if (retval)
 216                 goto out_unlock;
 217 
 218         /* conversion can change page contents, must flush */
 219         flush_dcache_page(page);
 220         retval = reiserfs_commit_write(NULL, page, write_from, write_from);
 221         REISERFS_I(inode)->i_flags |= i_nopack_mask;
 222 
 223 out_unlock:
 224         unlock_page(page);
 225         put_page(page);
 226 
 227 out:
 228         inode_unlock(inode);
 229         reiserfs_write_unlock(inode->i_sb);
 230         return retval;
 231 }

/* [<][>][^][v][top][bottom][index][help] */