Annotation of dmsdos/src/dblspace_fileops.c-2.1.80, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.