📄 fs.c
字号:
{ int error; struct inode *r = 0; ntfs_volume *vol; ntfs_inode *ino; ntfs_attribute *si; ntfs_debug (DEBUG_DIR1, "mkdir %s in %x\n",d->d_name.name, dir->i_ino); error = ENAMETOOLONG; if (d->d_name.len > /* FIXME */255) goto out; error = EIO; r = new_inode(dir->i_sb); if (!r) goto out; vol = NTFS_INO2VOL(dir);#ifdef NTFS_IN_LINUX_KERNEL ino = NTFS_LINO2NINO(r);#else ino = ntfs_malloc(sizeof(ntfs_inode)); error = ENOMEM; if(!ino) goto out; r->u.generic_ip = ino;#endif error = ntfs_mkdir(NTFS_LINO2NINO(dir), d->d_name.name, d->d_name.len, ino); if(error) goto out; r->i_uid = vol->uid; r->i_gid = vol->gid; si = ntfs_find_attr(ino,vol->at_standard_information,NULL); if(si){ char *attr = si->d.data; r->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr+0x18)); r->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr)); r->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr+8)); } /* It's a directory */ r->i_op = &ntfs_dir_inode_operations; r->i_fop = &ntfs_dir_operations; r->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;#ifdef CONFIG_NTFS_RW r->i_mode|=S_IWUGO;#endif r->i_mode &= ~vol->umask; insert_inode_hash(r); d_instantiate(d, r); error = 0; out: ntfs_debug (DEBUG_DIR1, "mkdir returns %d\n", -error); return -error;}#endif#if 0static int ntfs_bmap(struct inode *ino,int block){ int ret=ntfs_vcn_to_lcn(NTFS_LINO2NINO(ino),block); ntfs_debug(DEBUG_OTHER, "bmap of %lx,block %x is %x\n", ino->i_ino,block,ret); return (ret==-1) ? 0:ret;}#endif/* It's fscking broken. *//* FIXME: [bm]map code is disabled until ntfs_get_block gets sorted! *//*static int ntfs_get_block(struct inode *inode, long block, struct buffer_head *bh, int create){ BUG(); return -1;}static struct file_operations ntfs_file_operations = { read: ntfs_read, mmap: generic_file_mmap,#ifdef CONFIG_NTFS_RW write: ntfs_write,#endif};static struct inode_operations ntfs_inode_operations;*/static struct file_operations ntfs_dir_operations = { read: generic_read_dir, readdir: ntfs_readdir,};static struct inode_operations ntfs_dir_inode_operations = { lookup: ntfs_lookup,#ifdef CONFIG_NTFS_RW create: ntfs_create, mkdir: _linux_ntfs_mkdir,#endif};/*static int ntfs_writepage(struct page *page){ return block_write_full_page(page,ntfs_get_block);}static int ntfs_readpage(struct file *file, struct page *page){ return block_read_full_page(page,ntfs_get_block);}static int ntfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to){ return cont_prepare_write(page,from,to,ntfs_get_block, &page->mapping->host->u.ntfs_i.mmu_private);}static int _ntfs_bmap(struct address_space *mapping, long block){ return generic_block_bmap(mapping,block,ntfs_get_block);}struct address_space_operations ntfs_aops = { readpage: ntfs_readpage, writepage: ntfs_writepage, sync_page: block_sync_page, prepare_write: ntfs_prepare_write, commit_write: generic_commit_write, bmap: _ntfs_bmap};*//* ntfs_read_inode is called by the Virtual File System (the kernel layer that * deals with filesystems) when iget is called requesting an inode not already * present in the inode table. Typically filesystems have separate * inode_operations for directories, files and symlinks. */static void ntfs_read_inode(struct inode* inode){ ntfs_volume *vol; int can_mmap=0; ntfs_inode *ino; ntfs_attribute *data; ntfs_attribute *si; vol=NTFS_INO2VOL(inode); inode->i_mode=0; ntfs_debug(DEBUG_OTHER, "ntfs_read_inode %x\n",(unsigned)inode->i_ino); switch(inode->i_ino) { /* those are loaded special files */ case FILE_MFT: ntfs_error("Trying to open MFT\n");return; default: #ifdef NTFS_IN_LINUX_KERNEL ino=&inode->u.ntfs_i; #else /* FIXME: check for ntfs_malloc failure */ ino=(ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode)); inode->u.generic_ip=ino; #endif if(!ino || ntfs_init_inode(ino, NTFS_INO2VOL(inode),inode->i_ino)) { ntfs_debug(DEBUG_OTHER, "NTFS:Error loading inode %x\n", (unsigned int)inode->i_ino); return; } } /* Set uid/gid from mount options */ inode->i_uid=vol->uid; inode->i_gid=vol->gid; inode->i_nlink=1; /* Use the size of the data attribute as file size */ data = ntfs_find_attr(ino,vol->at_data,NULL); if(!data) { inode->i_size=0; can_mmap=0; } else { inode->i_size=data->size; /* FIXME: once ntfs_get_block is implemented, uncomment the * next line and remove the can_mmap = 0; */ /* can_mmap=!data->resident && !data->compressed;*/ can_mmap = 0; } /* get the file modification times from the standard information */ si=ntfs_find_attr(ino,vol->at_standard_information,NULL); if(si){ char *attr=si->d.data; inode->i_atime=ntfs_ntutc2unixutc(NTFS_GETU64(attr+0x18)); inode->i_ctime=ntfs_ntutc2unixutc(NTFS_GETU64(attr)); inode->i_mtime=ntfs_ntutc2unixutc(NTFS_GETU64(attr+8)); } /* if it has an index root, it's a directory */ if(ntfs_find_attr(ino,vol->at_index_root,"$I30")) { ntfs_attribute *at; at = ntfs_find_attr (ino, vol->at_index_allocation, "$I30"); inode->i_size = at ? at->size : 0; inode->i_op=&ntfs_dir_inode_operations; inode->i_fop=&ntfs_dir_operations; inode->i_mode=S_IFDIR|S_IRUGO|S_IXUGO; } else { /* As long as ntfs_get_block() is just a call to BUG() do not * define any [bm]map ops or we get the BUG() whenever someone * runs mc or mpg123 on an ntfs partition! * FIXME: Uncomment the below code when ntfs_get_block is * implemented. */ /* if (can_mmap) { inode->i_op = &ntfs_inode_operations; inode->i_fop = &ntfs_file_operations; inode->i_mapping->a_ops = &ntfs_aops; inode->u.ntfs_i.mmu_private = inode->i_size; } else */ { inode->i_op=&ntfs_inode_operations_nobmap; inode->i_fop=&ntfs_file_operations_nommap; } inode->i_mode=S_IFREG|S_IRUGO; }#ifdef CONFIG_NTFS_RW if(!data || !data->compressed) inode->i_mode|=S_IWUGO;#endif inode->i_mode &= ~vol->umask;}#ifdef CONFIG_NTFS_RWstatic void ntfs_write_inode (struct inode *ino, int unused){ lock_kernel(); ntfs_debug (DEBUG_LINUX, "ntfs:write inode %x\n", ino->i_ino); ntfs_update_inode (NTFS_LINO2NINO (ino)); unlock_kernel();}#endifstatic void _ntfs_clear_inode(struct inode *ino){ lock_kernel(); ntfs_debug(DEBUG_OTHER, "ntfs_clear_inode %lx\n",ino->i_ino);#ifdef NTFS_IN_LINUX_KERNEL if(ino->i_ino!=FILE_MFT) ntfs_clear_inode(&ino->u.ntfs_i);#else if(ino->i_ino!=FILE_MFT && ino->u.generic_ip) { ntfs_clear_inode(ino->u.generic_ip); ntfs_free(ino->u.generic_ip); ino->u.generic_ip=0; }#endif unlock_kernel(); return;}/* Called when umounting a filesystem by do_umount() in fs/super.c */static void ntfs_put_super(struct super_block *sb){ ntfs_volume *vol; ntfs_debug(DEBUG_OTHER, "ntfs_put_super\n"); vol=NTFS_SB2VOL(sb); ntfs_release_volume(vol); if(vol->nls_map) unload_nls(vol->nls_map);#ifndef NTFS_IN_LINUX_KERNEL ntfs_free(vol);#endif ntfs_debug(DEBUG_OTHER, "ntfs_put_super: done\n");}/* Called by the kernel when asking for stats */static int ntfs_statfs(struct super_block *sb, struct statfs *sf){ struct inode *mft; ntfs_volume *vol; ntfs_u64 size; int error; ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n"); vol=NTFS_SB2VOL(sb); sf->f_type=NTFS_SUPER_MAGIC; sf->f_bsize=vol->clustersize; error = ntfs_get_volumesize( NTFS_SB2VOL( sb ), &size ); if( error ) return -error; sf->f_blocks = size; /* volumesize is in clusters */ sf->f_bfree=ntfs_get_free_cluster_count(vol->bitmap); sf->f_bavail=sf->f_bfree; mft=iget(sb,FILE_MFT); if (!mft) return -EIO; /* So ... we lie... thus this following cast of loff_t value is ok here.. */ sf->f_files = (unsigned long)mft->i_size / vol->mft_recordsize; iput(mft); /* should be read from volume */ sf->f_namelen=255; return 0;}/* Called when remounting a filesystem by do_remount_sb() in fs/super.c */static int ntfs_remount_fs(struct super_block *sb, int *flags, char *options){ if(!parse_options(NTFS_SB2VOL(sb), options)) return -EINVAL; return 0;}/* Define the super block operation that are implemented */static struct super_operations ntfs_super_operations = { read_inode: ntfs_read_inode,#ifdef CONFIG_NTFS_RW write_inode: ntfs_write_inode,#endif put_super: ntfs_put_super, statfs: ntfs_statfs, remount_fs: ntfs_remount_fs, clear_inode: _ntfs_clear_inode,};/* Called to mount a filesystem by read_super() in fs/super.c * Return a super block, the main structure of a filesystem * * NOTE : Don't store a pointer to an option, as the page containing the * options is freed after ntfs_read_super() returns. * * NOTE : A context switch can happen in kernel code only if the code blocks * (= calls schedule() in kernel/sched.c). */struct super_block * ntfs_read_super(struct super_block *sb, void *options, int silent){ ntfs_volume *vol; struct buffer_head *bh; int i; ntfs_debug(DEBUG_OTHER, "ntfs_read_super\n");#ifdef NTFS_IN_LINUX_KERNEL vol = NTFS_SB2VOL(sb);#else if(!(vol = ntfs_malloc(sizeof(ntfs_volume)))) goto ntfs_read_super_dec; NTFS_SB2VOL(sb)=vol;#endif if(!parse_options(vol,(char*)options)) goto ntfs_read_super_vol;#if 0 /* Set to read only, user option might reset it */ sb->s_flags |= MS_RDONLY;#endif /* Assume a 512 bytes block device for now */ set_blocksize(sb->s_dev, 512); /* Read the super block (boot block) */ if(!(bh=bread(sb->s_dev,0,512))) { ntfs_error("Reading super block failed\n"); goto ntfs_read_super_unl; } ntfs_debug(DEBUG_OTHER, "Done reading boot block\n"); /* Check for 'NTFS' magic number */ if(!IS_NTFS_VOLUME(bh->b_data)){ ntfs_debug(DEBUG_OTHER, "Not a NTFS volume\n"); brelse(bh); goto ntfs_read_super_unl; } ntfs_debug(DEBUG_OTHER, "Going to init volume\n"); ntfs_init_volume(vol,bh->b_data); ntfs_debug(DEBUG_OTHER, "MFT record at cluster 0x%X\n",vol->mft_cluster); brelse(bh); NTFS_SB(vol)=sb; ntfs_debug(DEBUG_OTHER, "Done to init volume\n"); /* Inform the kernel that a device block is a NTFS cluster */ sb->s_blocksize=vol->clustersize; for(i=sb->s_blocksize,sb->s_blocksize_bits=0;i != 1;i>>=1) sb->s_blocksize_bits++; set_blocksize(sb->s_dev,sb->s_blocksize); ntfs_debug(DEBUG_OTHER, "set_blocksize\n"); /* Allocate a MFT record (MFT record can be smaller than a cluster) */ if(!(vol->mft=ntfs_malloc(max(vol->mft_recordsize,vol->clustersize)))) goto ntfs_read_super_unl; /* Read at least the MFT record for $MFT */ for(i=0;i<max(vol->mft_clusters_per_record,1);i++){ if(!(bh=bread(sb->s_dev,vol->mft_cluster+i,vol->clustersize))) { ntfs_error("Could not read MFT record 0\n"); goto ntfs_read_super_mft; } ntfs_memcpy(vol->mft+i*vol->clustersize,bh->b_data,vol->clustersize); brelse(bh); ntfs_debug(DEBUG_OTHER, "Read cluster %x\n",vol->mft_cluster+i); } /* Check and fixup this MFT record */ if(!ntfs_check_mft_record(vol,vol->mft)){ ntfs_error("Invalid MFT record 0\n"); goto ntfs_read_super_mft; } /* Inform the kernel about which super operations are available */ sb->s_op = &ntfs_super_operations; sb->s_magic = NTFS_SUPER_MAGIC; ntfs_debug(DEBUG_OTHER, "Reading special files\n"); if(ntfs_load_special_files(vol)){ ntfs_error("Error loading special files\n"); goto ntfs_read_super_mft; } ntfs_debug(DEBUG_OTHER, "Getting RootDir\n"); /* Get the root directory */ if(!(sb->s_root=d_alloc_root(iget(sb,FILE_ROOT)))){ ntfs_error("Could not get root dir inode\n"); goto ntfs_read_super_mft; } ntfs_debug(DEBUG_OTHER, "read_super: done\n"); return sb;ntfs_read_super_mft: ntfs_free(vol->mft);ntfs_read_super_unl:ntfs_read_super_vol: #ifndef NTFS_IN_LINUX_KERNEL ntfs_free(vol);ntfs_read_super_dec: #endif ntfs_debug(DEBUG_OTHER, "read_super: done\n"); return NULL;}/* Define the filesystem */static DECLARE_FSTYPE_DEV(ntfs_fs_type, "ntfs", ntfs_read_super);static int __init init_ntfs_fs(void){ /* Comment this if you trust klogd. There are reasons not to trust it */#if defined(DEBUG) && !defined(MODULE) console_verbose();#endif printk(KERN_NOTICE "NTFS version " NTFS_VERSION "\n"); SYSCTL(1); ntfs_debug(DEBUG_OTHER, "registering %s\n",ntfs_fs_type.name); /* add this filesystem to the kernel table of filesystems */ return register_filesystem(&ntfs_fs_type);}static void __exit exit_ntfs_fs(void){ SYSCTL(0); ntfs_debug(DEBUG_OTHER, "unregistering %s\n",ntfs_fs_type.name); unregister_filesystem(&ntfs_fs_type);}EXPORT_NO_SYMBOLS;MODULE_AUTHOR("Martin von L鰓is");MODULE_DESCRIPTION("NTFS driver");#ifdef DEBUGMODULE_PARM(ntdebug, "i");MODULE_PARM_DESC(ntdebug, "Debug level");#endifmodule_init(init_ntfs_fs)module_exit(exit_ntfs_fs)/* * Local variables: * c-file-style: "linux" * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -