1 /* BLURB lgpl
2 
3                            Coda File System
4                               Release 5
5 
6           Copyright (c) 1987-1999 Carnegie Mellon University
7                   Additional copyrights listed below
8 
9 This  code  is  distributed "AS IS" without warranty of any kind under
10 the  terms of the  GNU  Library General Public Licence  Version 2,  as
11 shown in the file LICENSE. The technical and financial contributors to
12 Coda are listed in the file CREDITS.
13 
14                         Additional copyrights
15                            none currently
16 
17 #*/
18 
19 /*
20 *                       Definitions for RVM
21 *
22 *
23 */
24 
25 /*LINTLIBRARY*/
26 
27 /* permit multiple includes */
28 #ifndef RVM_VERSION
29 
30 /* Version string for initialization */
31 #define RVM_VERSION         "RVM Interface Version 1.3  7 Mar 1994"
32 #define RVM_VERSION_MAX     128         /* 128 char maximum version str length */
33 
34 /* be sure parallel libraries are used */
35 #ifndef _PARALLEL_LIBRARIES
36 #define _PARALLEL_LIBRARIES 1
37 #endif
38 
39 /* get timestamp structures and system constants */
40 #include <sys/time.h>
41 #include <sys/param.h>
42 
43 /* define bool, TRUE, and FALSE */
44 
45 #ifndef TRUE
46 #define TRUE 1
47 #endif
48 
49 #ifndef FALSE
50 #define FALSE 0
51 #endif
52 
53 /* RVM's use of false, true and bool causes trouble with versions of gcc
54    above 2.6 or so; because of this, the names of RVM's definitions
55    have been changed to rvm_{false,true,bool_t}. (Originally changed
56    in rvm.h by Satya (7/31/96); propogated to the rest of the RVM code
57    8/23/96 by tilt */
58 
59 typedef enum { rvm_false = 0, rvm_true = 1 } rvm_bool_t;
60 
61 /*  structure identifiers: rvm_struct_id_t
62     codes placed in the first field of each
63     structure instance to identify the object.
64 */
65 typedef enum
66     {
67     rvm_first_struct_id = 39,           /* internal use only */
68 
69     rvm_region_id,                      /* identifier for rvm_region's */
70     rvm_options_id,                     /* identifier for rvm_options */
71     rvm_tid_id,                         /* identifier for rvm_tid's */
72     rvm_statistics_id,                  /* identifier for rvm_statistics rec's */
73     rvm_last_struct_id                  /* internal use only */
74     }
75 rvm_struct_id_t;
76 
77 /*  Transaction mode codes: rvm_mode_t */
78 typedef enum
79     {
80     rvm_first_mode = 139,               /* internal use only */
81 
82     restore,                            /* restore memory on abort */
83     no_restore,                         /* do not restore memory on abort */
84     flush,                              /* flush records to logdev on commit */
85     no_flush,                           /* do not flush records on commit */
86 
87     rvm_last_mode                       /* internal use only */
88     }
89 rvm_mode_t;
90 
91 /*  Function return codes:  rvm_return_t */
92 typedef int  rvm_return_t;
93 #define 	RVM_SUCCESS     0  /* success return code */
94 #define rvm_first_code  199        /* internal use only */
95 #define RVM_EINIT       200        /* RVM not initialized */
96 #define RVM_EINTERNAL   201        /* internal error, see rvm_errmsg */
97 #define RVM_EIO         202        /* I/O error, see errno */
98 #define RVM_ELOG        204        /* invalid log device */
99 #define RVM_ELOG_VERSION_SKEW 205  /* RVM log format version skew */
100 #define RVM_EMODE 206              /* invalid transaction begin/end mode */
101 #define RVM_ENAME_TOO_LONG 207     /* device name longer than 1023 chars */
102 #define RVM_ENO_MEMORY 208         /* heap exhausted */
103 #define RVM_ENOT_MAPPED  209       /* designated region not mapped */
104 #define RVM_EOFFSET 210            /* invalid segment offset */
105 #define RVM_EOPTIONS 211           /* invalid options record or pointer */
106 #define RVM_EOVERLAP 212           /* region overlaps existing seg mapping */
107 #define RVM_EPAGER 213             /* invalid external pager */
108 #define RVM_ERANGE 214             /* invalid virtual memory address */
109 #define RVM_EREGION 215            /* invalid region descriptor or pointer */
110 #define RVM_EREGION_DEF 216        /* invalid region definition descriptor */
111 #define RVM_ESRC 217               /* invalid address range for new values */
112 #define RVM_ESTATISTICS 218        /* invalid statistics record */
113 #define RVM_ESTAT_VERSION_SKEW 219 /* RVM statistics format version skew */
114 #define RVM_ETERMINATED 220        /* terminated by error already reported */
115 #define RVM_ETHREADS 221           /* illegal C Thread library */
116 #define RVM_ETID 222               /* invalid transaction identifier or ptr */
117 #define RVM_ETOO_BIG 223           /* internal resouces exceeded */
118 #define RVM_EUNCOMMIT 224          /* uncommitted transaction(s) pending */
119 #define RVM_EVERSION_SKEW 225      /* RVM library version skew */
120 #define RVM_EVM_OVERLAP 226        /* region overlaps existing vm mapping */
121 #define rvm_last_code  227         /* internal use only */
122 
123 /* Enumeration type print name functions */
124 extern char *rvm_return(rvm_return_t code);
125 extern char *rvm_mode(rvm_mode_t  mode);
126 extern char *rvm_type(rvm_struct_id_t id);
127 
128 
129 /*  RVM basic length and offset types:
130     these types are used throughout RVM to hide machine-dependent
131     representations of maximum virtual memory region lengths and
132     64 bit offsets.  Do not use internal types or fields or
133     portability can be compromised
134 */
135 /*  region length: rvm_length_t
136     size must be >= sizeof(char *),
137     type must be unsigned arithmetic */
138 
139 typedef unsigned long rvm_length_t;
140 
141 /*  region offset descriptor: rvm_offset_t supports 64 bit unsigned integers
142     struct unecessary if machine has 64-bit ops */
143 
144 typedef struct
145     {                                   /* INTERNAL FIELDS static */
146     rvm_length_t    high;               /* private */
147     rvm_length_t    low;                /* private */
148     }
149 rvm_offset_t;
150 
151 /* construct offset from two rvm_length_t sized quantities x,y
152    -- this will construct an offset from two lengths even if
153    8*sizeof(rvm_length_t) is > sizeof(rvm_offset_t); the "extra"
154    bits, the highest order bits of parameter y, will be discarded */
155 #define RVM_MK_OFFSET(x,y)      rvm_mk_offset((rvm_length_t)(x), \
156                                               (rvm_length_t)(y))
157 
158 /* offset initializer -- same as RVM_MK_OFFSET, but compile time */
159 #define RVM_OFFSET_INITIALIZER(x,y)     {(x),(y)}
160 
161 /* Zero an offset: create a zero offset and assign it to the parameter. */
162 #define RVM_ZERO_OFFSET(x)      (x) = RVM_MK_OFFSET(0,0)
163 
164 /* offset and length conversion macros */
165 
166 /* return low-order bits of offset x as length
167    -- "low-order bits" are the lowest numerically valued bits
168    of the same size as rvm_length_t */
169 #define RVM_OFFSET_TO_LENGTH(x) ((x).low)
170 
171 /* return high order bits of offset x as length
172    -- "high-order bits" are defined as the highest ordered
173    bits remaining after the low-order bits are extracted
174    they are returned as rvm_length_t */
175 #define RVM_OFFSET_HIGH_BITS_TO_LENGTH(x) ((x).high)
176 
177 /* return length x as rvm_offset_t */
178 #define RVM_LENGTH_TO_OFFSET(x) RVM_MK_OFFSET(0,(x))
179 
180 /* rvm_offset_t and rvm_length_t arithmetic support */
181 
182 /* add rvm_offset to rvm_offset; returns result (x+y)
183    implemented as function call -- or simple add if
184    machine has 64-bit integer operations */
185 #define RVM_ADD_OFFSETS(x,y) \
186     rvm_add_offsets(&(x),&(y))
187 
188 /* add rvm_length to rvm_offset; return result (length+offset)
189    as rvm_offset_t
190    implemented as function call -- or simple add if
191    machine has 64-bit integer operations */
192 #define RVM_ADD_LENGTH_TO_OFFSET(x,y) \
193     rvm_add_length_to_offset(&(x),(y))
194 
195 /* add rvm_length_t to vm address; returns address (char *)
196    always implemented as simple add */
197 #define RVM_ADD_LENGTH_TO_ADDR(length,vmaddr) \
198     ((char *)((rvm_length_t)(length)+(rvm_length_t)(vmaddr)))
199 
200 /* subtract rvm_offset from rvm_offset; return result (x-y) as rvm_offset_t
201    implemented as function call -- or simple subtract if
202    machine has 64-bit integer operations */
203 #define RVM_SUB_OFFSETS(x,y) \
204     rvm_sub_offsets(&(x),&(y))
205 
206 /* subtract rvm_length from rvm_offset; return result (offset-length)
207    as rvm_offset_t
208    implemented as function call or simple subtract if
209    machine has 64-bit integer operations  */
210 #define RVM_SUB_LENGTH_FROM_OFFSET(x,y) \
211     rvm_sub_length_from_offset(&(x),(y))
212 
213 /* subtract rvm_length_t from vm address; returns address (char *)
214    always implemented as simple subtract */
215 #define RVM_SUB_LENGTH_FROM_ADDR(vmaddr,length) \
216     ((char *)((rvm_length_t)(vmaddr)-(rvm_length_t)(length)))
217 
218 /*  rvm_offset_t comparison macros */
219 #define RVM_OFFSET_LSS(x,y)     (((x).high < (y).high) || \
220                                  ((((x).high == (y).high) && \
221                                  ((x).low < (y).low))))
222 #define RVM_OFFSET_GTR(x,y)     (((x).high > (y).high) || \
223                                  ((((x).high == (y).high) && \
224                                  ((x).low > (y).low))))
225 #define RVM_OFFSET_LEQ(x,y)     (!RVM_OFFSET_GTR((x),(y)))
226 #define RVM_OFFSET_GEQ(x,y)     (!RVM_OFFSET_LSS((x),(y)))
227 #define RVM_OFFSET_EQL(x,y)     (((x).high == (y).high) && \
228                                  ((x).low == (y).low))
229 #define RVM_OFFSET_EQL_ZERO(x)  (((x).high == 0) && ((x).low == 0))
230 
231 /* page-size rounding macros */
232 
233 /* return page size as rvm_length_t */
234 #define RVM_PAGE_SIZE           rvm_page_size()
235 
236 /* return rvm_length x rounded up to next integral page-size length */
237 #define RVM_ROUND_LENGTH_UP_TO_PAGE_SIZE(x)  ((rvm_length_t)( \
238     ((rvm_length_t)(x)+rvm_page_size()-1) & rvm_page_mask()))
239 
240 /* return rvm_length x rounded down to integral page-size length */
241 #define RVM_ROUND_LENGTH_DOWN_TO_PAGE_SIZE(x)  ((rvm_length_t)( \
242      (rvm_length_t)(x) & rvm_page_mask()))
243 
244 /* return address x rounded up to next page boundary */
245 #define RVM_ROUND_ADDR_UP_TO_PAGE_SIZE(x)  ((char *)( \
246     ((rvm_length_t)(x)+rvm_page_size()-1) & rvm_page_mask()))
247 
248 /* return address x rounded down to page boundary */
249 #define RVM_ROUND_ADDR_DOWN_TO_PAGE_SIZE(x)  ((char *)( \
250     (rvm_length_t)(x) & rvm_page_mask()))
251 
252 /* return rvm_offset x rounded up to next integral page-size offset */
253 #define RVM_ROUND_OFFSET_UP_TO_PAGE_SIZE(x)  \
254     rvm_rnd_offset_up_to_page(&(x))
255 
256 /* return rvm_offset x rounded down to integral page-size offset */
257 #define RVM_ROUND_OFFSET_DOWN_TO_PAGE_SIZE(x)  \
258     rvm_rnd_offset_dn_to_page(&(x))
259 
260 /* transaction identifier descriptor */
261 typedef struct
262     {
263     rvm_struct_id_t struct_id;          /* self-identifier, do not change */
264     rvm_bool_t      from_heap;          /* true if heap allocated;
265                                            do not change */
266     struct timeval  uname;              /* unique name (timestamp) */
267 
268     void            *tid;               /* internal use only */
269     rvm_length_t    reserved;           /* internal use only */
270     }
271 rvm_tid_t;
272 
273 /* rvm_tid_t initializer, copier & finalizer */
274 
275 extern rvm_tid_t    *rvm_malloc_tid ();
276 
277 extern void rvm_init_tid(rvm_tid_t       *tid); /* pointer to record to initialize */
278 extern rvm_tid_t *rvm_copy_tid(rvm_tid_t *tid); /* pointer to record to be copied */
279 extern void rvm_free_tid(rvm_tid_t  *tid);      /* pointer to record to be copied */
280 
281 /*  options descriptor:  rvm_options_t */
282 typedef struct
283     {
284     rvm_struct_id_t struct_id;          /* self-identifier, do not change */
285     rvm_bool_t      from_heap;          /* true if heap allocated;
286                                            do not change */
287 
288     char            *log_dev;           /* device name */
289     long            truncate;           /* truncation threshold, % of log */
290     rvm_length_t    recovery_buf_len;   /* length of recovery buffer */
291     rvm_length_t    flush_buf_len;      /* length of flush buffer (partitions only) */
292     rvm_length_t    max_read_len;       /* maximum single read length */
293     rvm_bool_t      log_empty;          /* TRUE  ==> log empty */
294     char            *pager;             /* char array for external pager name */
295     long            n_uncommit;         /* length of uncommitted tid array */
296     rvm_tid_t       *tid_array;         /* ptr to array of uncommitted tid's */
297 
298     rvm_length_t    flags;              /* bit vector for optimization and
299                                            other flags */
300     rvm_bool_t      create_log_file;    /* TRUE  ==> create the log file */
301     rvm_offset_t    create_log_size;    /* when creating a new log file, this
302                                            is the wanted size */
303     long            create_log_mode;    /* when creating a new log file, this
304                                            is the wanted mode */
305     }
306 rvm_options_t;
307 
308 /* rvm_options default values and other constants */
309 
310 #define TRUNCATE            50          /* 50% default truncation threshold */
311 #define RECOVERY_BUF_LEN    (256*1024)  /* default recovery buffer length */
312 #define MIN_RECOVERY_BUF_LEN (64*1024)  /* minimum recovery buffer length */
313 #define FLUSH_BUF_LEN       (256*1024)  /* default flush buffer length */
314 #define MIN_FLUSH_BUF_LEN    (64*1024)  /* minimum flush buffer length */
315 #define MAX_READ_LEN        (512*1024)  /* default maximum single read length */
316 
317 #define RVM_COALESCE_RANGES 1           /* coalesce adjacent or shadowed
318                                            ranges within a transaction */
319 #define RVM_COALESCE_TRANS  2           /* coalesce adjacent or shadowed ranges
320                                            within no_flush transactions */
321 
322 #define RVM_ALL_OPTIMIZATIONS   (RVM_COALESCE_RANGES | RVM_COALESCE_TRANS)
323 
324 /* Other flags */
325 
326 #define RVM_MAP_PRIVATE     8		/* Use private mapping, if available */
327 
328 /* rvm_options_t initializer, copier & finalizer */
329 
330 extern rvm_options_t *rvm_malloc_options();
331 
332 extern void rvm_init_options(rvm_options_t *options);
333 extern rvm_options_t *rvm_copy_options(rvm_options_t *options);
334 extern void rvm_free_options(rvm_options_t   *options);
335 
336 /*  region descriptor: rvm_region_t */
337 typedef struct
338     {
339     rvm_struct_id_t struct_id;          /* self-identifier, do not change */
340     rvm_bool_t      from_heap;          /* true if heap allocated;
341                                            do not change */
342 
343     char            *data_dev;          /* device name */
344     rvm_offset_t    dev_length;         /* maximum device length */
345     rvm_offset_t    offset;             /* offset of region in segment */
346     char            *vmaddr;            /* vm address of region/range */
347     rvm_length_t    length;             /* length of region/range */
348     rvm_bool_t      no_copy;            /* do not copy mapped data if true */
349     }
350 rvm_region_t;
351 
352 /* rvm_region_t allocator, initializer, copier & finalizer */
353 extern rvm_region_t *rvm_malloc_region ();
354 extern void rvm_init_region(rvm_region_t *region);
355 /* note: copier copies pointers to the char arrays */
356 extern rvm_region_t *rvm_copy_region(rvm_region_t *region);
357 extern void rvm_free_region(rvm_region_t *region);
358 
359 /*
360         Main Function Declarations
361 */
362 
363 /* RVM initialization: pass version and optional options
364    descriptor */
365 extern rvm_return_t rvm_initialize(const char *version, rvm_options_t *opts);
366 /* init macro */
367 #define RVM_INIT(options) rvm_initialize(RVM_VERSION,(options))
368 
369 /* shutdown RVM */
370 extern rvm_return_t rvm_terminate (void);   /* no parameters */
371 
372 /* map recoverable storage */
373 extern rvm_return_t rvm_map(
374     rvm_region_t         *region,       /* pointer to region descriptor */
375     rvm_options_t        *options       /* optional ptr to option descriptor */
376     );
377 
378 /* unmap recoverable storage */
379 extern rvm_return_t rvm_unmap(rvm_region_t *region);
380 
381 /* set RVM options */
382 extern rvm_return_t rvm_set_options(rvm_options_t *options);
383 
384 /* query RVM options */
385 extern rvm_return_t rvm_query(
386     rvm_options_t       *options,       /* address of pointer to option
387                                            descriptor [out] */
388     rvm_region_t        *region         /* optional pointer to region descriptor */
389     );
390 
391 /* begin a transaction */
392 extern rvm_return_t rvm_begin_transaction(
393     rvm_tid_t           *tid,           /* pointer to transaction identifier */
394     rvm_mode_t          mode            /* transaction begin mode */
395     );
396 
397 /* declare a modification region for a transaction */
398 extern rvm_return_t rvm_set_range(
399     rvm_tid_t           *tid,           /* pointer to transaction identifier */
400     void                *dest,          /* base address of modification range */
401     rvm_length_t        length          /* length of modification range */
402     );
403 
404 /* modification of a region for a transaction */
405 extern rvm_return_t rvm_modify_bytes(
406     rvm_tid_t           *tid,           /* pointer to transaction identifier */
407     void                *dest,          /* base address of modification range */
408     const void          *src,           /* base address of source range */
409     rvm_length_t        length          /* length of modification range */
410     );
411 
412 /* abort a transaction */
413 extern rvm_return_t rvm_abort_transaction(
414     rvm_tid_t           *tid            /* pointer to transaction identifier */
415     );
416 
417 /* commit a transaction */
418 extern rvm_return_t rvm_end_transaction(
419     rvm_tid_t           *tid,           /* pointer to transaction identifier */
420     rvm_mode_t          mode            /* transaction commit mode */
421     );
422 
423 /* flush log cache buffer to log device */
424 extern rvm_return_t rvm_flush(); /* no parameters */
425 
426 /* apply logged changes to segments and garbage collect the log device */
427 extern rvm_return_t rvm_truncate(); /* no parameters */
428 
429 /* initialize log */
430 extern rvm_return_t rvm_create_log(
431     rvm_options_t   *rvm_options,       /* ptr to options record */
432     rvm_offset_t    *log_len,           /* length of log data area */
433     long            mode                /* file creation protection mode */
434     );
435 
436 /* underlying support functions for length, offset, and rounding macros
437 
438    *** use outside of the macros can compromise portability ***
439 
440    these functions will not be implemented on machines with 64-bit
441    integer formats since their operations will be available in the
442    native instruction set
443 */
444 extern rvm_offset_t rvm_mk_offset(
445     rvm_length_t        x,
446     rvm_length_t        y
447     );
448 extern rvm_offset_t rvm_add_offsets(
449     rvm_offset_t        *x,
450     rvm_offset_t        *y
451 );
452 extern rvm_offset_t rvm_add_length_to_offset(
453     rvm_offset_t        *offset,
454     rvm_length_t        length
455     );
456 extern rvm_offset_t rvm_sub_offsets(
457     rvm_offset_t        *x,
458     rvm_offset_t        *y
459     );
460 extern rvm_offset_t rvm_sub_length_from_offset(
461     rvm_offset_t        *offset,
462     rvm_length_t        length
463     );
464 
465 /* private functions to support page rounding */
466 
467 extern rvm_length_t rvm_page_size ();
468 extern rvm_length_t rvm_page_mask ();
469 extern rvm_offset_t rvm_rnd_offset_up_to_page(rvm_offset_t *x);
470 extern rvm_offset_t rvm_rnd_offset_dn_to_page(rvm_offset_t *x);
471 
472 #endif /* RVM_VERSION */
473