ループバックマウント


Rev.3を表示中。最新版はこちら

loopbackとは自分自身に戻る。と言うことで、ループバックマウントは、以下のように、マウント済みファイルシステム下にファイルを作成し、それをマウントすると言う事です。
[root@localhost tmp]# dd if=/dev/zero of=disk bs=1M count=1
1+0 レコード入力
1+0 レコード出力
1048576 バイト (1.0 MB) コピーされました、 0.0105052 秒、 99.8 MB/秒

[root@localhost tmp]# mkfs.ext2 disk
mke2fs 1.41.14 (22-Dec-2010)
disk is not a block special device.
Proceed anyway? (y,n) y
 :
Writing inode tables: done
Writing superblocks and filesystem accounting information: done

[root@localhost tmp]# mount ./disk /mnt1

[root@localhost tmp]# ls /mnt1
lost+found
となります。この操作は、一般的にループバックデバイスによるマウントという事ですが、カーネルサイドからは、通常のマウントとして扱っています。

上記での処理の概要でstraceの内容の抜粋です。./diskが通常ファイルなら、/dev/loopデバイスファイルをオープンし、/dev/loopデバイスファイルのコールバック関数となるioctl()で、./diskをバンドリングしています。mountコマンドでは、この処理をmountコマンド内で行っており、システムコールのsys_mountへは、デバイスファイルとして/dev/loopとして、コールしているだけで、通常のmount処理と同じなのです。

実装的には、ループバックもそうでないマウントも、両者ともvfsmountを取得するのですが、/dev/loopの場合、すでにスーパブロックは./diskのファイルシステム下で取得済みであり、従ってスーパブロックの参照カウントをインクリメントすることにあります。
[root@localhost tmp]# strace mount ./disk /mnt1
execve("/bin/mount", ["mount", "./disk", "/mnt1"], [/* 23 vars */]) = 0
 :
open("/tmp/disk", O_RDWR|O_LARGEFILE)   = 3
open("/dev/loop0", O_RDWR|O_LARGEFILE)  = 4
readlink("/tmp", 0xbf8f570b, 4096)      = -1 EINVAL (Invalid argument)
readlink("/tmp/disk", 0xbf8f570b, 4096) = -1 EINVAL (Invalid argument)
 :
ioctl(4, LOOP_SET_FD, 0x3)              = 0
close(3)                                = 0
ioctl(4, LOOP_SET_STATUS64, {offset=0, number=0, flags=LO_FLAGS_AUTOCLEAR, file_name="/tmp/disk", ...}) = 0
 :
mount("/dev/loop0", "/mnt1", "ext2", MS_MGC_VAL, NULL) = 0
 :
ループバックデバイスのファイルオペレーションコールバック
static struct block_device_operations lo_fops = {
       .owner =        THIS_MODULE,
       .open =         lo_open,
       .release =      lo_release,
       .ioctl =        lo_ioctl,
};

static int lo_ioctl(struct inode * inode, struct file * file,
       unsigned int cmd, unsigned long arg)
{
       struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
       int err;

       down(&lo->lo_ctl_mutex);
       switch (cmd) {
       case LOOP_SET_FD:
               err = loop_set_fd(lo, file, inode->i_bdev, arg);
               break;
       case LOOP_CLR_FD:
               err = loop_clr_fd(lo, inode->i_bdev);
               break;
       case LOOP_SET_STATUS:
               err = loop_set_status_old(lo, (struct loop_info *) arg);
               break;
       case LOOP_GET_STATUS:
               err = loop_get_status_old(lo, (struct loop_info *) arg);
               break;
       case LOOP_SET_STATUS64:
               err = loop_set_status64(lo, (struct loop_info64 *) arg);
               break;
       case LOOP_GET_STATUS64:
               err = loop_get_status64(lo, (struct loop_info64 *) arg);
               break;
       default:
               err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL;
       }
       up(&lo->lo_ctl_mutex);
       return err;
}

補足

long do_mount(char * dev_name, char * dir_name, char *type_page,
                 unsigned long flags, void *data_page)
{
 :
       if (flags & MS_REMOUNT)
               retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
                                   data_page);
       else if (flags & MS_BIND)
               retval = do_loopback(&nd, dev_name, flags & MS_REC);
       else if (flags & MS_MOVE)
               retval = do_move_mount(&nd, dev_name);
       else
               retval = do_add_mount(&nd, type_page, flags, mnt_flags,
                                     dev_name, data_page);
 :
}
/dev/loopでコールされても、do_add_mount()がコールされ、カーネルとしてループバックマウントは、bindオプションのmountとなるわけです。

最終更新 2013/06/13 20:52:25 - north
(2013/06/13 19:34:52 作成)


検索

アクセス数
3330277
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。