1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 
  27 #ifndef _SYS_LOFI_H
  28 #define _SYS_LOFI_H
  29 
  30 #pragma ident   "%Z%%M% %I%     %E% SMI"
  31 
  32 #include <sys/types.h>
  33 #include <sys/time.h>
  34 #include <sys/taskq.h>
  35 #include <sys/vtoc.h>
  36 #include <sys/dkio.h>
  37 #include <sys/vnode.h>
  38 
  39 #ifdef  __cplusplus
  40 extern "C" {
  41 #endif
  42 
  43 /*
  44  * /dev names:
  45  *      /dev/lofictl    - master control device
  46  *      /dev/lofi       - block devices, named by minor number
  47  *      /dev/rlofi      - character devices, named by minor number
  48  */
  49 #define LOFI_DRIVER_NAME        "lofi"
  50 #define LOFI_CTL_NODE           "ctl"
  51 #define LOFI_CTL_NAME           LOFI_DRIVER_NAME LOFI_CTL_NODE
  52 #define LOFI_BLOCK_NAME         LOFI_DRIVER_NAME
  53 #define LOFI_CHAR_NAME          "r" LOFI_DRIVER_NAME
  54 
  55 /*
  56  *
  57  * Use is:
  58  *      ld = open("/dev/lofictl", O_RDWR | O_EXCL);
  59  *
  60  * lofi must be opened exclusively. Access is controlled by permissions on
  61  * the device, which is 644 by default. Write-access is required for ioctls
  62  * that change state, but only read-access is required for the ioctls that
  63  * return information. Basically, only root can add and remove files, but
  64  * non-root can look at the current lists.
  65  *
  66  * ioctl usage:
  67  *
  68  * kernel ioctls
  69  *
  70  *      strcpy(li.li_filename, "somefilename");
  71  *      ioctl(ld, LOFI_MAP_FILE, &li);
  72  *      newminor = li.li_minor;
  73  *
  74  *      strcpy(li.li_filename, "somefilename");
  75  *      ioctl(ld, LOFI_UNMAP_FILE, &li);
  76  *
  77  *      strcpy(li.li_filename, "somefilename");
  78  *      li.li_minor = minor_number;
  79  *      ioctl(ld, LOFI_MAP_FILE_MINOR, &li);
  80  *
  81  *      li.li_minor = minor_number;
  82  *      ioctl(ld, LOFI_UNMAP_FILE_MINOR, &li);
  83  *
  84  *      li.li_minor = minor_number;
  85  *      ioctl(ld, LOFI_GET_FILENAME, &li);
  86  *
  87  *      strcpy(li.li_filename, "somefilename");
  88  *      ioctl(ld, LOFI_GET_MINOR, &li);
  89  *
  90  *      li.li_minor = 0;
  91  *      ioctl(ld, LOFI_GET_MAXMINOR, &li);
  92  *      maxminor = li.li_minor;
  93  *
  94  *      strcpy(li.li_filename, "somefilename");
  95  *      li.li_minor = 0;
  96  *      ioctl(ld, LOFI_CHECK_COMPRESSED, &li);
  97  *
  98  * If the 'li_force' flag is set for any of the LOFI_UNMAP_* commands, then if
  99  * the device is busy, the underlying vnode will be closed, and any subsequent
 100  * operations will fail.  It will behave as if the device had been forcibly
 101  * removed, so the DKIOCSTATE ioctl will return DKIO_DEV_GONE.  When the device
 102  * is last closed, it will be torn down.
 103  *
 104  * Oh, and last but not least: these ioctls are totally private and only
 105  * for use by lofiadm(1M).
 106  *
 107  */
 108 
 109 struct lofi_ioctl {
 110         uint32_t        li_minor;
 111         boolean_t       li_force;
 112         char    li_filename[MAXPATHLEN];
 113         char    li_algorithm[MAXPATHLEN];
 114 };
 115 
 116 #define LOFI_IOC_BASE           (('L' << 16) | ('F' << 8))
 117 
 118 #define LOFI_MAP_FILE           (LOFI_IOC_BASE | 0x01)
 119 #define LOFI_MAP_FILE_MINOR     (LOFI_IOC_BASE | 0x02)
 120 #define LOFI_UNMAP_FILE         (LOFI_IOC_BASE | 0x03)
 121 #define LOFI_UNMAP_FILE_MINOR   (LOFI_IOC_BASE | 0x04)
 122 #define LOFI_GET_FILENAME       (LOFI_IOC_BASE | 0x05)
 123 #define LOFI_GET_MINOR          (LOFI_IOC_BASE | 0x06)
 124 #define LOFI_GET_MAXMINOR       (LOFI_IOC_BASE | 0x07)
 125 #define LOFI_CHECK_COMPRESSED   (LOFI_IOC_BASE | 0x08)
 126 
 127 /*
 128  * file types that might be usable with lofi, maybe. Only regular
 129  * files are documented though.
 130  */
 131 #define S_ISLOFIABLE(mode) \
 132         (S_ISREG(mode) || S_ISBLK(mode) || S_ISCHR(mode))
 133 
 134 #define SEGHDR          1
 135 #define COMPRESSED      1
 136 #define UNCOMPRESSED    0
 137 
 138 #if defined(_KERNEL)
 139 
 140 /*
 141  * We limit the maximum number of active lofi devices to 128, which seems very
 142  * large. You can tune this by changing lofi_max_files in /etc/system.
 143  * If you change it dynamically, which you probably shouldn't do, make sure
 144  * to only _increase_ it.
 145  */
 146 #define LOFI_MAX_FILES  128
 147 extern uint32_t lofi_max_files;
 148 
 149 #define V_ISLOFIABLE(vtype) \
 150         ((vtype == VREG) || (vtype == VBLK) || (vtype == VCHR))
 151 
 152 struct lofi_state {
 153         char            *ls_filename;   /* filename to open */
 154         size_t          ls_filename_sz;
 155         struct vnode    *ls_vp;         /* open vnode */
 156         kmutex_t        ls_vp_lock;     /* protects ls_vp */
 157         kcondvar_t      ls_vp_cv;       /* signal changes to ls_vp */
 158         uint32_t        ls_vp_iocount;  /* # pending I/O requests */
 159         boolean_t       ls_vp_closereq; /* force close requested */
 160         u_offset_t      ls_vp_size;
 161         uint32_t        ls_blk_open;
 162         uint32_t        ls_chr_open;
 163         uint32_t        ls_lyr_open_count;
 164         int             ls_openflag;
 165         taskq_t         *ls_taskq;
 166         kstat_t         *ls_kstat;
 167         kmutex_t        ls_kstat_lock;
 168         struct dk_geom  ls_dkg;
 169         struct vtoc     ls_vtoc;
 170         struct dk_cinfo ls_ci;
 171 
 172         /* the following fields are required for compression support */
 173 
 174         /*
 175          * index into lofi_compress_table for the compression algorithm
 176          * used
 177          */
 178         int             ls_comp_algorithm_index;
 179         uint32_t        ls_comp_algorithm_len;
 180         /* size of an uncompressed segment */
 181         uint32_t        ls_uncomp_seg_sz;
 182         /* number of index entries */
 183         uint32_t        ls_comp_index_sz;
 184         /* exponent for byte shift, power of 2 */
 185         uint32_t        ls_comp_seg_shift;
 186         /*
 187          * size of the last uncompressed segment (the file may
 188          * not be an exact multiple of the segment size ls_uncomp_seg_sz)
 189          */
 190         uint32_t        ls_uncomp_last_seg_sz;
 191         /*
 192          * the offset in the file where the header ends and the
 193          * actual compressed data begins. The segment offsets in
 194          * the index do not account for the header so this value must
 195          * be added
 196          */
 197         uint64_t        ls_comp_offbase;
 198         /*
 199          * the array holding the segment index. This is a pointer
 200          * into ls_comp_index_data
 201          */
 202         uint64_t        *ls_comp_seg_index;
 203         /*
 204          * holds the index pages loaded from the file. This is aligned
 205          * on a disk block boundary so lsecomp_seg_index above is used
 206          * to point to the actual array
 207          */
 208         caddr_t         ls_comp_index_data;
 209         /* size of ls_comp_index_data */
 210         uint32_t        ls_comp_index_data_sz;
 211         /*
 212          * incase of compressed files, ls_vp_size above is
 213          * tweaked to represent the actual uncompressed file
 214          * size so that fake_disk_geometry gives the correct
 215          * values. However we need the actual compressed file
 216          * size while faulting in pages from the compressed
 217          * file in lofi_mapped_rdwr
 218          */
 219         u_offset_t      ls_vp_comp_size;
 220 };
 221 
 222 #endif  /* _KERNEL */
 223 
 224 /*
 225  * Common signature for all lofi compress functions
 226  */
 227 typedef int lofi_compress_func_t(void *src, size_t srclen, void *dst,
 228         size_t *destlen, int level);
 229 
 230 /*
 231  * Information about each compression function
 232  */
 233 typedef struct lofi_compress_info {
 234         lofi_compress_func_t    *l_decompress;
 235         lofi_compress_func_t    *l_compress;
 236         int                     l_level;
 237         char                    *l_name;        /* algorithm name */
 238 } lofi_compress_info_t;
 239 
 240 enum lofi_compress {
 241         LOFI_COMPRESS_GZIP = 0,
 242         LOFI_COMPRESS_GZIP_6 = 1,
 243         LOFI_COMPRESS_GZIP_9 = 2,
 244         LOFI_COMPRESS_FUNCTIONS
 245 };
 246 
 247 #ifdef  __cplusplus
 248 }
 249 #endif
 250 
 251 #endif  /* _SYS_LOFI_H */