/dev/loop-control


システム起動時、マイナ番号0から7の8つの/dev/loopデバイスが作成されますが、/dev/loop-controlでloopデバイスの追加/削除をユザー空間から可能とします。

サンプル
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define LOOP_CTL_ADD            0x4C80
#define LOOP_CTL_REMOVE         0x4C81
#define LOOP_CTL_GET_FREE       0x4C82

void    main(int argc, char *argv[])
{
    int    lfd, ret;

    lfd = open("/dev/loop-control", O_RDWR);
    if (!strcmp(argv[1], "LOOP_CTL_ADD")) {
        ret = ioctl(lfd, LOOP_CTL_ADD, atoi(argv[2]));
        printf("add /dev/loop%d\n", ret);
    }
    else {
        if (!strcmp(argv[1], "LOOP_CTL_REMOVE")) {
            ret = ioctl(lfd, LOOP_CTL_REMOVE, atoi(argv[2]));
            printf("rm /dev/loop%d\n", ret);
        }
        else {
            if (!strcmp(argv[1], "LOOP_CTL_GET_FREE")) {
                ret = ioctl(lfd, LOOP_CTL_GET_FREE, 0);
                printf("unused loop/dev/loop%d\n", ret);
            }
            else {
                printf("argv err\n");
            }
        }
    }
    close(lfd);
}

実行結果
[root@localhost north]# ls /dev/loop*
/dev/loop-control  /dev/loop1  /dev/loop3  /dev/loop5  /dev/loop7
/dev/loop0         /dev/loop2  /dev/loop4  /dev/loop6

[root@localhost north]# ./a.out LOOP_CTL_ADD 8
add /dev/loop8
[root@localhost north]# ls /dev/loop*
/dev/loop-control  /dev/loop1  /dev/loop3  /dev/loop5  /dev/loop7
/dev/loop0         /dev/loop2  /dev/loop4  /dev/loop6  /dev/loop8

[root@localhost north]# ./a.out LOOP_CTL_REMOVE 8
rm /dev/loop8
[root@localhost north]# ls /dev/loop*
/dev/loop-control  /dev/loop1  /dev/loop3  /dev/loop5  /dev/loop7
/dev/loop0         /dev/loop2  /dev/loop4  /dev/loop6

[root@localhost north]# ./a.out LOOP_CTL_GET_FREE 
unused loop/dev/loop0
[root@localhost north]# mount -o loop disk /mnt4
[root@localhost north]# df | grep loop
/dev/loop0                          1011       27      933    3% /mnt4
[root@localhost north]# ./a.out LOOP_CTL_GET_FREE
unused loop/dev/loop1
実装
loopデバイスはloop_index_idrでリスト管理されています。
static  struct idr loop_index_idr

static const struct file_operations loop_ctl_fops = {
       .open           = nonseekable_open,
       .unlocked_ioctl = loop_control_ioctl,
       .compat_ioctl   = loop_control_ioctl,
       .owner          = THIS_MODULE,
       .llseek         = noop_llseek,
};

static struct miscdevice loop_misc = {
       .minor          = LOOP_CTRL_MINOR,
       .name           = "loop-control",
       .fops           = &loop_ctl_fops,
};

static long loop_control_ioctl(struct file *file, unsigned int cmd,
                              unsigned long parm)
{
       struct loop_device *lo;
       int ret = -ENOSYS;

       mutex_lock(&loop_index_mutex);
       switch (cmd) {
       case LOOP_CTL_ADD:
               ret = loop_lookup(&lo, parm);
               if (ret >= 0) {
                       ret = -EEXIST;
                       break;
               }
               ret = loop_add(&lo, parm);
               break;
       case LOOP_CTL_REMOVE:
               ret = loop_lookup(&lo, parm);
               if (ret < 0)
                       break;
               mutex_lock(&lo->lo_ctl_mutex);
               if (lo->lo_state != Lo_unbound) {
                       ret = -EBUSY;
                       mutex_unlock(&lo->lo_ctl_mutex);
                       break;
               }
               if (lo->lo_refcnt > 0) {
                       ret = -EBUSY;
                       mutex_unlock(&lo->lo_ctl_mutex);
                       break;
               }
               lo->lo_disk->private_data = NULL;
               mutex_unlock(&lo->lo_ctl_mutex);
               idr_remove(&loop_index_idr, lo->lo_number);
               loop_remove(lo);
               break;
       case LOOP_CTL_GET_FREE:
               ret = loop_lookup(&lo, -1);
               if (ret >= 0)
                       break;
               ret = loop_add(&lo, -1);
       }
       mutex_unlock(&loop_index_mutex);

       return ret;
}

static int loop_lookup(struct loop_device **l, int i)
{
       struct loop_device *lo;
       int ret = -ENODEV;

       if (i < 0) {
               int err;

               err = idr_for_each(&loop_index_idr, &find_free_cb, &lo);
               if (err == 1) {
                       *l = lo;
                       ret = lo->lo_number;
               }
               goto out;
       }

       lo = idr_find(&loop_index_idr, i);
       if (lo) {
               *l = lo;
               ret = lo->lo_number;
       }
out:
       return ret;
}

補足

LOOP_CTL_GET_FREEで未使用なデバイスが取得できない時、新規にデバイスを作成しそのマイナ番号を返します。

LOOP_CTL_ADDで追加されたデバイスと初期で作成されているデバイスとの違いはなく、LOOP_CTL_REMOVEはシステム起動時に作成されているデバイス(loop0からloop7)にも適用されます。


最終更新 2016/04/18 16:30:57 - north
(2016/04/18 16:30:57 作成)


検索

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