|
|
1.1 ! root 1: /* ! 2: dblspace_fileops.c-2.1.80 ! 3: ! 4: DMSDOS CVF-FAT module: file operation routines (for kernel>=2.1.80). ! 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: #include <linux/sched.h> ! 30: #include <linux/ctype.h> ! 31: #include <linux/major.h> ! 32: #include <linux/blkdev.h> ! 33: #include <linux/fs.h> ! 34: #include <linux/stat.h> ! 35: #include <linux/locks.h> ! 36: #include <asm/segment.h> ! 37: #include <linux/mm.h> ! 38: #include <linux/malloc.h> ! 39: #include <linux/string.h> ! 40: #include <linux/msdos_fs.h> ! 41: #include <linux/errno.h> ! 42: #include <linux/kernel.h> ! 43: #include <linux/shm.h> ! 44: #include <linux/mman.h> ! 45: #include <asm/system.h> ! 46: #include "dmsdos.h" ! 47: ! 48: extern unsigned long dmsdos_speedup; ! 49: ! 50: #define MIN(x,y) ( ( (x)<(y) ) ? (x) : (y) ) ! 51: ! 52: void do_cluster_reada(struct super_block*sb,int clusternr) ! 53: { /* read one cluster ahead without waiting for the data */ ! 54: int nextclust; ! 55: ! 56: nextclust=dbl_fat_nextcluster(sb,clusternr,NULL); ! 57: if(nextclust>0) ! 58: { /* no need to read-ahead if it is in cache */ ! 59: /* for a simple search for existence we needn't lock the cache */ ! 60: if(find_in_ccache(sb,nextclust,NULL,NULL)==NULL) ! 61: dmsdos_read_cluster(sb,NULL,nextclust); ! 62: } ! 63: } ! 64: ! 65: int dblspace_file_read( ! 66: struct file *filp, ! 67: char *buf, ! 68: size_t count, ! 69: loff_t *ppos) ! 70: { ! 71: int clusternr; ! 72: /*unsigned char*clusterd;*/ ! 73: int offset; ! 74: int bytes_read; ! 75: int membytes; ! 76: int membytes_bits; ! 77: int ret; ! 78: char * b; ! 79: int toread; ! 80: char datum; ! 81: int need_cluster; ! 82: Cluster_head*ch; ! 83: struct inode *inode; ! 84: struct super_block*sb; ! 85: Dblsb*dblsb; ! 86: ! 87: LOG_FS("DMSDOS: file_read start...\n"); ! 88: ! 89: inode = filp->f_dentry->d_inode; ! 90: LOG_FS("DMSDOS: file_read: got inode\n"); ! 91: sb=inode->i_sb; ! 92: LOG_FS("DMSDOS: file_read: got sb\n"); ! 93: dblsb=MSDOS_SB(sb)->private_data; ! 94: LOG_FS("DMSDOS: file_read: got dblsb\n"); ! 95: ! 96: if (!inode) { ! 97: printk(KERN_ERR "DMSDOS: file_read: inode = NULL, rejected.\n"); ! 98: return -EINVAL; ! 99: } ! 100: /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */ ! 101: if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) { ! 102: printk(KERN_ERR "DMSDOS: file_read: mode = %07o, rejected.\n",inode->i_mode); ! 103: return -EINVAL; ! 104: } ! 105: ! 106: LOG_FS("DMSDOS: file_read init complete...\n"); ! 107: ! 108: if(count<=0)return 0; ! 109: ! 110: if(*ppos>=inode->i_size)return 0; ! 111: ! 112: if(*ppos+count>inode->i_size)count=inode->i_size-*ppos; ! 113: ! 114: ret=verify_area(VERIFY_WRITE, buf, count); ! 115: if(ret<0)return ret; ! 116: ret=0; ! 117: ! 118: membytes=SECTOR_SIZE*dblsb->s_sectperclust; ! 119: membytes_bits=SECTOR_BITS+dblsb->s_spc_bits; ! 120: ! 121: /* calculate clusternr for cluster to read */ ! 122: offset=*ppos&(membytes-1); ! 123: LOG_CLUST("DMSDOS: file_read: get_cluster...\n"); ! 124: clusternr=get_cluster(inode,*ppos>>membytes_bits); ! 125: if(clusternr<=0) ! 126: { printk(KERN_ERR "DMSDOS: file_readx: FAT mismatches file size for ino=%ld\n", ! 127: inode->i_ino); ! 128: return 0; ! 129: } ! 130: ! 131: bytes_read=0; ! 132: b=buf; ! 133: ! 134: if(MSDOS_I(inode)->i_binary==0)goto text_read; ! 135: ! 136: do ! 137: { LOG_CLUST("DMSDOS: file_read: calling ch_read...\n"); ! 138: ch=ch_read(sb,clusternr,0); ! 139: LOG_CLUST("DMSDOS: file_read: after ch_read\n"); ! 140: ret=(ch==NULL)?-EIO:0; ! 141: if(ret>=0) ! 142: { if(count>READA_THRESHOLD&&(dmsdos_speedup&SP_USE_READ_AHEAD)!=0) ! 143: do_cluster_reada(inode->i_sb,clusternr); ! 144: toread=(membytes-offset>count) ? count : membytes-offset; ! 145: /*printk("DMSDOS file_readx: memcpy_tofs(0x%08x,0x%08x,0x%08x)\n", ! 146: b,clusterd+offset,toread);*/ ! 147: memcpy_tofs(b,ch->c_data+offset,toread); ! 148: bytes_read+=toread; ! 149: *ppos+=toread; ! 150: count-=toread; ! 151: ch_free(ch); ! 152: if(count>0) ! 153: { b+=toread; ! 154: offset=0; ! 155: LOG_CLUST("DMSDOS: file_read: get_cluster...\n"); ! 156: clusternr=get_cluster(inode,*ppos>>membytes_bits); ! 157: if(*ppos&(membytes-1)) ! 158: panic("DMSDOS: read_file bug: f_pos not cluster-aligned"); ! 159: if(clusternr<=0) ! 160: { ret=-EIO; ! 161: printk(KERN_ERR "DMSDOS: file_readx: FAT mismatches file size for ino=%ld\n", ! 162: inode->i_ino); ! 163: } ! 164: } ! 165: } ! 166: } ! 167: while(count>0&&ret>=0); ! 168: ! 169: return (bytes_read==0&&ret<0)?ret:bytes_read; ! 170: ! 171: text_read: ! 172: /* ok, let's do it byte for byte..... */ ! 173: bytes_read=0; ! 174: need_cluster=1; ! 175: ch=NULL; ! 176: while(count>0&&inode->i_size>*ppos) ! 177: { if(need_cluster) ! 178: { clusternr=get_cluster(inode,*ppos>>membytes_bits); ! 179: if(clusternr<=0) ! 180: { printk(KERN_ERR "DMSDOS: get_cluster failed (FAT problem ?)\n"); ! 181: return -EIO; ! 182: } ! 183: ch=ch_read(sb,clusternr,0); ! 184: if(ch==NULL)return -EIO; ! 185: if(count>READA_THRESHOLD&&(dmsdos_speedup&SP_USE_READ_AHEAD)!=0) ! 186: do_cluster_reada(inode->i_sb,clusternr); ! 187: clusternr=dbl_fat_nextcluster(sb,clusternr,NULL); ! 188: need_cluster=0; ! 189: } ! 190: ! 191: datum=ch->c_data[offset++]; ! 192: ! 193: ++(*ppos); ! 194: if(datum!=13) ! 195: { /*put_fs_byte(datum,&(buf[bytes_read]));*/ ! 196: memcpy_tofs(&(buf[bytes_read]),&datum,1); ! 197: ++bytes_read; ! 198: --count; ! 199: } ! 200: if(offset==membytes) ! 201: { need_cluster=1; ! 202: ch_free(ch); ! 203: ch=NULL; ! 204: offset=0; ! 205: } ! 206: } ! 207: ! 208: if(ch)ch_free(ch); ! 209: return bytes_read; ! 210: } ! 211: ! 212: int dblspace_file_write( ! 213: struct file *filp, ! 214: const char *buf, ! 215: size_t count, ! 216: loff_t *ppos) ! 217: { ! 218: int cluster; ! 219: int ret=0; ! 220: unsigned int offset; ! 221: const unsigned char *b; ! 222: int canwrite; ! 223: int written; ! 224: int clustersize; ! 225: int clustersize_bits; ! 226: int uc; ! 227: int cr; ! 228: char datum; ! 229: int need_cluster; ! 230: Cluster_head*ch; ! 231: struct inode *inode = filp->f_dentry->d_inode; ! 232: struct super_block*sb=inode->i_sb; ! 233: Dblsb*dblsb=MSDOS_SB(sb)->private_data; ! 234: ! 235: if (!inode) { ! 236: printk(KERN_ERR "dmsdos_file_write: inode = NULL\n"); ! 237: return -EINVAL; ! 238: } ! 239: /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */ ! 240: if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) { ! 241: printk(KERN_ERR "dmsdos_file_write: mode = %07o\n",inode->i_mode); ! 242: return -EINVAL; ! 243: } ! 244: /* ! 245: * ok, append may not work when many processes are writing at the same time ! 246: * but so what. That way leads to madness anyway. ! 247: */ ! 248: if(sb->s_flags&MS_RDONLY) ! 249: { printk(KERN_ERR "DMSDOS: file_write: READ-ONLY filesystem\n"); ! 250: return -EROFS; ! 251: } ! 252: ! 253: if(dblsb->s_comp==READ_ONLY)return -EPERM; ! 254: ! 255: if (filp->f_flags & O_APPEND) *ppos = inode->i_size; ! 256: if (count <= 0) return 0; ! 257: ! 258: ret=verify_area(VERIFY_READ, buf, count); ! 259: if(ret<0)return ret; ! 260: ret=0; ! 261: ! 262: clustersize=dblsb->s_sectperclust*SECTOR_SIZE; ! 263: clustersize_bits=dblsb->s_spc_bits+SECTOR_BITS; ! 264: ! 265: uc=0; ! 266: if(dmsdos_speedup&SP_NO_EMD_COMPR) ! 267: uc=(MSDOS_I(inode)->i_binary>1)?1:0; /* uncompressed forced */ ! 268: ! 269: offset=*ppos&(clustersize-1); ! 270: do ! 271: { cluster=get_cluster(inode,*ppos>>clustersize_bits); ! 272: if(cluster>0)break; ! 273: if(dblsb->s_full==2) ! 274: { printk(KERN_ERR "DMSDOS: write_file: CVF full (full flag set)\n"); ! 275: return -ENOSPC; ! 276: } ! 277: if(dblsb->s_free_sectors<MIN_FREE_SECTORS) ! 278: { printk(KERN_ERR "DMSDOS: write_file: CVF full (free sector count too low)\n"); ! 279: return -ENOSPC; ! 280: } ! 281: if(fat_add_cluster(inode)<0) ! 282: { printk(KERN_ERR "DMSDOS: write_file: fat_add_cluster failed\n"); ! 283: return -ENOSPC; ! 284: } ! 285: } ! 286: while(cluster<=0); ! 287: ! 288: LOG_CLUST("DMSDOS: file_write: beginning with cluster %d\n", ! 289: cluster); ! 290: ! 291: b=buf; ! 292: written=0; ! 293: ! 294: if(MSDOS_I(inode)->i_binary==0)goto text_write; ! 295: ! 296: while(count>0) ! 297: { ! 298: if(offset>0||count<clustersize) ! 299: { /* cluster must be read because it will only partially overwritten */ ! 300: LOG_CLUST("DMSDOS: write_file: reading cluster %d...\n",cluster); ! 301: ch=ch_read(sb,cluster,C_KEEP_LOCK); ! 302: if(ch==NULL) ! 303: { printk(KERN_ERR "DMSDOS: write_file: read_cluster failed!\n"); ! 304: ret=-EIO; ! 305: break; ! 306: } ! 307: /*lock_ch(ch); we call with KEEP_LOCK above */ ! 308: } ! 309: else ! 310: { /* cluster will be fully overwritten, don't read it */ ! 311: ch=ch_read(sb,cluster,C_KEEP_LOCK|C_NO_READ); ! 312: if(ch==NULL) ! 313: { printk(KERN_ERR "DMSDOS: write_file: ch_noread failed!\n"); ! 314: ret=-EIO; ! 315: break; ! 316: } ! 317: /*lock_ch(ch); we call with KEEP_LOCK above */ ! 318: ch->c_length= (count+offset<clustersize) ? ! 319: count+offset : clustersize; ! 320: } ! 321: canwrite=MIN(clustersize-offset,count); ! 322: memcpy_fromfs(&(ch->c_data[offset]),b,canwrite); ! 323: ! 324: /* did cluster grow ? */ ! 325: if(canwrite+offset>ch->c_length) ! 326: { /*printk(KERN_ERR "DMSDOS: write_file: write beyond logical cluster end, appending.\n"); ! 327: */ ! 328: ch->c_length=canwrite+offset; ! 329: } ! 330: if(ch->c_length>clustersize) ! 331: { printk(KERN_ERR "DMSDOS: write_file: length>clustersize ??? bug !!!\n"); ! 332: ch->c_length=clustersize; ! 333: } ! 334: ! 335: /*unlock_ch(ch); no not here*/ ! 336: ! 337: LOG_CLUST("DMSDOS: write_file: writing cluster %d...\n",cluster); ! 338: ! 339: /* ch_dirty_locked unlocks the cluster */ ! 340: if(ch_dirty_locked(ch,0,uc)<0) ! 341: { printk(KERN_ERR "DMSDOS: write_file: ch_dirty failed!\n"); ! 342: ch_free(ch); ! 343: ch=NULL; ! 344: ret=-EIO; ! 345: break; ! 346: } ! 347: ch_free(ch); ! 348: ch=NULL; ! 349: ! 350: offset=0; ! 351: b+=canwrite; ! 352: *ppos+=canwrite; ! 353: written+=canwrite; ! 354: count-=canwrite; ! 355: ! 356: if(count==0)break; /* braucht keinen neuen cluster mehr*/ ! 357: ! 358: /* next cluster ? */ ! 359: cluster=get_cluster(inode,*ppos>>clustersize_bits); ! 360: if(cluster<=0) ! 361: { LOG_CLUST("DMSDOS: write_file: write_loop: allocating new cluster\n"); ! 362: if(dblsb->s_full==2) ! 363: { printk(KERN_ERR "DMSDOS: write_file: CVF full (full flag set)\n"); ! 364: ret=-ENOSPC; ! 365: break; ! 366: } ! 367: if(dblsb->s_free_sectors<MIN_FREE_SECTORS) ! 368: { printk(KERN_ERR "DMSDOS: write_file: CVF full (free sector count too low)\n"); ! 369: ret=-ENOSPC; ! 370: break; ! 371: } ! 372: if(fat_add_cluster(inode)<0) ! 373: { printk(KERN_ERR "DMSDOS: write_file: fat_add_cluster failed\n"); ! 374: ret=-ENOSPC; ! 375: break; ! 376: } ! 377: cluster=get_cluster(inode,*ppos>>clustersize_bits); ! 378: if(cluster<=0) ! 379: { printk(KERN_ERR "DMSDOS: write_file: something's wrong, cannot happen\n"); ! 380: ret=-EIO; ! 381: break; ! 382: } ! 383: } ! 384: } ! 385: ! 386: if(*ppos>inode->i_size) ! 387: { inode->i_size=*ppos; ! 388: /*inode->i_dirt=1; .... HMMM .... */ ! 389: mark_inode_dirty(inode); ! 390: } ! 391: ! 392: return (written==0)?ret:written; ! 393: ! 394: text_write: ! 395: written=0; ! 396: need_cluster=1; ! 397: cr=0; ! 398: ch=NULL; ! 399: while(count>0||cr==1) ! 400: { if(need_cluster) ! 401: { LOG_CLUST("DMSDOS: text_write: need_cluster=%d\n", ! 402: cluster); ! 403: /* we cannot simply calculate here... ! 404: so we never know and must always read the cluster */ ! 405: ch=ch_read(sb,cluster,C_KEEP_LOCK); ! 406: if(ch==NULL) ! 407: { printk(KERN_ERR "DMSDOS: write_file: read_cluster failed!\n"); ! 408: ret=-EIO; ! 409: break; ! 410: } ! 411: /*lock_ch(ch); we call with KEEP_LOCK above */ ! 412: need_cluster=0; ! 413: } ! 414: ! 415: if(cr==1) ! 416: { datum=10; ! 417: cr=0; ! 418: } ! 419: else ! 420: { /*datum=get_fs_byte(&(buf[written]));*/ ! 421: memcpy_fromfs(&datum,&(buf[written]),1); ! 422: ++written; ! 423: if(datum==10) ! 424: { datum=13; ! 425: cr=1; ! 426: } ! 427: --count; ! 428: } ! 429: ! 430: ch->c_data[offset++]=datum; ! 431: ! 432: ++(*ppos); ! 433: if(offset>ch->c_length)ch->c_length=offset; ! 434: ! 435: if(offset==clustersize) ! 436: { /* cluster is full and must be written back */ ! 437: /*unlock_ch(ch);*/ ! 438: /* ch_dirty_locked unlocks the cluster *after* write */ ! 439: if(ch_dirty_locked(ch,0,uc)<0) ! 440: { printk(KERN_ERR "DMSDOS: write_file: ch_dirty failed!\n"); ! 441: ch_free(ch); ! 442: ch=NULL; ! 443: ret=-EIO; ! 444: break; ! 445: } ! 446: ch_free(ch); ! 447: ch=NULL; ! 448: ! 449: /*check whether end reached */ ! 450: if(count==0&&cr==0) ! 451: { offset=0; /* tells that there's no rest */ ! 452: break; ! 453: } ! 454: /* check whether a new cluster is needed */ ! 455: cluster=get_cluster(inode,*ppos>>clustersize_bits); ! 456: if(cluster<=0) ! 457: { ! 458: if(dblsb->s_full==2) ! 459: { printk(KERN_ERR "DMSDOS: write_file: CVF full (full flag set)\n"); ! 460: ret=-ENOSPC; ! 461: break; ! 462: } ! 463: if(dblsb->s_free_sectors<MIN_FREE_SECTORS) ! 464: { printk(KERN_ERR "DMSDOS: write_file: CVF full (free sector count too low)\n"); ! 465: ret=-ENOSPC; ! 466: break; ! 467: } ! 468: if(fat_add_cluster(inode)<0) ! 469: { printk(KERN_ERR "DMSDOS: write_file: fat_add_cluster failed\n"); ! 470: ret=-ENOSPC; ! 471: break; ! 472: } ! 473: cluster=get_cluster(inode,*ppos>>clustersize_bits); ! 474: if(cluster<=0) ! 475: { printk(KERN_ERR "DMSDOS: write_file: something wrong, cannot happen\n"); ! 476: ret=-EIO; ! 477: break; ! 478: } ! 479: ch=ch_read(sb,cluster,C_KEEP_LOCK|C_NO_READ); ! 480: if(ch==NULL) ! 481: { printk(KERN_ERR "DMSDOS: write_file: ch_noread failed\n"); ! 482: ret=-EIO; ! 483: break; ! 484: } ! 485: /*lock_ch(ch); we called with KEEP_LOCK above */ ! 486: ch->c_length=SECTOR_SIZE; ! 487: } ! 488: else need_cluster=1; ! 489: offset=0; ! 490: } ! 491: } ! 492: ! 493: /* check whether there's a rest to be written */ ! 494: if(offset) ! 495: { /*unlock_ch(ch);*/ ! 496: /* ch_dirty_locked unlocks the cluster *after* write */ ! 497: if(ch_dirty_locked(ch,0,uc)<0) ! 498: { printk(KERN_ERR "DMSDOS: write_file: ch_dirty failed!\n"); ! 499: if(ret==0)ret=-EIO; ! 500: } ! 501: } ! 502: ! 503: if(ch)ch_free(ch); ! 504: ! 505: if(*ppos>inode->i_size) ! 506: { inode->i_size=*ppos; ! 507: /*inode->i_dirt=1; .... HMMM .... */ ! 508: mark_inode_dirty(inode); ! 509: } ! 510: ! 511: return (written==0)?ret:written; ! 512: } ! 513: ! 514: ! 515: /* Grmpf.... partially untested code. Don't know an application that does ! 516: writable mmaps, but it would be needed for testing this piece of code */ ! 517: ! 518: /* idea: kernel does buffer reads with bmap calculated buffers - impossible ! 519: for dmsdos. (see kernel mmap code). ! 520: kernel emulates writable mmap by calling file_write when no buffers ! 521: are present - should work for dmsdos. ! 522: so we do file_read-emulated readable mmaps here though the ! 523: generic_mmap function is used. ! 524: */ ! 525: ! 526: #ifdef DMSDOS_USE_READPAGE ! 527: int read_the_page(unsigned long address, unsigned long pos, ! 528: struct inode*inode) ! 529: { ! 530: unsigned int clear; ! 531: long gap; /* distance from eof to pos */ ! 532: ! 533: LOG_FS("DMSDOS: read_the_page\n"); ! 534: ! 535: address &= PAGE_MASK; ! 536: ! 537: clear = 0; ! 538: gap = inode->i_size - pos; ! 539: if (gap <= 0){ ! 540: /* mmaping beyond end of file */ ! 541: clear = PAGE_SIZE; ! 542: }else{ ! 543: int cur_read; ! 544: int need_read; ! 545: struct file filp; ! 546: if (gap < PAGE_SIZE){ ! 547: clear = PAGE_SIZE - gap; ! 548: } ! 549: filp.f_reada = 0; ! 550: filp.f_pos = pos; ! 551: need_read = PAGE_SIZE - clear; ! 552: { mm_segment_t cur_fs = get_fs(); ! 553: filp.f_dentry=kmalloc(sizeof(struct dentry),GFP_KERNEL); ! 554: if(filp.f_dentry==NULL) ! 555: { printk(KERN_ERR "DMSDOS: read_the_page: no memory!\n"); ! 556: return -1; ! 557: } ! 558: filp.f_dentry->d_inode=inode; ! 559: ! 560: set_fs (KERNEL_DS); ! 561: LOG_FS("DMSDOS: read_the_page: calling file_read...\n"); ! 562: cur_read = dblspace_file_read (&filp, ! 563: (char*)address, ! 564: need_read, ! 565: &(filp.f_pos)); ! 566: set_fs (cur_fs); ! 567: kfree(filp.f_dentry); ! 568: } ! 569: if (cur_read != need_read){ ! 570: printk ("DMSDOS: Error while reading an mmap file %d <> %d\n" ! 571: ,cur_read,need_read); ! 572: return -1; ! 573: } ! 574: } ! 575: if (clear > 0){ ! 576: memset ((char*)address+PAGE_SIZE-clear,0,clear); ! 577: } ! 578: return 0; ! 579: } ! 580: ! 581: #ifdef READPAGE_DENTRY ! 582: int dblspace_readpage(struct dentry*dentry, struct page *page) ! 583: { unsigned long address; ! 584: int error = -1; ! 585: struct inode*inode=dentry->d_inode; ! 586: #else ! 587: int dblspace_readpage(struct inode *inode, struct page *page) ! 588: { unsigned long address; ! 589: int error = -1; ! 590: #endif ! 591: LOG_FS("DMSDOS: readpage %08lx\n", page_address(page)); ! 592: ! 593: address = page_address(page); ! 594: atomic_inc(&page->count); ! 595: set_bit(PG_locked, &page->flags); ! 596: ! 597: /* now read the data */ ! 598: error=read_the_page(address,page->offset,inode); ! 599: ! 600: LOG_FS("DMSDOS: readpage: read_the_page returned %d\n",error); ! 601: ! 602: if(error==0)set_bit(PG_uptodate, &page->flags); ! 603: ! 604: clear_bit(PG_locked, &page->flags); ! 605: wake_up(&page->wait); ! 606: ! 607: free_page(address); ! 608: return error; ! 609: } ! 610: ! 611: #else /* from: ifdef DMSDOS_USE_READPAGE */ ! 612: ! 613: /* this is supposed to be obsolete stuff for older kernels... */ ! 614: ! 615: #if LINUX_VERSION_CODE >= LVC(2,1,90) ! 616: #error kernel >=2.1.90 requires readpage interface, rerun dmsdos configuration ! 617: #endif ! 618: ! 619: /* ! 620: * Fill in the supplied page for mmap ! 621: */ ! 622: static unsigned long dblspace_file_mmap_nopage( ! 623: struct vm_area_struct * area, ! 624: unsigned long address, ! 625: int error_code) ! 626: { ! 627: struct inode * inode = area->vm_dentry->d_inode; ! 628: unsigned long page; ! 629: unsigned int clear; ! 630: int pos; ! 631: long gap; /* distance from eof to pos */ ! 632: ! 633: LOG_FS("DMSDOS: file_mmap_nopage\n"); ! 634: page = __get_free_page(GFP_KERNEL); ! 635: if (!page)return page; ! 636: LOG_FS("DMSDOS: file_mmap_nopage: got page\n"); ! 637: ! 638: address &= PAGE_MASK; ! 639: pos = address - area->vm_start + area->vm_offset; ! 640: ! 641: clear = 0; ! 642: gap = inode->i_size - pos; ! 643: if (gap <= 0){ ! 644: /* mmaping beyond end of file */ ! 645: clear = PAGE_SIZE; ! 646: }else{ ! 647: int cur_read; ! 648: int need_read; ! 649: struct file filp; ! 650: if (gap < PAGE_SIZE){ ! 651: clear = PAGE_SIZE - gap; ! 652: } ! 653: filp.f_reada = 0; ! 654: filp.f_pos = pos; ! 655: need_read = PAGE_SIZE - clear; ! 656: { mm_segment_t cur_fs = get_fs(); ! 657: filp.f_dentry=kmalloc(sizeof(struct dentry),GFP_KERNEL); ! 658: if(filp.f_dentry==NULL) ! 659: { printk(KERN_ERR "DMSDOS: file_mmap_nopage: no memory!\n"); ! 660: return -1; ! 661: } ! 662: filp.f_dentry->d_inode=inode; ! 663: ! 664: set_fs (KERNEL_DS); ! 665: LOG_FS("DMSDOS: file_mmap_nopage: calling file_read...\n"); ! 666: cur_read = dblspace_file_read (&filp,(char*)page, ! 667: need_read,&filp.f_pos); ! 668: LOG_FS("DMSDOS: file_mmap_nopage: file_read returned\n"); ! 669: set_fs (cur_fs); ! 670: kfree(filp.f_dentry); ! 671: } ! 672: if (cur_read != need_read){ ! 673: printk ("DMSDOS: Error while reading an mmap file %d <> %d\n" ! 674: ,cur_read,need_read); ! 675: } ! 676: } ! 677: if (clear > 0){ ! 678: memset ((char*)page+PAGE_SIZE-clear,0,clear); ! 679: } ! 680: LOG_FS("DMSDOS: file_mmap_nopage: end\n"); ! 681: return page; ! 682: } ! 683: ! 684: struct vm_operations_struct dblspace_file_mmap = { ! 685: NULL, /* open */ ! 686: NULL, /* close */ ! 687: NULL, /* unmap */ ! 688: NULL, /* protect */ ! 689: NULL, /* sync */ ! 690: NULL, /* advise */ ! 691: dblspace_file_mmap_nopage, /* nopage */ ! 692: NULL, /* wppage */ ! 693: NULL, /* swapout */ ! 694: NULL, /* swapin */ ! 695: }; ! 696: ! 697: /* ! 698: * This is used for a general mmap of a dmsdos file ! 699: * Returns 0 if ok, or a negative error code if not. ! 700: */ ! 701: int dblspace_mmap(struct file*file,struct vm_area_struct*vma) ! 702: { struct inode *inode = file->f_dentry->d_inode; ! 703: LOG_FS("DMSDOS: mmap ino=%ld\n",inode->i_ino); ! 704: if (vma->vm_flags & VM_SHARED) /* only PAGE_COW or read-only supported now */ ! 705: return -EINVAL; ! 706: if (vma->vm_offset & (inode->i_sb->s_blocksize - 1)) ! 707: return -EINVAL; ! 708: if (!inode->i_sb || !S_ISREG(inode->i_mode)) ! 709: return -EACCES; ! 710: if (!IS_RDONLY(inode)) { ! 711: inode->i_atime = CURRENT_TIME; ! 712: /*inode->i_dirt = 1;*/ ! 713: mark_inode_dirty(inode); ! 714: } ! 715: ! 716: vma->vm_dentry = dget(file->f_dentry); ! 717: vma->vm_ops = &dblspace_file_mmap; ! 718: return 0; ! 719: } ! 720: ! 721: #endif /* from: else / ifdef DMSDOS_USE_READPAGE */ ! 722:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.