カテゴリ:ソフト開発日誌
iSCSI Enterprise Target 0.4.15 を改造して Logical Unit (Drive) を Removable Media として Windows の initiator に見せる様にした。Data Salvager LE でサルベージができるようになった。ファイナルデータ フォトリカバリーでも物理ドライブスキャンができるようになる。iSCSI Target の実体がハードディスクの仮想ドライブでも、フロッピーの仮想ドライブでも、サルベージ対象になった。
クレバリーの不幸袋に入っていた物で少し幸せになった。 はじめ Removal Media として見せるため INQUIRY の応答で RMB (Removable flag) を 1 にするだけで良いのか少し悩んだ。Removable だと START STOP UNIT (STU), PREVENT ALLOW MEDIUM REMOVAL(PAMR) で Load/Unload, Eject Lock/Unlock が可能なドライブがある。よく考えてみると普通の USB メモリカードリーダーはこれができない。なので STU, PAMR はエラーのまま放置することにした。 iSCSI Enterprise Target のパッチを示す。一度コンパイルして Kernel Version に合わせたパッチを当てた後に修正する必要がある。 参考までに Vine Linux 4.1 Kernel 2.6.16-0vl76.3 に合わせて make したソースのスナップショットを用意した。元々が GPL ライセンスなので、同様のライセンスで扱ってほしい。 修正の詳細を以下に示す。 /etc/ietd.conf の仕様を変更し Removable=yes を付けることができるようにする。Removable Media の振りをするようになる。例えば次のように記述する。 [/etc/ietd.conf] Target iqn.2007-11.blacky:virtualdrive Lun 0 Path=/vhd0/virtualdrive.vhdd,Removable=yes この仕様に合わせたソース改造箇所を示していく。kernel ディレクトリ以下の修正だ。volume.c を修正して Removal=yes を解釈できるようにする。3 箇所修正箇所がある。 [volume.c part 1 of 3] enum { Opt_type, Opt_iomode, Opt_removable, Opt_err, }; [volume.c part 2 of 3] static match_table_t tokens = { {Opt_type, "Type=%s"}, {Opt_iomode, "IOMode=%s"}, {Opt_removable, "Removable=%s"}, {Opt_err, NULL}, }; [volume.c part 3 of 3] case Opt_iomode: if (!(argp = match_strdup(&args[0]))) err = -ENOMEM; if (argp && !strcmp(argp, "ro")) SetLUReadonly(volume); else if (argp && !strcmp(argp, "wb")) SetLUAsync(volume); kfree(argp); break; case Opt_removable: if (!(argp = match_strdup(&args[0]))) { err = -ENOMEM; } if (argp && !strcmp(argp, "no")) { ClearLURemovable(volume); } else { if (argp && !strcmp(argp, "yes")) { SetLURemovable(volume); } } kfree(argp); break; default: break; block-io.c を修正して Removal=yes を読み飛ばすようにする。 [block-io.c] /* Create a match table using our action enums and their matching options */ static match_table_t tokens = { {Opt_scsiid, "ScsiId=%s"}, {Opt_scsisn, "ScsiSN=%s"}, {Opt_path, "Path=%s"}, {Opt_ignore, "Type=%s"}, {Opt_ignore, "IOMode=%s"}, {Opt_ignore, "Removable=%s"}, {Opt_err, NULL}, }; file-io.c を修正して Removal=yes を読み飛ばすようにする。 [file-io.c] static match_table_t tokens = { {Opt_scsiid, "ScsiId=%s"}, {Opt_scsisn, "ScsiSN=%s"}, {Opt_path, "Path=%s"}, {Opt_ignore, "Type=%s"}, {Opt_ignore, "IOMode=%s"}, {Opt_ignore, "Removable=%s"}, {Opt_err, NULL}, }; target_disk.c を修正して INQUIRY の応答の RMB ビットを Removable= 指定に合わせるようにする。 [target_disk.c] if (!(scb[1] & 0x3)) { /* standard response */ if (LURemovable(cmnd->lun)) { data[1]=0x80; /* RMB=1 */ } else { data[1]=0x00; /* RMB=0 */ } data[2] = 4; iscsi.h を修正して Removal=yes を指定されたことを記憶できるようにする。 ノート: ここの修正内容は Door Lock, Eject もサポートする様に書いてある。しかし、利用していない。 [iscsi.h] enum lu_flags { LU_READONLY, LU_ASYNC, LU_REMOVABLE, /* Removable media emulation, 0:Not removavle, 1: Removable */ LU_EJECTED, /* Ejected, 0:Not Ejected, 1:Ejected */ LU_DOOR_LOCKED, /* Door locked, 0:Not Locked, 1:Locked */ }; #define LUReadonly(lu) test_bit(LU_READONLY, &(lu)->flags) #define SetLUReadonly(lu) set_bit(LU_READONLY, &(lu)->flags) #define LUAsync(lu) test_bit(LU_ASYNC, &(lu)->flags) #define SetLUAsync(lu) set_bit(LU_ASYNC, &(lu)->flags) #define LURemovable(lu) test_bit(LU_REMOVABLE, &(lu)->flags) #define SetLURemovable(lu) set_bit(LU_REMOVABLE, &(lu)->flags) #define ClearLURemovable(lu) clear_bit(LU_REMOVABLE, &(lu)->flags) #define LUEjected(lu) test_bit(LU_EJECTED, &(lu)->flags) #define SetLUEjected(lu) set_bit(LU_EJECTED, &(lu)->flags) #define ClearLUEjected(lu) clear_bit(LU_EJECTED, &(lu)->flags) #define LUDoorLocked(lu) test_bit(LU_DOOR_LOCKED, &(lu)->flags) #define SetLUDoorLocked(lu) set_bit(LU_DOOR_LOCKED, &(lu)->flags) #define ClearLUDoorLocked(lu) clear_bit(LU_DOOR_LOCKED, &(lu)->flags) dmesg を見ると PREVENT ALLOW MEDIUM REMOVAL に対して、エラーを返している。しかし、メモリカードリーダーも、同様な振る舞いをするので問題ない。 お気に入りの記事を「いいね!」で応援しよう
最終更新日
2007.12.25 23:27:10
コメント(0) | コメントを書く
[ソフト開発日誌] カテゴリの最新記事
|
|