The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/reiserfs/ioctl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 370fbae3a503ef79b11df40c93ccdddb


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.