📄 super.c
字号:
} // Erase it if (top != oldloc) free_alloc(r,oldloc); else { // The first entry we set to deleted and do not erase __u8 status = entry->Status; status = status & (~FFS_ENTRY_EXISTS); if (ffs2_write(r,block,offset,&status,sizeof(status)) != 0) return -EIO; } } return 0;} /*}}}*/// ffs2_read_super - Read the superblock (mount) /*{{{*/// ---------------------------------------------------------------------/* The process for locating the super block involves looking at every block in the filesystem for a block record that has a valid boot record pointer, following that pointer and then verifying that it is the boot block. */static struct super_block *ffs2_read_super(struct super_block *s, void *data,int silent){ struct ffs2_sb_info *sb; struct ffs_read r; unsigned long blocks; MOD_INC_USE_COUNT; // Setup the super block lock_super(s); set_blocksize(s->s_dev, BLOCK_SIZE); s->s_blocksize = BLOCK_SIZE; s->s_blocksize_bits = BLOCK_SIZE_BITS; sb = &getFFS2_sb(s); memset(sb,0,sizeof(*sb)); sb->EraseSize = 0x20000; // Temp memset(&r,0,sizeof(r)); r.super = s; // Allocate the block mapping structure blocks = blk_size[MAJOR(s->s_dev)][MINOR(s->s_dev)]*BLOCK_SIZE/sb->EraseSize; sb->BlockMap = kmalloc(sizeof(*sb->BlockMap)*blocks,GFP_KERNEL); if (sb->BlockMap == 0) { s->s_dev = 0; unlock_super(s); MOD_DEC_USE_COUNT; return 0; } memset(sb->BlockMap,0xFF,sizeof(*sb->BlockMap)*blocks); /* Perform the filesystem startup, locate the boot block, do a cleanup, etc. */ if (ffs2_find_boot_block(&r,blocks) != 0 || ffs2_prepare(&r) != 0 || ffs2_prepare_info(&r)) { printk("ffs2: Could not find the superblock\n"); kfree(sb->BlockMap); ffs2_relse(&r); s->s_dev = 0; unlock_super(s); MOD_DEC_USE_COUNT; return 0; } ffs2_relse(&r); s->s_op = &ffs2_ops; s->s_root = d_alloc_root(iget(s,sb->Boot.RootDirectoryPtr),NULL); unlock_super(s); return s;} /*}}}*/// ffs2_put_super - Put back the superblock (unmount) /*{{{*/// ---------------------------------------------------------------------/* Not much to do here..*/static void ffs2_put_super(struct super_block *s){ unsigned I; kfree(getFFS2_sb(s).BlockMap); for (I = 0; I != getFFS2_sb(s).Boot.TotalBlockCount; I++) kfree(getFFS2_sb(s).Blocks[I].FreeList); kfree(getFFS2_sb(s).Blocks); MOD_DEC_USE_COUNT; return;} /*}}}*/// ffs2_statfs - Stat the filesystem get free blocks, etc /*{{{*/// ---------------------------------------------------------------------/* */static int ffs2_statfs(struct super_block *s, struct statfs *buf, int bufsize){ struct statfs tmp; struct ffs2_sb_info *sb = &getFFS2_sb(s); unsigned int I; memset(&tmp, 0, sizeof(tmp)); tmp.f_type = FFS2_MAGIC; tmp.f_bsize = 1; tmp.f_blocks = sb->Boot.TotalBlockCount - sb->Boot.SpareBlockCount; tmp.f_blocks *= sb->Boot.BlockLen; tmp.f_namelen = FFS2_MAXFN; // Count up free space for (I = 0; I != sb->Boot.TotalBlockCount; I++) { tmp.f_bfree += sb->Blocks[I].FreeSpace + sb->Blocks[I].ReclaimableSpace; } tmp.f_bavail = tmp.f_bfree; return copy_to_user(buf, &tmp, bufsize) ? -EFAULT : 0;} /*}}}*/// ffs2_readdir - Read a list of files from a directory /*{{{*/// ---------------------------------------------------------------------/* read a directory. offset is the number of extents into the directory, I am not sure exactly how the calling code uses this, but it would be more effecient to store a pointer to the current entry in offset, but that is basically a random value.. */static int ffs2_readdir(struct file *filp, void *dirent, filldir_t filldir){ struct ffs2_entry *entry; struct inode *i = filp->f_dentry->d_inode; struct ffs_read r; unsigned int stored = 0; unsigned int offset = 1; unsigned long cur; memset(&r,0,sizeof(r)); r.super = i->i_sb; // Locate the inode entry = ffs2_find_entry(&r,i->i_ino); if (entry == 0) { ffs2_relse(&r); return 0; } if (offset > filp->f_pos) { filp->f_pos = offset; if (filldir(dirent,".",1,filp->f_pos,i->i_ino) < 0) { ffs2_relse(&r); return stored; } stored++; } offset++; if (offset > filp->f_pos) { unsigned long node = 0; if (i->i_ino == getFFS2_sb(i->i_sb).Boot.RootDirectoryPtr) node = i->i_ino; filp->f_pos = offset; if (filldir(dirent,"..",2,filp->f_pos,node) < 0) { ffs2_relse(&r); return stored; } stored++; } offset++; // Iterate over all of the extents for the directory if (!isFNULL(entry->PrimaryPtr) && (entry->Status & FFS_ENTRY_PRIMARY) != FFS_ENTRY_PRIMARY) { cur = entry->PrimaryPtr; while (1) { struct ffs2_entry *extent = ffs2_find_entry(&r,cur); if (extent == 0) { printk("ffs2: Failure reading directory component\n"); break; } // This should not happen. if (isflagset(extent->Status,FFS_ENTRY_TYPEMASK,FFS_ENTRY_TYPEEXTENT)) { printk("ffs2: Filesystem corruption, an extent in the directory list\n"); break; } // Fill in the dirent structure if ((extent->Status & FFS_ENTRY_EXISTS) == FFS_ENTRY_EXISTS) { if (offset > filp->f_pos) { char S[100]; strncpy(S,extent->Name,extent->NameLen); S[extent->NameLen] = 0; filp->f_pos = offset; if (filldir(dirent,extent->Name,extent->NameLen,filp->f_pos,cur) < 0) break; stored++; } offset++; } // Skip to the next one if (isFNULL(extent->SiblingPtr) == 0 && (extent->Status & FFS_ENTRY_SIBLING) != FFS_ENTRY_SIBLING) cur = extent->SiblingPtr; else break; } } ffs2_relse(&r); return stored;} /*}}}*/// ffs2_lookup - Lookup a file in a directory by name /*{{{*/// ---------------------------------------------------------------------/* This is the same as ffs2_readdir, but doesnt do adds, just compares */static struct dentry *ffs2_lookup(struct inode *dir, struct dentry *dentry){ struct inode *inode; struct ffs_read r; unsigned long pos; int res; memset(&r,0,sizeof(r)); r.super = dir->i_sb; res = ffs2_find_dirent(&r,dir->i_ino,&dentry->d_name,&pos); if (res != 0) { ffs2_relse(&r); if (res == -1) { d_add(dentry,0); return ERR_PTR(0); } return ERR_PTR(-EIO); } ffs2_relse(&r); if ((inode = iget(dir->i_sb,pos)) == NULL) return ERR_PTR(-EACCES); d_add(dentry, inode); return 0;} /*}}}*/// ffs2_readpage - Read a page from the file /*{{{*/// ---------------------------------------------------------------------/* This is the 'read' function, it works in PAGE_SIZE blocks, reading from the file system directly into the page. It is forced to iterate over many of the extent headers which will slow things down.. */static int ffs2_readpage(struct file *file, struct page *page){ struct dentry *dentry = file->f_dentry; struct inode *inode = dentry->d_inode; unsigned char *buf; unsigned long offset, avail, readlen; int result = -EIO; struct ffs2_entry *entry; struct ffs_read r; unsigned long cur; memset(&r,0,sizeof(r)); r.super = inode->i_sb; // Setup the page atomic_inc(&page->count); set_bit(PG_locked, &page->flags); buf = (unsigned char *)page_address(page); clear_bit(PG_uptodate, &page->flags); clear_bit(PG_error, &page->flags); // Past then end is == 0 readlen = 1; while (page->offset < inode->i_size) { avail = inode->i_size - page->offset; readlen = PAGE_SIZE; if (avail < readlen) readlen = avail; // Blank out the end of the page if (readlen < PAGE_SIZE) memset(buf + readlen,0,PAGE_SIZE-readlen); // Get the inode and follow to find the first extent if ((entry = ffs2_find_entry(&r,inode->i_ino)) == 0 || isFNULL(entry->PrimaryPtr) || (entry->Status & FFS_ENTRY_PRIMARY) == FFS_ENTRY_PRIMARY) break; // Check for compression if ((entry->Status >> FFS_ENTRY_COMPIP_SHIFT) != 0xFF) { printk("ffs2: No support for compressed format %x\n", entry->Status >> FFS_ENTRY_COMPIP_SHIFT); break; } cur = entry->PrimaryPtr; offset = 0; while (readlen > 0) { unsigned long length = 0; struct ffs2_fileinfo *extent = (struct ffs2_fileinfo *)ffs2_find_entry(&r,cur); if (extent == 0) break; if (!isflagset(extent->Status,FFS_ENTRY_TYPEMASK,FFS_ENTRY_TYPEEXTENT)) break; // Skip cur to the next one if (isFNULL(extent->PrimaryPtr) == 0 && (extent->Status & FFS_ENTRY_PRIMARY) != FFS_ENTRY_PRIMARY) cur = extent->PrimaryPtr; else cur = 0xFFFFFFFF; if ((extent->Status & FFS_ENTRY_EXISTS) != FFS_ENTRY_EXISTS) continue; // See if we have entered the copy region length = extent->UncompressedExtentLen; if (offset + extent->UncompressedExtentLen > page->offset) { unsigned long toread = extent->UncompressedExtentLen; int res; if (toread > readlen) toread = readlen; if (page->offset >= offset) res = ffs2_copy_to_buff(&r,buf,extent,toread,page->offset - offset); else res = ffs2_copy_to_buff(&r,buf + offset - page->offset,extent,toread,0); if (res != 0) break; readlen -= toread; } if (length == 0) break; offset += length; if (cur == 0xFFFFFFFF) break; } break; } ffs2_relse(&r); if (readlen == 0) { set_bit(PG_uptodate, &page->flags); result = 0; } else { set_bit(PG_error, &page->flags); memset((void *)buf, 0, PAGE_SIZE); } clear_bit(PG_locked, &page->flags); wake_up(&page->wait); free_page((unsigned long)buf); return result;} /*}}}*/// ffs2_readlink - Read a symlink /*{{{*/// ---------------------------------------------------------------------/* */static int ffs2_readlink(struct dentry *dentry, char *buffer, int len){ printk("readlink\n"); return -EIO; } /*}}}*/// ffs2_follow_link - ?? /*{{{*/// ---------------------------------------------------------------------/* */static struct dentry *ffs2_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow){ printk("followlink\n"); return ERR_PTR(EAGAIN);} /*}}}*/// ffs2_read_inode - Fill in an inode /*{{{*/// ---------------------------------------------------------------------/* This function fills in the information for an inode. For FFS an inode is defined to be the DirEntry/FileEntry for the object in question. The inode number is the pointer this structure. */static void ffs2_read_inode(struct inode *i){ struct ffs2_entry *entry; struct ffs_read r; unsigned long cur; memset(&r,0,sizeof(r)); r.super = i->i_sb; // Setup the super block //lock_super(i->i_sb); // Locate the real inode entry = ffs2_find_entry(&r,i->i_ino); if (entry == 0) { ffs2_relse(&r); return; } i->i_mode = 0; i->i_nlink = 1; // FFS does not have a link concept i->i_size = 0; i->i_mtime = i->i_atime = i->i_ctime = 0; i->i_uid = i->i_gid = 0; i->i_op = ffs2_inoops[1]; // Decide on the mode if (isflagset(entry->Status,FFS_ENTRY_TYPEMASK,FFS_ENTRY_TYPEDIR)) { i->i_op = ffs2_inoops[1]; i->i_mode = S_IRWXUGO | S_IFDIR; } else { i->i_op = ffs2_inoops[2]; // i->i_mode = (S_IRWXUGO & (~S_IXUGO)) | S_IFREG; i->i_mode = S_IRWXUGO | S_IFREG; } // Compute the size and locate the date/time if (!isFNULL(entry->PrimaryPtr) && (entry->Status & FFS_ENTRY_PRIMARY) != FFS_ENTRY_PRIMARY) { cur = entry->PrimaryPtr; while (1) { struct ffs2_entry *extent = ffs2_find_entry(&r,cur); if (extent == 0) { ffs2_relse(&r); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -