Good catch but I don't think that's quite correct. To be accurate, the function list_first_entry(...) returns the first entry in the list or a pointer to the list head if empty. The return is LUN0 only because LUN0 is created automatically when the target is created. The function list_first_entry(...) is called at 10 places in all the source and only ONE place to find a device. So let me augment my patch and insert in target_cmd_queue(...) a test for this. I believe this will cause requests to a server with a LUN-less target to simply fail until a LUN gets defined - just like an absent target. BTW - this begs the question about when the sockets become available. =============================================================================== diff -Naurp -X diff.exclude old/usr/mgmt.c new/usr/mgmt.c --- old/usr/mgmt.c 2012-10-30 21:49:30.000000000 -0400 +++ new/usr/mgmt.c 2012-11-28 19:18:51.000000000 -0500 @@ -247,7 +247,7 @@ static tgtadm_err device_mgmt(int lld_no params, 1); break; case OP_DELETE: - adm_err = tgt_device_destroy(req->tid, req->lun, 0); + adm_err = tgt_device_destroy(req->tid, req->lun, req->op); break; case OP_UPDATE: adm_err = tgt_device_update(req->tid, req->lun, params); @@ -777,7 +777,7 @@ int ipc_init(void) err = bind(fd, (struct sockaddr *) &addr, sizeof(addr)); if (err) { - eprintf("can't bind a socket, %m\n"); + eprintf("can't bind to socket \"%s\", %m\n", mgmt_path); goto out; } diff -Naurp -X diff.exclude old/usr/target.c new/usr/target.c --- old/usr/target.c 2012-10-30 21:49:30.000000000 -0400 +++ new/usr/target.c 2012-12-10 14:30:09.000000000 -0500 @@ -702,7 +702,7 @@ tgtadm_err tgt_device_destroy(int tid, u struct registration *reg, *reg_next; int ret; - dprintf("%u %" PRIu64 "\n", tid, lun); + dprintf("%u %" PRIu64 "%s\n", tid, lun, force ? " Forced" : ""); /* lun0 is special */ if (!lun && !force) @@ -1093,7 +1093,15 @@ int target_cmd_queue(int tid, struct scs return -ENOENT; } - cmd->c_target = target = itn->nexus_target; + target = itn->nexus_target; + + if (list_empty(&target->device_list)) + { + eprintf("No devices for nexus %d %" PRIx64 "\n", tid, itn_id); + return -ENOENT; + } + + cmd->c_target = target; cmd->it_nexus = itn; dev_id = scsi_get_devid(target->lid, cmd->lun); diff -Naurp -X diff.exclude old/usr/tgtadm.c new/usr/tgtadm.c --- old/usr/tgtadm.c 2012-10-30 21:49:30.000000000 -0400 +++ new/usr/tgtadm.c 2012-11-28 19:06:06.000000000 -0500 @@ -818,7 +818,7 @@ int main(int argc, char **argv) break; case OP_DELETE: case OP_STATS: - rc = verify_mode_params(argc, argv, "LmotlC"); + rc = verify_mode_params(argc, argv, "LmotlCF"); if (rc) { eprintf("target mode: option '-%c' is not " "allowed/supported\n", rc); =================================================================== -----Original Message----- From: Arne Redlich [mailto:arne.redlich@xxxxxxxxxxxxxx] Sent: Monday, December 10, 2012 1:24 PM To: Braun, David Cc: Boaz Harrosh; ronnie sahlberg; stgt@xxxxxxxxxxxxxxx Subject: Re: Why LUN0? 2012/12/10 Braun, David <David.Braun@xxxxxxx>: > By "like today the dummy-LUN0 will automatically be replaced" you mean with your patch - right? > > My --force code was very simple - basically a 2 line change. The other changes are just prints. Here's what I did. David, It's not as simple as that, as the dummy device mapped to LUN 0 is also abused to handle SCSI requests sent to LUNs that are not backed by a device: int target_cmd_queue(int tid, struct scsi_cmd *cmd) { /* ... snip ... */ cmd->dev = device_lookup(target, dev_id); /* use LUN0 */ if (!cmd->dev) cmd->dev = list_first_entry(&target->device_list, struct scsi_lu, device_siblings); /* ... snip ... */ /* * Call struct scsi_lu->cmd_perform() that will either be setup for * internal or passthrough CDB processing using 2 functions below. */ return cmd->dev->cmd_perform(tid, cmd); } This is addressed by the patch Boaz is carrying in his tree. HTH, Arne ��.n��������+%������w��{.n�������{ay�ʇڙ���f���h������_�(�階�ݢj"��������G����?���&��