Annotation of dmsdos/src/dblspace_fileops.c-2.1.80, revision 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.