|
|
1.1 ! root 1: /* ! 2: dblspace_interface.c ! 3: ! 4: DMSDOS CVF-FAT module: high-level interface functions. ! 5: ! 6: ****************************************************************************** ! 7: DMSDOS (compressed MSDOS filesystem support) for Linux ! 8: written 1995-1998 by Frank Gockel and Pavel Pisa ! 9: ! 10: (C) Copyright 1995-1998 by Frank Gockel ! 11: (C) Copyright 1996-1998 by Pavel Pisa ! 12: ! 13: Some code of dmsdos has been copied from the msdos filesystem ! 14: so there are the following additional copyrights: ! 15: ! 16: (C) Copyright 1992,1993 by Werner Almesberger (msdos filesystem) ! 17: (C) Copyright 1994,1995 by Jacques Gelinas (mmap code) ! 18: (C) Copyright 1992-1995 by Linus Torvalds ! 19: ! 20: DMSDOS was inspired by the THS filesystem (a simple doublespace ! 21: DS-0-2 compressed read-only filesystem) written 1994 by Thomas Scheuermann. ! 22: ! 23: The DMSDOS code is distributed under the Gnu General Public Licence. ! 24: See file COPYING for details. ! 25: ****************************************************************************** ! 26: ! 27: */ ! 28: ! 29: #ifdef __KERNEL__ ! 30: # include <linux/fs.h> ! 31: # include <linux/blkdev.h> ! 32: # include <linux/msdos_fs.h> ! 33: # include <linux/msdos_fs_sb.h> ! 34: # include <linux/fat_cvf.h> ! 35: # include <linux/string.h> ! 36: # include <linux/malloc.h> ! 37: # include <asm/semaphore.h> ! 38: # include <linux/module.h> ! 39: #endif ! 40: ! 41: #include"dmsdos.h" ! 42: ! 43: #ifdef __DMSDOS_LIB__ ! 44: /* some interface hacks */ ! 45: # include"lib_interface.h" ! 46: # include<string.h> ! 47: # include<malloc.h> ! 48: # define MAJOR(x) 0 ! 49: # define MINOR(x) 0 ! 50: extern long int blk_size[0][0]; ! 51: #endif ! 52: ! 53: extern Acache mdfat[]; ! 54: extern Acache dfat[]; ! 55: extern Acache bitfat[]; ! 56: ! 57: unsigned long loglevel=DEFAULT_LOGLEVEL; ! 58: unsigned long dmsdos_speedup=DEFAULT_SPEEDUP; ! 59: ! 60: /* evaluate numbers from options */ ! 61: char* read_number(char*p, unsigned long* n, int*error) ! 62: { *n=0; ! 63: *error=-1; ! 64: if(*p=='b'||*p=='B'||*p=='%') ! 65: { /*binary*/ ! 66: ++p; ! 67: while(*p=='0'||*p=='1') ! 68: { (*n)*=2; ! 69: if(*p=='1')++(*n); ! 70: ++p; ! 71: *error=0; ! 72: } ! 73: } ! 74: else if(*p=='0'&&(*(p+1)=='x'||*(p+1)=='X')) ! 75: { /*hexadecimal*/ ! 76: p+=2; ! 77: while((*p>='0'&&*p<='9')||(*p>='a'&&*p<='f')||(*p>='A'&&*p<='F')) ! 78: { (*n)*=16; ! 79: (*n)+=((*p<='9')?(*p):(*p)-'a'+10)&0xf; ! 80: ++p; ! 81: *error=0; ! 82: } ! 83: } ! 84: else if(*p=='0'||*p=='O'||*p=='o') ! 85: { /*octal*/ ! 86: ++p; ! 87: while(*p>='0'&&*p<='8') ! 88: { (*n)*=8; ! 89: (*n)+=(*p)-'0'; ! 90: ++p; ! 91: *error=0; ! 92: } ! 93: } ! 94: else ! 95: { /*decimal*/ ! 96: while(*p>='0'&&*p<='9') ! 97: { (*n)*=10; ! 98: (*n)+=(*p)-'0'; ! 99: ++p; ! 100: *error=0; ! 101: } ! 102: } ! 103: LOG_REST("DMSDOS: read_number: n=%lu=0x%lx error=%d\n",*n,*n,*error); ! 104: return p; ! 105: } ! 106: ! 107: /* evaluates a single option (needn't be '\0' terminated) */ ! 108: int evaluate_option(char*option,Dblsb*dblsb,int*repair) ! 109: { int ret=0; ! 110: ! 111: LOG_REST("DMSDOS: evaluate option: %s\n",option); ! 112: if(strncmp(option,"comp=",5)==0||strncmp(option,"comp:",5)==0) ! 113: { if(strncmp(option+5,"no",2)==0)dblsb->s_comp=UNCOMPRESSED; ! 114: /*else if(strncmp(option+5,"ro",2)==0)*comp=READ_ONLY;*/ ! 115: else if(strncmp(option+5,"ds00",4)==0)dblsb->s_comp=DS_0_0; ! 116: else if(strncmp(option+5,"ds01",4)==0)dblsb->s_comp=DS_0_1; ! 117: else if(strncmp(option+5,"ds02",4)==0)dblsb->s_comp=DS_0_2; ! 118: else if(strncmp(option+5,"jm00",4)==0)dblsb->s_comp=JM_0_0; ! 119: else if(strncmp(option+5,"jm01",4)==0)dblsb->s_comp=JM_0_1; ! 120: else if(strncmp(option+5,"sq00",4)==0)dblsb->s_comp=SQ_0_0; ! 121: else if(strncmp(option+5,"sd3",3)==0)dblsb->s_comp=SD_3; ! 122: else if(strncmp(option+5,"sd4",3)==0)dblsb->s_comp=SD_4; ! 123: else if(strncmp(option+5,"guess",5)==0)dblsb->s_comp=GUESS; ! 124: else ret=-1; ! 125: } ! 126: else if(strncmp(option,"cf=",3)==0||strncmp(option,"cf:",3)==0) ! 127: { if(option[3]=='1'&&option[4]>='0'&&option[4]<='2') ! 128: dblsb->s_cfaktor=option[4]-'0'+9; ! 129: else if(option[3]>='1'&&option[3]<='9') ! 130: dblsb->s_cfaktor=option[3]-'0'-1; ! 131: else ret=-1; ! 132: } ! 133: else if(strncmp(option,"loglevel=",9)==0||strncmp(option,"loglevel:",9)==0) ! 134: { /* must be decimal or hexadecimal (0x preceeded) number */ ! 135: read_number(option+9,&loglevel,&ret); ! 136: if(ret>=0) ! 137: LOG_REST("DMSDOS: evaluate_option: loglevel set to 0x%lx.\n",loglevel); ! 138: } ! 139: else if(strncmp(option,"speedup=",8)==0||strncmp(option,"speedup:",8)==0) ! 140: { /* must be decimal or hexadecimal (0x preceeded) number */ ! 141: read_number(option+8,&dmsdos_speedup,&ret); ! 142: if(ret>=0) ! 143: LOG_REST("DMSDOS: evaluate_option: speedup set to 0x%lx.\n",dmsdos_speedup); ! 144: } ! 145: else if(strncmp(option,"bitfaterrs=",11)==0||strncmp(option,"bitfaterrs:",11)==0) ! 146: { if(strncmp(option+11,"repair",6)==0)*repair=1; ! 147: else if(strncmp(option+11,"ignore",6)==0)*repair=2; ! 148: else if(strncmp(option+11,"setro",5)==0)*repair=0; ! 149: else if(strncmp(option+11,"nocheck",7)==0)*repair=-1; ! 150: else ret=-1; ! 151: } ! 152: else ! 153: { printk(KERN_ERR "DMSDOS: unknown option %s, rejected\n",option); ! 154: ret=-1; ! 155: } ! 156: return ret; ! 157: } ! 158: ! 159: int parse_dmsdos_options(char*options,Dblsb*dblsb,int*repair) ! 160: { if(options==NULL)return 0; ! 161: ! 162: while(*options) ! 163: { if(evaluate_option(options,dblsb,repair)<0)return -1; ! 164: while(*options!='\0'&&*options!='.'&&*options!='+')++options; ! 165: while(*options=='.'||*options=='+')++options; ! 166: } ! 167: return 0; ! 168: } ! 169: ! 170: int ilog2(int arg) ! 171: { /* integer log2 */ ! 172: int i=0; ! 173: ! 174: if(arg<=0)return -1; ! 175: ! 176: while(arg>>=1)++i; ! 177: return i; ! 178: } ! 179: ! 180: #ifndef __DMSDOS_LIB__ ! 181: void do_spc_init(void) ! 182: { /* first call of DMSDOS filesystem, initialising variables */ ! 183: int i; ! 184: ! 185: printk(KERN_NOTICE "DMSDOS CVF-FAT extension version %d.%d.%d" DMSDOS_VLT ! 186: " compiled " __DATE__ " " __TIME__ " with options:" ! 187: #ifndef DBL_WRITEACCESS ! 188: " read-only" ! 189: #else ! 190: " read-write" ! 191: #endif ! 192: #ifdef USE_XMALLOC ! 193: ", xmalloc" ! 194: #else ! 195: #ifdef USE_VMALLOC ! 196: ", vmalloc" ! 197: #else ! 198: ", kmalloc" ! 199: #endif ! 200: #endif ! 201: #ifdef DMSDOS_USE_READPAGE ! 202: ", readpage" ! 203: #endif ! 204: #ifdef USE_READA_LIST ! 205: ", reada list" ! 206: #endif ! 207: #ifdef INTERNAL_DAEMON ! 208: ", internal daemon" ! 209: #endif ! 210: #ifdef DMSDOS_CONFIG_DBLSP_DRVSP ! 211: ", doublespace/drivespace(<3)" ! 212: #endif ! 213: #ifdef DMSDOS_CONFIG_DRVSP3 ! 214: ", drivespace 3" ! 215: #endif ! 216: #ifdef DMSDOS_CONFIG_STAC3 ! 217: ", stacker 3" ! 218: #endif ! 219: #ifdef DMSDOS_CONFIG_STAC4 ! 220: ", stacker 4" ! 221: #endif ! 222: "\n", ! 223: DMSDOS_MAJOR,DMSDOS_MINOR,DMSDOS_ACT_REL); ! 224: ! 225: /* init cluster cache */ ! 226: ccache_init(); ! 227: ! 228: /* no this is done by mount ... and removed by unmount ! 229: otherwise the module cannot be unloaded again if the ! 230: internal daemon is running ! 231: init_daemon(); ! 232: */ ! 233: ! 234: #ifdef USE_READA_LIST ! 235: init_reada_list(); ! 236: #endif ! 237: ! 238: for(i=0;i<MDFATCACHESIZE;++i) ! 239: { mdfat[i].a_time=0; ! 240: mdfat[i].a_acc=0; ! 241: mdfat[i].a_buffer=NULL; ! 242: } ! 243: for(i=0;i<DFATCACHESIZE;++i) ! 244: { dfat[i].a_time=0; ! 245: dfat[i].a_acc=0; ! 246: dfat[i].a_buffer=NULL; ! 247: } ! 248: for(i=0;i<BITFATCACHESIZE;++i) ! 249: { bitfat[i].a_time=0; ! 250: bitfat[i].a_acc=0; ! 251: bitfat[i].a_buffer=NULL; ! 252: } ! 253: } ! 254: ! 255: void do_spc_exit(void) ! 256: { ! 257: force_exit_daemon(); ! 258: } ! 259: #endif ! 260: ! 261: #ifdef DMSDOS_CONFIG_DBL ! 262: int detect_dblspace(struct super_block*sb) ! 263: { struct buffer_head*bh; ! 264: ! 265: MOD_INC_USE_COUNT; ! 266: bh=raw_bread(sb,0); ! 267: if(bh==NULL) ! 268: { printk(KERN_ERR "DMSDOS: unable to read super block\n"); ! 269: MOD_DEC_USE_COUNT; ! 270: return 0; ! 271: } ! 272: if(strncmp(bh->b_data+3,"MSDBL6.0",8)==0 ! 273: ||strncmp(bh->b_data+3,"MSDSP6.0",8)==0) ! 274: { raw_brelse(sb,bh); ! 275: MOD_DEC_USE_COUNT; ! 276: return 1; ! 277: } ! 278: raw_brelse(sb,bh); ! 279: MOD_DEC_USE_COUNT; ! 280: return 0; ! 281: } ! 282: ! 283: int mount_dblspace(struct super_block*sb,char*options) ! 284: { struct buffer_head*bh; ! 285: struct buffer_head*bh2; ! 286: int i,mdfatb,fatb; ! 287: unsigned int version_flag; ! 288: unsigned char * pp; ! 289: Dblsb* dblsb; ! 290: int repair=0; ! 291: int mdrc,m_sector=0; ! 292: ! 293: MOD_INC_USE_COUNT; ! 294: LOG_REST("DMSDOS: dblspace/drvspace module mounting...\n"); ! 295: bh=raw_bread(sb,0); ! 296: if(bh==NULL) ! 297: { printk(KERN_ERR "DMSDOS: unable to read super block\n"); ! 298: MOD_DEC_USE_COUNT; ! 299: return -1; ! 300: } ! 301: if(strncmp(bh->b_data+3,"MSDBL6.0",8)&&strncmp(bh->b_data+3,"MSDSP6.0",8)) ! 302: { printk(KERN_ERR "DMSDOS: MSDBL/MSDSP signature not found, CVF skipped\n"); ! 303: raw_brelse(sb,bh); ! 304: MOD_DEC_USE_COUNT; ! 305: return -1; ! 306: } ! 307: dblsb=kmalloc(sizeof(Dblsb),GFP_KERNEL); ! 308: if(dblsb==NULL) ! 309: { printk(KERN_ERR "DMSDOS: mount_dblspace: out of memory\n"); ! 310: raw_brelse(sb,bh); ! 311: MOD_DEC_USE_COUNT; ! 312: return -1; ! 313: } ! 314: MSDOS_SB(sb)->private_data=dblsb; ! 315: /*dblsb->mdfat_alloc_sem=MUTEX;*/ ! 316: ! 317: #ifdef __KERNEL__ ! 318: { struct semaphore* sem; ! 319: ! 320: sem=kmalloc(sizeof(struct semaphore),GFP_KERNEL); ! 321: if(sem==NULL) ! 322: { printk(KERN_ERR "DMSDOS: mount_dblspace: out of memory\n"); ! 323: raw_brelse(sb,bh); ! 324: MOD_DEC_USE_COUNT; ! 325: return -1; ! 326: } ! 327: *sem=MUTEX; ! 328: dblsb->mdfat_alloc_semp=sem; ! 329: } ! 330: #endif ! 331: ! 332: /* find out size */ ! 333: dblsb->s_dataend=blk_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)]*2; ! 334: ! 335: dblsb->s_comp=GUESS; ! 336: dblsb->s_cfaktor=DEFAULT_CF; ! 337: ! 338: if(parse_dmsdos_options(options,dblsb,&repair)) ! 339: { ! 340: raw_brelse(sb,bh); ! 341: MOD_DEC_USE_COUNT; ! 342: return -1; ! 343: } ! 344: ! 345: ! 346: if(sb->s_flags & MS_RDONLY)dblsb->s_comp=READ_ONLY; ! 347: printk(KERN_INFO "DMSDOS: mounting CVF on device 0x%x %s...\n", ! 348: sb->s_dev, ! 349: dblsb->s_comp==READ_ONLY?"read-only":"read-write"); ! 350: ! 351: /* dblspace correction was relocated. Pavel */ ! 352: dblsb->s_dataend-=1; ! 353: ! 354: pp=&(bh->b_data[45]); ! 355: dblsb->s_dcluster=CHS(pp); ! 356: if(dblsb->s_dcluster&0x8000)dblsb->s_dcluster|=0xffff0000; ! 357: pp=&(bh->b_data[36]); ! 358: dblsb->s_mdfatstart=CHS(pp)+1; ! 359: pp=&(bh->b_data[17]); ! 360: dblsb->s_rootdirentries=CHS(pp); ! 361: dblsb->s_sectperclust=((unsigned long)(bh->b_data[13])); ! 362: dblsb->s_spc_bits=ilog2(dblsb->s_sectperclust); ! 363: pp=&(bh->b_data[39]);i=CHS(pp);/*i=res0*/ ! 364: dblsb->s_bootblock=i; ! 365: pp=&(bh->b_data[14]); ! 366: dblsb->s_fatstart=i+CHS(pp); ! 367: pp=&(bh->b_data[41]); ! 368: dblsb->s_rootdir=i+CHS(pp); ! 369: pp=&(bh->b_data[43]); ! 370: dblsb->s_datastart=i+CHS(pp)+2; ! 371: dblsb->s_2nd_fat_offset=0; /* dblsp doesn't have a second fat */ ! 372: dblsb->s_cvf_version=DBLSP; ! 373: version_flag=bh->b_data[51]; ! 374: if(version_flag==2)dblsb->s_cvf_version=DRVSP; ! 375: if(version_flag==3||dblsb->s_sectperclust>16)dblsb->s_cvf_version=DRVSP3; ! 376: if(version_flag>3)printk(KERN_WARNING "DMSDOS: strange version flag %d, assuming 0.\n", ! 377: version_flag); ! 378: ! 379: #ifndef DMSDOS_CONFIG_DBLSP_DRVSP ! 380: if(dblsb->s_cvf_version<=DRVSP) ! 381: { printk(KERN_ERR "DMSDOS: support for doublespace/drivespace(<3) not compiled in.\n"); ! 382: raw_brelse(sb,bh); ! 383: MOD_DEC_USE_COUNT; ! 384: return -1; ! 385: } ! 386: #endif ! 387: #ifndef DMSDOS_CONFIG_DRVSP3 ! 388: if(dblsb->s_cvf_version==DRVSP3) ! 389: { printk(KERN_ERR "DMSDOS: support for drivespace 3 not compiled in.\n"); ! 390: raw_brelse(sb,bh); ! 391: MOD_DEC_USE_COUNT; ! 392: return -1; ! 393: } ! 394: #endif ! 395: ! 396: bh2=raw_bread(sb,dblsb->s_bootblock); ! 397: if(bh2==NULL) ! 398: { printk(KERN_ERR "DMSDOS: unable to read emulated boot block\n"); ! 399: raw_brelse(sb,bh); ! 400: MOD_DEC_USE_COUNT; ! 401: return -1; ! 402: } ! 403: pp=&(bh2->b_data[57]); ! 404: if(CHL(pp)==0x20203631)dblsb->s_16bitfat=1; ! 405: else if(CHL(pp)==0x20203231)dblsb->s_16bitfat=0; ! 406: else if(CHL(pp)==0x20203233) ! 407: { printk(KERN_ERR "DMSDOS: CVF has FAT32 signature, not mounted. Please report this.\n"); ! 408: raw_brelse(sb,bh2); ! 409: raw_brelse(sb,bh); ! 410: MOD_DEC_USE_COUNT; ! 411: return -1; ! 412: } ! 413: else ! 414: { pp=&(bh->b_data[62]); ! 415: dblsb->s_16bitfat=(CHS(pp)>32) ? 1 : 0; ! 416: printk(KERN_WARNING "DMSDOS: FAT bit size not recognized, guessed %d bit\n", ! 417: CHS(pp)>32 ? 16 : 12 ); ! 418: } ! 419: raw_brelse(sb,bh2); ! 420: ! 421: /* try to verify correct end of CVF */ ! 422: mdrc=0; ! 423: for(i=-1;i<=1;++i) ! 424: { bh2=raw_bread(sb,dblsb->s_dataend+i); ! 425: if(bh2==NULL) ! 426: { LOG_REST("DMSDOS: MDR test breaks at i=%d\n",i); ! 427: break; ! 428: } ! 429: if(strcmp(bh2->b_data,"MDR")==0) ! 430: { ++mdrc; ! 431: m_sector=dblsb->s_dataend+i; ! 432: LOG_REST("DMSDOS: MDR signature found at sector %d\n",m_sector); ! 433: } ! 434: raw_brelse(sb,bh2); ! 435: } ! 436: if(mdrc!=1) ! 437: printk(KERN_WARNING "DMSDOS: could not find MDR signature or found more than one, mdrc=%d (ignored)\n", ! 438: mdrc); ! 439: else ! 440: { if(dblsb->s_dataend!=m_sector-1) ! 441: { LOG_REST("DMSDOS: dataend corrected due to MDR signature old=%d new=%d\n", ! 442: dblsb->s_dataend,m_sector-1); ! 443: dblsb->s_dataend=m_sector-1; ! 444: } ! 445: } ! 446: ! 447: dblsb->s_full=0; ! 448: ! 449: /* calculate maximum cluster nr (fixes lost cluster messages) */ ! 450: mdfatb=(dblsb->s_bootblock-dblsb->s_mdfatstart); ! 451: mdfatb*=((dblsb->s_sectperclust>16)?102:128); ! 452: mdfatb-=dblsb->s_dcluster; ! 453: fatb=512*(dblsb->s_rootdir-dblsb->s_fatstart); ! 454: if(dblsb->s_16bitfat)fatb/=2; else fatb=(2*fatb)/3; ! 455: dblsb->s_max_cluster=((mdfatb<fatb)?mdfatb:fatb)-1; ! 456: if(dblsb->s_16bitfat) ! 457: { if(dblsb->s_max_cluster>0xFFF6)dblsb->s_max_cluster=0xFFF6; ! 458: } ! 459: else ! 460: { if(dblsb->s_max_cluster>0xFF6)dblsb->s_max_cluster=0xFF6; ! 461: } ! 462: ! 463: /* adapt max_cluster according to dos' limits */ ! 464: dblsb->s_max_cluster2=dblsb->s_max_cluster; ! 465: pp=&(bh->b_data[32]); ! 466: i=CHL(pp); ! 467: pp=&(bh->b_data[22]); ! 468: i-=CHS(pp); ! 469: pp=&(bh->b_data[14]); ! 470: i-=CHS(pp); ! 471: i-=dblsb->s_rootdirentries>>4; ! 472: /*i=(i>>4)+1;*/ ! 473: i=(i/dblsb->s_sectperclust)+1; ! 474: if(i<=dblsb->s_max_cluster) ! 475: { dblsb->s_max_cluster=i; ! 476: } ! 477: else ! 478: { printk(KERN_WARNING "DMSDOS: dos max_cluster=%d too large, cutting to %d.\n", ! 479: i,dblsb->s_max_cluster); ! 480: } ! 481: ! 482: LOG_REST("DMSDOS: dcluster=%d\n",dblsb->s_dcluster); ! 483: LOG_REST("DMSDOS: mdfatstart=%d\n",dblsb->s_mdfatstart); ! 484: LOG_REST("DMSDOS: rootdirentries=%d\n",dblsb->s_rootdirentries); ! 485: LOG_REST("DMSDOS: sectperclust=%d\n",dblsb->s_sectperclust); ! 486: LOG_REST("DMSDOS: fatstart=%d\n",dblsb->s_fatstart); ! 487: LOG_REST("DMSDOS: rootdir=%d\n",dblsb->s_rootdir); ! 488: LOG_REST("DMSDOS: %d bit FAT\n",dblsb->s_16bitfat ? 16 : 12); ! 489: ! 490: dblsb->s_lastnear=0; ! 491: dblsb->s_lastbig=0; ! 492: dblsb->s_free_sectors=-1; /* -1 means unknown */ ! 493: ! 494: /* error test (counts sectors) */ ! 495: if(repair!=-1) /* repair==-1 means do not even check */ ! 496: { ! 497: i=simple_check(sb,repair&1); ! 498: if(i==-1||i==-2) ! 499: { printk(KERN_WARNING "DMSDOS: CVF has serious errors or compatibility problems, setting to read-only.\n"); ! 500: dblsb->s_comp=READ_ONLY; ! 501: } ! 502: if(i==-3) ! 503: { if(repair&2) ! 504: { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, ignored.\n"); ! 505: } ! 506: else ! 507: { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, setting to read-only.\n"); ! 508: dblsb->s_comp=READ_ONLY; ! 509: } ! 510: } ! 511: } ! 512: ! 513: /* if still unknown then count now */ ! 514: if(dblsb->s_free_sectors<0)check_free_sectors(sb); ! 515: ! 516: /* print doublespace version */ ! 517: if(dblsb->s_cvf_version==DBLSP&&dblsb->s_sectperclust==16) ! 518: { printk(KERN_INFO "DMSDOS: CVF is in doublespace format (version 1).\n"); ! 519: } ! 520: else if(dblsb->s_cvf_version==DRVSP&&dblsb->s_sectperclust==16) ! 521: { printk(KERN_INFO "DMSDOS: CVF is in drivespace format (version 2).\n"); ! 522: } ! 523: else if(dblsb->s_cvf_version==DRVSP3&&dblsb->s_sectperclust==64) ! 524: { printk(KERN_INFO "DMSDOS: CVF is in drivespace 3 format.\n"); ! 525: } ! 526: else ! 527: { printk(KERN_INFO "DMSDOS: CVF is in unknown (new?) format, please report.\n"); ! 528: printk(KERN_INFO "DMSDOS: version_flag=%d sectperclust=%d\n",version_flag, ! 529: dblsb->s_sectperclust); ! 530: printk(KERN_NOTICE "DMSDOS: CVF set to read-only.\n"); ! 531: dblsb->s_comp=READ_ONLY; ! 532: } ! 533: ! 534: raw_brelse(sb,bh); ! 535: ! 536: /* set some msdos fs important stuff */ ! 537: MSDOS_SB(sb)->dir_start=FAKED_ROOT_DIR_OFFSET; ! 538: MSDOS_SB(sb)->dir_entries=dblsb->s_rootdirentries; ! 539: MSDOS_SB(sb)->data_start=FAKED_DATA_START_OFFSET; /*begin of virtual cluster 2*/ ! 540: MSDOS_SB(sb)->clusters=dblsb->s_max_cluster; ! 541: if(MSDOS_SB(sb)->fat_bits!=dblsb->s_16bitfat?16:12) ! 542: { LOG_REST("DMSDOS: fat bit size mismatch in fat driver, trying to correct\n"); ! 543: MSDOS_SB(sb)->fat_bits=dblsb->s_16bitfat?16:12; ! 544: } ! 545: MSDOS_SB(sb)->cluster_size=dblsb->s_sectperclust; ! 546: ! 547: /* these *must* always match */ ! 548: if(dblsb->s_comp==READ_ONLY)sb->s_flags |= MS_RDONLY; ! 549: ! 550: /* we allow using the daemon - calling this more than once doesn't matter */ ! 551: init_daemon(); ! 552: ! 553: return 0; ! 554: } ! 555: #endif ! 556: ! 557: int unmount_dblspace(struct super_block*sb) ! 558: { int j; ! 559: #if defined(__KERNEL__)||defined(DMSDOS_CONFIG_STAC) ! 560: Dblsb*dblsb=MSDOS_SB(sb)->private_data; ! 561: #endif ! 562: ! 563: LOG_REST("DMSDOS: CVF on device 0x%x unmounted.\n",sb->s_dev); ! 564: ! 565: /* discard/write cached clusters */ ! 566: free_ccache_dev(sb); ! 567: /* the same for the daemon if it is running */ ! 568: clear_list_dev(sb); ! 569: ! 570: #ifdef DMSDOS_CONFIG_STAC ! 571: /* mark stacker bitfat as up to date and unmounted */ ! 572: if(dblsb->s_cvf_version>=STAC3) ! 573: stac_bitfat_state(sb,1); ! 574: #endif ! 575: ! 576: /* kill buffers used by unmounted cvf */ ! 577: for(j=0;j<MDFATCACHESIZE;++j) ! 578: { if(mdfat[j].a_buffer!=NULL) ! 579: { if(mdfat[j].a_sb->s_dev==sb->s_dev) ! 580: { raw_brelse(sb,mdfat[j].a_buffer); ! 581: mdfat[j].a_buffer=NULL; ! 582: } ! 583: mdfat[j].a_time=0; ! 584: mdfat[j].a_acc=0; ! 585: } ! 586: } ! 587: for(j=0;j<DFATCACHESIZE;++j) ! 588: { if(dfat[j].a_buffer!=NULL) ! 589: { if(dfat[j].a_sb->s_dev==sb->s_dev) ! 590: { raw_brelse(sb,dfat[j].a_buffer); ! 591: dfat[j].a_buffer=NULL; ! 592: } ! 593: dfat[j].a_time=0; ! 594: dfat[j].a_acc=0; ! 595: } ! 596: } ! 597: for(j=0;j<BITFATCACHESIZE;++j) ! 598: { if(bitfat[j].a_buffer!=NULL) ! 599: { if(bitfat[j].a_sb->s_dev==sb->s_dev) ! 600: { raw_brelse(sb,bitfat[j].a_buffer); ! 601: bitfat[j].a_buffer=NULL; ! 602: } ! 603: bitfat[j].a_time=0; ! 604: bitfat[j].a_acc=0; ! 605: } ! 606: } ! 607: ! 608: #ifdef __KERNEL__ ! 609: #ifdef USE_READA_LIST ! 610: /* throw away all stacked reada entries for this dev */ ! 611: kill_reada_list_dev(sb->s_dev); ! 612: #endif ! 613: /* this is unused in the library */ ! 614: kfree(dblsb->mdfat_alloc_semp); ! 615: #endif ! 616: kfree(MSDOS_SB(sb)->private_data); ! 617: MSDOS_SB(sb)->private_data=NULL; ! 618: /*MSDOS_SB(sb)->cvf_format=NULL;*/ /*this causes a segfault in ! 619: dec_cvf_format_use_count_by_version*/ ! 620: exit_daemon(); ! 621: MOD_DEC_USE_COUNT; ! 622: return 0; ! 623: } ! 624: ! 625: #ifdef DMSDOS_CONFIG_STAC ! 626: int detect_stacker(struct super_block*sb) ! 627: { struct buffer_head*bh; ! 628: ! 629: MOD_INC_USE_COUNT; ! 630: bh=raw_bread(sb,0); ! 631: if(bh==NULL) ! 632: { printk(KERN_ERR "DMSDOS: unable to read super block\n"); ! 633: MOD_DEC_USE_COUNT; ! 634: return 0; ! 635: } ! 636: if(strncmp(bh->b_data,"STACKER",7)==0) ! 637: { raw_brelse(sb,bh); ! 638: MOD_DEC_USE_COUNT; ! 639: return 1; ! 640: } ! 641: raw_brelse(sb,bh); ! 642: MOD_DEC_USE_COUNT; ! 643: return 0; ! 644: } ! 645: ! 646: int mount_stacker(struct super_block*sb,char*options) ! 647: { ! 648: struct buffer_head*bh; ! 649: struct buffer_head*bh2; ! 650: int i; ! 651: unsigned char * pp, *p; ! 652: unsigned char buf[512]; ! 653: unsigned char b,c; ! 654: int SectSize, ClustSects, ClustSize, ReservSects, FATCnt; ! 655: int RootDirEnt, TotalSects, FATSize, HidenSects, FirstRootSect; ! 656: int FirstDataSect, FirstDataSect2, FAT12, FirstFATSect; ! 657: int StacVersion; ! 658: /* parameters of virtual DOS drive */ ! 659: int BB_FirstDataSect, BB_ClustCnt, BB_SectSize, BB_TotalSects; ! 660: Dblsb*dblsb; ! 661: int repair=0; ! 662: ! 663: MOD_INC_USE_COUNT; ! 664: LOG_REST("DMSDOS: stacker 3/4 module mounting...\n"); ! 665: ! 666: LOG_REST("DMSDOS: reading super block...\n"); ! 667: bh=raw_bread(sb,0); ! 668: if(bh==NULL) ! 669: { printk(KERN_ERR "DMSDOS: unable to read super block of CVF\n"); ! 670: MOD_DEC_USE_COUNT; ! 671: return -1; ! 672: } ! 673: LOG_REST("DMSDOS: super block read finished\n"); ! 674: pp=&(bh->b_data[0]); ! 675: if(strncmp(pp,"STACKER",7)!=0) ! 676: { printk(KERN_ERR "DMSDOS: STACKER signature not found\n"); ! 677: raw_brelse(sb,bh); ! 678: MOD_DEC_USE_COUNT; ! 679: return -1; ! 680: } ! 681: ! 682: /* copy block (must not directly modify kernel buffer!!!) */ ! 683: memcpy(buf,bh->b_data,SECTOR_SIZE); ! 684: /* decode super block */ ! 685: for(i=0x30,p=buf+0x50,b=buf[0x4c];i--;p++) ! 686: { b=0xc4-b; ! 687: b=b<0x80?b*2:b*2+1; ! 688: b^=c=*p; ! 689: *p=b;b=c; ! 690: } ! 691: if(buf[0x4e]!=0xa||buf[0x4f]!=0x1a) ! 692: { printk(KERN_ERR "DMSDOS: Stacker 0x1A0A signature not found\n"); ! 693: raw_brelse(sb,bh); ! 694: MOD_DEC_USE_COUNT; ! 695: return -1; ! 696: } ! 697: ! 698: dblsb=kmalloc(sizeof(Dblsb),GFP_KERNEL); ! 699: if(dblsb==NULL) ! 700: { printk(KERN_ERR "DMSDOS: mount_stacker: out of memory\n"); ! 701: raw_brelse(sb,bh); ! 702: MOD_DEC_USE_COUNT; ! 703: return -1; ! 704: } ! 705: MSDOS_SB(sb)->private_data=dblsb; ! 706: /*dblsb->mdfat_alloc_sem=MUTEX;*/ ! 707: ! 708: #ifdef __KERNEL__ ! 709: { struct semaphore* sem; ! 710: ! 711: sem=kmalloc(sizeof(struct semaphore),GFP_KERNEL); ! 712: if(sem==NULL) ! 713: { printk(KERN_ERR "DMSDOS: mount_stacker: out of memory\n"); ! 714: raw_brelse(sb,bh); ! 715: MOD_DEC_USE_COUNT; ! 716: return -1; ! 717: } ! 718: *sem=MUTEX; ! 719: dblsb->mdfat_alloc_semp=sem; ! 720: } ! 721: #endif ! 722: ! 723: /* find out size */ ! 724: dblsb->s_dataend=blk_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)]*2; ! 725: ! 726: dblsb->s_comp=GUESS; ! 727: dblsb->s_cfaktor=DEFAULT_CF; ! 728: ! 729: if(parse_dmsdos_options(options,dblsb,&repair)) ! 730: { ! 731: raw_brelse(sb,bh); ! 732: MOD_DEC_USE_COUNT; ! 733: return -1; ! 734: } ! 735: ! 736: if(sb->s_flags & MS_RDONLY)dblsb->s_comp=READ_ONLY; ! 737: printk(KERN_NOTICE "DMSDOS: mounting CVF on device 0x%x %s...\n", ! 738: sb->s_dev, ! 739: dblsb->s_comp==READ_ONLY?"read-only":"read-write"); ! 740: ! 741: /* extract important info */ ! 742: pp=&(buf[0x6C]); ! 743: TotalSects=CHL(pp); ! 744: pp=&(buf[0x70]); ! 745: dblsb->s_bootblock=CHS(pp); ! 746: pp=&(buf[0x74]); ! 747: dblsb->s_mdfatstart=CHS(pp); /* here it's AMAP start !!! */ ! 748: pp=&(buf[0x76]); ! 749: FirstFATSect=dblsb->s_fatstart=CHS(pp); ! 750: pp=&(buf[0x7a]); ! 751: FirstDataSect2=dblsb->s_datastart=CHS(pp); ! 752: pp=&(buf[0x60]); ! 753: StacVersion=CHS(pp); ! 754: if(StacVersion>=410)dblsb->s_cvf_version=STAC4; ! 755: else dblsb->s_cvf_version=STAC3; ! 756: /* if(buf[0x64]==9)dblsb->s_cvf_version=STAC4; ! 757: else dblsb->s_cvf_version=STAC3; */ ! 758: ! 759: #ifndef DMSDOS_CONFIG_STAC3 ! 760: if(dblsb->s_cvf_version==STAC3) ! 761: { printk(KERN_ERR "DMSDOS: support for stacker 3 not compiled in.\n"); ! 762: raw_brelse(sb,bh); ! 763: MOD_DEC_USE_COUNT; ! 764: return -1; ! 765: } ! 766: #endif ! 767: #ifndef DMSDOS_CONFIG_STAC4 ! 768: if(dblsb->s_cvf_version==STAC4) ! 769: { printk(KERN_ERR "DMSDOS: support for stacker 4 not compiled in.\n"); ! 770: raw_brelse(sb,bh); ! 771: MOD_DEC_USE_COUNT; ! 772: return -1; ! 773: } ! 774: #endif ! 775: ! 776: /* now we need the boot block */ ! 777: bh2=raw_bread(sb,dblsb->s_bootblock); ! 778: if(bh2==NULL) ! 779: { printk(KERN_ERR "DMSDOS: unable to read emulated boot block of CVF\n"); ! 780: raw_brelse(sb,bh); ! 781: MOD_DEC_USE_COUNT; ! 782: return -1; ! 783: } ! 784: /* read values */ ! 785: dblsb->s_sectperclust=bh2->b_data[0xd]; ! 786: dblsb->s_spc_bits=ilog2(dblsb->s_sectperclust); ! 787: pp=&(bh2->b_data[0x11]); ! 788: dblsb->s_rootdirentries=CHS(pp); ! 789: ! 790: pp=&(buf[0x62]); SectSize=CHS(pp); ! 791: pp=&(bh2->b_data[0xB]); BB_SectSize=CHS(pp); ! 792: if(SectSize!=SECTOR_SIZE||BB_SectSize!=SECTOR_SIZE) ! 793: printk(KERN_WARNING "DMSDOS: Stacker sector size not 512 bytes, hmm...\n"); ! 794: ClustSects=bh2->b_data[0xD]; ! 795: ClustSize=ClustSects*SectSize; ! 796: pp=&(bh2->b_data[0xE]); ReservSects=CHS(pp); ! 797: FATCnt=bh2->b_data[0x10]; ! 798: pp=&(bh2->b_data[0x11]); RootDirEnt=CHS(pp); ! 799: pp=&(bh2->b_data[0x13]); BB_TotalSects=CHS(pp); ! 800: if(!BB_TotalSects) ! 801: { pp=&(bh2->b_data[0x20]); BB_TotalSects=CHL(pp);}; ! 802: pp=&(bh2->b_data[0x16]); FATSize=CHS(pp); ! 803: pp=&(bh2->b_data[0x1B]); HidenSects=CHS(pp); ! 804: if(BB_SectSize!=SectSize)printk(KERN_WARNING "DMSDOS: Inconsistent sector length\n"); ! 805: FirstRootSect=FirstFATSect+3*FATCnt*FATSize; ! 806: ! 807: dblsb->s_2nd_fat_offset=3*(FATCnt-1)*FATSize; ! 808: ! 809: /* Number of sectors in root directory */ ! 810: FirstDataSect=((long)RootDirEnt*0x20+SectSize-1)/SectSize; ! 811: /* Emulated data start sector for DOS */ ! 812: BB_FirstDataSect=FirstDataSect+FATCnt*FATSize+ReservSects; ! 813: /* ??? +HidenSects; */ ! 814: /* Real data start sector */ ! 815: FirstDataSect+=FirstRootSect; ! 816: /* Counting BB_ClustCnt from emulated boot block */ ! 817: BB_ClustCnt=(BB_TotalSects-BB_FirstDataSect)/ClustSects; ! 818: if(BB_ClustCnt>=0xFED)FAT12=0; else FAT12=1; ! 819: if(BB_ClustCnt<2||BB_ClustCnt>0xfff7) ! 820: { printk(KERN_ERR "DMSDOS: BB_ClustCnt=0x%x impossible (FAT32?)\n",BB_ClustCnt); ! 821: raw_brelse(sb,bh2); ! 822: raw_brelse(sb,bh); ! 823: MOD_DEC_USE_COUNT; ! 824: return -1; ! 825: } ! 826: if(FirstDataSect2!=FirstDataSect) ! 827: { printk(KERN_WARNING "DMSDOS: Inconsistent first data sector number. Mounting READ ONLY.\n"); ! 828: printk(KERN_WARNING "In header found %u but computed %u\n",(unsigned)FirstDataSect2,(unsigned)FirstDataSect); ! 829: dblsb->s_comp=READ_ONLY; ! 830: } ! 831: ! 832: LOG_REST("DMSDOS: Stac version %u start of FAT %u, root %u, data %u; FATSize %u; FATCnt %u; clusts %u; sects %u\n", ! 833: (unsigned)StacVersion,(unsigned)FirstFATSect,(unsigned)FirstRootSect, ! 834: (unsigned)FirstDataSect,(unsigned)FATSize,(unsigned)FATCnt, ! 835: (unsigned)BB_ClustCnt,(unsigned)BB_TotalSects); ! 836: ! 837: /* try dos standard method to detect fat bit size - does not work */ ! 838: /* pp=&(bh2->b_data[57]); */ ! 839: /* if(CHL(pp)==0x20203631)dblsb->s_16bitfat=1; */ ! 840: /* else if(CHL(pp)==0x20203231)dblsb->s_16bitfat=0; else */ ! 841: ! 842: /* used only stacker method for fat entry size now */ ! 843: dblsb->s_16bitfat=FAT12? 0: 1; ! 844: LOG_REST("DMSDOS: FAT bit size of CVF is %d bit\n", ! 845: (FAT12) ? 12 : 16 ); ! 846: ! 847: /* check if clusters fits in FAT */ ! 848: if(BB_ClustCnt+2>(FAT12?(SECTOR_SIZE*FATSize*2)/3:(SECTOR_SIZE*FATSize)/2)) ! 849: { printk(KERN_WARNING "DMSDOS: FAT size does not match cluster count. Mounting READ ONLY.\n"); ! 850: dblsb->s_comp=READ_ONLY; ! 851: } ! 852: ! 853: /* check size of physical media against stacvol parameters */ ! 854: if((TotalSects<=0)||(TotalSects-1)>dblsb->s_dataend) ! 855: { printk(KERN_WARNING "DMSDOS: CVF is shorter about %d sectors. Mounting READ ONLY.\n", ! 856: (int)TotalSects-1-dblsb->s_dataend); ! 857: dblsb->s_comp=READ_ONLY; ! 858: } ! 859: else if((TotalSects-1)<dblsb->s_dataend) ! 860: { printk(KERN_INFO "DMSDOS: CVF end padding %d sectors.\n", ! 861: (int)dblsb->s_dataend-TotalSects+1); ! 862: dblsb->s_dataend=TotalSects-1; ! 863: } ! 864: ! 865: raw_brelse(sb,bh2); ! 866: dblsb->s_full=0; ! 867: raw_brelse(sb,bh); ! 868: ! 869: dblsb->s_rootdir=FirstRootSect; ! 870: dblsb->s_max_cluster=dblsb->s_max_cluster2=BB_ClustCnt+1; ! 871: ! 872: LOG_REST("DMSDOS: mdfatstart=%d\n",dblsb->s_mdfatstart); ! 873: LOG_REST("DMSDOS: rootdirentries=%d\n",dblsb->s_rootdirentries); ! 874: LOG_REST("DMSDOS: sectperclust=%d\n",dblsb->s_sectperclust); ! 875: LOG_REST("DMSDOS: fatstart=%d\n",dblsb->s_fatstart); ! 876: LOG_REST("DMSDOS: rootdir=%d\n",dblsb->s_rootdir); ! 877: LOG_REST("DMSDOS: %d bit FAT\n",dblsb->s_16bitfat ? 16 : 12); ! 878: ! 879: /* allocation informations */ ! 880: dblsb->s_lastnear=0; ! 881: dblsb->s_lastbig=0; ! 882: dblsb->s_free_sectors=-1; /* -1 means unknown */ ! 883: ! 884: /* set some msdos fs important stuff */ ! 885: MSDOS_SB(sb)->dir_start=FAKED_ROOT_DIR_OFFSET; ! 886: MSDOS_SB(sb)->dir_entries=dblsb->s_rootdirentries; ! 887: MSDOS_SB(sb)->data_start=FAKED_DATA_START_OFFSET; /*begin of virtual cluster 2*/ ! 888: MSDOS_SB(sb)->clusters=BB_ClustCnt; ! 889: if(MSDOS_SB(sb)->fat_bits!=dblsb->s_16bitfat?16:12) ! 890: { LOG_REST("DMSDOS: fat bit size mismatch in fat driver, trying to correct\n"); ! 891: MSDOS_SB(sb)->fat_bits=dblsb->s_16bitfat?16:12; ! 892: } ! 893: MSDOS_SB(sb)->cluster_size=dblsb->s_sectperclust; ! 894: ! 895: /* error test */ ! 896: if(repair!=-1) /* repair==-1 means do not even check */ ! 897: { ! 898: i=simple_check(sb,repair&1); ! 899: if(i==-1||i==-2) ! 900: { printk(KERN_WARNING "DMSDOS: CVF has serious errors or compatibility problems, setting to read-only.\n"); ! 901: dblsb->s_comp=READ_ONLY; ! 902: } ! 903: if(i==-3) ! 904: { if(repair&2) ! 905: { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, ignored.\n"); ! 906: } ! 907: else ! 908: { printk(KERN_WARNING "DMSDOS: CVF has bitfat mismatches, setting to read-only.\n"); ! 909: dblsb->s_comp=READ_ONLY; ! 910: } ! 911: } ! 912: } ! 913: ! 914: /* print stacker version */ ! 915: if(dblsb->s_cvf_version==STAC3) ! 916: { printk(KERN_NOTICE "DMSDOS: CVF is in stacker 3 format.\n"); ! 917: } ! 918: else if(dblsb->s_cvf_version==STAC4) ! 919: { printk(KERN_NOTICE "DMSDOS: CVF is in stacker 4 format.\n"); ! 920: } ! 921: ! 922: /* if still unknown then count now */ ! 923: if(dblsb->s_free_sectors<0)check_free_sectors(sb); ! 924: ! 925: /* these *must* always match */ ! 926: if(dblsb->s_comp==READ_ONLY)sb->s_flags |= MS_RDONLY; ! 927: ! 928: /* mark stacker bitfat as mounted and changing */ ! 929: /* if not regulary unmounted, it must be repaired before */ ! 930: /* next write access */ ! 931: if((sb->s_flags&MS_RDONLY)==0)stac_bitfat_state(sb,2); ! 932: ! 933: /* we allow using the daemon - calling this more than once doesn't matter */ ! 934: init_daemon(); ! 935: ! 936: return 0; ! 937: } ! 938: #endif ! 939: ! 940: #ifdef DMSDOS_USE_READPAGE ! 941: #define READPAGE dblspace_readpage ! 942: #define MMAP NULL ! 943: #define RMFLAG CVF_USE_READPAGE ! 944: #else ! 945: #define READPAGE NULL ! 946: #define MMAP dblspace_mmap ! 947: #define RMFLAG 0 ! 948: #endif ! 949: ! 950: #ifndef __DMSDOS_LIB__ ! 951: #ifdef DMSDOS_CONFIG_DBL ! 952: struct cvf_format dblspace_format = { ! 953: 0x0001, /* version id */ ! 954: "dblspace", /* version text */ ! 955: RMFLAG, /* flags */ ! 956: detect_dblspace, /* detect */ ! 957: mount_dblspace, /* mount */ ! 958: unmount_dblspace, /* unmount */ ! 959: dblspace_bread, /* bread */ ! 960: dblspace_getblk, /* getblk */ ! 961: dblspace_brelse, /* brelse */ ! 962: dblspace_mark_buffer_dirty, /* mark_buffer_dirty */ ! 963: dblspace_set_uptodate, /* set_uptodate */ ! 964: dblspace_is_uptodate, /* is_uptodate */ ! 965: dblspace_ll_rw_block, /* ll_rw_block */ ! 966: dblspace_fat_access, /* fat_access */ ! 967: NULL, /* statfs */ ! 968: dblspace_bmap, /* bmap */ ! 969: dblspace_smap, /* smap */ ! 970: dblspace_file_read, /* file_read */ ! 971: dblspace_file_write, /* file_write */ ! 972: MMAP, /* mmap */ ! 973: READPAGE, /* readpage */ ! 974: NULL, /* writepage */ ! 975: dmsdos_ioctl_dir, /* dir ioctl */ ! 976: dblspace_zero_new_cluster /* zero_new_cluster */ ! 977: }; ! 978: #endif ! 979: ! 980: #ifdef DMSDOS_CONFIG_STAC ! 981: struct cvf_format stacker_format = { ! 982: 0x0002, /* version id */ /**** only ****/ ! 983: "stacker", /* version text */ /**** these ****/ ! 984: RMFLAG, /* flags */ ! 985: detect_stacker, /* detect */ /**** four ****/ ! 986: mount_stacker, /* mount */ /**** differ :) ****/ ! 987: unmount_dblspace, /* unmount */ ! 988: dblspace_bread, /* bread */ ! 989: dblspace_getblk, /* getblk */ ! 990: dblspace_brelse, /* brelse */ ! 991: dblspace_mark_buffer_dirty, /* mark_buffer_dirty */ ! 992: dblspace_set_uptodate, /* set_uptodate */ ! 993: dblspace_is_uptodate, /* is_uptodate */ ! 994: dblspace_ll_rw_block, /* ll_rw_block */ ! 995: dblspace_fat_access, /* fat_access */ ! 996: NULL, /* statfs */ ! 997: dblspace_bmap, /* bmap */ ! 998: dblspace_smap, /* smap */ ! 999: dblspace_file_read, /* file_read */ ! 1000: dblspace_file_write, /* file_write */ ! 1001: MMAP, /* mmap */ ! 1002: READPAGE, /* readpage */ ! 1003: NULL, /* writepage */ ! 1004: dmsdos_ioctl_dir, /* dir ioctl */ ! 1005: dblspace_zero_new_cluster /* zero_new_cluster */ ! 1006: }; ! 1007: #endif ! 1008: ! 1009: int init_module(void) ! 1010: { int i; ! 1011: ! 1012: do_spc_init(); ! 1013: #ifdef DMSDOS_CONFIG_DBL ! 1014: i=register_cvf_format(&dblspace_format); ! 1015: if(i<0) ! 1016: { printk(KERN_ERR "register_cvf_format failed, module not loaded successfully\n"); ! 1017: do_spc_exit(); ! 1018: return i; ! 1019: } ! 1020: #endif ! 1021: #ifdef DMSDOS_CONFIG_STAC ! 1022: i=register_cvf_format(&stacker_format); ! 1023: if(i<0) ! 1024: { printk(KERN_ERR "register_cvf_format failed, module not loaded successfully\n"); ! 1025: do_spc_exit(); ! 1026: #ifdef DMSDOS_CONFIG_DBL ! 1027: unregister_cvf_format(&dblspace_format); ! 1028: #endif ! 1029: return i; ! 1030: } ! 1031: #endif ! 1032: LOG_REST("CVF format(s) successfully registered\n"); ! 1033: ! 1034: return 0; ! 1035: } ! 1036: ! 1037: void cleanup_module(void) ! 1038: { do_spc_exit(); ! 1039: #ifdef DMSDOS_CONFIG_DBL ! 1040: unregister_cvf_format(&dblspace_format); ! 1041: #endif ! 1042: #ifdef DMSDOS_CONFIG_STAC ! 1043: unregister_cvf_format(&stacker_format); ! 1044: #endif ! 1045: } ! 1046: #endif /* ifndef __DMSDOS_LIB__ */ ! 1047: ! 1048: char seq[]="000000"; ! 1049: ! 1050: #ifdef __DMSDOS_LIB__ ! 1051: /* we don't need locking in the library */ ! 1052: void lock_prseq(void) {} ! 1053: void unlock_prseq(void) {} ! 1054: #else ! 1055: struct semaphore prseq_sem=MUTEX; /* Must be initialized to green light */ ! 1056: void lock_prseq(void) {down(&prseq_sem);} ! 1057: void unlock_prseq(void) {up(&prseq_sem);} ! 1058: #endif ! 1059: ! 1060: int log_prseq(void) ! 1061: { int i; ! 1062: ! 1063: lock_prseq(); ! 1064: ! 1065: i=5; ! 1066: while(i>=0) ! 1067: { ++seq[i]; ! 1068: if(seq[i]<='9')break; ! 1069: seq[i]='0'; ! 1070: --i; ! 1071: } ! 1072: ! 1073: printk(seq); ! 1074: ! 1075: unlock_prseq(); ! 1076: ! 1077: return 1; ! 1078: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.