aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/dmsdos.h
blob: 5606f524a36ef63d668617c9a3e3c0615b295eed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
/*
dmsdos.h

DMSDOS CVF-FAT module: declaration of dmsdos functions and structures.

******************************************************************************
DMSDOS (compressed MSDOS filesystem support) for Linux
written 1995-1998 by Frank Gockel and Pavel Pisa

    (C) Copyright 1995-1998 by Frank Gockel
    (C) Copyright 1996-1998 by Pavel Pisa

Some code of dmsdos has been copied from the msdos filesystem
so there are the following additional copyrights:

    (C) Copyright 1992,1993 by Werner Almesberger (msdos filesystem)
    (C) Copyright 1994,1995 by Jacques Gelinas (mmap code)
    (C) Copyright 1992-1995 by Linus Torvalds

DMSDOS was inspired by the THS filesystem (a simple doublespace
DS-0-2 compressed read-only filesystem) written 1994 by Thomas Scheuermann.

The DMSDOS code is distributed under the Gnu General Public Licence.
See file COPYING for details.
******************************************************************************

*/

#ifndef _DMSDOS_H
#define _DMSDOS_H

/* version number hacks */
#define LVC(x,y,z) ((x)*65536+(y)*256+(z))

#ifdef __KERNEL__

#ifndef LINUX_VERSION_CODE
 #include<linux/version.h>
#endif
#if LINUX_VERSION_CODE == LVC(2,2,1)
 /* this works around a bug in Linux 2.2.1 */
 #include<asm/page.h>
#endif
#include<asm/semaphore.h>
#include<linux/fs.h>
#if LINUX_VERSION_CODE < LVC(2,3,3)
 #define init_MUTEX(sem) (*sem=MUTEX)
 #define DECLARE_MUTEX(name) struct semaphore name=MUTEX
 #define DECLARE_WAIT_QUEUE_HEAD(name) \
  	struct wait_queue * name=NULL
#endif

#if LINUX_VERSION_CODE >= LVC(2,1,78)
 #define __FOR_KERNEL_2_1_80
 #if LINUX_VERSION_CODE < LVC(2,1,80)
  #define READPAGE_DENTRY
 #else
  #define FAT_GET_CLUSTER
  #if LINUX_VERSION_CODE < LVC(2,3,0)
    #define READPAGE_INODE
  #else
   #if LINUX_VERSION_CODE < LVC(2,3,10)
    #define READPAGE_FILE
   #else
    #define __FOR_KERNEL_2_3_10
    #if LINUX_VERSION_CODE >= LVC(2,3,30)
     #define __FOR_KERNEL_2_3_30
     #define READPAGE_DENTRY
     #define HAS_SB_CLUSTER_BITS
    #endif
   #endif
  #endif
 #endif
#endif
#if (LINUX_VERSION_CODE >= LVC(2,1,0)) && (LINUX_VERSION_CODE < LVC(2,1,78))
 #error dmsdos 0.9.x needs kernel >= 2.1.80 or use 2.0.33
#endif

#ifdef FAT_GET_CLUSTER
#define get_cluster fat_get_cluster
#endif

#endif /* __KERNEL__*/

#include "dmsdos-config.h"
/* hacks for new Configure */
#ifndef DMSDOS_EXPERT
#define USE_VMALLOC
#define LISTSIZE 1024
#define MDFATCACHESIZE 40
#define DFATCACHESIZE 20
#define BITFATCACHESIZE 10
#define MAX_CACHE_TIME 60
#define CCACHESIZE 64
#define MAX_CCACHE_TIME 240
#define MAX_READA 64
#define USE_READA_LIST
#define READA_LIST_SIZE 256
#define READA_THRESHOLD 4095
#define DEFAULT_LOGLEVEL 0
#define DEFAULT_CF 11
#define DMSDOS_USE_READPAGE
#define IDMSDOSD_TIME 30
#define SP_BIT0 /* never compress dir */
#define SP_BIT1 /* never compress EMD */
#define SP_BIT4 /* write-back caching */
#define SP_BIT5 /* read-ahead */
#define SP_BIT7 /* daemon compresses */
#endif /* DMSDOS_EXPERT */

#ifndef SP_BIT0
#define SP_BIT0 0
#else
#undef SP_BIT0
#define SP_BIT0 1
#endif

#ifndef SP_BIT1
#define SP_BIT1 0
#else
#undef SP_BIT1
#define SP_BIT1 1
#endif

#ifndef SP_BIT2
#define SP_BIT2 0
#else
#undef SP_BIT2
#define SP_BIT2 1
#endif

#ifndef SP_BIT3
#define SP_BIT3 0
#else
#undef SP_BIT3
#define SP_BIT3 1
#endif

#ifndef SP_BIT4
#define SP_BIT4 0
#else
#undef SP_BIT4
#define SP_BIT4 1
#endif

#ifndef SP_BIT5
#define SP_BIT5 0
#else
#undef SP_BIT5
#define SP_BIT5 1
#endif

#ifndef SP_BIT6
#define SP_BIT6 0
#else
#undef SP_BIT6
#define SP_BIT6 1
#endif

#ifndef SP_BIT7
#define SP_BIT7 0
#else
#undef SP_BIT7
#define SP_BIT7 1
#endif

#ifndef SP_BIT8
#define SP_BIT8 0
#else
#undef SP_BIT8
#define SP_BIT8 1
#endif

#ifndef DEFAULT_SPEEDUP
#define DEFAULT_SPEEDUP ((SP_BIT8<<8)|(SP_BIT7<<7)|(SP_BIT6<<6)|(SP_BIT5<<5)|(SP_BIT4<<4)|(SP_BIT3<<3)|(SP_BIT2<<2)|(SP_BIT1<<1)|(SP_BIT0))
#endif
#ifndef DEFAULT_COMP
#define DEFAULT_COMP GUESS
#endif
#ifndef LISTSIZE
#define LISTSIZE 1024
#endif
#ifndef MDFATCACHESIZE
#define MDFATCACHESIZE 40
#endif
#ifndef DFATCACHESIZE
#define DFATCACHESIZE 20
#endif
#ifndef BITFATCACHESIZE
#define BITFATCACHESIZE 10
#endif
#ifndef MAX_CACHE_TIME
#define MAX_CACHE_TIME 60
#endif
#ifndef CCACHESIZE
#define CCACHESIZE 64
#endif
#ifndef MAX_CCACHE_TIME
#define MAX_CCACHE_TIME 240
#endif
#ifndef MAX_READA
#define MAX_READA 64
#endif
#ifndef READA_LIST_SIZE
#define READA_LIST_SIZE 256
#endif
#ifndef READA_THRESHOLD
#define READA_THRESHOLD 4095
#endif
#ifndef DEFAULT_LOGLEVEL
#define DEFAULT_LOGLEVEL 0
#endif
#ifndef DEFAULT_CF
#define DEFAULT_CF 11
#endif
#ifndef IDMSDOSD_TIME
#define IDMSDOSD_TIME 30
#endif


#define DMSDOS_MAJOR      0
#define DMSDOS_MINOR      9
#define DMSDOS_ACT_REL    2
#define DMSDOS_COMP_REL   2
#define DMSDOS_PL         "2"
#define DMSDOS_EXTRA      "(alpha test)"

#define DMSDOS_VERSION ((DMSDOS_MAJOR<<16)|(DMSDOS_MINOR<<8)|DMSDOS_ACT_REL)
#define DMSDOS_LOWEST_COMPATIBLE_VERSION ((DMSDOS_MAJOR<<16)|(DMSDOS_MINOR<<8)|DMSDOS_COMP_REL)
#define DMSDOS_VLT "pl" DMSDOS_PL DMSDOS_EXTRA

/* config hacks */
#if (defined(DMSDOS_CONFIG_DBLSP_DRVSP) || defined(DMSDOS_CONFIG_DRVSP3))
#define DMSDOS_CONFIG_DBL
#endif
#if (defined(DMSDOS_CONFIG_STAC3) || defined(DMSDOS_CONFIG_STAC4))
#define DMSDOS_CONFIG_STAC
#endif
#if (!defined(DMSDOS_CONFIG_DBL) && !defined(DMSDOS_CONFIG_STAC))
#error configuration: no CVF format to compile in !!!
#endif

/* known compression methods */
#define DS_0_0 0x00005344
#define DS_0_1 0x01005344
#define DS_0_2 0x02005344
#define JM_0_0 0x00004D4A
/* drivespace 3 high compression */ 
#define JM_0_1 0x01004D4A
/* drivespace 3 ultra compression */
#define SQ_0_0 0x00005153
/* stacker 3 compression (no header) */
#define SD_3 0x00000000
/* stacker 4 compression */
#define SD_4 0x00000081

/* other defines for options */
#define READ_ONLY -1
#define UNCOMPRESSED -2
#define GUESS -3

#define MIN_FREE_SECTORS ( (dblsb->s_cvf_version==DRVSP3              \
                            &&(dmsdos_speedup&SP_NO_FRAG_WRITE)==0)  \
                           ?dblsb->s_sectperclust+1                   \
                           :10*dblsb->s_sectperclust )

typedef struct
{ unsigned long free_sectors;
  unsigned long used_sectors;
  unsigned long max_hole;
  unsigned long free_clusters;
  unsigned long used_clusters;
  unsigned long lost_clusters;
  unsigned long sectors_lo;
  unsigned long sectors_hi;
  unsigned long compressed_clusters;
  unsigned long uncompressed_clusters;
} Dblstat;                                                            

typedef struct
{ long sector_minus_1;
  short size_lo_minus_1;
  short size_hi_minus_1;
  short unknown; /* some bits I don't know to handle.... */
  short flags; /* 00...0uc - u=used, c=compressed */ 
} Mdfat_entry;

/* flag values */
#define D_EMPTY       0
#define D_VALID       1    /* entry is valid -> cluster to be compressed */
#define D_IN_D_ACTION 2    /* is being compressed by daemon */
#define D_OVERWRITTEN 3    /* has been overwritten by dmsdos while daemon
                            is compressing it -> throw away the result from
                            the daemon */
#ifdef __KERNEL__
# ifdef USE_XMALLOC
   void* xmalloc(unsigned long);
   void xfree(void*);
#  define MALLOC(x) xmalloc(x)
#  define FREE(x) xfree(x)
# else
#  ifdef USE_VMALLOC
#   include<linux/mm.h>
#   ifdef __FOR_KERNEL_2_1_80
#    include<linux/vmalloc.h>
#   endif
#   define MALLOC(x) vmalloc(x)
#   define FREE(x) vfree(x)
#  else
#   include<linux/malloc.h>
#   define MALLOC(x) kmalloc(x,GFP_KERNEL)
#   define FREE(x) kfree(x)
#  endif
# endif
#endif

/* this must be known outside the kernel too */
typedef struct {
  int s_dcluster;/*[45-46]*/
  int s_mdfatstart;/*[36-37]+1*/
  int s_fatstart;/*[39-40]+[14-15]*/ 
  int s_rootdir;/*[41-42]+[39-40]*/
  int s_rootdirentries;
  int s_sectperclust;
  int s_spc_bits;
  int s_16bitfat;
  int s_datastart;
  int s_dataend;
  int s_comp;
  int s_bootblock;/*[39-40]*/
  int s_cfaktor;
  int s_full;
  int s_max_cluster;
  int s_max_cluster2;
  int s_cvf_version;   /* dblsp/drvsp/drvsp3/stac3/stac4 */
  int s_2nd_fat_offset;
  int s_lastnear;
  int s_lastbig;
  int s_free_sectors;
  void * mdfat_alloc_semp;
} Dblsb;

#define DBLSP   0
#define DRVSP   1
#define DRVSP3  2
#define STAC3   3
#define STAC4   4

#define UC_NORMAL 0
#define UC_UNCOMPR 1
#define UC_TEST 2
#define UC_DIRECT 3

/* cvf version capabilities - boolean values */
#define DIR_MAY_BE_SHORT(dblsb)       (dblsb->s_cvf_version==DRVSP3)
#define DIR_MAY_BE_COMPRESSED(dblsb)  (dblsb->s_cvf_version>=DRVSP3&&(dmsdos_speedup&SP_NO_DIR_COMPR)==0)
#define UMOUNT_UCFLAG ((dmsdos_speedup&SP_NO_UNMOUNT_COMPR)?UC_UNCOMPR:UC_DIRECT)

typedef struct {
  struct buffer_head * a_buffer;
  unsigned int a_area;
  unsigned long a_time;
  struct super_block* a_sb;
  unsigned int a_acc;
} Acache;

#define C_FREE 0                /* cluster cache entry is free */
#define C_VALID 1               /* data points to valid cluster data */
#define C_DIRTY_NORMAL 2        /* like VALID but data need to be written */
#define C_DIRTY_UNCOMPR 3       /* like VALID but data need to be written */
#define C_DELETED 4             /* like VALID but last request was a delete */
#define C_INVALID 5             /* data are junk but valid memory adress */
#define C_NOT_MALLOCD 6         /* data pointer is not a valid address */ 

#define C_KEEP_LOCK 1
#define C_NO_READ 2

#ifdef __KERNEL__
typedef struct {
  unsigned int c_time;
  unsigned int c_flags;
  unsigned int c_count;
  unsigned int c_length;
  unsigned int c_clusternr;
  struct super_block* c_sb;
  unsigned char* c_data;
  struct semaphore c_sem;
  unsigned int c_errors;
} Cluster_head;
#endif /*__KERNEL__*/

int dbl_mdfat_value(struct super_block*sb, int clusternr,
                     Mdfat_entry*new,Mdfat_entry*mde);
int dbl_fat_nextcluster(struct super_block*sb,int clusternr,int*);
int dbl_bitfat_value(struct super_block*sb,int sektornr,int*);
void exit_dbl(struct super_block*sb);
int find_free_bitfat(struct super_block*sb, int sektornr, int size);
int dbl_replace_existing_cluster(struct super_block*sb, int cluster, 
                             int near_sector,
                             Mdfat_entry*,unsigned char*);
int stac_replace_existing_cluster(struct super_block*sb, int cluster, 
                             int near_sector,
                             Mdfat_entry*);
int dbl_compress(unsigned char* clusterk, unsigned char* clusterd, 
                      int size, int method,int);
#if 0
int stac_compress(void* pin,int lin, void* pout, int lout,
                  int method, int cfaktor);
#else
int stac_compress(unsigned char* pin,int lin, unsigned char* pout, int lout,
                  int method, int cfaktor);
#endif
int sq_comp(void* pin,int lin, void* pout, int lout, int flg);
int dbl_decompress(unsigned char*clusterd, unsigned char*clusterk,
               Mdfat_entry*mde);
int dmsdos_write_cluster(struct super_block*sb,
                         unsigned char* clusterd, int length, int clusternr,
                         int near_sector, int ucflag);

#define CHS(i) ( (unsigned short)i[0]|(unsigned short)i[1]<<8 )
#define CHL(i) ( (unsigned long)i[0]|(unsigned long)i[1]<<8| \
                 (unsigned long)i[2]<<16|(unsigned long)i[3]<<24 )

int dbl_mdfat_cluster2sector(struct super_block*sb,int clusternr);
int simple_check(struct super_block*sb,int repair);
void do_spc_init(void);
void do_spc_exit(void);
void lock_mdfat_alloc(Dblsb*);
void unlock_mdfat_alloc(Dblsb*);
void free_cluster_sectors(struct super_block*sb, int clusternr);
void stac_special_free(struct super_block*sb, int clusternr);
int stac_write_cluster(struct super_block*sb,
                       unsigned char* clusterd, int length, int clusternr,
                       int near_sector, int ucflag);
int stac_read_cluster(struct super_block*sb,unsigned char*clusterd,
                      int clusternr);
void free_idle_cache(void);
void free_idle_ccache(void);
void ccache_init(void);
void free_ccache_dev(struct super_block*sb);
#ifdef __KERNEL__
Cluster_head* ch_read(struct super_block*sb,int clusternr,int flag);
Cluster_head* find_in_ccache(struct super_block*sb,
                             int clusternr,Cluster_head**lastfree,
                             Cluster_head**oldest);
int ch_dirty(Cluster_head*,int near,int ucflag);
int ch_dirty_locked(Cluster_head*,int near,int ucflag);
void lock_ch(Cluster_head*);
void unlock_ch(Cluster_head*);
void ch_dirty_retry_until_success(Cluster_head*,int near,int ucflag);
void ch_free(Cluster_head*);
#endif
void sync_cluster_cache(int allow_daemon);
void delete_cache_cluster(struct super_block*sb, int clusternr);
void log_list_statistics(void);
void log_ccache_statistics(void);
void log_found_statistics(void);
int sq_dec(void* pin,int lin, void* pout, int lout, int flg);
                                               
/* Stacker cluster allocation types access */

#if defined(__KERNEL__)||defined(__DMSDOS_LIB__)
/* structure for walking/working with each sector of cluster */
typedef struct {
  struct super_block*sb;
  int clusternr;
  int start_sect;
  int start_len;
  int flags;
  int sect_cnt;
  int compressed;
  int bytes_in_last;
  int bytes_in_clust;
  struct buffer_head *fbh; /* first sector of fragmented clust */
  /* changes during fragments reads */
  int fcnt;	/* count of unreaded fragments */
  int flen;	/* rest sectors in fragment */
  int sect;	/* actual sector */
  int offset;	/* byte offset in sector */
  int bytes;	/* number of data bytes in sector */
  unsigned char* finfo;	/* points to actual field in fbh */
} Stac_cwalk;

int stac_cwalk_init(Stac_cwalk *cw,struct super_block*sb,
		 int clusternr,int flg);
int stac_cwalk_sector(Stac_cwalk *cw);
void stac_cwalk_done(Stac_cwalk *cw);
#endif /* __KERNEL__||__DMSDOS_LIB__*/

/* loglevel defines */

extern unsigned long loglevel;

#ifdef SEQLOG
int log_prseq(void);
#define LOGCMD if(log_prseq())printk
#else
#define LOGCMD printk
#endif

#ifndef NOLOG
#define LOG_FS      if(loglevel&0x00000001)LOGCMD
#define LOG_CLUST   if(loglevel&0x00000002)LOGCMD
#define LOG_LLRW    if(loglevel&0x00000008)LOGCMD
#define LOG_DFAT    if(loglevel&0x00000010)LOGCMD
#define LOG_MDFAT   if(loglevel&0x00000020)LOGCMD
#define LOG_BITFAT  if(loglevel&0x00000040)LOGCMD
#define LOG_DECOMP  if(loglevel&0x00000080)LOGCMD
#define LOG_COMP    if(loglevel&0x00000100)LOGCMD
#define LOG_ALLOC   if(loglevel&0x00000200)LOGCMD
#define LOG_DAEMON  if(loglevel&0x00000400)LOGCMD
#define LOG_CCACHE  if(loglevel&0x00000800)LOGCMD
#define LOG_ACACHE  if(loglevel&0x00001000)LOGCMD
#define LOG_REST    if(loglevel&0x80000000)LOGCMD
#else
#define LOG_FS(x,args...)
#define LOG_CLUST(x,args...)
#define LOG_LLRW(x,args...)
#define LOG_DFAT(x,args...)
#define LOG_MDFAT(x,args...)
#define LOG_BITFAT(x,args...)
#define LOG_DECOMP(x,args...)
#define LOG_COMP(x,args...)
#define LOG_ALLOC(x,args...)
#define LOG_DAEMON(x,args...)
#define LOG_CCACHE(x,args...)
#define LOG_ACACHE(x,args...)
#define LOG_REST(x,args...)
#endif

#ifdef __FOR_KERNEL_2_1_80
/* some hacks since the memcpy_from/tofs functions have changed here */
#include  <asm/uaccess.h>
#define memcpy_fromfs copy_from_user
#define memcpy_tofs copy_to_user
#endif

struct buffer_head *raw_bread (
        struct super_block *sb,
        int block);
struct buffer_head *raw_getblk (
        struct super_block *sb,
        int block);
void raw_brelse (
        struct super_block *sb,
        struct buffer_head *bh);
void raw_mark_buffer_dirty (
        struct super_block *sb,
        struct buffer_head *bh,
        int dirty_val);
void raw_set_uptodate (
        struct super_block *sb,
        struct buffer_head *bh,
        int val);
int raw_is_uptodate (
        struct super_block *sb,
        struct buffer_head *bh);
void raw_ll_rw_block (
        struct super_block *sb,
        int opr,
        int nbreq,
        struct buffer_head *bh[32]);

#define FAKED_ROOT_DIR_OFFSET 1
#define FAKED_DATA_START_OFFSET 1000
int dmsdos_read_cluster(struct super_block*sb,
                        unsigned char*clusterd, int clusternr);

struct buffer_head* dblspace_bread(struct super_block*sb,int vsector);
struct buffer_head *dblspace_getblk (
        struct super_block *sb,
        int block);
void dblspace_brelse(struct super_block* sb,struct buffer_head*bh);
void dblspace_mark_buffer_dirty(struct super_block*sb,struct buffer_head*bh,
                                int dirty_val);
void dblspace_set_uptodate (
        struct super_block *sb,
        struct buffer_head *bh,
        int val);
int dblspace_is_uptodate (
        struct super_block *sb,
        struct buffer_head *bh);
void dblspace_ll_rw_block (
        struct super_block *sb,
        int opr,
        int nbreq,
        struct buffer_head *bh[32]);
int stac_bitfat_state(struct super_block*sb,int new_state);
int dblspace_fat_access(struct super_block*sb, int clusternr,int newval);
#ifdef __KERNEL__
int dblspace_bmap(struct inode*inode, int block);
int dblspace_smap(struct inode*inode, int block);
#endif
int ds_dec(void* pin,int lin, void* pout, int lout, int flg);
#ifdef __KERNEL__
void dblspace_zero_new_cluster(struct inode*,int clusternr);
#ifdef __FOR_KERNEL_2_1_80
ssize_t dblspace_file_read(struct file *filp,char *buf,size_t count,
                           loff_t *ppos);
ssize_t dblspace_file_write(struct file *filp,const char *buf,size_t count,
                           loff_t *ppos);
int dblspace_mmap(struct file*file,
                  struct vm_area_struct*vma);
#else
int dblspace_file_read(struct inode *inode,struct file *filp,char *buf,
                                int count);
int dblspace_file_write(struct inode *inode,struct file *filp,const char *buf,
                                int count);
int dblspace_mmap(struct inode*inode,struct file*file,
                  struct vm_area_struct*vma);
#endif

#ifdef READPAGE_DENTRY
 int dblspace_readpage(struct dentry*dentry, struct page *page);
#else
 #ifdef READPAGE_FILE
  int dblspace_readpage(struct file *file, struct page *page);
 #else
  #ifdef READPAGE_INODE 
   int dblspace_readpage(struct inode *inode, struct page *page);
  #else
   #error Unknown readpage parameters
  #endif
 #endif
#endif

int dmsdos_ioctl_dir(struct inode *dir,struct file *filp,
                     unsigned int cmd, unsigned long data);
#endif /* __KERNEL__ */
int try_daemon(struct super_block*sb,int clusternr, int length, int method);
void remove_from_daemon_list(struct super_block*sb,int clusternr);
void force_exit_daemon(void);
void dblspace_reada(struct super_block*sb, int sector,int count);
void init_reada_list(void);
void kill_reada_list_dev(int dev);
int daemon_write_cluster(struct super_block*sb,unsigned char*data,
                         int len, int clusternr, int rawlen);
void check_free_sectors(struct super_block*sb);
void get_memory_usage_acache(int*, int*max);
void get_memory_usage_ccache(int*, int*max);
int mount_dblspace(struct super_block*sb,char*options);
int mount_stacker(struct super_block*sb,char*options);
int detect_dblspace(struct super_block*sb);
int detect_stacker(struct super_block*sb);
int unmount_dblspace(struct super_block*sb);

typedef struct
{ int clusternr;
  struct super_block*sb;
  int length;   /* in bytes */
  char flag;
  int method;
} Rwlist;

void init_daemon(void);
void exit_daemon(void);
void clear_list_dev(struct super_block*sb);

/* speedup bits */
#define SP_NO_DIR_COMPR 0x0001
#define SP_NO_EMD_COMPR 0x0002
#define SP_NO_EXACT_SEARCH 0x0004
#define SP_NO_UNMOUNT_COMPR 0x0008
#define SP_USE_WRITE_BACK 0x0010
#define SP_USE_READ_AHEAD 0x0020
#define SP_FAST_BITFAT_ALLOC 0x0040
#define SP_USE_DAEMON 0x0080
#define SP_NO_FRAG_WRITE 0x0100

typedef struct
{ int ccachebytes;
  int max_ccachebytes;
  int acachebytes;
  int max_acachebytes;
} Memuse;


#define DMSDOS_IOCTL_MIN 0x2000
#define DMSDOS_IOCTL_MAX 0x201F
#define DMSDOS_GET_DBLSB 0x2000
#define DMSDOS_EXTRA_STATFS 0x2001
#define DMSDOS_READ_BLOCK 0x2002
#define DMSDOS_WRITE_BLOCK 0x2003
#define DMSDOS_READ_DIRENTRY 0x2004  /* obsolete */
#define DMSDOS_WRITE_DIRENTRY 0x2005 /* obsolete */
#define DMSDOS_READ_BITFAT 0x2006
#define DMSDOS_WRITE_BITFAT 0x2007
#define DMSDOS_READ_MDFAT 0x2008
#define DMSDOS_WRITE_MDFAT 0x2009
#define DMSDOS_READ_DFAT 0x200a
#define DMSDOS_WRITE_DFAT 0x200b
#define DMSDOS_SET_COMP 0x200c
#define DMSDOS_SET_CF 0x200d
#define DMSDOS_SIMPLE_CHECK 0x200e
#define DMSDOS_DUMPCACHE 0x200f
#define DMSDOS_D_ASK 0x2010
#define DMSDOS_D_READ 0x2011
#define DMSDOS_D_WRITE 0x2012
#define DMSDOS_D_EXIT 0x2013
#define DMSDOS_MOVEBACK 0x2014       /* obsolete */
#define DMSDOS_SET_MAXCLUSTER 0x2015 /* currently not supported */
#define DMSDOS_READ_CLUSTER 0x2016
#define DMSDOS_FREE_IDLE_CACHE 0x2017
#define DMSDOS_SET_LOGLEVEL 0x2018
#define DMSDOS_SYNC_CCACHE 0x2019
#define DMSDOS_LOG_STATISTICS 0x201a
#define DMSDOS_SET_SPEEDUP 0x201b
#define DMSDOS_RECOMPRESS 0x201c     /* obsolete */
#define DMSDOS_REPORT_MEMORY 0x201d
#define IS_DMSDOS_IOCTL(cmd) ((cmd)>=DMSDOS_IOCTL_MIN&&(cmd)<=DMSDOS_IOCTL_MAX)

/* dmsdos library interface */
struct super_block* open_cvf(char*filename,int rwflag);
void close_cvf(struct super_block*sb);

#endif