⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 super.c

📁 mtd最新cvs的ffs系统
💻 C
📖 第 1 页 / 共 4 页
字号:
   if (block > 0)      block = sb->BlockMap[block];         // Select a block that has enough free space to insert the data   for (I = 0; I != sb->Boot.TotalBlockCount; I++)   {      if (sb->Blocks[I].LargestSpace < len + FFS_SIZEOF_BLOCKALLOC)	 continue;      if (best == -1)	 best = I;            if (sb->Blocks[I].FreeSpace > sb->Blocks[best].FreeSpace)	 best = I;   }   /* If there is no space in the requested block or none was given use      the best one. This should possibly try to reclaim the best if that      would help */   if (block < 0 ||        sb->Blocks[block].LargestSpace < len + FFS_SIZEOF_BLOCKALLOC)      block = best;      // No block found   if (block == -1)      return -1;      // Locate the block we are going to use   info = &sb->Blocks[block];   for (writeblock = 0; info->FreeList[writeblock].Stop != 0; writeblock++)      if (info->FreeList[writeblock].Stop - info->FreeList[writeblock].Start >= len)	 break;   if (info->FreeList[writeblock].Stop == 0)      return -1;      // Look for a free allocation entry to use   for (cur = 0; ; cur++)   {	        offset = sb->EraseSize - FFS_SIZEOF_BLOCK - 	       (cur + 1)*FFS_SIZEOF_BLOCKALLOC;      if (offset <= 100)      {	 printk("ffs2: Allocation list too long");	 return -1;      }            // XX can be advoided      if (ffs2_read(r,block,offset,FFS_SIZEOF_BLOCKALLOC) == 0)	 return -1;      alloc = (struct ffs2_blockalloc *)r->p;            // It is free..      if (isflagset(alloc->Status,FFS_ALLOC_SMASK,FFS_ALLOC_FREE) != 0)      {	 // Make sure that this was not an abortive write	 if (alloc->Len == 0xFFFF && alloc->Offset[0] == 0xFF &&	     alloc->Offset[1] == 0xFF && alloc->Offset[2] == 0xFF)	    break;      }            // End of the list      if (isflagset(alloc->Status,FFS_ALLOC_EMASK,FFS_ALLOC_END) != 0)	 break;   }      // End of the list, allocate a new entry past the very end.   if (isflagset(alloc->Status,FFS_ALLOC_EMASK,FFS_ALLOC_END) != 0)   {      __u8 newStatus;            // Update the allocation table      for (I = 0; info->FreeList[I].Stop != 0; I++)      {	 if (info->FreeList[I].Stop == offset)	    break;      }            if (info->FreeList[I].Stop == 0)      {	 printk("ffs2: Corrupted allocation list");	 return -1;      }            // Rewrite the status bit on the last entry      newStatus = alloc->Status & (~FFS_ALLOC_END);      if (ffs2_write(r,block,offset,&newStatus,sizeof(newStatus)) != 0)	 return -1;            cur++;      offset = sb->EraseSize - FFS_SIZEOF_BLOCK - 	       (cur + 1)*FFS_SIZEOF_BLOCKALLOC;      info->FreeList[I].Stop = offset;   }   // Double check   if (info->FreeList[writeblock].Stop - info->FreeList[writeblock].Start < len)   {      printk("ffs2: Logic error allocation new free block\n");      return -1;   }    if (ffs2_read(r,block,offset,FFS_SIZEOF_BLOCKALLOC) == 0)      return -1;   alloc = (struct ffs2_blockalloc *)r->p;   // The region that is supposed to be FF isnt!   if (alloc->Len != 0xFFFF || alloc->Offset[0] != 0xFF ||       alloc->Offset[1] != 0xFF || alloc->Offset[2] != 0xFF)   {      printk("ffs2: Block allocations corrupted\n");      return -1;   }      // Now write the offset and length bytes   outalloc->Status = (alloc->Status & (~FFS_ALLOC_SMASK)) | FFS_ALLOC_ALLOCATED;   outalloc->Len = len;   outalloc->Offset[2] = (__u8)(info->FreeList[writeblock].Start >> 16);   outalloc->Offset[1] = (__u8)(info->FreeList[writeblock].Start >> 8);   outalloc->Offset[0] = (__u8)(info->FreeList[writeblock].Start);      if (ffs2_write(r,block,offset + sizeof(outalloc->Status),		  outalloc->Offset,FFS_SIZEOF_BLOCKALLOC - 		  sizeof(outalloc->Status)) != 0)      return -1;   if (ffs2_write(r,block,offset,&outalloc->Status,sizeof(outalloc->Status)) != 0)      return -1;   // Remove it from the free list   offset = info->FreeList[writeblock].Start;   info->FreeList[writeblock].Start += len;   // Recalculate the available space.   info->LargestSpace = 0;   info->FreeSpace = 0;   for (I = 0; info->FreeList[I].Stop != 0; I++)   {      if (info->FreeList[I].Stop - info->FreeList[I].Start > info->LargestSpace)	 info->LargestSpace = info->FreeList[I].Stop - info->FreeList[I].Start;      info->FreeSpace += info->FreeList[I].Stop - info->FreeList[I].Start;   }   r->block = block;   r->offset = offset;   return (info->VirtualBlock << 16) + cur;}									/*}}}*/// update_pointer - Update a pointer in a block				/*{{{*/// ---------------------------------------------------------------------/* This does some small writes to update a single pointer to point to a new   location. */#define FFS_PTR_SIBLING 2#define FFS_PTR_PRIMARY 6#define FFS_PTR_SECONDARY 10static int update_pointer(struct ffs_read *r,unsigned long from,			  unsigned long target,unsigned type){   struct ffs2_entry *extent = ffs2_find_entry(r,from);   unsigned long block = r->block;   unsigned long offset = r->offset;   __u16 status;      if (extent == 0)      return -1;      status = extent->Status;      // First update the pointer   if (ffs2_write(r,block,offset + type,(unsigned char *)&target,4) != 0)      return -1;      // Then the status   if (type == FFS_PTR_PRIMARY)      status = status & (~FFS_ENTRY_PRIMARY);   if (type == FFS_PTR_SECONDARY)      status = status & (~FFS_ENTRY_SECONDARY);   if (type == FFS_PTR_SIBLING)      status = status & (~FFS_ENTRY_SIBLING);      if (ffs2_write(r,block,offset,(unsigned char *)&status,sizeof(status)) != 0)      return -1;      return 0;}									/*}}}*/// ffs2_entry_add - Add a new entry to a directory			/*{{{*/// ---------------------------------------------------------------------/* This adds a new entry to a directory. The steps are,    1 - Find allocation space    2 - Mark as allocated, write the data to it    3 - Update the directory pointer to point to the new allocation    Flash space will be lost if there is a failure between 2 and 3. */int ffs2_entry_add(struct ffs_read *r,struct ffs2_entry *dir,		   struct ffs2_entry *new,unsigned long *loc){   unsigned long cur;   unsigned long allocloc;   int Primary = 0;   int res;   struct ffs2_blockalloc alloc;         // The directory is empty, we need to add the new entry below the head.   if (isFNULL(dir->PrimaryPtr) ||       (dir->Status & FFS_ENTRY_PRIMARY) == FFS_ENTRY_PRIMARY)   {      cur = r->location;      Primary = 1;            // XXX Perform block reclimation instead      if (isFNULL(dir->PrimaryPtr) == 0)      {	 return -1;      }   }      else   {      struct ffs2_entry *extent;            // Walk the directory and find the end point of the linked list      cur = dir->PrimaryPtr;      while (1)      {	 extent = ffs2_find_entry(r,cur);	 if (extent == 0)	    return -1;	 	 // This should not happen.	 if (isflagset(extent->Status,FFS_ENTRY_TYPEMASK,FFS_ENTRY_TYPEEXTENT))	    return -1;	 	 // Skip to the next one	 if (isFNULL(extent->SiblingPtr) == 0 &&	     (extent->Status & FFS_ENTRY_SIBLING) != FFS_ENTRY_SIBLING)	    cur = extent->SiblingPtr;	 else	    break;      }          // XXX Perform block reclimation instead      if (isFNULL(extent->SiblingPtr) == 0)      {	 return -1;      }   }      /* Cur is now the location that we will be linking too. If this is a new      primary link then we choose a block at random, otherwise we try to       get a new allocation in the same block */   if (Primary == 0)      allocloc = find_free_alloc(r,&alloc,FFS_SIZEOF_ENTRY + new->VarStructLen +				 new->NameLen,cur >> 16);   else      allocloc = find_free_alloc(r,&alloc,FFS_SIZEOF_ENTRY + new->VarStructLen +				 new->NameLen,-1);   if (allocloc == (unsigned long)-1)      return -1;   // Write the block (find_free_alloc resets r->block/r->offset)   if (ffs2_write(r,r->block,r->offset,(unsigned char *)new,alloc.Len) != 0)      return -1;      // Update the directory entry   if (Primary == 0)      res = update_pointer(r,cur,allocloc,FFS_PTR_SIBLING);   else      res = update_pointer(r,cur,allocloc,FFS_PTR_PRIMARY);         *loc = allocloc;      return res;}									/*}}}*/// ffs2_new_entry - Create an arbitary new entry			/*{{{*/// ---------------------------------------------------------------------/* This goes through the process of creating a new sub entry to a   directory. Type may either be a file or a directory */static int ffs2_new_entry(struct inode *dir,struct dentry *dentry,			   struct qstr *name,__u8 type){   struct inode *inode;   struct ffs2_entry *entry;   struct ffs2_entry *direntry;   struct ffs_read r;   unsigned char tmp[300];   unsigned long now = CURRENT_TIME;   unsigned long cur;   memset(&r,0,sizeof(r));      memset(tmp,0xFF,sizeof(tmp));   r.super = dir->i_sb;   if (name->len >= sizeof(tmp) - sizeof(*entry))      return -ENAMETOOLONG;          // Fill in the entry structure   entry = (struct ffs2_entry *)tmp;     entry->Status = type | (0xFFFF & (~FFS_ENTRY_TYPEMASK));   entry->Attrib = 0;   entry->Time = (__u16)now;   entry->Date = (__u16)(now >> 16);   entry->VarStructLen = 0;   entry->NameLen = name->len;   memcpy(entry->Name,name->name,entry->NameLen);   // Get the directory inode   direntry = ffs2_find_entry(&r,dir->i_ino);   if (direntry == 0)   {      ffs2_relse(&r);      return -EIO;   }		     // Append the entry   if (ffs2_entry_add(&r,direntry,entry,&cur) != 0)   {      ffs2_relse(&r);      return -EIO;   }      ffs2_relse(&r);      if (dentry == 0)      return 0;      // Update the dentry cache   if ((inode = iget(dir->i_sb,cur))==NULL)      return -EACCES;   d_instantiate(dentry,inode);   return 0;}									/*}}}*/// ffs2_new_extent - Create a new extent				/*{{{*/// ---------------------------------------------------------------------/* This creates a new, unlinked extent. The caller must link the extent to   something. */static int ffs2_new_extent(struct ffs_read *r,unsigned char *buf,			   unsigned long length,unsigned long *loc){   struct ffs2_fileinfo *entry;   struct ffs2_blockalloc alloc;   unsigned char tmp[300];   unsigned long now = CURRENT_TIME;   unsigned long cur;      memset(tmp,0xFF,sizeof(tmp));      // Fill in the entry structure   entry = (struct ffs2_fileinfo *)tmp;     entry->Status = FFS_ENTRY_TYPEEXTENT | (0xFFFF & (~FFS_ENTRY_TYPEMASK));   entry->Attrib = 0;   entry->Time = (__u16)now;   entry->Date = (__u16)(now >> 16);   entry->VarStructLen = 0;   entry->UncompressedExtentLen = length;   entry->CompressedExtentLen = length;   // Allocate the data block   entry->ExtentPtr = find_free_alloc(r,&alloc,length,-1);   if (entry->ExtentPtr == (unsigned long)-1 ||       ffs2_write(r,r->block,r->offset,buf,alloc.Len) != 0)      return -1;   entry->Status = entry->Status & (~FFS_ENTRY_SIBLING);      /* Allocate the entry for the extent info in the same block as the data      if possible */   cur = find_free_alloc(r,&alloc,FFS_SIZEOF_FILEINFO +			 entry->VarStructLen,entry->ExtentPtr >> 16);   if (cur == (unsigned long)-1 ||       ffs2_write(r,r->block,r->offset,(unsigned char *)entry,alloc.Len) != 0)      return -1;      *loc = cur;   return 0;}									/*}}}*/// free_alloc - Set an allocation entry to be reclaimable		/*{{{*/// ---------------------------------------------------------------------/* */static int free_alloc(struct ffs_read *r,unsigned long location){   struct ffs2_blockalloc *alloc;   unsigned long length;   __u8 status;   unsigned long block = getFFS2_sb(r->super).BlockMap[location >> 16];   signed long offset = getFFS2_sb(r->super).EraseSize - FFS_SIZEOF_BLOCK;   offset -= FFS_SIZEOF_BLOCKALLOC*((location & 0xFFFF) + 1);   if (offset <= 0)      return -1;      // Fetch it..   if (ffs2_read(r,block,offset,FFS_SIZEOF_BLOCKALLOC) == 0)      return -1;      alloc = (struct ffs2_blockalloc *)r->p;      // Make sure it is allocated   if (isflagset(alloc->Status,FFS_ALLOC_SMASK,FFS_ALLOC_ALLOCATED) == 0)      return -1;      // Deallocate   length = alloc->Len;   status = (alloc->Status & (~FFS_ALLOC_SMASK)) | FFS_ALLOC_DEALLOCATED;   if (ffs2_write(r,block,offset,&status,sizeof(status)) != 0)      return -1;      getFFS2_sb(r->super).Blocks[block].ReclaimableSpace += length;   return 0;}									/*}}}*/// ffs2_erase - Erase an arbitary entry					/*{{{*/// ---------------------------------------------------------------------/* This does a very unsafe unlink operation. It goes over the linked list   of extents and marks them all as erased. If this routine is interrupted   the filesystem will have unreclaimable blocks but will still be    consistent */int ffs2_erase(struct ffs_read *r,unsigned long loc,int isdir){   struct ffs2_blockalloc alloc;   struct ffs2_entry *entry;   unsigned long top;   unsigned long oldloc;      // Go along the linked list and destroy it.   top = loc;   while (loc != 0xFFFFFFFF)   {      unsigned long block;      unsigned long offset;            oldloc = loc;      if (ffs2_find_blockalloc(r,loc,&alloc) != 0)	 break;      entry = (struct ffs2_entry *)r->p;      block = r->block;      offset = r->offset;            if (isFNULL(entry->SecondaryPtr) == 0 &&	  (entry->Status & FFS_ENTRY_SECONDARY) != FFS_ENTRY_SECONDARY)      {	 loc = entry->SecondaryPtr;      }            else      {	 // Skip cur to the next one	 if (isdir == 0)	 {	    if (isFNULL(entry->PrimaryPtr) == 0 &&		(entry->Status & FFS_ENTRY_PRIMARY) != FFS_ENTRY_PRIMARY)	       loc = entry->PrimaryPtr;	    else	       loc = 0xFFFFFFFF;	 }	 else	 {	    if (isFNULL(entry->SiblingPtr) == 0 &&		(entry->Status & FFS_ENTRY_SIBLING) != FFS_ENTRY_SIBLING)	       loc = entry->SiblingPtr;	    else	       loc = 0xFFFFFFFF;	 }	 	 if (isflagset(entry->Status,FFS_ENTRY_TYPEMASK,FFS_ENTRY_TYPEEXTENT))	 {	    // Purge the datablock	    if ((entry->Status & FFS_ENTRY_EXISTS) == FFS_ENTRY_EXISTS)	       free_alloc(r,entry->SiblingPtr);	    	 }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -