diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2009-11-12 15:22:32 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2009-11-12 15:22:32 +1100 |
commit | 5c0146c225e4ceae74d44e55f3285bdac6367e33 (patch) | |
tree | ff513ab43ceeb2a7262e22dbd951082231a85414 | |
parent | d201ee6c8fdf9304e2594a7490a701bdb93cd83c (diff) | |
parent | 64ac8e00e36e78c0de3b99e0b79ba1147f2f571b (diff) |
Merge remote branch 'osd/linux-next'
-rw-r--r-- | Documentation/filesystems/00-INDEX | 2 | ||||
-rw-r--r-- | Documentation/filesystems/exofs.txt | 23 | ||||
-rw-r--r-- | drivers/scsi/osd/osd_initiator.c | 26 | ||||
-rw-r--r-- | drivers/scsi/osd/osd_uld.c | 259 | ||||
-rw-r--r-- | fs/exofs/inode.c | 23 | ||||
-rw-r--r-- | fs/exofs/super.c | 11 | ||||
-rw-r--r-- | include/scsi/osd_initiator.h | 55 | ||||
-rw-r--r-- | include/scsi/osd_sense.h | 3 |
8 files changed, 283 insertions, 119 deletions
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX index 658154f52557..875d49696b6e 100644 --- a/Documentation/filesystems/00-INDEX +++ b/Documentation/filesystems/00-INDEX @@ -34,6 +34,8 @@ dnotify.txt - info about directory notification in Linux. ecryptfs.txt - docs on eCryptfs: stacked cryptographic filesystem for Linux. +exofs.txt + - info, usage, mount options, design about EXOFS. ext2.txt - info, mount options and specifications for the Ext2 filesystem. ext3.txt diff --git a/Documentation/filesystems/exofs.txt b/Documentation/filesystems/exofs.txt index 0ced74c2f73c..abd2a9b5b787 100644 --- a/Documentation/filesystems/exofs.txt +++ b/Documentation/filesystems/exofs.txt @@ -60,13 +60,13 @@ USAGE mkfs.exofs --pid=65536 --format /dev/osd0 - The --format is optional if not specified no OSD_FORMAT will be - preformed and a clean file system will be created in the specified pid, + The --format is optional. If not specified, no OSD_FORMAT will be + performed and a clean file system will be created in the specified pid, in the available space of the target. (Use --format=size_in_meg to limit the total LUN space available) - If pid already exist it will be deleted and a new one will be created in it's - place. Be careful. + If pid already exists, it will be deleted and a new one will be created in + its place. Be careful. An exofs lives inside a single OSD partition. You can create multiple exofs filesystems on the same device using multiple pids. @@ -81,7 +81,7 @@ USAGE 7. For reference (See do-exofs example script): do-exofs start - an example of how to perform the above steps. - do-exofs stop - an example of how to unmount the file system. + do-exofs stop - an example of how to unmount the file system. do-exofs format - an example of how to format and mkfs a new exofs. 8. Extra compilation flags (uncomment in fs/exofs/Kbuild): @@ -104,8 +104,8 @@ Where: exofs specific options: Options are separated by commas (,) pid=<integer> - The partition number to mount/create as container of the filesystem. - This option is mandatory - to=<integer> - Timeout in ticks for a single command + This option is mandatory. + to=<integer> - Timeout in ticks for a single command. default is (60 * HZ) [for debugging only] =============================================================================== @@ -116,7 +116,7 @@ DESIGN with a special ID (defined in common.h). Information included in the file system control block is used to fill the in-memory superblock structure at mount time. This object is created before - the file system is used by mkexofs.c It contains information such as: + the file system is used by mkexofs.c. It contains information such as: - The file system's magic number - The next inode number to be allocated @@ -134,8 +134,8 @@ DESIGN attributes. This applies to both regular files and other types (directories, device files, symlinks, etc.). -* Credentials are generated per object (inode and superblock) when they is - created in memory (read off disk or created). The credential works for all +* Credentials are generated per object (inode and superblock) when they are + created in memory (read from disk or created). The credential works for all operations and is used as long as the object remains in memory. * Async OSD operations are used whenever possible, but the target may execute @@ -145,7 +145,8 @@ DESIGN from executing in reverse order: - The following are handled with the OBJ_CREATED and OBJ_2BCREATED flags. OBJ_CREATED is set when we know the object exists on the OSD - - in create's callback function, and when we successfully do a read_inode. + in create's callback function, and when we successfully do a + read_inode. OBJ_2BCREATED is set in the beginning of the create function, so we know that we should wait. - create/delete: delete should wait until the object is created diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 7a117c18114c..60b7ca1e9bc0 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -73,7 +73,8 @@ static const char *_osd_ver_desc(struct osd_request *or) #define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len) -static int _osd_print_system_info(struct osd_dev *od, void *caps) +static int _osd_get_print_system_info(struct osd_dev *od, + void *caps, struct osd_dev_info *odi) { struct osd_request *or; struct osd_attr get_attrs[] = { @@ -137,8 +138,12 @@ static int _osd_print_system_info(struct osd_dev *od, void *caps) OSD_INFO("PRODUCT_SERIAL_NUMBER [%s]\n", (char *)pFirst); - pFirst = get_attrs[a].val_ptr; - OSD_INFO("OSD_NAME [%s]\n", (char *)pFirst); + odi->osdname_len = get_attrs[a].len; + /* Avoid NULL for memcmp optimization 0-length is good enough */ + odi->osdname = kzalloc(odi->osdname_len + 1, GFP_KERNEL); + if (odi->osdname_len) + memcpy(odi->osdname, get_attrs[a].val_ptr, odi->osdname_len); + OSD_INFO("OSD_NAME [%s]\n", odi->osdname); a++; pFirst = get_attrs[a++].val_ptr; @@ -171,6 +176,14 @@ static int _osd_print_system_info(struct osd_dev *od, void *caps) sid_dump, sizeof(sid_dump), true); OSD_INFO("OSD_SYSTEM_ID(%d)\n" " [%s]\n", len, sid_dump); + + if (unlikely(len > sizeof(odi->systemid))) { + OSD_ERR("OSD Target error: OSD_SYSTEM_ID too long(%d). " + "device idetification might not work\n", len); + len = sizeof(odi->systemid); + } + odi->systemid_len = len; + memcpy(odi->systemid, get_attrs[a].val_ptr, len); a++; } out: @@ -178,16 +191,17 @@ out: return ret; } -int osd_auto_detect_ver(struct osd_dev *od, void *caps) +int osd_auto_detect_ver(struct osd_dev *od, + void *caps, struct osd_dev_info *odi) { int ret; /* Auto-detect the osd version */ - ret = _osd_print_system_info(od, caps); + ret = _osd_get_print_system_info(od, caps, odi); if (ret) { osd_dev_set_ver(od, OSD_VER1); OSD_DEBUG("converting to OSD1\n"); - ret = _osd_print_system_info(od, caps); + ret = _osd_get_print_system_info(od, caps, odi); } return ret; diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c index 0bdef3390902..0484bae00738 100644 --- a/drivers/scsi/osd/osd_uld.c +++ b/drivers/scsi/osd/osd_uld.c @@ -71,8 +71,7 @@ #define SCSI_OSD_MAX_MINOR 64 static const char osd_name[] = "osd"; -static const char *osd_version_string = "open-osd 0.1.0"; -const char osd_symlink[] = "scsi_osd"; +static const char *osd_version_string = "open-osd 0.2.0"; MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>"); MODULE_DESCRIPTION("open-osd Upper-Layer-Driver osd.ko"); @@ -82,15 +81,25 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_OSD); struct osd_uld_device { int minor; - struct kref kref; + struct device class_dev; struct cdev cdev; struct osd_dev od; + struct osd_dev_info odi; struct gendisk *disk; - struct device *class_member; }; -static void __uld_get(struct osd_uld_device *oud); -static void __uld_put(struct osd_uld_device *oud); +struct osd_dev_handle { + struct osd_dev od; + struct file *file; + struct osd_uld_device *oud; +} ; + +static DEFINE_IDA(osd_minor_ida); + +static struct class osd_uld_class = { + .owner = THIS_MODULE, + .name = "scsi_osd", +}; /* * Char Device operations @@ -101,7 +110,7 @@ static int osd_uld_open(struct inode *inode, struct file *file) struct osd_uld_device *oud = container_of(inode->i_cdev, struct osd_uld_device, cdev); - __uld_get(oud); + get_device(&oud->class_dev); /* cache osd_uld_device on file handle */ file->private_data = oud; OSD_DEBUG("osd_uld_open %p\n", oud); @@ -114,7 +123,7 @@ static int osd_uld_release(struct inode *inode, struct file *file) OSD_DEBUG("osd_uld_release %p\n", file->private_data); file->private_data = NULL; - __uld_put(oud); + put_device(&oud->class_dev); return 0; } @@ -177,7 +186,7 @@ static const struct file_operations osd_fops = { struct osd_dev *osduld_path_lookup(const char *name) { struct osd_uld_device *oud; - struct osd_dev *od; + struct osd_dev_handle *odh; struct file *file; int error; @@ -186,8 +195,8 @@ struct osd_dev *osduld_path_lookup(const char *name) return ERR_PTR(-EINVAL); } - od = kzalloc(sizeof(*od), GFP_KERNEL); - if (!od) + odh = kzalloc(sizeof(*odh), GFP_KERNEL); + if (unlikely(!odh)) return ERR_PTR(-ENOMEM); file = filp_open(name, O_RDWR, 0); @@ -203,33 +212,133 @@ struct osd_dev *osduld_path_lookup(const char *name) oud = file->private_data; - *od = oud->od; - od->file = file; + odh->od = oud->od; + odh->file = file; + odh->oud = oud; - return od; + return &odh->od; close_file: fput(file); free_od: - kfree(od); + kfree(odh); return ERR_PTR(error); } EXPORT_SYMBOL(osduld_path_lookup); -void osduld_put_device(struct osd_dev *od) +static inline bool _the_same_or_null(const u8 *a1, unsigned a1_len, + const u8 *a2, unsigned a2_len) { + if (!a2_len) /* User string is Empty means don't care */ + return true; + + if (a1_len != a2_len) + return false; + + return 0 == memcmp(a1, a2, a1_len); +} + +struct find_oud_t { + const struct osd_dev_info *odi; + struct device *dev; + struct osd_uld_device *oud; +} ; + +int _mach_odi(struct device *dev, void *find_data) +{ + struct osd_uld_device *oud = dev_get_drvdata(dev); + struct find_oud_t *fot = find_data; + const struct osd_dev_info *odi = fot->odi; + + if (_the_same_or_null(oud->odi.systemid, oud->odi.systemid_len, + odi->systemid, odi->systemid_len) && + _the_same_or_null(oud->odi.osdname, oud->odi.osdname_len, + odi->osdname, odi->osdname_len)) { + OSD_DEBUG("found device sysid_len=%d osdname=%d\n", + odi->systemid_len, odi->osdname_len); + fot->oud = oud; + return 1; + } else { + return 0; + } +} + +/* osduld_info_lookup - Loop through all devices, return the requested osd_dev. + * + * if @odi->systemid_len and/or @odi->osdname_len are zero, they act as a don't + * care. .e.g if they're both zero /dev/osd0 is returned. + */ +struct osd_dev *osduld_info_lookup(const struct osd_dev_info *odi) +{ + struct find_oud_t find = {.odi = odi}; + + find.dev = class_find_device(&osd_uld_class, NULL, &find, _mach_odi); + if (likely(find.dev)) { + struct osd_dev_handle *odh = kzalloc(sizeof(*odh), GFP_KERNEL); + if (unlikely(!odh)) { + put_device(find.dev); + return ERR_PTR(-ENOMEM); + } + + odh->od = find.oud->od; + odh->oud = find.oud; + + return &odh->od; + } + + return ERR_PTR(-ENODEV); +} +EXPORT_SYMBOL(osduld_info_lookup); + +void osduld_put_device(struct osd_dev *od) +{ if (od && !IS_ERR(od)) { - struct osd_uld_device *oud = od->file->private_data; + struct osd_dev_handle *odh = + container_of(od, struct osd_dev_handle, od); + struct osd_uld_device *oud = odh->oud; BUG_ON(od->scsi_device != oud->od.scsi_device); - fput(od->file); - kfree(od); + /* If scsi has released the device (logout), and exofs has last + * reference on oud it will be freed by above osd_uld_release + * within fput below. But this will oops in cdev_release which + * is called after the fops->release. A get_/put_ pair makes + * sure we have a cdev for the duration of fput + */ + if (odh->file) { + get_device(&oud->class_dev); + fput(odh->file); + } + put_device(&oud->class_dev); + kfree(odh); } } EXPORT_SYMBOL(osduld_put_device); +const struct osd_dev_info *osduld_device_info(struct osd_dev *od) +{ + struct osd_dev_handle *odh = + container_of(od, struct osd_dev_handle, od); + return &odh->oud->odi; +} +EXPORT_SYMBOL(osduld_device_info); + +bool osduld_device_same(struct osd_dev *od, const struct osd_dev_info *odi) +{ + struct osd_dev_handle *odh = + container_of(od, struct osd_dev_handle, od); + struct osd_uld_device *oud = odh->oud; + + return (oud->odi.systemid_len == odi->systemid_len) && + _the_same_or_null(oud->odi.systemid, oud->odi.systemid_len, + odi->systemid, odi->systemid_len) && + (oud->odi.osdname_len == odi->osdname_len) && + _the_same_or_null(oud->odi.osdname, oud->odi.osdname_len, + odi->osdname, odi->osdname_len); +} +EXPORT_SYMBOL(osduld_device_same); + /* * Scsi Device operations */ @@ -250,14 +359,34 @@ static int __detect_osd(struct osd_uld_device *oud) OSD_ERR("warning: scsi_test_unit_ready failed\n"); osd_sec_init_nosec_doall_caps(caps, &osd_root_object, false, true); - if (osd_auto_detect_ver(&oud->od, caps)) + if (osd_auto_detect_ver(&oud->od, caps, &oud->odi)) return -ENODEV; return 0; } -static struct class *osd_sysfs_class; -static DEFINE_IDA(osd_minor_ida); +static void __remove(struct device *dev) +{ + struct osd_uld_device *oud = dev_get_drvdata(dev); + struct scsi_device *scsi_device = oud->od.scsi_device; + + kfree(oud->odi.osdname); + + if (oud->cdev.owner) + cdev_del(&oud->cdev); + + osd_dev_fini(&oud->od); + scsi_device_put(scsi_device); + + OSD_INFO("osd_remove %s\n", + oud->disk ? oud->disk->disk_name : NULL); + + if (oud->disk) + put_disk(oud->disk); + ida_remove(&osd_minor_ida, oud->minor); + + kfree(oud); +} static int osd_probe(struct device *dev) { @@ -289,7 +418,6 @@ static int osd_probe(struct device *dev) if (NULL == oud) goto err_retract_minor; - kref_init(&oud->kref); dev_set_drvdata(dev, oud); oud->minor = minor; @@ -327,18 +455,26 @@ static int osd_probe(struct device *dev) OSD_ERR("cdev_add failed\n"); goto err_put_disk; } - kobject_get(&oud->cdev.kobj); /* 2nd ref see osd_remove() */ - - /* class_member */ - oud->class_member = device_create(osd_sysfs_class, dev, - MKDEV(SCSI_OSD_MAJOR, oud->minor), "%s", disk->disk_name); - if (IS_ERR(oud->class_member)) { - OSD_ERR("class_device_create failed\n"); - error = PTR_ERR(oud->class_member); + + /* class device member */ + oud->class_dev.devt = oud->cdev.dev; + oud->class_dev.class = &osd_uld_class; + oud->class_dev.parent = dev; + oud->class_dev.release = __remove; + dev_set_drvdata(&oud->class_dev, oud); + error = dev_set_name(&oud->class_dev, disk->disk_name); + if (error) { + OSD_ERR("dev_set_name failed => %d\n", error); + goto err_put_cdev; + } + + error = device_register(&oud->class_dev); + if (error) { + OSD_ERR("device_register failed => %d\n", error); goto err_put_cdev; } - dev_set_drvdata(oud->class_member, oud); + get_device(&oud->class_dev); OSD_INFO("osd_probe %s\n", disk->disk_name); return 0; @@ -367,54 +503,12 @@ static int osd_remove(struct device *dev) scsi_device); } - if (oud->class_member) - device_destroy(osd_sysfs_class, - MKDEV(SCSI_OSD_MAJOR, oud->minor)); + device_unregister(&oud->class_dev); - /* We have 2 references to the cdev. One is released here - * and also takes down the /dev/osdX mapping. The second - * Will be released in __remove() after all users have released - * the osd_uld_device. - */ - if (oud->cdev.owner) - cdev_del(&oud->cdev); - - __uld_put(oud); + put_device(&oud->class_dev); return 0; } -static void __remove(struct kref *kref) -{ - struct osd_uld_device *oud = container_of(kref, - struct osd_uld_device, kref); - struct scsi_device *scsi_device = oud->od.scsi_device; - - /* now let delete the char_dev */ - kobject_put(&oud->cdev.kobj); - - osd_dev_fini(&oud->od); - scsi_device_put(scsi_device); - - OSD_INFO("osd_remove %s\n", - oud->disk ? oud->disk->disk_name : NULL); - - if (oud->disk) - put_disk(oud->disk); - - ida_remove(&osd_minor_ida, oud->minor); - kfree(oud); -} - -static void __uld_get(struct osd_uld_device *oud) -{ - kref_get(&oud->kref); -} - -static void __uld_put(struct osd_uld_device *oud) -{ - kref_put(&oud->kref, __remove); -} - /* * Global driver and scsi registration */ @@ -432,11 +526,10 @@ static int __init osd_uld_init(void) { int err; - osd_sysfs_class = class_create(THIS_MODULE, osd_symlink); - if (IS_ERR(osd_sysfs_class)) { - OSD_ERR("Unable to register sysfs class => %ld\n", - PTR_ERR(osd_sysfs_class)); - return PTR_ERR(osd_sysfs_class); + err = class_register(&osd_uld_class); + if (err) { + OSD_ERR("Unable to register sysfs class => %d\n", err); + return err; } err = register_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), @@ -459,7 +552,7 @@ static int __init osd_uld_init(void) err_out_chrdev: unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR); err_out: - class_destroy(osd_sysfs_class); + class_unregister(&osd_uld_class); return err; } @@ -467,7 +560,7 @@ static void __exit osd_uld_exit(void) { scsi_unregister_driver(&osd_driver.gendrv); unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR); - class_destroy(osd_sysfs_class); + class_unregister(&osd_uld_class); OSD_INFO("UNLOADED %s\n", osd_version_string); } diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 6c10f7476699..243bc466e86a 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -41,6 +41,8 @@ # define EXOFS_DEBUG_OBJ_ISIZE 1 #endif +#define EXOFS_DBGMSG2(M...) do{}while(0) + struct page_collect { struct exofs_sb_info *sbi; struct request_queue *req_q; @@ -198,7 +200,7 @@ static int __readpages_done(struct osd_request *or, struct page_collect *pcol, else page_stat = ret; - EXOFS_DBGMSG(" readpages_done(0x%lx, 0x%lx) %s\n", + EXOFS_DBGMSG2(" readpages_done(0x%lx, 0x%lx) %s\n", inode->i_ino, page->index, page_stat ? "bad_bytes" : "good_bytes"); @@ -370,7 +372,7 @@ try_again: if (len != PAGE_CACHE_SIZE) zero_user(page, len, PAGE_CACHE_SIZE - len); - EXOFS_DBGMSG(" readpage_strip(0x%lx, 0x%lx) len=0x%zx\n", + EXOFS_DBGMSG2(" readpage_strip(0x%lx, 0x%lx) len=0x%zx\n", inode->i_ino, page->index, len); ret = pcol_add_page(pcol, page, len); @@ -482,7 +484,7 @@ static void writepages_done(struct osd_request *or, void *p) update_write_page(page, page_stat); unlock_page(page); - EXOFS_DBGMSG(" writepages_done(0x%lx, 0x%lx) status=%d\n", + EXOFS_DBGMSG2(" writepages_done(0x%lx, 0x%lx) status=%d\n", inode->i_ino, page->index, page_stat); length += bvec->bv_len; @@ -609,7 +611,7 @@ try_again: goto fail; } - EXOFS_DBGMSG(" writepage_strip(0x%lx, 0x%lx) len=0x%zx\n", + EXOFS_DBGMSG2(" writepage_strip(0x%lx, 0x%lx) len=0x%zx\n", inode->i_ino, page->index, len); ret = pcol_add_page(pcol, page, len); @@ -906,6 +908,12 @@ out: return ret; } + +static void __oi_init(struct exofs_i_info *oi) +{ + init_waitqueue_head(&oi->i_wq); + oi->i_flags = 0; +} /* * Fill in an inode read from the OSD and set it up for use */ @@ -923,13 +931,13 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino) if (!(inode->i_state & I_NEW)) return inode; oi = exofs_i(inode); + __oi_init(oi); /* read the inode from the osd */ ret = exofs_get_inode(sb, oi, &fcb, &sanity); if (ret) goto bad_inode; - init_waitqueue_head(&oi->i_wq); set_obj_created(oi); /* copy stuff from on-disk struct to in-memory struct */ @@ -950,8 +958,7 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino) #ifdef EXOFS_DEBUG_OBJ_ISIZE if ((inode->i_size != sanity) && (!exofs_inode_is_fast_symlink(inode))) { - EXOFS_ERR("WARNING: Size of object from inode and " - "attributes differ (%lld != %llu)\n", + EXOFS_ERR("WARNING: Size of inode=%llu != object=%llu\n", inode->i_size, _LLU(sanity)); } #endif @@ -1061,8 +1068,8 @@ struct inode *exofs_new_inode(struct inode *dir, int mode) return ERR_PTR(-ENOMEM); oi = exofs_i(inode); + __oi_init(oi); - init_waitqueue_head(&oi->i_wq); set_obj_2bcreated(oi); sbi = sb->s_fs_info; diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 9f500dec3b59..920f0165edf3 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -257,6 +257,15 @@ static void exofs_write_super(struct super_block *sb) sb->s_dirt = 0; } +static void _exofs_print_device(const char *msg, const char *dev_path, + struct osd_dev *od, u64 pid) +{ + const struct osd_dev_info *odi = osduld_device_info(od); + + printk(KERN_NOTICE "exofs: %s %s osd_name-%s pid-0x%llx\n", + msg, dev_path ?: "", odi->osdname, _LLU(pid)); +} + /* * This function is called when the vfs is freeing the superblock. We just * need to free our own part. @@ -279,6 +288,7 @@ static void exofs_put_super(struct super_block *sb) msecs_to_jiffies(100)); } + _exofs_print_device("Unmounting", NULL, sbi->s_dev, sbi->s_pid); osduld_put_device(sbi->s_dev); kfree(sb->s_fs_info); sb->s_fs_info = NULL; @@ -395,6 +405,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) goto free_sbi; } + _exofs_print_device("Mounting", opts->dev_name, sbi->s_dev, sbi->s_pid); ret = 0; out: if (or) diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h index 02bd9f716357..3ec346e15dda 100644 --- a/include/scsi/osd_initiator.h +++ b/include/scsi/osd_initiator.h @@ -48,7 +48,6 @@ enum osd_std_version { */ struct osd_dev { struct scsi_device *scsi_device; - struct file *file; unsigned def_timeout; #ifdef OSD_VER1_SUPPORT @@ -56,10 +55,24 @@ struct osd_dev { #endif }; -/* Retrieve/return osd_dev(s) for use by Kernel clients */ -struct osd_dev *osduld_path_lookup(const char *dev_name); /*Use IS_ERR/ERR_PTR*/ +/* Unique Identification of an OSD device */ +struct osd_dev_info { + unsigned systemid_len; + u8 systemid[OSD_SYSTEMID_LEN]; + unsigned osdname_len; + u8 *osdname; +}; + +/* Retrieve/return osd_dev(s) for use by Kernel clients + * Use IS_ERR/ERR_PTR on returned "osd_dev *". + */ +struct osd_dev *osduld_path_lookup(const char *dev_name); +struct osd_dev *osduld_info_lookup(const struct osd_dev_info *odi); void osduld_put_device(struct osd_dev *od); +const struct osd_dev_info *osduld_device_info(struct osd_dev *od); +bool osduld_device_same(struct osd_dev *od, const struct osd_dev_info *odi); + /* Add/remove test ioctls from external modules */ typedef int (do_test_fn)(struct osd_dev *od, unsigned cmd, unsigned long arg); int osduld_register_test(unsigned ioctl, do_test_fn *do_test); @@ -69,8 +82,24 @@ void osduld_unregister_test(unsigned ioctl); void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device); void osd_dev_fini(struct osd_dev *od); -/* some hi level device operations */ -int osd_auto_detect_ver(struct osd_dev *od, void *caps); /* GFP_KERNEL */ +/** + * osd_auto_detect_ver - Detect the OSD version, return Unique Identification + * + * @od: OSD target lun handle + * @caps: Capabilities authorizing OSD root read attributes access + * @odi: Retrieved information uniquely identifying the osd target lun + * Note: odi->osdname must be kfreed by caller. + * + * Auto detects the OSD version of the OSD target and sets the @od + * accordingly. Meanwhile also returns the "system id" and "osd name" root + * attributes which uniquely identify the OSD target. This member is usually + * called by the ULD. ULD users should call osduld_device_info(). + * This rutine allocates osd requests and memory at GFP_KERNEL level and might + * sleep. + */ +int osd_auto_detect_ver(struct osd_dev *od, + void *caps, struct osd_dev_info *odi); + static inline struct request_queue *osd_request_queue(struct osd_dev *od) { return od->scsi_device->request_queue; @@ -84,6 +113,15 @@ static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v) #endif } +static inline bool osd_dev_is_ver1(struct osd_dev *od) +{ +#ifdef OSD_VER1_SUPPORT + return od->version == OSD_VER1; +#else + return false; +#endif +} + struct osd_request; typedef void (osd_req_done_fn)(struct osd_request *or, void *private); @@ -120,14 +158,9 @@ struct osd_request { int async_error; }; -/* OSD Version control */ static inline bool osd_req_is_ver1(struct osd_request *or) { -#ifdef OSD_VER1_SUPPORT - return or->osd_dev->version == OSD_VER1; -#else - return false; -#endif + return osd_dev_is_ver1(or->osd_dev); } /* diff --git a/include/scsi/osd_sense.h b/include/scsi/osd_sense.h index ff9b33c773c7..91db543a5502 100644 --- a/include/scsi/osd_sense.h +++ b/include/scsi/osd_sense.h @@ -255,6 +255,9 @@ enum osdv2_cdb_field_offset { OSD_CFO_STARTING_BYTE = OSD_CDB_OFFSET(v2.start_address), OSD_CFO_PARTITION_ID = OSD_CDB_OFFSET(partition), OSD_CFO_OBJECT_ID = OSD_CDB_OFFSET(object), + OSD_CFO_PERMISSIONS = sizeof(struct osd_cdb_head) + + offsetof(struct osd_capability_head, + permissions_bit_mask), }; #endif /* ndef __OSD_SENSE_H__ */ |