オペレーティングシステムの大規模な実験進展(6)---Linuxカーネルファイルシステムと設備の操作フロー分析

31189 ワード

変換先:http://www.whitecell.org/list.php?id=45
     linux kernel                   ,    
  ext3       open      ,              :

1、         ,       struct file   struct dentry
      struct inode      ?

2、           VFS(Virtual File System)       struct file 
        ,          ?        ?

3、linux        UNIX VFS(Virtual File System)     struct vnode
     ,                         ?

4、   (super block)                ?

5、         struct file             ?

6、               ?    ?          ?

 :                ,            ,
                 ,       ,        。
                      。      ,    
        ,              。       ,  
                ,        。


      linux kernel  ,         ,      filp_open()
   kernel api        ,            。    
filp_open()          ,      do_filp_open()   ,  
      open_namei()        fd     struct nameidata   。
     nameidata_to_filp()        struct file   。

static struct file *do_filp_open(int dfd, const char *filename, int flags,
				 int mode)
{
	int namei_flags, error;
	struct nameidata nd;

	namei_flags = flags;
	if ((namei_flags+1) & O_ACCMODE)
		namei_flags++;

        //
        //        path_lookup_xxx()          
        //      struct nameidata   。         
        //   ,               。      
        //         nameidata   。
        //
	error = open_namei(dfd, filename, namei_flags, mode, &nd);
	if (!error)
                
                //
                //       struct file             。
                //         。
                //
		return nameidata_to_filp(&nd, flags);

	return ERR_PTR(error);
}


       struct nameidata        struct file。    
struct file       __dentry_open()        ,     
      nameidata->dentry,            struct nameidata
       ,          struct dentry   。

struct file *nameidata_to_filp(struct nameidata *nd, int flags)
{
	struct file *filp;

	/* Pick up the filp from the open intent */
	filp = nd->intent.open.file;
	/* Has the filesystem initialised the file for us? */
	if (filp->f_dentry == NULL)

                //
                //              struct file   ,    
                //        ,   struct file       。
                //
		filp = __dentry_open(nd->dentry, nd->mnt, flags, filp, NULL);
	else
		path_release(nd);
	return filp;
}


           struct file   。             ,
   struct file       struct dentry,struct inode,struct vfsmount
           。  struct dentry           struct inode 
  ,             struct dentry     。   struct inode
                               ,  ext3 
    。               ,       。      ?
        。

static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
					int flags, struct file *f,
					int (*open)(struct inode *, struct file *))
{
	struct inode *inode;
	int error;

        //
        //       
        // 
	f->f_flags = flags;
	f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK |
				FMODE_PREAD | FMODE_PWRITE;
        //
        //    struct dentry    struct inode   
        //
	inode = dentry->d_inode;

        //
        //       (inode)       ,   
        //     cleanup_file    
        //
	if (f->f_mode & FMODE_WRITE) {
		error = get_write_access(inode);
		if (error)
			goto cleanup_file;
	}

        //
        //    vfsmount,dentry,inode   
        //    struct file     。
        //
	f->f_mapping = inode->i_mapping;
	f->f_dentry = dentry;
	f->f_vfsmnt = mnt;
	f->f_pos = 0;

        //
        //   :       struct inode    struct file_operations
        //          struct file->f_op。     struct file   
        //       inode->file_operations       。    struct
        // file          ,     open             
        // struct file   ,   inode->i_fop     ,struct file    
        //      ,        ,  task_struct    files_struct 
        //      struct file      。         struct file
        //      ,         ,        。;)
        //
	f->f_op = fops_get(inode->i_fop);       
	file_move(f, &inode->i_sb->s_files);

        //
        //   :      struct file->f_op->open   ,       
        // struct inode->i_fop->open   。         ,  struct
        // inode    ,           ,    struct
        // file_operations     struct inode_operations。    open   
        //      file_operations   ,       。    struct inode
        //    i_fop                     , 
        // ext3_file_operations    。                 
        //     def_chr_fops    。
        //
	if (!open && f->f_op)
		open = f->f_op->open;
	if (open) {
		error = open(inode, f);
		if (error)
			goto cleanup_all;
	}

        //
        //        。
        //
	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);

	/* NB: we're sure to have correct a_ops only after f_op->open */
	if (f->f_flags & O_DIRECT) {
		if (!f->f_mapping->a_ops ||
		    ((!f->f_mapping->a_ops->direct_IO) &&
		    (!f->f_mapping->a_ops->get_xip_page))) {
			fput(f);
			f = ERR_PTR(-EINVAL);
		}	}

	return f;

//
//       ,         。   struct file  
//       ,     。
//
cleanup_all:
	fops_put(f->f_op);
	if (f->f_mode & FMODE_WRITE)
		put_write_access(inode);
	file_kill(f);
	f->f_dentry = NULL;
	f->f_vfsmnt = NULL;
cleanup_file:
	put_filp(f);
	dput(dentry);
	mntput(mnt);
	return ERR_PTR(error);
}


            struct file      f_op     struct inode->i_fop
      。           ,    register_xxx     “  ” 
  “ ”      ,       struct file           。  
         ,       *nix                   ,
    inode,    file system   device driver          
     struct inode    ,      file_operations    ,    
           file system        device driver  ?   
device driver                         ?    
  ext3       ,     ext3_read_inode()      。      
       ,       ?           ext3       open
                     ,         ,    
 ,          。

void ext3_read_inode(struct inode * inode)
{
	struct ext3_iloc iloc;
	struct ext3_inode *raw_inode;
	struct ext3_inode_info *ei = EXT3_I(inode);
	struct buffer_head *bh;
	int block;

        //
        //     ,               。
        //

#ifdef CONFIG_EXT3_FS_POSIX_ACL
	ei->i_acl = EXT3_ACL_NOT_CACHED;
	ei->i_default_acl = EXT3_ACL_NOT_CACHED;
#endif
	ei->i_block_alloc_info = NULL;

        //
        //   :    __ext3_get_inode_loc    
        //      I/O          struct inode
        //     in core    。         
        //      ,  0        I/O    
        //   ,    buffer_head        。
        //
	if (__ext3_get_inode_loc(inode, &iloc, 0))

                //
                //         inode            ,
                //            。
                //
		goto bad_inode;

        ......
        ......

        //
        //     ,  /  /             。
        //

	if (S_ISREG(inode->i_mode)) {

                //
                //          ,    ext3_file_xxx    
                //   :    ext3_file_operations     ,  
                // open        generic_file_open()   ,     
                //             ,         ,    
                //        ext3      ,open           
                //   ,     。       ?          
                //    。
                //
		inode->i_op = &ext3_file_inode_operations;
		inode->i_fop = &ext3_file_operations;
		ext3_set_aops(inode);
	} else if (S_ISDIR(inode->i_mode)) {

                //
                //        ,      ,   ext3_dir_xxx    
                //
		inode->i_op = &ext3_dir_inode_operations;
		inode->i_fop = &ext3_dir_operations;
	} else if (S_ISLNK(inode->i_mode)) {

                //
                //        ,      ,   ext3_symlink_xxx    
                //
		if (ext3_inode_is_fast_symlink(inode))
			inode->i_op = &ext3_fast_symlink_inode_operations;
		else {
			inode->i_op = &ext3_symlink_inode_operations;
			ext3_set_aops(inode);
		}
	} else {
               
                //
                //             ,               
                //   :      inode->i_op           。   
                // inode->i_fop         init_special_inode()   
                //      
                //
		inode->i_op = &ext3_special_inode_operations;
		if (raw_inode->i_block[0])
			init_special_inode(inode, inode->i_mode,
			   old_decode_dev(le32_to_cpu(raw_inode->i_block[0])));
		else
			init_special_inode(inode, inode->i_mode,
			   new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
	}

   ......
   ......
}


                            ,      
                             。     
        ,              ,           
        “  ”,“ ”,“FIFO”,“SOCKET”   ,    
“FIFO”,“SOCK”        ,       “ ”   ,    
    ,        。

void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
{
	inode->i_mode = mode;

        //
        //        ,    def_chr_fops    
        //             inode->i_rdev   
        //
	if (S_ISCHR(mode)) {
		inode->i_fop = &def_chr_fops;
		inode->i_rdev = rdev;

        //
        //       ,    def_blk_fops    
        //             inode->i_rdev   
        //
	} else if (S_ISBLK(mode)) {
		inode->i_fop = &def_blk_fops;
		inode->i_rdev = rdev;

        //
        //     FIFO,    def_fifo_fops    
        //
	} else if (S_ISFIFO(mode))
		inode->i_fop = &def_fifo_fops;
        //
        //     SOCKET,    def_sock_fops    
        //
	else if (S_ISSOCK(mode))
		inode->i_fop = &bad_sock_fops;

        //
        //              ,       。
        //
	else
		printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o)
", mode); } , “ ” , file_operations open , chrdev_open() 。 struct file->f_op ? chrdev_open() 。 const struct file_operations def_chr_fops = { .open = chrdev_open, }; struct file->f_op 。 , 。 int chrdev_open(struct inode * inode, struct file * filp) { struct cdev *p; struct cdev *new = NULL; int ret = 0; spin_lock(&cdev_lock); // // // p = inode->i_cdev; if (!p) { struct kobject *kobj; int idx; spin_unlock(&cdev_lock); // // , // kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx); if (!kobj) return -ENXIO; new = container_of(kobj, struct cdev, kobj); spin_lock(&cdev_lock); // // // p = inode->i_cdev; if (!p) { inode->i_cdev = p = new; inode->i_cindex = idx; list_add(&inode->i_devices, &p->list); new = NULL; // // cdev_get() // // } else if (!cdev_get(p)) ret = -ENXIO; // // , cdev_get() // , 。 // } else if (!cdev_get(p)) ret = -ENXIO; spin_unlock(&cdev_lock); cdev_put(new); // // , 。 // if (ret) return ret; // // : cdev->file_operations // struct file->f_op // 。 // filp->f_op = fops_get(p->ops); // // struct file->f_op , // , 。 : // , , // , 。 // if (!filp->f_op) { cdev_put(p); return -ENXIO; } // // open , // // if (filp->f_op->open) { lock_kernel(); ret = filp->f_op->open(inode,filp); unlock_kernel(); } if (ret) cdev_put(p); return ret; } , , open , ext3, ext3 , , 。 。 , , ext3_read_inode() , ? ? ext3 open ? , open_namei() 。 struct nameidata , , 。 , path_look_xxx() 。 int open_namei(int dfd, const char *pathname, int flag, int mode, struct nameidata *nd) { int acc_mode, error; struct path path; struct dentry *dir; int count = 0; // // , 。 // ...... // // , path_lookup_open() // if (!(flag & O_CREAT)) { // // inode, dentry nameidata 。 // error = path_lookup_open(dfd, pathname, lookup_flags(flag), nd, flag); if (error) return error; goto ok; } /* * Create - we need to know the parent. */ // // path_lookup_create() // error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode); if (error) return error; ...... } path_lookup_open() path_lookup_create() __path_lookup_intent_open() , 。 struct nameidata do_path_lookup() 。 static int __path_lookup_intent_open(int dfd, const char *name, unsigned int lookup_flags, struct nameidata *nd, int open_flags, int create_mode) { // // struct file // struct file *filp = get_empty_filp(); int err; if (filp == NULL) return -ENFILE; // // struct nameidata // nd->intent.open.file = filp; nd->intent.open.flags = open_flags; // // , path_lookup_open() // path_lookup_create() // nd->intent.open.create_mode = create_mode; // // do_path_lookup() struct nameidata // err = do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd); if (IS_ERR(nd->intent.open.file)) { if (err == 0) { err = PTR_ERR(nd->intent.open.file); path_release(nd); } } else if (err != 0) release_open_intent(nd); return err; } "/" AT_FDCWD struct vfsmount struct dentry struct nameidata , 。 link_path_walk() 。 static int fastcall do_path_lookup(int dfd, const char *name, unsigned int flags, struct nameidata *nd) { int retval = 0; int fput_needed; struct file *file; // // struct file // struct fs_struct *fs = current->fs; nd->last_type = LAST_ROOT; /* if there are only slashes... */ nd->flags = flags; nd->depth = 0; // // fs_struct->altrootmnt fs_struct->altroot // struct vfsmount struct dentry // if (*name=='/') { read_lock(&fs->lock); if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) { nd->mnt = mntget(fs->altrootmnt); nd->dentry = dget(fs->altroot); read_unlock(&fs->lock); if (__emul_lookup_dentry(name,nd)) goto out; /* found in altroot */ read_lock(&fs->lock); } nd->mnt = mntget(fs->rootmnt); nd->dentry = dget(fs->root); read_unlock(&fs->lock); // // AT_FDCWD fs_struct->pwdmnt // fs_struct->pwd struct vfsmount struct dentry // ? FIXME // } else if (dfd == AT_FDCWD) { read_lock(&fs->lock); nd->mnt = mntget(fs->pwdmnt); nd->dentry = dget(fs->pwd); read_unlock(&fs->lock); // // fget_light() struct file // struct file->f_vfsmnt struct vfsmount , // struct dentry struct file->f_dentry // } else { // // : struct dentry // struct dentry *dentry; file = fget_light(dfd, &fput_needed); retval = -EBADF; if (!file) goto out_fail; // // struct file // dentry = file->f_dentry; retval = -ENOTDIR; if (!S_ISDIR(dentry->d_inode->i_mode)) goto fput_fail; retval = file_permission(file, MAY_EXEC); if (retval) goto fput_fail; nd->mnt = mntget(file->f_vfsmnt); nd->dentry = dget(dentry); fput_light(file, fput_needed); } current->total_link_count = 0; // // : , 。 // , __link_path_walk() // 。 // retval = link_path_walk(name, nd); out: if (likely(retval == 0)) { if (unlikely(!audit_dummy_context() && nd && nd->dentry && nd->dentry->d_inode)) audit_inode(name, nd->dentry->d_inode); } out_fail: return retval; fput_fail: fput_light(file, fput_needed); goto out_fail; } link_path_walk() __link_path_walk(), , do_lookup() ,do_lookup() inode 。 , , , 。 static fastcall int __link_path_walk(const char * name, struct nameidata *nd) { struct path next; struct inode *inode; int err; unsigned int lookup_flags = nd->flags; // // , 。 // // // , // do_lookup() // inode 。 // /dir/temp/readme.txt // do_lookup() inode // readme.txt 。 // for(;;) { ....... // // inode // err = do_lookup(nd, &this, &next); if (err) break; ...... last_with_slashes: lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; last_component: /* Clear LOOKUP_CONTINUE iff it was previously unset */ nd->flags &= lookup_flags | ~LOOKUP_CONTINUE; ....... // // LOOKUP_CONTINUE , 。 // err = do_lookup(nd, &this, &next); if (err) break; ...... } path_release(nd); return_err: return err; } struct dentry , struct dentry 。 , real_lookup() inode 。 struct dentry struct inode 。 static int do_lookup(struct nameidata *nd, struct qstr *name, struct path *path) { struct vfsmount *mnt = nd->mnt; // // hlist struct dentry ,hlist // inode HASH 。 // struct dentry *dentry = __d_lookup(nd->dentry, name); // // real_lookup() // // if (!dentry) goto need_lookup; if (dentry->d_op && dentry->d_op->d_revalidate) goto need_revalidate; done: // // , struct path // path->mnt = mnt; path->dentry = dentry; __follow_mount(path); return 0; need_lookup: // // , inode // dentry = real_lookup(nd->dentry, name, nd); if (IS_ERR(dentry)) goto fail; goto done; need_revalidate: dentry = do_revalidate(dentry, nd); // // 。 struct dentry // real_lookup() // if (!dentry) goto need_lookup; if (IS_ERR(dentry)) goto fail; goto done; fail: return PTR_ERR(dentry); } real_lookup() , ext3 inode 。 lookup ext3_lookup() 。 struct inode_operations ext3_dir_inode_operations = { // // , // ...... .lookup = ext3_lookup, ...... }; inode, struct dentry , parent->d_inode->i_op->lookup ext3_lookup() inode。 static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd) { struct dentry * result; // // , 。 // // // inode。 // , inode 。 // struct inode *dir = parent->d_inode; ...... // // 。 // result = d_lookup(parent, name); if (!result) { // // , struct dentry // : struct dentry, // dentry 。 // struct dentry * dentry = d_alloc(parent, name); result = ERR_PTR(-ENOMEM); if (dentry) { // // ext3_lookup() , // ext3_dir_inode_operations // // result = dir->i_op->lookup(dir, dentry, nd); if (result) dput(dentry); else result = dentry; } mutex_unlock(&dir->i_mutex); return result; } ....... } 。 , dentry ext3_dir_entry_2 dentry , inode number, iget() struct inode , inode dentry 。 static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) { struct inode * inode; struct ext3_dir_entry_2 * de; struct buffer_head * bh; if (dentry->d_name.len > EXT3_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); // // dentry buffer_head // : dentry , d_parent // d_inode , 。 // de inode number。 // bh = ext3_find_entry(dentry, &de); // // : inode NULL // inode = NULL; if (bh) { unsigned long ino = le32_to_cpu(de->inode); brelse (bh); // // (super block) // if (!ext3_valid_inum(dir->i_sb, ino)) { ext3_error(dir->i_sb, "ext3_lookup", "bad inode number: %lu", ino); inode = NULL; } else // // iget() struct inode // (super block) // inode = iget(dir->i_sb, ino); if (!inode) return ERR_PTR(-EACCES); } // // inode dentry 。 // return d_splice_alias(inode, dentry); } iget() , (super block) 。 struct super_block { // // , // ...... // // 。 mount // 。 // struct file_system_type *s_type; // // (super block) // struct super_operations *s_op; ...... }; ext3 (super block) static struct super_operations ext3_sops = { // // , // ...... // // : ext3_read_inode() // .read_inode = ext3_read_inode, ...... }; ! , , (super block) read_inode , ext3_sops ext3_read_inode() 。 static inline struct inode *iget(struct super_block *sb, unsigned long ino) { struct inode *inode = iget_locked(sb, ino); if (inode && (inode->i_state & I_NEW)) { // // ext3_read_inode() // sb->s_op->read_inode(inode); unlock_new_inode(inode); } return inode; } ext3_read_inode() , open_namei() iget() , iget() (super block) ext3_sops ext3_read_inode() inode。 struct inode->i_fop ( ext3_file_operations ) open generic_file_open() 。 inode open_namei()->iget() , inode , inode / 。 generic_file_open() , 。 , open struct inode->i_fop->open , open 。 __dentry_open() 。 , , (super block) ext3_sops ? , mount 。 mount , , register_filesyste()。 struct file_system_type { // // , :ext3 // const char *name; int fs_flags; // // (super block) 。 mount // , inode 。 // int (*get_sb) (struct file_system_type *, int, const char *, void *, struct vfsmount *); void (*kill_sb) (struct super_block *); // // // struct module *owner; // // // struct file_system_type * next; struct list_head fs_supers; struct lock_class_key s_lock_key; struct lock_class_key s_umount_key; }; ext3 。 static struct file_system_type ext3_fs_type = { .owner = THIS_MODULE, .name = "ext3", // // ext3_get_sb() // .get_sb = ext3_get_sb, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; register_filesystem( &ext3_fs_type ); 。 , mount 。 , vfs_kern_mount() , mount , file_system_type , ext3 ext3_fs_type。 type->get_sb ext3_get_sb() 。 struct vfsmount * vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) { struct vfsmount *mnt; char *secdata = NULL; int error; if (!type) return ERR_PTR(-ENODEV); error = -ENOMEM; // // vfsmount 。 // mnt = alloc_vfsmnt(name); if (!mnt) goto out; if (data) { secdata = alloc_secdata(); if (!secdata) goto out_mnt; error = security_sb_copy_data(type, data, secdata); if (error) goto out_free_secdata; } // // : (super block) // ext3 , ext3_get_sb, // file_system_type 。 // error = type->get_sb(type, flags, name, data, mnt); if (error < 0) goto out_free_secdata; error = security_sb_kern_mount(mnt->mnt_sb, secdata); if (error) goto out_sb; // // dentry // mnt->mnt_mountpoint = mnt->mnt_root; // // vfsmount parent // parent mount // mnt->mnt_parent = mnt; up_write(&mnt->mnt_sb->s_umount); free_secdata(secdata); return mnt; // // // out_sb: dput(mnt->mnt_root); up_write(&mnt->mnt_sb->s_umount); deactivate_super(mnt->mnt_sb); out_free_secdata: free_secdata(secdata); out_mnt: free_vfsmnt(mnt); out: return ERR_PTR(error); } ext3_get_sb() , get_sb_bdev() , get_sb_bdev() ext3_get_sb() , ext3_fill_super , 。 static int ext3_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { // // : ext3_fill_super() 。 // return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super, mnt); } ext3_fill_super() , (super block) 。 ext3 (super block) ext3_sops 。 iget() (super block) 。 static int ext3_fill_super (struct super_block *sb, void *data, int silent) { // // , 。 // // // // sb->s_op = &ext3_sops; sb->s_export_op = &ext3_export_ops; sb->s_xattr = ext3_xattr_handlers; #ifdef CONFIG_QUOTA sb->s_qcop = &ext3_qctl_operations; sb->dq_op = &ext3_quota_operations; #endif INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */ sb->s_root = NULL; // // iget() inode。 // root = iget(sb, EXT3_ROOT_INO); // // inode (super block) // s_root struct dentry 。 // sb->s_root = d_alloc_root(root); // // dentry 。 // if (!sb->s_root) { printk(KERN_ERR "EXT3-fs: get root inode failed
"); iput(root); goto failed_mount4; } // // inode // 。 // if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { dput(sb->s_root); sb->s_root = NULL; printk(KERN_ERR "EXT3-fs: corrupt root inode, run e2fsck
"); goto failed_mount4; } } , 。 。 sys_open , filp_open()->do_filp_open() , do_filp_open() , open_namei() struct nameidata , __path_lookup_intent_open() struct nameidata->intent.open , do_path_lookup() , struct nameidata->mnt struct nameidata->dentry _link_path_walk() , do_lookup() struct inode。do_lookup() inode hlist inode, real_lookup() , struct dentry , struct inode->i_op->lookup() , ext3_lookup() , struct dentry inode number iget() struct inode。( , struct dentry , struct dentry , ) iget() struct inode (super block) ext3_read_inode() inode , in core struct inode / struct inode->i_op struct inode->i_fop 。 。 ext3_file_operations / , 。 , , 。 struct inode,struct dentry, struct nameidata 。 open_namei() nameidata nameidata_to_filp() , struct dentry __dentry_open() , struct file , struct inode->i_fop struct file->f_op ( , inode , )。 , 。 / / ext3_file_xxx ext3_dir_xxx 。 init_special_inode , chrdev_open() struct file 。 (super block) register_filesystem() , mount vfs_kern_mount() ext3_fill_super() 。 , 。 struct inode 。 / ,struct inode_operations (inode) / ( )/ / ,struct file_operations / / / (readdir)/ 。 :linux kernel source 2.6.19.1 /usr/fs/ext3/inode.c /usr/fs/ext3/namei.c /usr/fs/ext3/super.c /usr/fs/ext3/file.c /usr/fs/ext3/dir.c /usr/fs/block_dev.c /usr/fs/open.c /usr/fs/dcache.h /usr/fs/inode.c /usr/fs/namei.c /usr/fs/super.c /inlucde/linux/mount.h

WSS(Whitecell Security Systems)は、非営利民間技術組織であり、様々なシステムセキュリティ技術の研究に力を入れている.伝統的なhacker精神を堅持し、技術の精製を追求する.
WSSホームページ:http://www.whitecell.org/
WSSフォーラム:http://www.whitecell.org/forums/