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

Reply via email to