2 * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By downloading, copying, installing or
3 * using the software you agree to this license. If you do not agree to this license, do not download, install,
4 * copy or use the software.
6 * Intel License Agreement
8 * Copyright (c) 2002, Intel Corporation
11 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
12 * the following conditions are met:
14 * -Redistributions of source code must retain the above copyright notice, this list of conditions and the
15 * following disclaimer.
17 * -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
18 * following disclaimer in the documentation and/or other materials provided with the distribution.
20 * -The name of Intel Corporation may not be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 * Object-Based Storage Devices (OSD) Filesystem for Linux
38 #include <linux/module.h>
40 #include <linux/pagemap.h>
41 #include <linux/init.h>
42 #include <linux/string.h>
43 #include <linux/locks.h>
44 #include <asm/uaccess.h>
46 #include <linux/blkdev.h>
50 #include "iscsiutil.h"
59 #define OSDFS_MAGIC 0xabcdef01
60 #define MAX_INODES 32768
61 #define MAX_NAME_LEN 32
69 typedef struct osdfs_link_t
{
70 char name
[MAX_NAME_LEN
];
71 struct osdfs_link_t
* next
;
74 typedef struct osdfs_inode_t
{
78 typedef struct osdfs_metadata_t
{
88 static int osdfs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
, int dev
);
96 static struct super_operations osdfs_ops
;
97 static struct address_space_operations osdfs_aops
;
98 static struct file_operations osdfs_dir_operations
;
99 static struct file_operations osdfs_file_operations
;
100 static struct inode_operations osdfs_dir_inode_operations
;
101 static uint32_t root_gid
;
102 static uint64_t root_uid
;
103 static iscsi_mutex_t g_mutex
;
107 * SCSI transport function for OSD
111 int osd_exec_via_scsi(void *dev
, osd_args_t
*args
, OSD_OPS_MEM
*m
) {
114 unsigned char cdb
[256];
115 kdev_t kdev
= *((kdev_t
*) dev
);
119 if (m
->send_sg
||m
->recv_sg
) {
120 iscsi_err("scatter/gather not yet implemented!\n");
124 SDpnt
= blk_dev
[MAJOR(kdev
)].queue(kdev
)->queuedata
;
125 SRpnt
= scsi_allocate_request(SDpnt
);
126 SRpnt
->sr_cmd_len
= CONFIG_OSD_CDB_LEN
;
127 SRpnt
->sr_sense_buffer
[0] = 0;
128 SRpnt
->sr_sense_buffer
[2] = 0;
129 switch(args
->service_action
) {
134 SRpnt
->sr_data_direction
= SCSI_DATA_WRITE
;
137 case OSD_CREATE_GROUP
:
142 SRpnt
->sr_data_direction
= SCSI_DATA_READ
;
145 case OSD_REMOVE_GROUP
:
146 SRpnt
->sr_data_direction
= 0;
149 iscsi_err("unsupported OSD service action 0x%x\n", args
->service_action
);
152 OSD_ENCAP_CDB(args
, cdb
);
154 /* Exec SCSI command */
156 scsi_wait_req(SRpnt
, cdb
, ptr
, len
, 5*HZ
, 5);
157 if (SRpnt
->sr_result
!=0) {
158 iscsi_err("SCSI command failed (result %u)\n", SRpnt
->sr_result
);
159 scsi_release_request(SRpnt
);
163 scsi_release_request(SRpnt
);
170 * Internal OSDFS functions
174 /* Directory operations */
176 static int entries_get(kdev_t dev
, uint64_t uid
, char **entries
, uint32_t *num
, uint64_t *size
) {
180 if (osd_get_one_attr((void *)&dev
, root_gid
, uid
, 0x30000000, 0x0, sizeof(struct inode
), &osd_exec_via_scsi
, &len
, (void *) &inode
)!=0) {
181 iscsi_err("osd_get_one_attr() failed\n");
185 if ((*size
=inode
.i_size
)) {
189 if ((*entries
=vmalloc(*size
+1))==NULL
) {
190 iscsi_err("vmalloc() failed\n");
193 if (osd_read((void *)&dev
, root_gid
, uid
, 0, *size
, *entries
, 0, &osd_exec_via_scsi
)!=0) {
194 iscsi_err("osd_read() failed\n");
198 (*entries
)[*size
] = 0x0;
202 if ((ptr2
=strchr(ptr
, '\n'))!=NULL
) {
204 if ((ptr2
= strchr(ptr2
+1, '\n'))==NULL
) {
205 iscsi_err("directory 0x%llx corrupted (line %i)\n", uid
, n
);
210 iscsi_err("directory 0x%llx corrupted (line %i)\n", uid
, n
);
220 static int entry_add(kdev_t dev
, ino_t dir_ino
, ino_t entry_ino
,
221 const char *name
, uint64_t *new_size
) {
222 char entry
[MAX_NAME_LEN
+16];
223 uint64_t uid
= dir_ino
;
227 /* Get size of directory */
229 if (osd_get_one_attr((void *)&dev
, root_gid
, uid
, 0x30000000, 0x0, sizeof(struct inode
), &osd_exec_via_scsi
, &len
, (void *) &inode
)!=0) {
230 iscsi_err("osd_get_one_attr() failed\n");
234 /* Write entry at end */
236 sprintf(entry
, "%s\n", name
);
237 sprintf(entry
+strlen(entry
), "%li\n", entry_ino
);
238 if (osd_write((void *)&dev
, root_gid
, uid
, inode
.i_size
, strlen(entry
), entry
, 0, &osd_exec_via_scsi
)!=0) {
239 iscsi_err("osd_write() failed\n");
242 *new_size
+= strlen(entry
);
247 static int entry_del(kdev_t dev
, ino_t dir_ino
, ino_t ino
, const char *name
, uint64_t *new_size
) {
249 uint32_t num_entries
;
251 uint64_t dir_uid
= (unsigned) dir_ino
;
255 if (entries_get(dev
, dir_ino
, &entries
, &num_entries
, &size
)!=0) {
256 iscsi_err("entries_get() failed\n");
261 iscsi_trace(TRACE_OSDFS
, "dir_ino 0x%llx has %u entries\n", dir_uid
, num_entries
);
270 if ((nl
=strchr(ptr
, '\n'))==NULL
) {
271 iscsi_err("directory 0x%llx corrupted (line %i)\n", dir_uid
, n
);
275 if (!strcmp(ptr
, name
)) {
280 if ((ptr
=strchr(nl
+1, '\n'))==NULL
) {
281 iscsi_err("directory 0x%llx corrupted (line %i)\n", dir_uid
, n
);
285 } while (!tmp
&& *ptr
);
288 iscsi_err("entry \"%s\" not found in dir 0x%llx\n", name
, dir_uid
);
291 if (entries
+size
-ptr
) {
292 iscsi_trace(TRACE_OSDFS
, "writing remaining %u directory bytes at offset %u\n",
293 entries
+size
-ptr
, tmp
-entries
);
294 if (osd_write((void *)&dev
, root_gid
, dir_uid
, tmp
-entries
, entries
+size
-ptr
, ptr
, 0, &osd_exec_via_scsi
)!=0) {
295 iscsi_err("osd_write() failed\n");
299 *new_size
= size
-(ptr
-tmp
);
302 iscsi_err("dir 0x%llx has no entries\n", dir_uid
);
309 static int entry_num(kdev_t dev
, ino_t ino
) {
311 uint32_t num_entries
;
314 if (entries_get(dev
, ino
, &entries
, &num_entries
, &size
)!=0) {
315 iscsi_err("entries_get() failed\n");
318 iscsi_trace(TRACE_OSDFS
, "ino %li has %i entries\n", ino
, num_entries
);
319 if (num_entries
) vfree(entries
);
323 /* Inode operations */
325 static void osdfs_set_ops(struct inode
*inode
) {
326 switch (inode
->i_mode
& S_IFMT
) {
328 inode
->i_fop
= &osdfs_file_operations
;
331 inode
->i_op
= &osdfs_dir_inode_operations
;
332 inode
->i_fop
= &osdfs_dir_operations
;
335 inode
->i_op
= &page_symlink_inode_operations
;
338 iscsi_err("UNKNOWN MODE\n");
340 inode
->i_mapping
->a_ops
= &osdfs_aops
;
343 static struct inode
*osdfs_get_inode(struct super_block
*sb
, int mode
, int dev
, const char *name
,
346 ino_t ino
= ObjectID
;
348 iscsi_trace(TRACE_OSDFS
, "osdfs_get_inode(\"%s\", mode %i (%s))\n", name
, mode
,
349 S_ISDIR(mode
)?"DIR":(S_ISREG(mode
)?"REG":"LNK"));
351 /* iget() gets a free VFS inode and subsequently call */
352 /* osdfds_read_inode() to fill the inode structure. */
354 if ((inode
=iget(sb
, ino
))==NULL
) {
355 iscsi_err("iget() failed\n");
368 static void osdfs_read_inode(struct inode
*inode
) {
369 ino_t ino
= inode
->i_ino
;
370 kdev_t dev
= inode
->i_sb
->s_dev
;
375 iscsi_trace(TRACE_OSDFS
, "osdfs_read_inode(ino 0x%x, major %i, minor %i)\n",
376 (unsigned) ino
, MAJOR(dev
), MINOR(dev
));
378 /* Get object attributes for rest of inode */
380 if ((attr
=iscsi_malloc_atomic(sizeof(struct inode
)))==NULL
) {
381 iscsi_err("iscsi_malloc_atomic() failed\n");
383 if (osd_get_one_attr((void *)&dev
, root_gid
, uid
, 0x30000000, 0x0, sizeof(struct inode
), &osd_exec_via_scsi
, &len
, attr
)!=0) {
384 iscsi_err("osd_get_one_attr() failed\n");
388 inode
->i_size
= ((struct inode
*)(attr
))->i_size
;
389 inode
->i_mode
= ((struct inode
*)(attr
))->i_mode
;
390 inode
->i_nlink
= ((struct inode
*)(attr
))->i_nlink
;
391 inode
->i_gid
= ((struct inode
*)(attr
))->i_gid
;
392 inode
->i_uid
= ((struct inode
*)(attr
))->i_uid
;
393 inode
->i_ctime
= ((struct inode
*)(attr
))->i_ctime
;
394 inode
->i_atime
= ((struct inode
*)(attr
))->i_atime
;
395 inode
->i_mtime
= ((struct inode
*)(attr
))->i_mtime
;
397 iscsi_free_atomic(attr
);
399 osdfs_set_ops(inode
);
402 void osdfs_dirty_inode(struct inode
*inode
) {
403 iscsi_trace(TRACE_OSDFS
, "osdfs_dirty_inode(ino 0x%x)\n", (unsigned) inode
->i_ino
);
406 void osdfs_write_inode(struct inode
*inode
, int sync
) {
407 ino_t ino
= inode
->i_ino
;
408 kdev_t dev
= inode
->i_sb
->s_dev
;
411 iscsi_trace(TRACE_OSDFS
, "osdfs_write_inode(0x%llx)\n", uid
);
413 if (osd_set_one_attr((void *)&dev
, root_gid
, uid
, 0x30000000, 0x1, sizeof(struct inode
), (void *) inode
, &osd_exec_via_scsi
)!=0) {
414 iscsi_err("osd_set_one_attr() failed\n");
416 inode
->i_state
&= ~I_DIRTY
;
419 void osdfs_put_inode(struct inode
*inode
) {
420 iscsi_trace(TRACE_OSDFS
, "osdfs_put_inode(0x%x)\n", (unsigned) inode
->i_ino
);
423 void osdfs_delete_inode(struct inode
*inode
) {
424 iscsi_trace(TRACE_OSDFS
, "osdfs_delete_inode(%lu)\n", inode
->i_ino
);
428 void osdfs_put_super(struct super_block
*sb
) {
429 iscsi_err("osdfs_put_super() not implemented\n");
432 void osdfs_write_super(struct super_block
*sb
) {
433 iscsi_err("osdfs_write_super() not implemented\n");
436 void osdfs_write_super_lockfs(struct super_block
*sb
) {
437 iscsi_err("osdfs_write_super_lockfs() not implemented\n");
440 void osdfs_unlockfs(struct super_block
*sb
) {
441 iscsi_err("osdfs_unlockfs() not implemented\n");
444 int osdfs_statfs(struct super_block
*sb
, struct statfs
*buff
) {
445 iscsi_trace(TRACE_OSDFS
, "statfs()\n");
446 buff
->f_type
= OSDFS_MAGIC
;
447 buff
->f_bsize
= PAGE_CACHE_SIZE
;
448 buff
->f_blocks
= 256;
453 buff
->f_namelen
= MAX_NAME_LEN
;
458 int osdfs_remount_fs(struct super_block
*sb
, int *i
, char *c
) {
459 iscsi_err("osdfs_remount_fs() not implemented\n");
464 void osdfs_clear_inode(struct inode
*inode
) {
465 iscsi_trace(TRACE_OSDFS
, "osdfs_clear_inode(ino %lu)\n", inode
->i_ino
);
468 void osdfs_umount_begin(struct super_block
*sb
) {
469 iscsi_err("osdfs_unmount_begin() not implemented\n");
472 static struct super_operations osdfs_ops
= {
473 read_inode
: osdfs_read_inode
,
474 dirty_inode
: osdfs_dirty_inode
,
475 write_inode
: osdfs_write_inode
,
476 put_inode
: osdfs_put_inode
,
477 delete_inode
: osdfs_delete_inode
,
478 put_super
: osdfs_put_super
,
479 write_super
: osdfs_write_super
,
480 write_super_lockfs
: osdfs_write_super_lockfs
,
481 unlockfs
: osdfs_unlockfs
,
482 statfs
: osdfs_statfs
,
483 remount_fs
: osdfs_remount_fs
,
484 clear_inode
: osdfs_clear_inode
,
485 umount_begin
: osdfs_umount_begin
490 * Inode operations for directories
494 static int osdfs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
) {
496 iscsi_trace(TRACE_OSDFS
, "osdfs_create(\"%s\")\n", dentry
->d_name
.name
);
497 if (osdfs_mknod(dir
, dentry
, mode
| S_IFREG
, 0)!=0) {
498 iscsi_err("osdfs_mknod() failed\n");
501 iscsi_trace(TRACE_OSDFS
, "file \"%s\" is inode 0x%x\n", dentry
->d_name
.name
, (unsigned) dentry
->d_inode
->i_ino
);
506 static struct dentry
* osdfs_lookup(struct inode
*dir
, struct dentry
*dentry
) {
507 const char *name
= dentry
->d_name
.name
;
508 struct inode
*inode
= NULL
;
510 kdev_t dev
= dir
->i_sb
->s_dev
;
511 uint64_t uid
= dir
->i_ino
;
513 uint32_t num_entries
;
516 iscsi_trace(TRACE_OSDFS
, "osdfs_lookup(\"%s\" in dir ino %lu)\n", name
, dir
->i_ino
);
518 /* Get directory entries */
520 ISCSI_LOCK(&g_mutex
, return NULL
);
521 if (entries_get(dev
, uid
, &entries
, &num_entries
, &size
)!=0) {
522 iscsi_err("entries_get() failed\n");
523 ISCSI_UNLOCK(&g_mutex
, return NULL
);
526 ISCSI_UNLOCK(&g_mutex
, return NULL
);
527 iscsi_trace(TRACE_OSDFS
, "ino %li has %i entries\n", dir
->i_ino
, num_entries
);
529 /* Search for this entry */
536 if ((ptr2
=strchr(ptr
, '\n'))!=NULL
) {
538 ptr2
= strchr(ptr2
+1, '\n');
539 if (!strcmp(ptr
, name
)) {
540 sscanf(ptr
+strlen(ptr
)+1, "%li", &ino
);
541 iscsi_trace(TRACE_OSDFS
, "found \"%s\" at ino %li\n", name
, ino
);
542 if ((inode
=iget(dir
->i_sb
, ino
))==NULL
) {
543 iscsi_err("iget() failed\n");
548 } while (ptr2
&&(ptr
=ptr2
+1));
552 iscsi_trace(TRACE_OSDFS
, "\"%s\" not found\n", name
);
554 d_add(dentry
, inode
);
559 static int osdfs_link(struct dentry
*old_dentry
, struct inode
* dir
, struct dentry
* dentry
) {
560 struct inode
*inode
= old_dentry
->d_inode
;
561 kdev_t dev
= dir
->i_sb
->s_dev
;
562 ino_t dir_ino
= dir
->i_ino
;
563 ino_t ino
= inode
->i_ino
;
564 const char *name
= dentry
->d_name
.name
;
566 if (S_ISDIR(inode
->i_mode
)) return -EPERM
;
567 iscsi_trace(TRACE_OSDFS
, "osdfs_link(%lu, \"%s\")\n", ino
, name
);
568 ISCSI_LOCK(&g_mutex
, return -1);
569 if (entry_add(dev
, dir_ino
, ino
, name
, &dir
->i_size
)!=0) {
570 iscsi_err("entry_add() failed\n");
574 atomic_inc(&inode
->i_count
);
575 osdfs_write_inode(inode
, 0);
576 osdfs_write_inode(dir
, 0);
577 d_instantiate(dentry
, inode
);
578 ISCSI_UNLOCK(&g_mutex
, return -1);
583 static int osdfs_unlink(struct inode
* dir
, struct dentry
*dentry
) {
584 kdev_t dev
= dir
->i_sb
->s_dev
;
585 struct inode
*inode
= dentry
->d_inode
;
586 ino_t dir_ino
= dir
->i_ino
;
587 ino_t ino
= dentry
->d_inode
->i_ino
;
588 const char *name
= dentry
->d_name
.name
;
590 iscsi_trace(TRACE_OSDFS
, "osdfs_unlink(\"%s\", ino 0x%x)\n", name
, (unsigned) ino
);
591 ISCSI_LOCK(&g_mutex
, return -1);
592 switch (inode
->i_mode
& S_IFMT
) {
597 if (entry_num(dev
, ino
)) {
598 iscsi_err("directory 0x%x still has %i entries\n",
599 (unsigned) ino
, entry_num(dev
, ino
));
600 ISCSI_UNLOCK(&g_mutex
, return -1);
604 if (entry_del(dev
, dir_ino
, ino
, name
, &(dir
->i_size
))!=0) {
605 iscsi_err("entry_del() failed\n");
606 ISCSI_UNLOCK(&g_mutex
, return -1);
609 osdfs_write_inode(dir
, 0);
610 if (--inode
->i_nlink
) {
611 iscsi_trace(TRACE_OSDFS
, "ino 0x%x still has %i links\n", (unsigned) ino
, inode
->i_nlink
);
612 osdfs_write_inode(inode
, 0);
614 iscsi_trace(TRACE_OSDFS
, "ino 0x%x link count reached 0, removing object\n", (unsigned) ino
);
615 if (osd_remove((void *)&dev
, root_gid
, ino
, &osd_exec_via_scsi
)!=0) {
616 iscsi_err("osd_remove() failed\n");
620 ISCSI_UNLOCK(&g_mutex
, return -1);
625 static int osdfs_symlink(struct inode
* dir
, struct dentry
*dentry
, const char * symname
) {
628 iscsi_trace(TRACE_OSDFS
, "osdfs_symlink(\"%s\"->\"%s\")\n", dentry
->d_name
.name
, symname
);
629 if (osdfs_mknod(dir
, dentry
, S_IRWXUGO
| S_IFLNK
, 0)!=0) {
630 iscsi_err("osdfs_mknod() failed\n");
633 inode
= dentry
->d_inode
;
634 if (block_symlink(inode
, symname
, strlen(symname
)+1)!=0) {
635 iscsi_err("block_symlink() failed\n");
638 iscsi_trace(TRACE_OSDFS
, "symbolic link \"%s\" is inode %lu\n", dentry
->d_name
.name
, inode
->i_ino
);
643 static int osdfs_mkdir(struct inode
* dir
, struct dentry
* dentry
, int mode
) {
645 iscsi_trace(TRACE_OSDFS
, "osdfs_mkdir(\"%s\")\n", dentry
->d_name
.name
);
646 if (osdfs_mknod(dir
, dentry
, mode
| S_IFDIR
, 0)!=0) {
647 iscsi_err("osdfs_mkdir() failed\n");
653 static int osdfs_mknod(struct inode
*dir
, struct dentry
*dentry
, int mode
, int dev_in
) {
654 struct inode
*inode
= NULL
;
657 kdev_t dev
= dir
->i_sb
->s_dev
;
658 const char *name
= dentry
->d_name
.name
;
660 iscsi_trace(TRACE_OSDFS
, "osdfs_mknod(\"%s\")\n", dentry
->d_name
.name
);
664 if (osd_create((void *)&dev
, root_gid
, &osd_exec_via_scsi
, &uid
)!=0) {
665 iscsi_err("osd_create() failed\n");
669 /* Initialize object attributes */
671 memset(&attr
, 0, sizeof(struct inode
));
673 attr
.i_uid
= current
->fsuid
;
674 attr
.i_gid
= current
->fsgid
;
675 attr
.i_ctime
= CURRENT_TIME
;
676 attr
.i_atime
= CURRENT_TIME
;
677 attr
.i_mtime
= CURRENT_TIME
;
679 if (osd_set_one_attr((void *)&dir
->i_sb
->s_dev
, root_gid
, uid
, 0x30000000, 0x1, sizeof(struct inode
),
680 &attr
, &osd_exec_via_scsi
)!=0) {
681 iscsi_err("osd_set_one_attr() failed\n");
685 /* Assign to an inode */
687 if ((inode
= osdfs_get_inode(dir
->i_sb
, mode
, dev
, name
, uid
))==NULL
) {
688 iscsi_err("osdfs_get_inode() failed\n");
691 d_instantiate(dentry
, inode
);
693 /* Add entry to parent directory */
695 if (inode
->i_ino
!= 1) {
696 ISCSI_LOCK(&g_mutex
, return -1);
697 if (entry_add(dev
, dir
->i_ino
, inode
->i_ino
, name
, &dir
->i_size
)!=0) {
698 iscsi_err("entry_add() failed\n");
701 osdfs_write_inode(dir
, 0);
702 ISCSI_UNLOCK(&g_mutex
, return -1);
708 static int osdfs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
, struct inode
*new_dir
, struct dentry
*new_dentry
) {
709 kdev_t dev
= old_dir
->i_sb
->s_dev
;
710 ino_t old_dir_ino
= old_dir
->i_ino
;
711 ino_t new_dir_ino
= new_dir
->i_ino
;
712 ino_t old_ino
= old_dentry
->d_inode
->i_ino
;
713 ino_t new_ino
= new_dentry
->d_inode
?new_dentry
->d_inode
->i_ino
:old_ino
;
714 const char *old_name
= old_dentry
->d_name
.name
;
715 const char *new_name
= new_dentry
->d_name
.name
;
717 iscsi_trace(TRACE_OSDFS
, "old_dir = 0x%p (ino 0x%x)\n", old_dir
, (unsigned) old_dir_ino
);
718 iscsi_trace(TRACE_OSDFS
, "new_dir = 0x%p (ino 0x%x)\n", new_dir
, (unsigned) new_dir_ino
);
719 iscsi_trace(TRACE_OSDFS
, "old_dentry = 0x%p (ino 0x%x)\n", old_dentry
, (unsigned) old_ino
);
720 iscsi_trace(TRACE_OSDFS
, "new_dentry = 0x%p (ino 0x%x)\n", new_dentry
, (unsigned) new_ino
);
723 * If we return -1, the VFS will implement a rename with a combination
724 * of osdfs_unlink() and osdfs_create().
727 /* Delete entry from old directory */
729 ISCSI_LOCK(&g_mutex
, return -1);
730 if (entry_del(dev
, old_dir_ino
, old_ino
, old_name
, &old_dir
->i_size
)!=0) {
731 iscsi_err("error deleting old entry \"%s\"\n", old_name
);
732 ISCSI_UNLOCK(&g_mutex
, return -1);
735 osdfs_write_inode(old_dir
, 0);
736 ISCSI_UNLOCK(&g_mutex
, return -1);
738 /* Unlink entry from new directory */
740 if (new_dentry
->d_inode
) {
741 iscsi_trace(TRACE_OSDFS
, "unlinking existing file\n");
742 if (osdfs_unlink(new_dir
, new_dentry
)!=0) {
743 iscsi_err("osdfs_unlink() failed\n");
748 /* Add entry to new directory (might be the same dir) */
750 ISCSI_LOCK(&g_mutex
, return -1);
751 if (entry_add(dev
, new_dir_ino
, new_ino
, new_name
, &new_dir
->i_size
)!=0) {
752 iscsi_err("error adding new entry \"%s\"\n", new_name
);
753 ISCSI_UNLOCK(&g_mutex
, return -1);
756 osdfs_write_inode(new_dir
, 0);
757 ISCSI_UNLOCK(&g_mutex
, return -1);
762 static struct inode_operations osdfs_dir_inode_operations
= {
763 create
: osdfs_create
,
764 lookup
: osdfs_lookup
,
766 unlink
: osdfs_unlink
,
767 symlink
: osdfs_symlink
,
771 rename
: osdfs_rename
,
776 * File operations (regular files)
780 static int osdfs_sync_file(struct file
* file
, struct dentry
*dentry
, int datasync
) {
781 iscsi_err("osdfs_syncfile() not implemented\n");
785 static struct file_operations osdfs_file_operations
= {
786 read
: generic_file_read
,
787 write
: generic_file_write
,
788 mmap
: generic_file_mmap
,
789 fsync
: osdfs_sync_file
,
794 * File operations (directories)
798 static int osdfs_readdir(struct file
* filp
, void * dirent
, filldir_t filldir
) {
799 struct dentry
*dentry
= filp
->f_dentry
;
801 ino_t ino
= dentry
->d_inode
->i_ino
;
802 kdev_t dev
= dentry
->d_inode
->i_sb
->s_dev
;
803 int offset
= filp
->f_pos
;
804 char *entries
, *ptr
, *ptr2
;
805 uint32_t num_entries
;
809 name
= dentry
->d_name
.name
;
810 iscsi_trace(TRACE_OSDFS
, "osdfs_readdir(\"%s\", ino 0x%x, offset %i)\n",
811 name
, (unsigned) ino
, offset
);
812 ISCSI_LOCK(&g_mutex
, return -1);
813 if (entries_get(dev
, uid
, &entries
, &num_entries
, &size
)!=0) {
814 iscsi_err("entries_get() failed\n");
815 ISCSI_UNLOCK(&g_mutex
, return -1);
818 ISCSI_UNLOCK(&g_mutex
, return -1);
820 /* Update the offset if our number of entries has changed since the last */
821 /* call to osdfs_readdir(). filp->private_data stores the number of */
822 /* entries this directory had on the last call. */
825 if (((int)filp
->private_data
)>num_entries
) {
826 filp
->f_pos
= offset
-= (((int)filp
->private_data
)-num_entries
);
827 filp
->private_data
= (void *) num_entries
;
830 filp
->private_data
= (void *) num_entries
;
837 iscsi_trace(TRACE_OSDFS
, "adding \".\" (ino 0x%x)\n", (unsigned) ino
);
838 if (filldir(dirent
, ".", 1, filp
->f_pos
++, ino
, DT_DIR
) < 0) {
839 iscsi_err("filldir() failed for \".\"??\n");
846 iscsi_trace(TRACE_OSDFS
, "adding \"..\" (ino 0x%x)\n", (unsigned) dentry
->d_parent
->d_inode
->i_ino
);
847 if (filldir(dirent
, "..", 2, filp
->f_pos
++, dentry
->d_parent
->d_inode
->i_ino
, DT_DIR
) < 0) {
848 iscsi_err("filldir() failed for \"..\"??\n");
855 if (!num_entries
) return 0;
859 if ((ptr2
=strchr(ptr
, '\n'))!=NULL
) {
861 ptr2
= strchr(ptr2
+1, '\n');
865 sscanf(ptr
+strlen(ptr
)+1, "%li", &ino
);
866 iscsi_trace(TRACE_OSDFS
, "adding \"%s\" (ino 0x%x)\n", ptr
, (unsigned) ino
);
867 if (filldir(dirent
, ptr
, strlen(ptr
), filp
->f_pos
++, ino
, DT_UNKNOWN
) < 0) {
873 } while (ptr2
&&(ptr
=ptr2
+1));
875 if (num_entries
) vfree(entries
);
880 static struct file_operations osdfs_dir_operations
= {
881 read
: generic_read_dir
,
882 readdir
: osdfs_readdir
,
883 fsync
: osdfs_sync_file
,
888 * Address space operations
892 static int osdfs_readpage(struct file
*file
, struct page
* page
) {
893 uint64_t Offset
= page
->index
<<PAGE_CACHE_SHIFT
;
894 uint64_t Length
= 1<<PAGE_CACHE_SHIFT
;
895 struct inode
*inode
= page
->mapping
->host
;
896 kdev_t dev
= inode
->i_sb
->s_dev
;
897 ino_t ino
= inode
->i_ino
;
901 iscsi_trace(TRACE_OSDFS
, "osdfs_readpage(ino %lu, Offset %llu, Length %llu)\n", ino
, Offset
, Length
);
902 if (Offset
+Length
>inode
->i_size
) {
903 len
= inode
->i_size
-Offset
;
907 if (!Page_Uptodate(page
)) {
908 memset(kmap(page
), 0, PAGE_CACHE_SIZE
);
909 if (osd_read((void *)&dev
, root_gid
, uid
, Offset
, len
, page
->virtual, 0, &osd_exec_via_scsi
)!=0) {
910 iscsi_err("osd_read() failed\n");
915 flush_dcache_page(page
);
916 SetPageUptodate(page
);
918 iscsi_err("The page IS up to date???\n");
925 static int osdfs_prepare_write(struct file
*file
, struct page
*page
, unsigned offset
, unsigned to
) {
926 iscsi_trace(TRACE_OSDFS
, "osdfs_prepare_write(ino %lu, offset %u, to %u)\n", page
->mapping
->host
->i_ino
, offset
, to
);
930 static int osdfs_commit_write(struct file
*file
, struct page
*page
, unsigned offset
, unsigned to
) {
931 uint64_t Offset
= (page
->index
<<PAGE_CACHE_SHIFT
)+offset
;
932 uint64_t Length
= to
-offset
;
933 struct inode
*inode
= page
->mapping
->host
;
934 kdev_t dev
= inode
->i_sb
->s_dev
;
935 ino_t ino
= inode
->i_ino
;
938 iscsi_trace(TRACE_OSDFS
, "osdfs_commit_write(ino %lu, offset %u, to %u, Offset %llu, Length %llu)\n",
939 ino
, offset
, to
, Offset
, Length
);
940 if (osd_write((void *)&dev
, root_gid
, uid
, Offset
, Length
, page
->virtual+offset
, 0, &osd_exec_via_scsi
)!=0) {
941 iscsi_err("osd_write() failed\n");
944 if (Offset
+Length
>inode
->i_size
) {
945 inode
->i_size
= Offset
+Length
;
947 osdfs_write_inode(inode
, 0);
952 static struct address_space_operations osdfs_aops
= {
953 readpage
: osdfs_readpage
,
955 prepare_write
: osdfs_prepare_write
,
956 commit_write
: osdfs_commit_write
961 * Superblock operations
965 static struct super_block
*osdfs_read_super(struct super_block
*sb
, void *data
, int silent
) {
971 iscsi_trace(TRACE_OSDFS
, "osdfs_read_super(major %i minor %i)\n", MAJOR(sb
->s_dev
), MINOR(sb
->s_dev
));
973 root_gid
= root_uid
= 0;
978 while (ptr
&&strlen(ptr
)) {
979 if ((ptr2
=strchr(ptr
, ','))) {
980 strncpy(opt
, ptr
, ptr2
-ptr
);
987 if (!strncmp(opt
, "uid=", 3)) {
988 if (sscanf(opt
, "uid=0x%Lx", &root_uid
)!=1) {
989 iscsi_err("malformed option \"%s\"\n", opt
);
992 } else if (!strncmp(opt
, "gid=", 3)) {
993 if (sscanf(opt
, "gid=0x%x", &root_gid
)!=1) {
994 iscsi_err("malformed option \"%s\"\n", opt
);
998 iscsi_err("unknown option \"%s\"\n", opt
);
1003 /* Initialize superblock */
1005 sb
->s_blocksize
= PAGE_CACHE_SIZE
;
1006 sb
->s_blocksize_bits
= PAGE_CACHE_SHIFT
;
1007 sb
->s_magic
= OSDFS_MAGIC
;
1008 sb
->s_op
= &osdfs_ops
;
1010 if ((root_uid
==0)||(root_gid
==0)) {
1012 /* Create group object for root directory */
1014 if (osd_create_group((void *)&sb
->s_dev
, &osd_exec_via_scsi
, &root_gid
)!=0) {
1015 iscsi_err("osd_create_group() failed\n");
1018 printf("** ROOT DIRECTORY GROUP OBJECT IS 0x%x **\n", root_gid
);
1020 /* Create user object for root directory */
1022 if (osd_create((void *)&sb
->s_dev
, root_gid
, &osd_exec_via_scsi
, &root_uid
)!=0) {
1023 iscsi_err("osd_create() failed\n");
1026 printf("** ROOT DIRECTORY USER OBJECT IS 0x%llx **\n", root_uid
);
1028 /* Initialize Attributes */
1030 memset(&attr
, 0, sizeof(struct inode
));
1031 attr
.i_mode
= S_IFDIR
| 0755;
1032 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) {
1033 iscsi_err("osd_set_one_attr() failed\n");
1037 iscsi_trace(TRACE_OSDFS
, "using root directory in 0x%x:0x%llx\n", root_gid
, root_uid
);
1040 /* Create inode for root directory */
1042 if ((inode
=osdfs_get_inode(sb
, S_IFDIR
| 0755, 0, "/", root_uid
))==NULL
) {
1043 iscsi_err("osdfs_get_inode() failed\n");
1046 if ((sb
->s_root
=d_alloc_root(inode
))==NULL
) {
1047 iscsi_err("d_alloc_root() failed\n");
1055 static DECLARE_FSTYPE_DEV(osdfs_fs_type
, "osdfs", osdfs_read_super
);
1063 static int __init
init_osdfs_fs(void) {
1064 iscsi_trace(TRACE_OSDFS
, "init_osdfs_fs()\n");
1065 ISCSI_MUTEX_INIT(&g_mutex
, return -1);
1066 return register_filesystem(&osdfs_fs_type
);
1069 static void __exit
exit_osdfs_fs(void) {
1070 iscsi_trace(TRACE_OSDFS
, "exit_osdfs_fs()\n");
1071 ISCSI_MUTEX_DESTROY(&g_mutex
, printk("mutex_destroy() failed\n"));
1072 unregister_filesystem(&osdfs_fs_type
);
1075 module_init(init_osdfs_fs
)
1076 module_exit(exit_osdfs_fs
)