ファイルシステム

					2011年03月01日
情報科学類 オペレーティングシステム II

                                       筑波大学 システム情報工学研究科 
                                       コンピュータサイエンス専攻, 電子・情報工学系
                                       新城 靖
                                       <yas@is.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~yas/coins/os2-2010/2011-03-01
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~yas/
http://www.cs.tsukuba.ac.jp/~yas/

■連絡事項

試験について 欠席した時のクイズの回答を、レポートして受け取ります。試験の日までに提 出して下さい。紙はA4にしてください。

■今日の大事な話

■ファイルシステム

◆求められる機能

システム・コール 様々な物理媒体と接続方法の利用 様々なディスク上の表現(ファイルシステム) 注意: 「ファイルシステム」という言葉が、様々な意味で使われる

◆層構造

問題: 様々な物理媒体やディスク上の表現の違いを吸収して、共通のシステム・ コールでファイルを扱いたい。

解決策:

図? システム・コール、VFS、ブロックデバイス

図? ファイル・システム実現に置ける層構造

ディスク・キャッシュの層もある。

◆継承

問題: ファイルシステム間で共通部分のコードを再利用したい。

解決策

◆VFSレベルのファイルの概念

◆inode番号

ls -i で inode 番号が表示される。
$ ls -l /bin/{gunzip,gzip,zcat} [←]
-rwxr-xr-x 3 root root 62872 Jan 21  2010 /bin/gunzip
-rwxr-xr-x 3 root root 62872 Jan 21  2010 /bin/gzip
-rwxr-xr-x 3 root root 62872 Jan 21  2010 /bin/zcat
$ ls -li /bin/{gunzip,gzip,zcat} [←]
5636134 -rwxr-xr-x 3 root root 62872 Jan 21  2010 /bin/gunzip
5636134 -rwxr-xr-x 3 root root 62872 Jan 21  2010 /bin/gzip
5636134 -rwxr-xr-x 3 root root 62872 Jan 21  2010 /bin/zcat
$ []

◆/etc/fstab

/etc/fstab は、「起動時に」にマウントすべきファイルシステムのリストを保 持している。
$ cat /etc/fstab  [←]
LABEL=/                 /                       ext3    defaults        1 1
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
LABEL=SWAP-sda3         swap                    swap    defaults        0 0
130.158.86.2:/vol/vol1/home     /home   nfs     rw,hard,bg,nfsvers=3,intr      0 0
130.158.86.2:/vol/vol5/local3   /usr/local3     nfs     rw,hard,bg,nfsvers=3,intr       0 0
$ df -h [←]
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda2             222G   13G  198G   6% /
tmpfs                 2.0G     0  2.0G   0% /dev/shm
130.158.86.2:/vol/vol1/home
                      4.0T  1.5T  2.5T  38% /home
130.158.86.2:/vol/vol5/local3
                       80G  4.9G   76G   7% /usr/local3
$ []

■VFSのオブジェクト

VFSの実装では、次のようオブジェクトオブジェクト(データ+手続きをカプセル 化したもの)を通じて実装される。 ファイルシステム固有の処理は、_operations の手続きを入れ替えることで実 現される。固有のデータは、構造体を入れ子にしたり、固有データへのポイン タを使ったりして実現している。

◆struct super_block

include/linux/fs.h

1318:	struct super_block {
1319:	        struct list_head        s_list;         /* Keep this first */
...
1321:	        unsigned char           s_dirt;
...
1324:	        loff_t                  s_maxbytes;     /* Max file size */
...
1325:	        struct file_system_type *s_type;
1326:	        const struct super_operations   *s_op;
...
1332:	        struct dentry           *s_root;
...
1342:	        struct list_head        s_inodes;       /* all inodes */
...
1347:	        struct list_head        s_files;
...
1350:	        struct list_head        s_dentry_lru;   /* unused dentry lru */
1351:	        int                     s_nr_dentry_unused;     /* # of dentry on lru */
1352:	

1364:	        void                    *s_fs_info;     /* Filesystem private info */
1388:	};

◆struct super_operations

スーパーブロックの操作は、たとえば次のような形で行われる。
    struct super_block *sh;
    ...
    sh->s_op->write_super(sb);
s_op には、次のような手続きがある。各ファイルシステム (ext3,nfs,tmpfs,...) ごとに、手続きの実体は異なるが、インタフェースは同 じ。
1560:	struct super_operations {
1561:	        struct inode *(*alloc_inode)(struct super_block *sb);
1562:	        void (*destroy_inode)(struct inode *);
1563:	
1564:	        void (*dirty_inode) (struct inode *);
1565:	        int (*write_inode) (struct inode *, struct writeback_control *wbc);
1566:	        int (*drop_inode) (struct inode *);
1567:	        void (*evict_inode) (struct inode *);
1568:	        void (*put_super) (struct super_block *);
1569:	        void (*write_super) (struct super_block *);
1570:	        int (*sync_fs)(struct super_block *sb, int wait);
1571:	        int (*freeze_fs) (struct super_block *);
1572:	        int (*unfreeze_fs) (struct super_block *);
1573:	        int (*statfs) (struct dentry *, struct kstatfs *);
1574:	        int (*remount_fs) (struct super_block *, int *, char *);
1575:	        void (*umount_begin) (struct super_block *);
1576:	
1577:	        int (*show_options)(struct seq_file *, struct vfsmount *);
1578:	        int (*show_stats)(struct seq_file *, struct vfsmount *);
1579:	#ifdef CONFIG_QUOTA
1580:	        ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
1581:	        ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
1582:	#endif
1583:	        int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
1584:	};

◆struct inode

include/linux/fs.h

 725:	struct inode {
 726:	        struct hlist_node       i_hash;
 727:	        struct list_head        i_list;         /* backing dev IO list */
...
 729:	        struct list_head        i_dentry;
 730:	        unsigned long           i_ino;
 731:	        atomic_t                i_count;
 732:	        unsigned int            i_nlink;
 733:	        uid_t                   i_uid;
 734:	        gid_t                   i_gid;
 735:	        dev_t                   i_rdev;
 736:	        unsigned int            i_blkbits;
 737:	        u64                     i_version;
 738:	        loff_t                  i_size;
...
 742:	        struct timespec         i_atime;
 743:	        struct timespec         i_mtime;
 744:	        struct timespec         i_ctime;
 745:	        blkcnt_t                i_blocks;
 746:	        unsigned short          i_bytes;
 747:	        umode_t                 i_mode;
...
 751:	        const struct inode_operations   *i_op;
 752:	        const struct file_operations    *i_fop; /* former ->i_op->default_file_ops */
 753:	        struct super_block      *i_sb;
...
 774:	        unsigned long           i_state;
...
 788:	};

◆struct inode_operations

inodeの操作は、たとえば次のような形で行われる。
    struct inode *inode;
    ...
    inode->i_op->truncate(inode);
i_op には、次のような手続きがある。各ファイルシステム (ext3,nfs,tmpfs,...) ごとに、手続きの実体は異なるが、インタフェースは同じ。
1516:	struct inode_operations {
1517:	        int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
1518:	        struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
1519:	        int (*link) (struct dentry *,struct inode *,struct dentry *);
1520:	        int (*unlink) (struct inode *,struct dentry *);
1521:	        int (*symlink) (struct inode *,struct dentry *,const char *);
1522:	        int (*mkdir) (struct inode *,struct dentry *,int);
1523:	        int (*rmdir) (struct inode *,struct dentry *);
1524:	        int (*mknod) (struct inode *,struct dentry *,int,dev_t);
1525:	        int (*rename) (struct inode *, struct dentry *,
1526:	                        struct inode *, struct dentry *);
1527:	        int (*readlink) (struct dentry *, char __user *,int);
1528:	        void * (*follow_link) (struct dentry *, struct nameidata *);
1529:	        void (*put_link) (struct dentry *, struct nameidata *, void *);
1530:	        void (*truncate) (struct inode *);
1531:	        int (*permission) (struct inode *, int);
1532:	        int (*check_acl)(struct inode *, int);
1533:	        int (*setattr) (struct dentry *, struct iattr *);
1534:	        int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
1535:	        int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
1536:	        ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
1537:	        ssize_t (*listxattr) (struct dentry *, char *, size_t);
1538:	        int (*removexattr) (struct dentry *, const char *);
1539:	        void (*truncate_range)(struct inode *, loff_t, loff_t);
1540:	        long (*fallocate)(struct inode *inode, int mode, loff_t offset,
1541:	                          loff_t len);
1542:	        int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
1543:	                      u64 len);
1544:	};

◆struct dentry

struct dentry は、ディレクトリに含まれている名前の要素(「/」を含まない 名前)を表す構造体。
include/linux/dcache.h
  89:	struct dentry {
  90:	        atomic_t d_count;
  91:	        unsigned int d_flags;           /* protected by d_lock */
  92:	        spinlock_t d_lock;              /* per dentry lock */
  93:	        int d_mounted;
  94:	        struct inode *d_inode;          /* Where the name belongs to - NULL is
  95:	                                         * negative */
...
 100:	        struct hlist_node d_hash;       /* lookup hash list */
 101:	        struct dentry *d_parent;        /* parent directory */
 102:	        struct qstr d_name;
 103:	
 104:	        struct list_head d_lru;         /* LRU list */
...
 109:	                struct list_head d_child;       /* child of parent list */
...
 112:	        struct list_head d_subdirs;     /* our children */
 113:	        struct list_head d_alias;       /* inode alias list */
 114:	        unsigned long d_time;           /* used by d_revalidate */
 115:	        const struct dentry_operations *d_op;
 116:	        struct super_block *d_sb;       /* The root of the dentry tree */
 117:	        void *d_fsdata;                 /* fs-specific data */
 118:	
 119:	        unsigned char d_iname[DNAME_INLINE_LEN_MIN];    /* small names */
 120:	};

◆dentryの状態

dentry は、 スラブアロケータ (kmem_cache_create(),kmem_cache_alloc(),kmem_cache_free())で管理されて いる。

◆struct dentry_operations

include/linux/dcache.h

 134:	struct dentry_operations {
 135:	        int (*d_revalidate)(struct dentry *, struct nameidata *);
 136:	        int (*d_hash) (struct dentry *, struct qstr *);
 137:	        int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
 138:	        int (*d_delete)(struct dentry *);
 139:	        void (*d_release)(struct dentry *);
 140:	        void (*d_iput)(struct dentry *, struct inode *);
 141:	        char *(*d_dname)(struct dentry *, char *, int);
 142:	};

◆struct file

struct file は、プロセスがファイルを open() した割り当てられる。 ディスク上には対応するデータ構造は存在しない。
include/linux/fs.h

 909:	struct file {
...
 915:	                struct list_head        fu_list;
...
 918:	        struct path             f_path;
 919:	#define f_dentry        f_path.dentry
 920:	#define f_vfsmnt        f_path.mnt
 921:	        const struct file_operations    *f_op;
...
 926:	        atomic_long_t           f_count;
 927:	        unsigned int            f_flags;
 928:	        fmode_t                 f_mode;
 929:	        loff_t                  f_pos;
 930:	        struct fown_struct      f_owner;
 931:	        const struct cred       *f_cred;
 932:	        struct file_ra_state    f_ra;
...
 939:	        void                    *private_data;
...
 945:	        struct address_space    *f_mapping;
...
 949:	};

◆struct file_operations

デバイスドライバの回 でも登場している。再掲。
1488:	struct file_operations {
1489:	        struct module *owner;
1490:	        loff_t (*llseek) (struct file *, loff_t, int);
1491:	        ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
1492:	        ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
1493:	        ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
1494:	        ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
1495:	        int (*readdir) (struct file *, void *, filldir_t);
1496:	        unsigned int (*poll) (struct file *, struct poll_table_struct *);
1497:	        long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
1498:	        long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
1499:	        int (*mmap) (struct file *, struct vm_area_struct *);
1500:	        int (*open) (struct inode *, struct file *);
1501:	        int (*flush) (struct file *, fl_owner_t id);
1502:	        int (*release) (struct inode *, struct file *);
1503:	        int (*fsync) (struct file *, int datasync);
1504:	        int (*aio_fsync) (struct kiocb *, int datasync);
1505:	        int (*fasync) (int, struct file *, int);
1506:	        int (*lock) (struct file *, int, struct file_lock *);
1507:	        ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
1508:	        unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
1509:	        int (*check_flags)(int);
1510:	        int (*flock) (struct file *, int, struct file_lock *);
1511:	        ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
1512:	        ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
1513:	        int (*setlease)(struct file *, long, struct file_lock **);
1514:	};
主な手続きの意味

◆task_struct と struct file

struct task_struct から指される。ファイル記述子fdは、struct task_struct *p; の時、p->files->fd_array[fd] の struct file を表 す。
include/linux/fdtable.h
  44:	struct files_struct {
...
  58:	        struct file * fd_array[NR_OPEN_DEFAULT];
  59:	};

include/linux/sched.h
1163:	struct task_struct {
...
1319:	        struct files_struct *files;
...
1497:	};

◆block_device

ブロックデバイスのドライバは、次のことを行う。

■stat()

stat() システム・コールの実装例。

◆stat() システム・コール

fs/stat.c
 151:	SYSCALL_DEFINE2(stat, const char __user *, filename,
 152:	                struct __old_kernel_stat __user *, statbuf)
 153:	{
 154:	        struct kstat stat;
 155:	        int error;
 156:	
 157:	        error = vfs_stat(filename, &stat);
 158:	        if (error)
 159:	                return error;
 160:	
 161:	        return cp_old_stat(&stat, statbuf);
 162:	}

◆vfs_stat() と vfs_fstatat()

  95:	int vfs_stat(const char __user *name, struct kstat *stat)
  96:	{
  97:	        return vfs_fstatat(AT_FDCWD, name, stat, 0);
  98:	}

  71:	int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
  72:	                int flag)
  73:	{
  74:	        struct path path;
  75:	        int error = -EINVAL;
  76:	        int lookup_flags = 0;
...
  83:	
  84:	        error = user_path_at(dfd, filename, lookup_flags, &path);
  85:	        if (error)
  86:	                goto out;
  87:	
  88:	        error = vfs_getattr(path.mnt, path.dentry, stat);
  89:	        path_put(&path);
  90:	out:
  91:	        return error;
  92:	}

◆ vfs_getattr()

  40:	int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
  41:	{
  42:	        struct inode *inode = dentry->d_inode;
...
  49:	        if (inode->i_op->getattr)
  50:	                return inode->i_op->getattr(mnt, dentry, stat);
  51:	
  52:	        generic_fillattr(inode, stat);
  53:	        return 0;
  54:	}

■クイズ10 ファイルシステム

★問題(1001) オブジェクト指向

Linux におけるファイルシステムの実装では、C言語であるが、オブジェクト指 向的な考え方が取り入れられている。どの部分で取り入れられているか、次の 項目を埋めながら説明しなさい。

★問題(1002) struct fileの役割

Linux カーネルの中で、ファイルを表現するためのオブジェクトとしてstruct inode と struct file がある。struct inode だけでも、ファイルの操作(読 み、書き、属性変更)では十分と思えるが、struct file も使われている。 struct file の役割を1つ選んで簡単に説明しなさい。

★問題(1003) dirty

Linux のファイル・システムにおいて、dirty とは何か。簡単に説明しなさい。
Last updated: 2011/02/28 22:24:20
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>