Module Name: src
Committed By: agc
Date: Thu Jun 25 13:48:42 UTC 2009
Added Files:
src/external/bsd/iscsi/dist/src/osd: osd-target.c osd.c osdfs.c
start_osd stop_osd
Log Message:
Put the OSD sources in their own directory
To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/external/bsd/iscsi/dist/src/osd/osd-target.c \
src/external/bsd/iscsi/dist/src/osd/osd.c \
src/external/bsd/iscsi/dist/src/osd/osdfs.c \
src/external/bsd/iscsi/dist/src/osd/start_osd \
src/external/bsd/iscsi/dist/src/osd/stop_osd
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Added files:
Index: src/external/bsd/iscsi/dist/src/osd/osd-target.c
diff -u /dev/null src/external/bsd/iscsi/dist/src/osd/osd-target.c:1.1
--- /dev/null Thu Jun 25 13:48:42 2009
+++ src/external/bsd/iscsi/dist/src/osd/osd-target.c Thu Jun 25 13:48:42 2009
@@ -0,0 +1,181 @@
+/* $NetBSD: osd-target.c,v 1.1 2009/06/25 13:48:42 agc Exp $ */
+
+/*
+ * Copyright © 2006 Alistair Crooks. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+
+#ifndef lint
+__COPYRIGHT("@(#) Copyright © 2006 \
+ The NetBSD Foundation, Inc. All rights reserved.");
+__RCSID("$NetBSD: osd-target.c,v 1.1 2009/06/25 13:48:42 agc Exp $");
+#endif
+#include "config.h"
+
+#define EXTERN
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <unistd.h>
+
+#include "iscsi.h"
+#include "iscsiutil.h"
+#include "target.h"
+#include "device.h"
+
+#include "conffile.h"
+#include "storage.h"
+
+/*
+ * Globals
+ */
+
+static int g_main_pid;
+static globals_t g;
+
+/*
+ * Control-C handler
+ */
+
+/* ARGSUSED0 */
+static void
+handler(int s)
+{
+ if (ISCSI_GETPID != g_main_pid)
+ return;
+ if (target_shutdown(&g) != 0) {
+ iscsi_trace_error(__FILE__, __LINE__, "target_shutdown() failed\n");
+ return;
+ }
+ return;
+}
+
+int
+main(int argc, char **argv)
+{
+ const char *cf;
+ targv_t tv;
+ devv_t dv;
+ extv_t ev;
+ char TargetName[1024];
+ int detach_me_harder;
+ int i;
+
+ (void) memset(&g, 0x0, sizeof(g));
+ (void) memset(&tv, 0x0, sizeof(tv));
+ (void) memset(&dv, 0x0, sizeof(dv));
+ (void) memset(&ev, 0x0, sizeof(ev));
+
+ /* set defaults */
+ (void) strlcpy(TargetName, DEFAULT_TARGET_NAME, sizeof(TargetName));
+ g.port = ISCSI_PORT;
+ detach_me_harder = 1;
+
+ cf = _PATH_OSD_TARGETS;
+
+ while ((i = getopt(argc, argv, "Dd:p:t:v:")) != -1) {
+ switch (i) {
+ case 'D':
+ detach_me_harder = 0;
+ break;
+ case 'd':
+ device_set_var("directory", optarg);
+ break;
+ case 'f':
+ cf = optarg;
+ break;
+ case 'p':
+ g.port = (uint16_t) atoi(optarg);
+ break;
+ case 't':
+ (void) strlcpy(TargetName, optarg, sizeof(TargetName));
+ break;
+ case 'v':
+ if (strcmp(optarg, "net") == 0) {
+ set_debug("net");
+ } else if (strcmp(optarg, "iscsi") == 0) {
+ set_debug("iscsi");
+ } else if (strcmp(optarg, "scsi") == 0) {
+ set_debug("scsi");
+ } else if (strcmp(optarg, "osd") == 0) {
+ set_debug("osd");
+ } else if (strcmp(optarg, "all") == 0) {
+ set_debug("all");
+ }
+ break;
+ }
+ }
+
+ if (!read_conf_file(cf, &tv, &dv, &ev)) {
+ (void) fprintf(stderr, "Error: can't open `%s'\n", cf);
+ return EXIT_FAILURE;
+ }
+
+ (void) signal(SIGPIPE, SIG_IGN);
+
+ (void) signal(SIGINT, handler);
+ g_main_pid = ISCSI_GETPID;
+
+ if (tv.c == 0) {
+ (void) fprintf(stderr, "No targets to initialise\n");
+ return EXIT_FAILURE;
+ }
+ /* Initialize target */
+ for (i = optind ; i < argc ; i++) {
+ if (target_init(&g, &tv, TargetName, i) != 0) {
+ iscsi_trace_error(__FILE__, __LINE__, "target_init() failed\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+#ifdef HAVE_DAEMON
+ /* if we are supposed to be a daemon, detach from controlling tty */
+ if (detach_me_harder && daemon(0, 0) < 0) {
+ iscsi_trace_error(__FILE__, __LINE__, "daemon() failed\n");
+ exit(EXIT_FAILURE);
+ }
+#endif
+
+ /* write pid to a file */
+ write_pid_file(_PATH_OSD_PID_FILE);
+
+ /* Wait for connections */
+ if (target_listen(&g) != 0) {
+ iscsi_trace_error(__FILE__, __LINE__, "target_listen() failed\n");
+ }
+
+ return EXIT_SUCCESS;
+}
Index: src/external/bsd/iscsi/dist/src/osd/osd.c
diff -u /dev/null src/external/bsd/iscsi/dist/src/osd/osd.c:1.1
--- /dev/null Thu Jun 25 13:48:42 2009
+++ src/external/bsd/iscsi/dist/src/osd/osd.c Thu Jun 25 13:48:42 2009
@@ -0,0 +1,662 @@
+/*
+ * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
+ * using the software you agree to this license. If you do not agree to this license, do not download, install,
+ * copy or use the software.
+ *
+ * Intel License Agreement
+ *
+ * Copyright (c) 2000, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
+ * the following conditions are met:
+ *
+ * -Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ *
+ * -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * -The name of Intel Corporation may not be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "config.h"
+
+#include <sys/types.h>
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <unistd.h>
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <unistd.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+
+#include "scsi_cmd_codes.h"
+
+#include "iscsi.h"
+#include "iscsiutil.h"
+#include "device.h"
+#include "osd.h"
+
+/*
+ * Globals
+ */
+
+static int osd_luns = CONFIG_OSD_LUNS_DFLT;
+static uint64_t osd_capacity = CONFIG_OSD_CAPACITY_DFLT * 1048576;
+static char base_dir[64] = CONFIG_OSD_BASEDIR_DFLT;
+
+#ifndef __KERNEL__
+void
+device_set_var(const char *var, char *arg)
+{
+ if (strcmp(var, "capacity") == 0) {
+ osd_capacity = strtoll(arg, (char **) NULL, 10) * 1048576;
+ } else if (strcmp(var, "luns") == 0) {
+ osd_luns = atoi(arg);
+ } else if (strcmp(var, "directory") == 0) {
+ (void) strlcpy(base_dir, arg, sizeof(base_dir));
+ } else {
+ (void) fprintf(stderr, "Unrecognised variable: `%s'\n", var);
+ }
+}
+#endif
+
+int
+device_init(globals_t *gp, char *dev)
+{
+ struct stat st;
+ char FileName[1024];
+ int i;
+
+ if (stat(base_dir, &st) < 0) {
+
+ /* Create directory for OSD */
+
+ if (mkdir(base_dir, 0755) != 0) {
+ if (errno != EEXIST) {
+ iscsi_trace_error(__FILE__, __LINE__, "error creating directory \"%s\" for OSD: errno %d\n", base_dir, errno);
+ return -1;
+ }
+ }
+ /* Create directory for LU */
+
+ for (i = 0; i < osd_luns; i++) {
+ sprintf(FileName, "%s/lun_%d", base_dir, i);
+ if (mkdir(FileName, 0755) != 0) {
+ if (errno != EEXIST) {
+ iscsi_trace_error(__FILE__, __LINE__, "error creating \"%s\" for LU %d: errno %d\n", FileName, i, errno);
+ return -1;
+ }
+ }
+ }
+ }
+ /* Display LU info */
+
+ return 0;
+}
+
+int
+osd_read_callback(void *arg)
+{
+ struct iovec *sg = (struct iovec *) arg;
+ int i = 0;
+
+ while (sg[i].iov_base != NULL) {
+ iscsi_free_atomic(sg[i].iov_base);
+ i++;
+ }
+ return 0;
+}
+
+int
+device_command(target_session_t * sess, target_cmd_t * cmd)
+{
+ iscsi_scsi_cmd_args_t *args = cmd->scsi_cmd;
+ uint8_t *data;
+ char FileName[1024];
+ uint8_t *write_data = NULL;
+ uint8_t *read_data = NULL;
+ uint8_t *set_list = NULL;
+ uint8_t *get_list = NULL;
+ struct iovec sg[3];
+ int sg_len = 0;
+ int rc;
+ osd_args_t osd_args;
+ uint32_t GroupID = 0;
+ uint64_t UserID = 0;
+ char string[1024];
+ uint8_t *get_data = NULL;
+ uint32_t page = 0;
+ uint32_t index = 0;
+ int attr_len = 0;
+
+ iscsi_trace(TRACE_SCSI_CMD, __FILE__, __LINE__, "SCSI op 0x%x (lun %llu)\n", args->cdb[0], args->lun);
+
+ if (args->lun >= osd_luns) {
+ iscsi_trace(TRACE_SCSI_DEBUG, __FILE__, __LINE__, "invalid lun: %llu\n", args->lun);
+ args->status = 0x01;
+ return 0;
+ }
+ args->status = 1;
+
+ switch (args->cdb[0]) {
+
+ case TEST_UNIT_READY:
+
+ iscsi_trace(TRACE_SCSI_CMD, __FILE__, __LINE__, "TEST_UNIT_READY(lun %llu)\n", args->lun);
+ args->status = 0;
+ args->length = 0;
+ break;
+
+ case INQUIRY:
+
+ iscsi_trace(TRACE_SCSI_CMD, __FILE__, __LINE__, "INQUIRY(lun %llu)\n", args->lun);
+ data = args->send_data;
+ memset(data, 0, args->cdb[4]); /* Clear allocated buffer */
+ data[0] = 0x0e; /* Peripheral Device Type */
+ /* data[1] |= 0x80; // Removable Bit */
+ data[2] |= 0x02;/* ANSI-approved version */
+ /* data[3] |= 0x80; // AENC */
+ /* data[3] |= 0x40; // TrmIOP */
+ /* data[3] |= 0x20; // NormACA */
+ data[4] = args->cdb[4] - 4; /* Additional length */
+ /*
+ * data[7] |= 0x80; // Relative
+ * addressing
+ */
+ data[7] |= 0x40;/* WBus32 */
+ data[7] |= 0x20;/* WBus16 */
+ /* data[7] |= 0x10; // Sync */
+ /* data[7] |= 0x08; // Linked Commands */
+ /* data[7] |= 0x04; // TransDis */
+ /*
+ * data[7] |= 0x02; // Tagged Command
+ * Queueing
+ */
+ /* data[7] |= 0x01; // SftRe */
+ (void) memset(data + 8, 0x0, 32);
+ strlcpy(data + 8, OSD_VENDOR, 8); /* Vendor */
+ strlcpy(data + 16, OSD_PRODUCT, 16); /* Product ID */
+ (void) snprintf(data + 32, 8, "%d", OSD_VERSION); /* Product Revision */
+ args->input = 1;
+ args->length = args->cdb[4] + 1;
+ args->status = 0;
+
+ break;
+
+ case 0x7F:
+
+ OSD_DECAP_CDB(args->cdb, args->ext_cdb, &osd_args);
+ /* OSD_PRINT_CDB(args->cdb, args->ext_cdb); */
+ GroupID = osd_args.GroupID;
+ UserID = osd_args.UserID;
+
+ /*
+ * Transfer all data
+ */
+
+ if (osd_args.set_attributes_list_length) {
+ if ((set_list = iscsi_malloc_atomic(osd_args.set_attributes_list_length)) == NULL) {
+ iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
+ goto done;
+ }
+ sg[sg_len].iov_base = set_list;
+ sg[sg_len].iov_len = osd_args.set_attributes_list_length;
+ sg_len++;
+ }
+ if (osd_args.get_attributes_list_length) {
+ if ((get_list = iscsi_malloc_atomic(osd_args.get_attributes_list_length)) == NULL) {
+ iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
+ goto done;
+ }
+ sg[sg_len].iov_base = get_list;
+ sg[sg_len].iov_len = osd_args.get_attributes_list_length;
+ sg_len++;
+ }
+ if (osd_args.service_action == OSD_WRITE) {
+ if ((write_data = iscsi_malloc_atomic(osd_args.length)) == NULL) {
+ iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
+ goto done;
+ }
+ sg[sg_len].iov_base = write_data;
+ sg[sg_len].iov_len = osd_args.length;
+ sg_len++;
+ }
+ if (sg_len) {
+ if (target_transfer_data(sess, args, sg, sg_len) != 0) {
+ iscsi_trace_error(__FILE__, __LINE__, "target_transfer_data() failed\n");
+ goto done;
+ }
+ }
+ /*
+ * Set any attributes
+ */
+
+ if (osd_args.set_attributes_list_length) {
+ uint32_t page, attr;
+ uint16_t len;
+ int i;
+
+ iscsi_trace(TRACE_OSD, __FILE__, __LINE__, "OSD_SET_ATTR(lun %llu, GroupID 0x%x, UserID 0x%llx)\n", args->lun, osd_args.GroupID, osd_args.UserID);
+ for (i = 0; i < osd_args.set_attributes_list_length;) {
+ page = ISCSI_NTOHL(*((uint32_t *) (&(set_list[i]))));
+ i += 4;
+ attr = ISCSI_NTOHL(*((uint32_t *) (&(set_list[i]))));
+ i += 4;
+ len = ISCSI_NTOHS(*((uint16_t *) (&(set_list[i]))));
+ i += 2;
+ sprintf(FileName, "%s/lun_%llu/0x%x/0x%llx.0x%x.%u",
+ base_dir, args->lun, osd_args.GroupID, osd_args.UserID, page, attr);
+ if ((rc = open(FileName, O_WRONLY | O_CREAT, 0644)) == -1) {
+ iscsi_trace_error(__FILE__, __LINE__, "error opening \"%s\": errno %d\n", FileName, errno);
+ goto done;
+ }
+ if (write(rc, set_list + i, len) != len) {
+ iscsi_trace_error(__FILE__, __LINE__, "write() failed\n");
+ }
+ close(rc);
+ i += len;
+ iscsi_trace(TRACE_OSD, __FILE__, __LINE__, "SET(0x%x,%u,%u>\n", page, attr, len);
+ }
+ }
+ args->send_sg_len = 0;
+ sg_len = 0;
+
+ switch (osd_args.service_action) {
+
+ case OSD_CREATE_GROUP:
+
+ do {
+ GroupID = rand() % 1048576 * 1024 + 1;
+ sprintf(FileName, "%s/lun_%llu/0x%x", base_dir, args->lun, GroupID);
+ rc = mkdir(FileName, 0755);
+ } while (rc == -1 && errno == EEXIST);
+ iscsi_trace(TRACE_OSD, __FILE__, __LINE__, "OSD_CREATE_GROUP(lun %llu) --> 0x%x\n", args->lun, GroupID);
+ args->status = 0;
+ break;
+
+ case OSD_REMOVE_GROUP:
+
+ iscsi_trace(TRACE_OSD, __FILE__, __LINE__, "OSD_REMOVE_GROUP(lun %llu, 0x%x)\n", args->lun, osd_args.GroupID);
+ sprintf(FileName, "%s/lun_%llu/0x%x", base_dir, args->lun, osd_args.GroupID);
+ if ((rc = rmdir(FileName)) == -1) {
+ iscsi_trace_error(__FILE__, __LINE__, "rmdir(\"%s\") failed: errno %d\n", FileName, errno);
+ goto done;
+ }
+ args->status = 0;
+ break;
+
+ case OSD_CREATE:
+
+ UserID = rand() % 1048576 * 1024 + 1;
+create_user_again:
+ sprintf(FileName, "%s/lun_%llu/0x%x/0x%llx",
+ base_dir, args->lun, osd_args.GroupID, UserID);
+ rc = open(FileName, O_CREAT | O_EXCL | O_RDWR, 0644);
+ if ((rc == -1) && (errno == EEXIST)) {
+ UserID = rand() % 1048576 * 1024 + 1;
+ goto create_user_again;
+ }
+ close(rc);
+ iscsi_trace(TRACE_OSD, __FILE__, __LINE__, "OSD_CREATE(lun %llu, GroupID 0x%x) --> 0x%llx\n", args->lun, osd_args.GroupID, UserID);
+ args->status = 0;
+
+ break;
+
+ case OSD_REMOVE:
+
+ iscsi_trace(TRACE_OSD, __FILE__, __LINE__, "OSD_REMOVE(lun %llu, 0x%llx)\n", args->lun, osd_args.UserID);
+ sprintf(FileName, "%s/lun_%llu/0x%x/0x%llx",
+ base_dir, args->lun, osd_args.GroupID, osd_args.UserID);
+ if ((rc = unlink(FileName)) == -1) {
+ iscsi_trace_error(__FILE__, __LINE__, "unlink(\"%s\") failed: errno %d\n", FileName, errno);
+ goto done;
+ }
+ sprintf(string, "rm -f %s/lun_%llu/0x%x/0x%llx.*", base_dir, args->lun, osd_args.GroupID, osd_args.UserID);
+ if (system(string) != 0) {
+ iscsi_trace_error(__FILE__, __LINE__, "\"%s\" failed\n", string);
+ return -1;
+ }
+ args->status = 0;
+ break;
+
+ case OSD_WRITE:
+ iscsi_trace(TRACE_OSD, __FILE__, __LINE__, "OSD_WRITE(lun %llu, GroupID 0x%x, UserID 0x%llx, length %llu, offset %llu)\n",
+ args->lun, osd_args.GroupID, osd_args.UserID, osd_args.length, osd_args.offset);
+ sprintf(FileName, "%s/lun_%llu/0x%x/0x%llx",
+ base_dir, args->lun, osd_args.GroupID, osd_args.UserID);
+ if ((rc = open(FileName, O_WRONLY, 0644)) == -1) {
+ iscsi_trace_error(__FILE__, __LINE__, "error opening \"%s\": errno %d\n", FileName, errno);
+ goto write_done;
+ }
+ if (lseek(rc, osd_args.offset, SEEK_SET) == -1) {
+ iscsi_trace_error(__FILE__, __LINE__, "error seeking \"%s\": errno %d\n", FileName, errno);
+ goto write_done;
+ }
+ if (write(rc, write_data, osd_args.length) != osd_args.length) {
+ iscsi_trace_error(__FILE__, __LINE__, "write() failed\n");
+ goto write_done;
+ }
+ close(rc);
+ args->status = 0;
+write_done:
+ break;
+
+ case OSD_READ:
+ iscsi_trace(TRACE_OSD, __FILE__, __LINE__, "OSD_READ(lun %llu, GroupID 0x%x, UserID 0x%llx, length %llu, offset %llu)\n",
+ args->lun, osd_args.GroupID, osd_args.UserID, osd_args.length, osd_args.offset);
+ sprintf(FileName, "%s/lun_%llu/0x%x/0x%llx",
+ base_dir, args->lun, osd_args.GroupID, osd_args.UserID);
+ if ((rc = open(FileName, O_RDONLY, 0644)) == -1) {
+ iscsi_trace_error(__FILE__, __LINE__, "error opening \"%s\": errno %d\n", FileName, errno);
+ goto read_done;
+ }
+ if ((read_data = iscsi_malloc_atomic(osd_args.length)) == NULL) {
+ iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
+ goto read_done;
+ }
+ if (lseek(rc, osd_args.offset, SEEK_SET) == -1) {
+ iscsi_trace_error(__FILE__, __LINE__, "error seeking \"%s\": errno %d\n", FileName, errno);
+ goto read_done;
+ }
+ if (read(rc, read_data, osd_args.length) != osd_args.length) {
+ iscsi_trace_error(__FILE__, __LINE__, "read() failed\n");
+ goto read_done;
+ }
+ close(rc);
+ args->status = 0;
+read_done:
+ if (args->status == 0) {
+ args->input = 1;
+ sg[0].iov_base = read_data;
+ sg[0].iov_len = osd_args.length;
+ sg[1].iov_base = NULL;
+ sg[1].iov_len = 0;
+ args->send_data = (void *) sg;
+ args->send_sg_len = 1;
+ sg_len++;
+ cmd->callback = osd_read_callback;
+ cmd->callback_arg = sg;
+ } else {
+ if (read_data)
+ iscsi_free_atomic(read_data);
+ args->length = 0; /* Need a better way of
+ * specifying an error.. */
+ }
+ break;
+
+ case OSD_GET_ATTR:
+ iscsi_trace(TRACE_OSD, __FILE__, __LINE__, "OSD_GET_ATTR(lun %llu, GroupID 0x%x, UserID 0x%llx)\n",
+ args->lun, osd_args.GroupID, osd_args.UserID);
+ args->status = 0;
+ break;
+
+ case OSD_SET_ATTR:
+ args->status = 0;
+ break;
+ }
+
+ if (args->status)
+ goto done;
+
+ /*
+ * Send back requested attributes
+ */
+
+ if (osd_args.get_attributes_list_length || osd_args.get_attributes_page) {
+ if ((get_data = iscsi_malloc_atomic(osd_args.get_attributes_allocation_length)) == NULL) {
+ iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc_atomic() failed\n");
+ goto done;
+ }
+ }
+ if (osd_args.get_attributes_list_length) {
+ int i;
+
+ for (i = 0; i < osd_args.get_attributes_list_length;) {
+ page = ISCSI_NTOHL(*((uint32_t *) (&(get_list[i]))));
+ i += 4;
+ index = ISCSI_NTOHL(*((uint32_t *) (&(get_list[i]))));
+ i += 4;
+ iscsi_trace(TRACE_OSD, __FILE__, __LINE__, "GET(0x%x,%u)\n", page, index);
+
+ switch (page) {
+ case 0x40000001:
+ switch (index) {
+ case 0x1:
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(page);
+ attr_len += 4;
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(index);
+ attr_len += 4;
+ *((uint16_t *) & get_data[attr_len]) = ISCSI_HTONS(4);
+ attr_len += 2;
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(GroupID);
+ attr_len += 4;
+ break;
+ default:
+ iscsi_trace_error(__FILE__, __LINE__, "unknown attr index %u\n", index);
+ goto done;
+ }
+ break;
+ case 0x00000001:
+ switch (index) {
+ case 0x1:
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(page);
+ attr_len += 4;
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(index);
+ attr_len += 4;
+ *((uint16_t *) & get_data[attr_len]) = ISCSI_HTONS(4);
+ attr_len += 2;
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(GroupID);
+ attr_len += 4;
+ break;
+ case 0x2:
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(page);
+ attr_len += 4;
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(index);
+ attr_len += 4;
+ *((uint16_t *) & get_data[attr_len]) = ISCSI_HTONS(8);
+ attr_len += 2;
+ *((uint64_t *) & get_data[attr_len]) = ISCSI_HTONLL(UserID);
+ attr_len += 8;
+ break;
+ default:
+ iscsi_trace_error(__FILE__, __LINE__, "unknown attr index %u\n", index);
+ goto done;
+ }
+ break;
+
+ /* Vendor-specific */
+
+ case 0x30000000:
+ switch (index) {
+ case 0x1:
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(page);
+ attr_len += 4;
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(index);
+ attr_len += 4;
+ *((uint16_t *) & get_data[attr_len]) = ISCSI_HTONS(480);
+ attr_len += 2;
+ sprintf(FileName, "%s/lun_%llu/0x%x/0x%llx.0x%x.%u",
+ base_dir, args->lun, osd_args.GroupID, osd_args.UserID, page, index);
+ if ((rc = open(FileName, O_RDONLY, 0644)) == -1) {
+ iscsi_trace_error(__FILE__, __LINE__, "error opening \"%s\": errno %d\n", FileName, errno);
+ }
+ if (read(rc, get_data + attr_len, 480) != 480) {
+ iscsi_trace_error(__FILE__, __LINE__, "read() failed\n");
+ goto done;
+ }
+ close(rc);
+ attr_len += 480;
+ break;
+ default:
+ iscsi_trace_error(__FILE__, __LINE__, "unknown vendor attr index %u\n", index);
+ goto done;
+ }
+ break;
+
+ default:
+ iscsi_trace_error(__FILE__, __LINE__, "unknown page 0x%x\n", page);
+ goto done;
+ }
+ }
+ }
+ if (osd_args.get_attributes_page) {
+
+ /*
+ * Right now, if we get a request for an entire page,
+ * we return only one attribute.
+ */
+
+ page = osd_args.get_attributes_page;
+
+ switch (osd_args.get_attributes_page) {
+ case 0x40000001:
+ index = 1;
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(page);
+ attr_len += 4;
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(index);
+ attr_len += 4;
+ *((uint16_t *) & get_data[attr_len]) = ISCSI_HTONS(4);
+ attr_len += 2;
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(GroupID);
+ attr_len += 4;
+ break;
+
+ case 0x00000001:
+ index = 2;
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(page);
+ attr_len += 4;
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(index);
+ attr_len += 4;
+ *((uint16_t *) & get_data[attr_len]) = ISCSI_HTONS(8);
+ attr_len += 2;
+ *((uint64_t *) & get_data[attr_len]) = ISCSI_HTONLL(UserID);
+ attr_len += 8;
+ break;
+
+ case 0x30000000:
+ index = 1;
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(page);
+ attr_len += 4;
+ *((uint32_t *) & get_data[attr_len]) = ISCSI_HTONL(index);
+ attr_len += 4;
+ *((uint16_t *) & get_data[attr_len]) = ISCSI_HTONS(480);
+ attr_len += 2;
+ sprintf(FileName, "%s/lun_%llu/0x%x/0x%llx.0x%x.%u",
+ base_dir, args->lun, osd_args.GroupID, osd_args.UserID, page, index);
+ if ((rc = open(FileName, O_RDONLY, 0644)) == -1) {
+ iscsi_trace_error(__FILE__, __LINE__, "error opening \"%s\": errno %d\n", FileName, errno);
+ }
+ if (read(rc, get_data + attr_len, 480) != 480) {
+ iscsi_trace_error(__FILE__, __LINE__, "read() failed\n");
+ goto done;
+ }
+ close(rc);
+ attr_len += 480;
+ break;
+ default:
+ iscsi_trace_error(__FILE__, __LINE__, "page not yet supported\n");
+ goto done;
+ }
+ }
+ if (attr_len) {
+ if (attr_len != osd_args.get_attributes_allocation_length) {
+ iscsi_trace_error(__FILE__, __LINE__, "allocation lengths differ: got %u, expected %u\n",
+ osd_args.get_attributes_allocation_length, attr_len);
+ goto done;
+ }
+ if (!args->status) {
+ args->input = 1;
+ sg[sg_len].iov_base = get_data;
+ sg[sg_len].iov_len = osd_args.get_attributes_allocation_length;
+ sg_len++;
+ sg[sg_len].iov_base = NULL;
+ sg[sg_len].iov_len = 0;
+ args->send_data = (void *) sg;
+ args->send_sg_len++;
+ cmd->callback = osd_read_callback;
+ cmd->callback_arg = sg;
+ } else {
+ if (get_data)
+ iscsi_free_atomic(get_data);
+ }
+ }
+ break;
+
+ default:
+ iscsi_trace_error(__FILE__, __LINE__, "UNKNOWN OPCODE 0x%x\n", args->cdb[0]);
+ args->status = 0x01;
+ break;
+ }
+
+
+done:
+ iscsi_trace(TRACE_SCSI_DEBUG, __FILE__, __LINE__, "SCSI op 0x%x: done (status 0x%x)\n", args->cdb[0], args->status);
+ if (set_list) {
+ iscsi_free_atomic(set_list);
+ }
+ if (get_list) {
+ iscsi_free_atomic(get_list);
+ }
+ if (write_data) {
+ iscsi_free_atomic(write_data);
+ }
+ return 0;
+}
+
+/* ARGSUSED */
+int
+device_shutdown(target_session_t *sess)
+{
+ return 0;
+}
Index: src/external/bsd/iscsi/dist/src/osd/osdfs.c
diff -u /dev/null src/external/bsd/iscsi/dist/src/osd/osdfs.c:1.1
--- /dev/null Thu Jun 25 13:48:42 2009
+++ src/external/bsd/iscsi/dist/src/osd/osdfs.c Thu Jun 25 13:48:42 2009
@@ -0,0 +1,1076 @@
+/*
+ * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
+ * using the software you agree to this license. If you do not agree to this license, do not download, install,
+ * copy or use the software.
+ *
+ * Intel License Agreement
+ *
+ * Copyright (c) 2002, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
+ * the following conditions are met:
+ *
+ * -Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ *
+ * -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * -The name of Intel Corporation may not be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Object-Based Storage Devices (OSD) Filesystem for Linux
+ */
+
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/locks.h>
+#include <asm/uaccess.h>
+#include <endian.h>
+#include <linux/blkdev.h>
+#include <scsi.h>
+#include "osd.h"
+#include "osd_ops.h"
+#include "iscsiutil.h"
+#include "util.c"
+
+
+/*
+ * Contants
+ */
+
+
+#define OSDFS_MAGIC 0xabcdef01
+#define MAX_INODES 32768
+#define MAX_NAME_LEN 32
+
+
+/*
+ * Types
+ */
+
+
+typedef struct osdfs_link_t {
+ char name[MAX_NAME_LEN];
+ struct osdfs_link_t* next;
+} osdfs_link_t;
+
+typedef struct osdfs_inode_t {
+ osdfs_link_t *link;
+} osdfs_inode_t;
+
+typedef struct osdfs_metadata_t {
+ uint64_t ObjectID;
+ int used;
+} osdfs_metadata_t;
+
+
+/*
+ * Prototypes
+ */
+
+static int osdfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev);
+
+
+/*
+ * Globals
+ */
+
+
+static struct super_operations osdfs_ops;
+static struct address_space_operations osdfs_aops;
+static struct file_operations osdfs_dir_operations;
+static struct file_operations osdfs_file_operations;
+static struct inode_operations osdfs_dir_inode_operations;
+static uint32_t root_gid;
+static uint64_t root_uid;
+static iscsi_mutex_t g_mutex;
+
+
+/*
+ * SCSI transport function for OSD
+ */
+
+
+int osd_exec_via_scsi(void *dev, osd_args_t *args, OSD_OPS_MEM *m) {
+ Scsi_Request *SRpnt;
+ Scsi_Device *SDpnt;
+ unsigned char cdb[256];
+ kdev_t kdev = *((kdev_t *) dev);
+ void *ptr = NULL;
+ int len = 0;
+
+ if (m->send_sg||m->recv_sg) {
+ iscsi_trace_error("scatter/gather not yet implemented!\n");
+ return -1;
+ }
+
+ SDpnt = blk_dev[MAJOR(kdev)].queue(kdev)->queuedata;
+ SRpnt = scsi_allocate_request(SDpnt);
+ SRpnt->sr_cmd_len = CONFIG_OSD_CDB_LEN;
+ SRpnt->sr_sense_buffer[0] = 0;
+ SRpnt->sr_sense_buffer[2] = 0;
+ switch(args->service_action) {
+ case OSD_WRITE:
+ case OSD_SET_ATTR:
+ len = m->send_len;
+ ptr = m->send_data;
+ SRpnt->sr_data_direction = SCSI_DATA_WRITE;
+ break;
+ case OSD_CREATE:
+ case OSD_CREATE_GROUP:
+ case OSD_READ:
+ case OSD_GET_ATTR:
+ len = m->recv_len;
+ ptr = m->recv_data;
+ SRpnt->sr_data_direction = SCSI_DATA_READ;
+ break;
+ case OSD_REMOVE:
+ case OSD_REMOVE_GROUP:
+ SRpnt->sr_data_direction = 0;
+ break;
+ default:
+ iscsi_trace_error("unsupported OSD service action 0x%x\n", args->service_action);
+ return -1;
+ }
+ OSD_ENCAP_CDB(args, cdb);
+
+ /* Exec SCSI command */
+
+ scsi_wait_req(SRpnt, cdb, ptr, len, 5*HZ, 5);
+ if (SRpnt->sr_result!=0) {
+ iscsi_trace_error("SCSI command failed (result %u)\n", SRpnt->sr_result);
+ scsi_release_request(SRpnt);
+ SRpnt = NULL;
+ return -1;
+ }
+ scsi_release_request(SRpnt);
+ SRpnt = NULL;
+
+ return 0;
+}
+
+/*
+ * Internal OSDFS functions
+ */
+
+
+/* Directory operations */
+
+static int entries_get(kdev_t dev, uint64_t uid, char **entries, uint32_t *num, uint64_t *size) {
+ struct inode inode;
+ uint16_t len;
+
+ if (osd_get_one_attr((void *)&dev, root_gid, uid, 0x30000000, 0x0, sizeof(struct inode), &osd_exec_via_scsi, &len, (void *) &inode)!=0) {
+ iscsi_trace_error("osd_get_one_attr() failed\n");
+ return -1;
+ }
+ *num = 0;
+ if ((*size=inode.i_size)) {
+ char *ptr, *ptr2;
+ int n = 0;
+
+ if ((*entries=vmalloc(*size+1))==NULL) {
+ iscsi_trace_error("vmalloc() failed\n");
+ return -1;
+ }
+ if (osd_read((void *)&dev, root_gid, uid, 0, *size, *entries, 0, &osd_exec_via_scsi)!=0) {
+ iscsi_trace_error("osd_read() failed\n");
+ vfree(*entries);
+ return -1;
+ }
+ (*entries)[*size] = 0x0;
+ ptr = *entries;
+ do {
+ n++;
+ if ((ptr2=strchr(ptr, '\n'))!=NULL) {
+ n++;
+ if ((ptr2 = strchr(ptr2+1, '\n'))==NULL) {
+ iscsi_trace_error("directory 0x%llx corrupted (line %i)\n", uid, n);
+ return -1;
+ }
+ (*num)++;
+ } else {
+ iscsi_trace_error("directory 0x%llx corrupted (line %i)\n", uid, n);
+ return -1;
+ }
+ ptr = ptr2+1;
+ } while (*ptr);
+ }
+
+ return 0;
+}
+
+static int entry_add(kdev_t dev, ino_t dir_ino, ino_t entry_ino,
+ const char *name, uint64_t *new_size) {
+ char entry[MAX_NAME_LEN+16];
+ uint64_t uid = dir_ino;
+ struct inode inode;
+ uint16_t len;
+
+ /* Get size of directory */
+
+ if (osd_get_one_attr((void *)&dev, root_gid, uid, 0x30000000, 0x0, sizeof(struct inode), &osd_exec_via_scsi, &len, (void *) &inode)!=0) {
+ iscsi_trace_error("osd_get_one_attr() failed\n");
+ return -1;
+ }
+
+ /* Write entry at end */
+
+ sprintf(entry, "%s\n", name);
+ sprintf(entry+strlen(entry), "%li\n", entry_ino);
+ if (osd_write((void *)&dev, root_gid, uid, inode.i_size, strlen(entry), entry, 0, &osd_exec_via_scsi)!=0) {
+ iscsi_trace_error("osd_write() failed\n");
+ return -1;
+ }
+ *new_size += strlen(entry);
+
+ return 0;
+}
+
+static int entry_del(kdev_t dev, ino_t dir_ino, ino_t ino, const char *name, uint64_t *new_size) {
+ char *entries;
+ uint32_t num_entries;
+ uint64_t size;
+ uint64_t dir_uid = (unsigned) dir_ino;
+
+ /* Read */
+
+ if (entries_get(dev, dir_ino, &entries, &num_entries, &size)!=0) {
+ iscsi_trace_error("entries_get() failed\n");
+ return -1;
+ }
+ entries[size] = 0x0;
+
+ iscsi_trace(TRACE_OSDFS, "dir_ino 0x%llx has %u entries\n", dir_uid, num_entries);
+ if (num_entries) {
+ char *ptr = entries;
+ char *tmp = NULL;
+ char *nl;
+ int n = 0;
+
+ do {
+ n++;
+ if ((nl=strchr(ptr, '\n'))==NULL) {
+ iscsi_trace_error("directory 0x%llx corrupted (line %i)\n", dir_uid, n);
+ return -1;
+ }
+ *nl = 0x0;
+ if (!strcmp(ptr, name)) {
+ tmp = ptr;
+ }
+ *nl = '\n';
+ n++;
+ if ((ptr=strchr(nl+1, '\n'))==NULL) {
+ iscsi_trace_error("directory 0x%llx corrupted (line %i)\n", dir_uid, n);
+ return -1;
+ }
+ ptr++;
+ } while (!tmp && *ptr);
+
+ if (!tmp) {
+ iscsi_trace_error("entry \"%s\" not found in dir 0x%llx\n", name, dir_uid);
+ return -1;
+ }
+ if (entries+size-ptr) {
+ iscsi_trace(TRACE_OSDFS, "writing remaining %u directory bytes at offset %u\n",
+ entries+size-ptr, tmp-entries);
+ if (osd_write((void *)&dev, root_gid, dir_uid, tmp-entries, entries+size-ptr, ptr, 0, &osd_exec_via_scsi)!=0) {
+ iscsi_trace_error("osd_write() failed\n");
+ return -1;
+ }
+ }
+ *new_size = size-(ptr-tmp);
+ vfree(entries);
+ } else {
+ iscsi_trace_error("dir 0x%llx has no entries\n", dir_uid);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int entry_num(kdev_t dev, ino_t ino) {
+ char *entries;
+ uint32_t num_entries;
+ uint64_t size;
+
+ if (entries_get(dev, ino, &entries, &num_entries, &size)!=0) {
+ iscsi_trace_error("entries_get() failed\n");
+ return -1;
+ }
+ iscsi_trace(TRACE_OSDFS, "ino %li has %i entries\n", ino, num_entries);
+ if (num_entries) vfree(entries);
+ return num_entries;
+}
+
+/* Inode operations */
+
+static void osdfs_set_ops(struct inode *inode) {
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFREG:
+ inode->i_fop = &osdfs_file_operations;
+ break;
+ case S_IFDIR:
+ inode->i_op = &osdfs_dir_inode_operations;
+ inode->i_fop = &osdfs_dir_operations;
+ break;
+ case S_IFLNK:
+ inode->i_op = &page_symlink_inode_operations;
+ break;
+ default:
+ iscsi_trace_error("UNKNOWN MODE\n");
+ }
+ inode->i_mapping->a_ops = &osdfs_aops;
+}
+
+static struct inode *osdfs_get_inode(struct super_block *sb, int mode, int dev, const char *name,
+ uint64_t ObjectID) {
+ struct inode *inode;
+ ino_t ino = ObjectID;
+
+ iscsi_trace(TRACE_OSDFS, "osdfs_get_inode(\"%s\", mode %i (%s))\n", name, mode,
+ S_ISDIR(mode)?"DIR":(S_ISREG(mode)?"REG":"LNK"));
+
+ /* iget() gets a free VFS inode and subsequently call */
+ /* osdfds_read_inode() to fill the inode structure. */
+
+ if ((inode=iget(sb, ino))==NULL) {
+ iscsi_trace_error("iget() failed\n");
+ return NULL;
+ }
+
+ return inode;
+}
+
+
+/*
+ * Super Operations
+ */
+
+
+static void osdfs_read_inode(struct inode *inode) {
+ ino_t ino = inode->i_ino;
+ kdev_t dev = inode->i_sb->s_dev;
+ uint64_t uid = ino;
+ unsigned char *attr;
+ uint16_t len;
+
+ iscsi_trace(TRACE_OSDFS, "osdfs_read_inode(ino 0x%x, major %i, minor %i)\n",
+ (unsigned) ino, MAJOR(dev), MINOR(dev));
+
+ /* Get object attributes for rest of inode */
+
+ if ((attr=iscsi_malloc_atomic(sizeof(struct inode)))==NULL) {
+ iscsi_trace_error("iscsi_malloc_atomic() failed\n");
+ }
+ if (osd_get_one_attr((void *)&dev, root_gid, uid, 0x30000000, 0x0, sizeof(struct inode), &osd_exec_via_scsi, &len, attr)!=0) {
+ iscsi_trace_error("osd_get_one_attr() failed\n");
+ return;
+ }
+
+ inode->i_size = ((struct inode *)(attr))->i_size;
+ inode->i_mode = ((struct inode *)(attr))->i_mode;
+ inode->i_nlink = ((struct inode *)(attr))->i_nlink;
+ inode->i_gid = ((struct inode *)(attr))->i_gid;
+ inode->i_uid = ((struct inode *)(attr))->i_uid;
+ inode->i_ctime = ((struct inode *)(attr))->i_ctime;
+ inode->i_atime = ((struct inode *)(attr))->i_atime;
+ inode->i_mtime = ((struct inode *)(attr))->i_mtime;
+
+ iscsi_free_atomic(attr);
+
+ osdfs_set_ops(inode);
+}
+
+void osdfs_dirty_inode(struct inode *inode) {
+ iscsi_trace(TRACE_OSDFS, "osdfs_dirty_inode(ino 0x%x)\n", (unsigned) inode->i_ino);
+}
+
+void osdfs_write_inode(struct inode *inode, int sync) {
+ ino_t ino = inode->i_ino;
+ kdev_t dev = inode->i_sb->s_dev;
+ uint64_t uid = ino;
+
+ iscsi_trace(TRACE_OSDFS, "osdfs_write_inode(0x%llx)\n", uid);
+
+ if (osd_set_one_attr((void *)&dev, root_gid, uid, 0x30000000, 0x1, sizeof(struct inode), (void *) inode, &osd_exec_via_scsi)!=0) {
+ iscsi_trace_error("osd_set_one_attr() failed\n");
+ }
+ inode->i_state &= ~I_DIRTY;
+}
+
+void osdfs_put_inode(struct inode *inode) {
+ iscsi_trace(TRACE_OSDFS, "osdfs_put_inode(0x%x)\n", (unsigned) inode->i_ino);
+}
+
+void osdfs_delete_inode(struct inode *inode) {
+ iscsi_trace(TRACE_OSDFS, "osdfs_delete_inode(%lu)\n", inode->i_ino);
+ clear_inode(inode);
+}
+
+void osdfs_put_super(struct super_block *sb) {
+ iscsi_trace_error("osdfs_put_super() not implemented\n");
+}
+
+void osdfs_write_super(struct super_block *sb) {
+ iscsi_trace_error("osdfs_write_super() not implemented\n");
+}
+
+void osdfs_write_super_lockfs(struct super_block *sb) {
+ iscsi_trace_error("osdfs_write_super_lockfs() not implemented\n");
+}
+
+void osdfs_unlockfs(struct super_block *sb) {
+ iscsi_trace_error("osdfs_unlockfs() not implemented\n");
+}
+
+int osdfs_statfs(struct super_block *sb, struct statfs *buff) {
+ iscsi_trace(TRACE_OSDFS, "statfs()\n");
+ buff->f_type = OSDFS_MAGIC;
+ buff->f_bsize = PAGE_CACHE_SIZE;
+ buff->f_blocks = 256;
+ buff->f_bfree = 128;
+ buff->f_bavail = 64;
+ buff->f_files = 0;
+ buff->f_ffree = 0;
+ buff->f_namelen = MAX_NAME_LEN;
+
+ return 0;
+}
+
+int osdfs_remount_fs(struct super_block *sb, int *i, char *c) {
+ iscsi_trace_error("osdfs_remount_fs() not implemented\n");
+
+ return -1;
+}
+
+void osdfs_clear_inode(struct inode *inode) {
+ iscsi_trace(TRACE_OSDFS, "osdfs_clear_inode(ino %lu)\n", inode->i_ino);
+}
+
+void osdfs_umount_begin(struct super_block *sb) {
+ iscsi_trace_error("osdfs_unmount_begin() not implemented\n");
+}
+
+static struct super_operations osdfs_ops = {
+ read_inode: osdfs_read_inode,
+ dirty_inode: osdfs_dirty_inode,
+ write_inode: osdfs_write_inode,
+ put_inode: osdfs_put_inode,
+ delete_inode: osdfs_delete_inode,
+ put_super: osdfs_put_super,
+ write_super: osdfs_write_super,
+ write_super_lockfs: osdfs_write_super_lockfs,
+ unlockfs: osdfs_unlockfs,
+ statfs: osdfs_statfs,
+ remount_fs: osdfs_remount_fs,
+ clear_inode: osdfs_clear_inode,
+ umount_begin: osdfs_umount_begin
+};
+
+
+/*
+ * Inode operations for directories
+ */
+
+
+static int osdfs_create(struct inode *dir, struct dentry *dentry, int mode) {
+
+ iscsi_trace(TRACE_OSDFS, "osdfs_create(\"%s\")\n", dentry->d_name.name);
+ if (osdfs_mknod(dir, dentry, mode | S_IFREG, 0)!=0) {
+ iscsi_trace_error("osdfs_mknod() failed\n");
+ return -1;
+ }
+ iscsi_trace(TRACE_OSDFS, "file \"%s\" is inode 0x%x\n", dentry->d_name.name, (unsigned) dentry->d_inode->i_ino);
+
+ return 0;
+}
+
+static struct dentry * osdfs_lookup(struct inode *dir, struct dentry *dentry) {
+ const char *name = dentry->d_name.name;
+ struct inode *inode = NULL;
+ ino_t ino;
+ kdev_t dev = dir->i_sb->s_dev;
+ uint64_t uid = dir->i_ino;
+ char *entries;
+ uint32_t num_entries;
+ uint64_t size;
+
+ iscsi_trace(TRACE_OSDFS, "osdfs_lookup(\"%s\" in dir ino %lu)\n", name, dir->i_ino);
+
+ /* Get directory entries */
+
+ ISCSI_LOCK(&g_mutex, return NULL);
+ if (entries_get(dev, uid, &entries, &num_entries, &size)!=0) {
+ iscsi_trace_error("entries_get() failed\n");
+ ISCSI_UNLOCK(&g_mutex, return NULL);
+ return NULL;
+ }
+ ISCSI_UNLOCK(&g_mutex, return NULL);
+ iscsi_trace(TRACE_OSDFS, "ino %li has %i entries\n", dir->i_ino, num_entries);
+
+ /* Search for this entry */
+
+ if (num_entries) {
+ char *ptr = entries;
+ char *ptr2;
+
+ do {
+ if ((ptr2=strchr(ptr, '\n'))!=NULL) {
+ *ptr2 = 0x0;
+ ptr2 = strchr(ptr2+1, '\n');
+ if (!strcmp(ptr, name)) {
+ sscanf(ptr+strlen(ptr)+1, "%li", &ino);
+ iscsi_trace(TRACE_OSDFS, "found \"%s\" at ino %li\n", name, ino);
+ if ((inode=iget(dir->i_sb, ino))==NULL) {
+ iscsi_trace_error("iget() failed\n");
+ return NULL;
+ }
+ }
+ }
+ } while (ptr2&&(ptr=ptr2+1));
+ vfree(entries);
+ }
+ if (!inode) {
+ iscsi_trace(TRACE_OSDFS, "\"%s\" not found\n", name);
+ }
+ d_add(dentry, inode);
+
+ return NULL;
+}
+
+static int osdfs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry) {
+ struct inode *inode = old_dentry->d_inode;
+ kdev_t dev = dir->i_sb->s_dev;
+ ino_t dir_ino = dir->i_ino;
+ ino_t ino = inode->i_ino;
+ const char *name = dentry->d_name.name;
+
+ if (S_ISDIR(inode->i_mode)) return -EPERM;
+ iscsi_trace(TRACE_OSDFS, "osdfs_link(%lu, \"%s\")\n", ino, name);
+ ISCSI_LOCK(&g_mutex, return -1);
+ if (entry_add(dev, dir_ino, ino, name, &dir->i_size)!=0) {
+ iscsi_trace_error("entry_add() failed\n");
+ return -1;
+ }
+ inode->i_nlink++;
+ atomic_inc(&inode->i_count);
+ osdfs_write_inode(inode, 0);
+ osdfs_write_inode(dir, 0);
+ d_instantiate(dentry, inode);
+ ISCSI_UNLOCK(&g_mutex, return -1);
+
+ return 0;
+}
+
+static int osdfs_unlink(struct inode * dir, struct dentry *dentry) {
+ kdev_t dev = dir->i_sb->s_dev;
+ struct inode *inode = dentry->d_inode;
+ ino_t dir_ino = dir->i_ino;
+ ino_t ino = dentry->d_inode->i_ino;
+ const char *name = dentry->d_name.name;
+
+ iscsi_trace(TRACE_OSDFS, "osdfs_unlink(\"%s\", ino 0x%x)\n", name, (unsigned) ino);
+ ISCSI_LOCK(&g_mutex, return -1);
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFREG:
+ case S_IFLNK:
+ break;
+ case S_IFDIR:
+ if (entry_num(dev, ino)) {
+ iscsi_trace_error("directory 0x%x still has %i entries\n",
+ (unsigned) ino, entry_num(dev, ino));
+ ISCSI_UNLOCK(&g_mutex, return -1);
+ return -ENOTEMPTY;
+ }
+ }
+ if (entry_del(dev, dir_ino, ino, name, &(dir->i_size))!=0) {
+ iscsi_trace_error("entry_del() failed\n");
+ ISCSI_UNLOCK(&g_mutex, return -1);
+ return -1;
+ }
+ osdfs_write_inode(dir, 0);
+ if (--inode->i_nlink) {
+ iscsi_trace(TRACE_OSDFS, "ino 0x%x still has %i links\n", (unsigned) ino, inode->i_nlink);
+ osdfs_write_inode(inode, 0);
+ } else {
+ iscsi_trace(TRACE_OSDFS, "ino 0x%x link count reached 0, removing object\n", (unsigned) ino);
+ if (osd_remove((void *)&dev, root_gid, ino, &osd_exec_via_scsi)!=0) {
+ iscsi_trace_error("osd_remove() failed\n");
+ return -1;
+ }
+ }
+ ISCSI_UNLOCK(&g_mutex, return -1);
+
+ return 0;
+}
+
+static int osdfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname) {
+ struct inode *inode;
+
+ iscsi_trace(TRACE_OSDFS, "osdfs_symlink(\"%s\"->\"%s\")\n", dentry->d_name.name, symname);
+ if (osdfs_mknod(dir, dentry, S_IRWXUGO | S_IFLNK, 0)!=0) {
+ iscsi_trace_error("osdfs_mknod() failed\n");
+ return -1;
+ }
+ inode = dentry->d_inode;
+ if (block_symlink(inode, symname, strlen(symname)+1)!=0) {
+ iscsi_trace_error("block_symlink() failed\n");
+ return -1;
+ }
+ iscsi_trace(TRACE_OSDFS, "symbolic link \"%s\" is inode %lu\n", dentry->d_name.name, inode->i_ino);
+
+ return 0;
+}
+
+static int osdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode) {
+
+ iscsi_trace(TRACE_OSDFS, "osdfs_mkdir(\"%s\")\n", dentry->d_name.name);
+ if (osdfs_mknod(dir, dentry, mode | S_IFDIR, 0)!=0) {
+ iscsi_trace_error("osdfs_mkdir() failed\n");
+ }
+
+ return 0;
+}
+
+static int osdfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev_in) {
+ struct inode *inode = NULL;
+ uint64_t uid;
+ struct inode attr;
+ kdev_t dev = dir->i_sb->s_dev;
+ const char *name = dentry->d_name.name;
+
+ iscsi_trace(TRACE_OSDFS, "osdfs_mknod(\"%s\")\n", dentry->d_name.name);
+
+ /* Create object */
+
+ if (osd_create((void *)&dev, root_gid, &osd_exec_via_scsi, &uid)!=0) {
+ iscsi_trace_error("osd_create() failed\n");
+ return -1;
+ }
+
+ /* Initialize object attributes */
+
+ memset(&attr, 0, sizeof(struct inode));
+ attr.i_mode = mode;
+ attr.i_uid = current->fsuid;
+ attr.i_gid = current->fsgid;
+ attr.i_ctime = CURRENT_TIME;
+ attr.i_atime = CURRENT_TIME;
+ attr.i_mtime = CURRENT_TIME;
+ attr.i_nlink = 1;
+ if (osd_set_one_attr((void *)&dir->i_sb->s_dev, root_gid, uid, 0x30000000, 0x1, sizeof(struct inode),
+ &attr, &osd_exec_via_scsi)!=0) {
+ iscsi_trace_error("osd_set_one_attr() failed\n");
+ return -1;
+ }
+
+ /* Assign to an inode */
+
+ if ((inode = osdfs_get_inode(dir->i_sb, mode, dev, name, uid))==NULL) {
+ iscsi_trace_error("osdfs_get_inode() failed\n");
+ return -ENOSPC;
+ }
+ d_instantiate(dentry, inode);
+
+ /* Add entry to parent directory */
+
+ if (inode->i_ino != 1) {
+ ISCSI_LOCK(&g_mutex, return -1);
+ if (entry_add(dev, dir->i_ino, inode->i_ino, name, &dir->i_size)!=0) {
+ iscsi_trace_error("entry_add() failed\n");
+ return -1;
+ }
+ osdfs_write_inode(dir, 0);
+ ISCSI_UNLOCK(&g_mutex, return -1);
+ }
+
+ return 0;
+}
+
+static int osdfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) {
+ kdev_t dev = old_dir->i_sb->s_dev;
+ ino_t old_dir_ino = old_dir->i_ino;
+ ino_t new_dir_ino = new_dir->i_ino;
+ ino_t old_ino = old_dentry->d_inode->i_ino;
+ ino_t new_ino = new_dentry->d_inode?new_dentry->d_inode->i_ino:old_ino;
+ const char *old_name = old_dentry->d_name.name;
+ const char *new_name = new_dentry->d_name.name;
+
+ iscsi_trace(TRACE_OSDFS, "old_dir = 0x%p (ino 0x%x)\n", old_dir, (unsigned) old_dir_ino);
+ iscsi_trace(TRACE_OSDFS, "new_dir = 0x%p (ino 0x%x)\n", new_dir, (unsigned) new_dir_ino);
+ iscsi_trace(TRACE_OSDFS, "old_dentry = 0x%p (ino 0x%x)\n", old_dentry, (unsigned) old_ino);
+ iscsi_trace(TRACE_OSDFS, "new_dentry = 0x%p (ino 0x%x)\n", new_dentry, (unsigned) new_ino);
+
+ /*
+ * If we return -1, the VFS will implement a rename with a combination
+ * of osdfs_unlink() and osdfs_create().
+ */
+
+ /* Delete entry from old directory */
+
+ ISCSI_LOCK(&g_mutex, return -1);
+ if (entry_del(dev, old_dir_ino, old_ino, old_name, &old_dir->i_size)!=0) {
+ iscsi_trace_error("error deleting old entry \"%s\"\n", old_name);
+ ISCSI_UNLOCK(&g_mutex, return -1);
+ return -1;
+ }
+ osdfs_write_inode(old_dir, 0);
+ ISCSI_UNLOCK(&g_mutex, return -1);
+
+ /* Unlink entry from new directory */
+
+ if (new_dentry->d_inode) {
+ iscsi_trace(TRACE_OSDFS, "unlinking existing file\n");
+ if (osdfs_unlink(new_dir, new_dentry)!=0) {
+ iscsi_trace_error("osdfs_unlink() failed\n");
+ return -1;
+ }
+ }
+
+ /* Add entry to new directory (might be the same dir) */
+
+ ISCSI_LOCK(&g_mutex, return -1);
+ if (entry_add(dev, new_dir_ino, new_ino, new_name, &new_dir->i_size)!=0) {
+ iscsi_trace_error("error adding new entry \"%s\"\n", new_name);
+ ISCSI_UNLOCK(&g_mutex, return -1);
+ return -1;
+ }
+ osdfs_write_inode(new_dir, 0);
+ ISCSI_UNLOCK(&g_mutex, return -1);
+
+ return 0;
+}
+
+static struct inode_operations osdfs_dir_inode_operations = {
+ create: osdfs_create,
+ lookup: osdfs_lookup,
+ link: osdfs_link,
+ unlink: osdfs_unlink,
+ symlink: osdfs_symlink,
+ mkdir: osdfs_mkdir,
+ rmdir: osdfs_unlink,
+ mknod: osdfs_mknod,
+ rename: osdfs_rename,
+};
+
+
+/*
+ * File operations (regular files)
+ */
+
+
+static int osdfs_sync_file(struct file * file, struct dentry *dentry, int datasync) {
+ iscsi_trace_error("osdfs_syncfile() not implemented\n");
+ return -1;
+}
+
+static struct file_operations osdfs_file_operations = {
+ read: generic_file_read,
+ write: generic_file_write,
+ mmap: generic_file_mmap,
+ fsync: osdfs_sync_file,
+};
+
+
+/*
+ * File operations (directories)
+ */
+
+
+static int osdfs_readdir(struct file * filp, void * dirent, filldir_t filldir) {
+ struct dentry *dentry = filp->f_dentry;
+ const char *name;
+ ino_t ino = dentry->d_inode->i_ino;
+ kdev_t dev = dentry->d_inode->i_sb->s_dev;
+ int offset = filp->f_pos;
+ char *entries, *ptr, *ptr2;
+ uint32_t num_entries;
+ uint64_t size;
+ uint64_t uid = ino;
+
+ name = dentry->d_name.name;
+ iscsi_trace(TRACE_OSDFS, "osdfs_readdir(\"%s\", ino 0x%x, offset %i)\n",
+ name, (unsigned) ino, offset);
+ ISCSI_LOCK(&g_mutex, return -1);
+ if (entries_get(dev, uid, &entries, &num_entries, &size)!=0) {
+ iscsi_trace_error("entries_get() failed\n");
+ ISCSI_UNLOCK(&g_mutex, return -1);
+ return -1;
+ }
+ ISCSI_UNLOCK(&g_mutex, return -1);
+
+ /* Update the offset if our number of entries has changed since the last */
+ /* call to osdfs_readdir(). filp->private_data stores the number of */
+ /* entries this directory had on the last call. */
+
+ if (offset) {
+ if (((int)filp->private_data)>num_entries) {
+ filp->f_pos = offset -= (((int)filp->private_data)-num_entries);
+ filp->private_data = (void *) num_entries;
+ }
+ } else {
+ filp->private_data = (void *) num_entries;
+ }
+
+ switch (offset) {
+
+ case 0:
+
+ iscsi_trace(TRACE_OSDFS, "adding \".\" (ino 0x%x)\n", (unsigned) ino);
+ if (filldir(dirent, ".", 1, filp->f_pos++, ino, DT_DIR) < 0) {
+ iscsi_trace_error("filldir() failed for \".\"??\n");
+ vfree(entries);
+ return -1;
+ }
+
+ case 1:
+
+ iscsi_trace(TRACE_OSDFS, "adding \"..\" (ino 0x%x)\n", (unsigned) dentry->d_parent->d_inode->i_ino);
+ if (filldir(dirent, "..", 2, filp->f_pos++, dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
+ iscsi_trace_error("filldir() failed for \"..\"??\n");
+ vfree(entries);
+ return -1;
+ }
+
+ default:
+
+ if (!num_entries) return 0;
+ ptr = entries;
+ offset -= 2;
+ do {
+ if ((ptr2=strchr(ptr, '\n'))!=NULL) {
+ *ptr2 = 0x0;
+ ptr2 = strchr(ptr2+1, '\n');
+ if (offset>0) {
+ offset--;
+ } else {
+ sscanf(ptr+strlen(ptr)+1, "%li", &ino);
+ iscsi_trace(TRACE_OSDFS, "adding \"%s\" (ino 0x%x)\n", ptr, (unsigned) ino);
+ if (filldir(dirent, ptr, strlen(ptr), filp->f_pos++, ino, DT_UNKNOWN) < 0) {
+ vfree(entries);
+ return 0;
+ }
+ }
+ }
+ } while (ptr2&&(ptr=ptr2+1));
+ }
+ if (num_entries) vfree(entries);
+
+ return 0;
+}
+
+static struct file_operations osdfs_dir_operations = {
+ read: generic_read_dir,
+ readdir: osdfs_readdir,
+ fsync: osdfs_sync_file,
+};
+
+
+/*
+ * Address space operations
+ */
+
+
+static int osdfs_readpage(struct file *file, struct page * page) {
+ uint64_t Offset = page->index<<PAGE_CACHE_SHIFT;
+ uint64_t Length = 1<<PAGE_CACHE_SHIFT;
+ struct inode *inode = page->mapping->host;
+ kdev_t dev = inode->i_sb->s_dev;
+ ino_t ino = inode->i_ino;
+ uint64_t len;
+ uint64_t uid = ino;
+
+ iscsi_trace(TRACE_OSDFS, "osdfs_readpage(ino %lu, Offset %llu, Length %llu)\n", ino, Offset, Length);
+ if (Offset+Length>inode->i_size) {
+ len = inode->i_size-Offset;
+ } else {
+ len = Length;
+ }
+ if (!Page_Uptodate(page)) {
+ memset(kmap(page), 0, PAGE_CACHE_SIZE);
+ if (osd_read((void *)&dev, root_gid, uid, Offset, len, page->virtual, 0, &osd_exec_via_scsi)!=0) {
+ iscsi_trace_error("osd_read() failed\n");
+ UnlockPage(page);
+ return -1;;
+ }
+ kunmap(page);
+ flush_dcache_page(page);
+ SetPageUptodate(page);
+ } else {
+ iscsi_trace_error("The page IS up to date???\n");
+ }
+ UnlockPage(page);
+
+ return 0;
+}
+
+static int osdfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) {
+ iscsi_trace(TRACE_OSDFS, "osdfs_prepare_write(ino %lu, offset %u, to %u)\n", page->mapping->host->i_ino, offset, to);
+ return 0;
+}
+
+static int osdfs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to) {
+ uint64_t Offset = (page->index<<PAGE_CACHE_SHIFT)+offset;
+ uint64_t Length = to-offset;
+ struct inode *inode = page->mapping->host;
+ kdev_t dev = inode->i_sb->s_dev;
+ ino_t ino = inode->i_ino;
+ uint64_t uid = ino;
+
+ iscsi_trace(TRACE_OSDFS, "osdfs_commit_write(ino %lu, offset %u, to %u, Offset %llu, Length %llu)\n",
+ ino, offset, to, Offset, Length);
+ if (osd_write((void *)&dev, root_gid, uid, Offset, Length, page->virtual+offset, 0, &osd_exec_via_scsi)!=0) {
+ iscsi_trace_error("osd_write() failed\n");
+ return -1;
+ }
+ if (Offset+Length>inode->i_size) {
+ inode->i_size = Offset+Length;
+ }
+ osdfs_write_inode(inode, 0);
+
+ return 0;
+}
+
+static struct address_space_operations osdfs_aops = {
+ readpage: osdfs_readpage,
+ writepage: NULL,
+ prepare_write: osdfs_prepare_write,
+ commit_write: osdfs_commit_write
+};
+
+
+/*
+ * Superblock operations
+ */
+
+
+static struct super_block *osdfs_read_super(struct super_block *sb, void *data, int silent) {
+ char opt[64];
+ char *ptr, *ptr2;
+ struct inode attr;
+ struct inode *inode;
+
+ iscsi_trace(TRACE_OSDFS, "osdfs_read_super(major %i minor %i)\n", MAJOR(sb->s_dev), MINOR(sb->s_dev));
+
+ root_gid = root_uid = 0;
+
+ /* Parse options */
+
+ ptr = (char *)data;
+ while (ptr&&strlen(ptr)) {
+ if ((ptr2=strchr(ptr, ','))) {
+ strncpy(opt, ptr, ptr2-ptr);
+ opt[ptr2-ptr] = 0x0;
+ ptr = ptr2+1;
+ } else {
+ strcpy(opt, ptr);
+ ptr = 0x0;
+ }
+ if (!strncmp(opt, "uid=", 3)) {
+ if (sscanf(opt, "uid=0x%Lx", &root_uid)!=1) {
+ iscsi_trace_error("malformed option \"%s\"\n", opt);
+ return NULL;
+ }
+ } else if (!strncmp(opt, "gid=", 3)) {
+ if (sscanf(opt, "gid=0x%x", &root_gid)!=1) {
+ iscsi_trace_error("malformed option \"%s\"\n", opt);
+ return NULL;
+ }
+ } else {
+ iscsi_trace_error("unknown option \"%s\"\n", opt);
+ return NULL;
+ }
+ }
+
+ /* Initialize superblock */
+
+ sb->s_blocksize = PAGE_CACHE_SIZE;
+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+ sb->s_magic = OSDFS_MAGIC;
+ sb->s_op = &osdfs_ops;
+
+ if ((root_uid==0)||(root_gid==0)) {
+
+ /* Create group object for root directory */
+
+ if (osd_create_group((void *)&sb->s_dev, &osd_exec_via_scsi, &root_gid)!=0) {
+ iscsi_trace_error("osd_create_group() failed\n");
+ return NULL;
+ }
+ printf("** ROOT DIRECTORY GROUP OBJECT IS 0x%x **\n", root_gid);
+
+ /* Create user object for root directory */
+
+ if (osd_create((void *)&sb->s_dev, root_gid, &osd_exec_via_scsi, &root_uid)!=0) {
+ iscsi_trace_error("osd_create() failed\n");
+ return NULL;
+ }
+ printf("** ROOT DIRECTORY USER OBJECT IS 0x%llx **\n", root_uid);
+
+ /* Initialize Attributes */
+
+ memset(&attr, 0, sizeof(struct inode));
+ attr.i_mode = S_IFDIR | 0755;
+ if (osd_set_one_attr((void *)&sb->s_dev, root_gid, root_uid, 0x30000000, 0x1, sizeof(struct inode), (void *) &attr, &osd_exec_via_scsi)!=0) {
+ iscsi_trace_error("osd_set_one_attr() failed\n");
+ return NULL;
+ }
+ } else {
+ iscsi_trace(TRACE_OSDFS, "using root directory in 0x%x:0x%llx\n", root_gid, root_uid);
+ }
+
+ /* Create inode for root directory */
+
+ if ((inode=osdfs_get_inode(sb, S_IFDIR | 0755, 0, "/", root_uid))==NULL) {
+ iscsi_trace_error("osdfs_get_inode() failed\n");
+ return NULL;
+ }
+ if ((sb->s_root=d_alloc_root(inode))==NULL) {
+ iscsi_trace_error("d_alloc_root() failed\n");
+ iput(inode);
+ return NULL;
+ }
+
+ return sb;
+}
+
+static DECLARE_FSTYPE_DEV(osdfs_fs_type, "osdfs", osdfs_read_super);
+
+
+/*
+ * Module operations
+ */
+
+
+static int __init init_osdfs_fs(void) {
+ iscsi_trace(TRACE_OSDFS, "init_osdfs_fs()\n");
+ ISCSI_MUTEX_INIT(&g_mutex, return -1);
+ return register_filesystem(&osdfs_fs_type);
+}
+
+static void __exit exit_osdfs_fs(void) {
+ iscsi_trace(TRACE_OSDFS, "exit_osdfs_fs()\n");
+ ISCSI_MUTEX_DESTROY(&g_mutex, printk("mutex_destroy() failed\n"));
+ unregister_filesystem(&osdfs_fs_type);
+}
+
+module_init(init_osdfs_fs)
+module_exit(exit_osdfs_fs)
Index: src/external/bsd/iscsi/dist/src/osd/start_osd
diff -u /dev/null src/external/bsd/iscsi/dist/src/osd/start_osd:1.1
--- /dev/null Thu Jun 25 13:48:42 2009
+++ src/external/bsd/iscsi/dist/src/osd/start_osd Thu Jun 25 13:48:42 2009
@@ -0,0 +1,5 @@
+#!/bin/sh
+insmod ./so.o
+insmod ./intel_iscsi.o
+insmod ./osdfs.o
+mount -t osdfs /dev/so0 /mnt -o gid=0x2d159c01 -o uid=0x2c8f1801
Index: src/external/bsd/iscsi/dist/src/osd/stop_osd
diff -u /dev/null src/external/bsd/iscsi/dist/src/osd/stop_osd:1.1
--- /dev/null Thu Jun 25 13:48:42 2009
+++ src/external/bsd/iscsi/dist/src/osd/stop_osd Thu Jun 25 13:48:42 2009
@@ -0,0 +1,5 @@
+#!/bin/sh
+umount /mnt
+rmmod osdfs
+rmmod intel_iscsi
+rmmod so