Commit 8690a2a5 authored by Stephen Rothwell's avatar Stephen Rothwell

Merge commit 'osd/linux-next'

parents d5f0f0f5 fb48922b
...@@ -36,6 +36,8 @@ dnotify.txt ...@@ -36,6 +36,8 @@ dnotify.txt
- info about directory notification in Linux. - info about directory notification in Linux.
ecryptfs.txt ecryptfs.txt
- docs on eCryptfs: stacked cryptographic filesystem for Linux. - docs on eCryptfs: stacked cryptographic filesystem for Linux.
exofs.txt
- info, usage, mount options, design about EXOFS.
ext2.txt ext2.txt
- info, mount options and specifications for the Ext2 filesystem. - info, mount options and specifications for the Ext2 filesystem.
ext3.txt ext3.txt
......
...@@ -60,13 +60,13 @@ USAGE ...@@ -60,13 +60,13 @@ USAGE
mkfs.exofs --pid=65536 --format /dev/osd0 mkfs.exofs --pid=65536 --format /dev/osd0
The --format is optional if not specified no OSD_FORMAT will be 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, 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 in the available space of the target. (Use --format=size_in_meg to limit
the total LUN space available) the total LUN space available)
If pid already exist it will be deleted and a new one will be created in it's If pid already exists, it will be deleted and a new one will be created in
place. Be careful. its place. Be careful.
An exofs lives inside a single OSD partition. You can create multiple exofs An exofs lives inside a single OSD partition. You can create multiple exofs
filesystems on the same device using multiple pids. filesystems on the same device using multiple pids.
...@@ -81,7 +81,7 @@ USAGE ...@@ -81,7 +81,7 @@ USAGE
7. For reference (See do-exofs example script): 7. For reference (See do-exofs example script):
do-exofs start - an example of how to perform the above steps. 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. do-exofs format - an example of how to format and mkfs a new exofs.
8. Extra compilation flags (uncomment in fs/exofs/Kbuild): 8. Extra compilation flags (uncomment in fs/exofs/Kbuild):
...@@ -104,8 +104,8 @@ Where: ...@@ -104,8 +104,8 @@ Where:
exofs specific options: Options are separated by commas (,) exofs specific options: Options are separated by commas (,)
pid=<integer> - The partition number to mount/create as pid=<integer> - The partition number to mount/create as
container of the filesystem. container of the filesystem.
This option is mandatory This option is mandatory.
to=<integer> - Timeout in ticks for a single command to=<integer> - Timeout in ticks for a single command.
default is (60 * HZ) [for debugging only] default is (60 * HZ) [for debugging only]
=============================================================================== ===============================================================================
...@@ -116,7 +116,7 @@ DESIGN ...@@ -116,7 +116,7 @@ DESIGN
with a special ID (defined in common.h). with a special ID (defined in common.h).
Information included in the file system control block is used to fill the 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 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 file system's magic number
- The next inode number to be allocated - The next inode number to be allocated
...@@ -134,8 +134,8 @@ DESIGN ...@@ -134,8 +134,8 @@ DESIGN
attributes. This applies to both regular files and other types (directories, attributes. This applies to both regular files and other types (directories,
device files, symlinks, etc.). device files, symlinks, etc.).
* Credentials are generated per object (inode and superblock) when they is * Credentials are generated per object (inode and superblock) when they are
created in memory (read off disk or created). The credential works for all 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. operations and is used as long as the object remains in memory.
* Async OSD operations are used whenever possible, but the target may execute * Async OSD operations are used whenever possible, but the target may execute
...@@ -145,7 +145,8 @@ DESIGN ...@@ -145,7 +145,8 @@ DESIGN
from executing in reverse order: from executing in reverse order:
- The following are handled with the OBJ_CREATED and OBJ_2BCREATED - 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 - 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 OBJ_2BCREATED is set in the beginning of the create function, so we
know that we should wait. know that we should wait.
- create/delete: delete should wait until the object is created - create/delete: delete should wait until the object is created
......
...@@ -73,7 +73,8 @@ static const char *_osd_ver_desc(struct osd_request *or) ...@@ -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) #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_request *or;
struct osd_attr get_attrs[] = { struct osd_attr get_attrs[] = {
...@@ -137,8 +138,13 @@ static int _osd_print_system_info(struct osd_dev *od, void *caps) ...@@ -137,8 +138,13 @@ static int _osd_print_system_info(struct osd_dev *od, void *caps)
OSD_INFO("PRODUCT_SERIAL_NUMBER [%s]\n", OSD_INFO("PRODUCT_SERIAL_NUMBER [%s]\n",
(char *)pFirst); (char *)pFirst);
pFirst = get_attrs[a].val_ptr; odi->osdname_len = get_attrs[a].len;
OSD_INFO("OSD_NAME [%s]\n", (char *)pFirst); if (odi->osdname_len) {
odi->osdname = kzalloc(odi->osdname_len + 1, GFP_KERNEL);
memcpy(odi->osdname, get_attrs[a].val_ptr, odi->osdname_len);
} else
odi->osdname = NULL;
OSD_INFO("OSD_NAME [%s]\n", odi->osdname);
a++; a++;
pFirst = get_attrs[a++].val_ptr; pFirst = get_attrs[a++].val_ptr;
...@@ -171,6 +177,9 @@ static int _osd_print_system_info(struct osd_dev *od, void *caps) ...@@ -171,6 +177,9 @@ static int _osd_print_system_info(struct osd_dev *od, void *caps)
sid_dump, sizeof(sid_dump), true); sid_dump, sizeof(sid_dump), true);
OSD_INFO("OSD_SYSTEM_ID(%d)\n" OSD_INFO("OSD_SYSTEM_ID(%d)\n"
" [%s]\n", len, sid_dump); " [%s]\n", len, sid_dump);
odi->systemid_len = len;
memcpy(odi->systemid, get_attrs[a].val_ptr, len);
a++; a++;
} }
out: out:
...@@ -178,16 +187,17 @@ out: ...@@ -178,16 +187,17 @@ out:
return ret; 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; int ret;
/* Auto-detect the osd version */ /* Auto-detect the osd version */
ret = _osd_print_system_info(od, caps); ret = _osd_get_print_system_info(od, caps, odi);
if (ret) { if (ret) {
osd_dev_set_ver(od, OSD_VER1); osd_dev_set_ver(od, OSD_VER1);
OSD_DEBUG("converting to OSD1\n"); OSD_DEBUG("converting to OSD1\n");
ret = _osd_print_system_info(od, caps); ret = _osd_get_print_system_info(od, caps, odi);
} }
return ret; return ret;
......
...@@ -87,6 +87,7 @@ struct osd_uld_device { ...@@ -87,6 +87,7 @@ struct osd_uld_device {
struct osd_dev od; struct osd_dev od;
struct gendisk *disk; struct gendisk *disk;
struct device *class_member; struct device *class_member;
struct osd_dev_info odi;
}; };
static void __uld_get(struct osd_uld_device *oud); static void __uld_get(struct osd_uld_device *oud);
...@@ -216,6 +217,48 @@ free_od: ...@@ -216,6 +217,48 @@ free_od:
} }
EXPORT_SYMBOL(osduld_path_lookup); EXPORT_SYMBOL(osduld_path_lookup);
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 osd_dev *osduld_info_lookup(const struct osd_dev_info *odi)
{
unsigned i;
for (i = 0; i < SCSI_OSD_MAX_MINOR; i++) {
char dev_str[16];
struct osd_uld_device *oud;
struct osd_dev *od;
sprintf(dev_str, "/dev/osd%d", i);
od = osduld_path_lookup(dev_str);
if (IS_ERR(od))
continue;
oud = od->file->private_data;
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);
return od;
}
osduld_put_device(od);
}
return ERR_PTR(-ENODEV);
}
EXPORT_SYMBOL(osduld_info_lookup);
void osduld_put_device(struct osd_dev *od) void osduld_put_device(struct osd_dev *od)
{ {
...@@ -230,6 +273,13 @@ void osduld_put_device(struct osd_dev *od) ...@@ -230,6 +273,13 @@ void osduld_put_device(struct osd_dev *od)
} }
EXPORT_SYMBOL(osduld_put_device); EXPORT_SYMBOL(osduld_put_device);
const struct osd_dev_info *osduld_device_info(struct osd_dev *od)
{
struct osd_uld_device *oud = od->file->private_data;
return &oud->odi;
}
EXPORT_SYMBOL(osduld_device_info);
/* /*
* Scsi Device operations * Scsi Device operations
*/ */
...@@ -250,7 +300,7 @@ static int __detect_osd(struct osd_uld_device *oud) ...@@ -250,7 +300,7 @@ static int __detect_osd(struct osd_uld_device *oud)
OSD_ERR("warning: scsi_test_unit_ready failed\n"); OSD_ERR("warning: scsi_test_unit_ready failed\n");
osd_sec_init_nosec_doall_caps(caps, &osd_root_object, false, true); 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 -ENODEV;
return 0; return 0;
...@@ -402,6 +452,7 @@ static void __remove(struct kref *kref) ...@@ -402,6 +452,7 @@ static void __remove(struct kref *kref)
put_disk(oud->disk); put_disk(oud->disk);
ida_remove(&osd_minor_ida, oud->minor); ida_remove(&osd_minor_ida, oud->minor);
kfree(oud->odi.osdname);
kfree(oud); kfree(oud);
} }
......
...@@ -906,6 +906,12 @@ out: ...@@ -906,6 +906,12 @@ out:
return ret; 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 * Fill in an inode read from the OSD and set it up for use
*/ */
...@@ -923,13 +929,13 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino) ...@@ -923,13 +929,13 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino)
if (!(inode->i_state & I_NEW)) if (!(inode->i_state & I_NEW))
return inode; return inode;
oi = exofs_i(inode); oi = exofs_i(inode);
__oi_init(oi);
/* read the inode from the osd */ /* read the inode from the osd */
ret = exofs_get_inode(sb, oi, &fcb, &sanity); ret = exofs_get_inode(sb, oi, &fcb, &sanity);
if (ret) if (ret)
goto bad_inode; goto bad_inode;
init_waitqueue_head(&oi->i_wq);
set_obj_created(oi); set_obj_created(oi);
/* copy stuff from on-disk struct to in-memory struct */ /* copy stuff from on-disk struct to in-memory struct */
...@@ -950,8 +956,7 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino) ...@@ -950,8 +956,7 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino)
#ifdef EXOFS_DEBUG_OBJ_ISIZE #ifdef EXOFS_DEBUG_OBJ_ISIZE
if ((inode->i_size != sanity) && if ((inode->i_size != sanity) &&
(!exofs_inode_is_fast_symlink(inode))) { (!exofs_inode_is_fast_symlink(inode))) {
EXOFS_ERR("WARNING: Size of object from inode and " EXOFS_ERR("WARNING: Size of inode=%llu != object=%llu\n",
"attributes differ (%lld != %llu)\n",
inode->i_size, _LLU(sanity)); inode->i_size, _LLU(sanity));
} }
#endif #endif
...@@ -1061,8 +1066,8 @@ struct inode *exofs_new_inode(struct inode *dir, int mode) ...@@ -1061,8 +1066,8 @@ struct inode *exofs_new_inode(struct inode *dir, int mode)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
oi = exofs_i(inode); oi = exofs_i(inode);
__oi_init(oi);
init_waitqueue_head(&oi->i_wq);
set_obj_2bcreated(oi); set_obj_2bcreated(oi);
sbi = sb->s_fs_info; sbi = sb->s_fs_info;
......
...@@ -214,7 +214,6 @@ int exofs_sync_fs(struct super_block *sb, int wait) ...@@ -214,7 +214,6 @@ int exofs_sync_fs(struct super_block *sb, int wait)
} }
lock_super(sb); lock_super(sb);
lock_kernel();
sbi = sb->s_fs_info; sbi = sb->s_fs_info;
fscb->s_nextid = cpu_to_le64(sbi->s_nextid); fscb->s_nextid = cpu_to_le64(sbi->s_nextid);
fscb->s_numfiles = cpu_to_le32(sbi->s_numfiles); fscb->s_numfiles = cpu_to_le32(sbi->s_numfiles);
...@@ -245,7 +244,6 @@ int exofs_sync_fs(struct super_block *sb, int wait) ...@@ -245,7 +244,6 @@ int exofs_sync_fs(struct super_block *sb, int wait)
out: out:
if (or) if (or)
osd_end_request(or); osd_end_request(or);
unlock_kernel();
unlock_super(sb); unlock_super(sb);
kfree(fscb); kfree(fscb);
return ret; return ret;
...@@ -259,6 +257,15 @@ static void exofs_write_super(struct super_block *sb) ...@@ -259,6 +257,15 @@ static void exofs_write_super(struct super_block *sb)
sb->s_dirt = 0; 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 * This function is called when the vfs is freeing the superblock. We just
* need to free our own part. * need to free our own part.
...@@ -268,8 +275,6 @@ static void exofs_put_super(struct super_block *sb) ...@@ -268,8 +275,6 @@ static void exofs_put_super(struct super_block *sb)
int num_pend; int num_pend;
struct exofs_sb_info *sbi = sb->s_fs_info; struct exofs_sb_info *sbi = sb->s_fs_info;
lock_kernel();
if (sb->s_dirt) if (sb->s_dirt)
exofs_write_super(sb); exofs_write_super(sb);
...@@ -283,11 +288,10 @@ static void exofs_put_super(struct super_block *sb) ...@@ -283,11 +288,10 @@ static void exofs_put_super(struct super_block *sb)
msecs_to_jiffies(100)); msecs_to_jiffies(100));
} }
_exofs_print_device("Unmounting", NULL, sbi->s_dev, sbi->s_pid);
osduld_put_device(sbi->s_dev); osduld_put_device(sbi->s_dev);
kfree(sb->s_fs_info); kfree(sb->s_fs_info);
sb->s_fs_info = NULL; sb->s_fs_info = NULL;
unlock_kernel();
} }
/* /*
...@@ -401,6 +405,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -401,6 +405,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
goto free_sbi; goto free_sbi;
} }
_exofs_print_device("Mounting", opts->dev_name, sbi->s_dev, sbi->s_pid);
ret = 0; ret = 0;
out: out:
if (or) if (or)
......
...@@ -56,10 +56,23 @@ struct osd_dev { ...@@ -56,10 +56,23 @@ struct osd_dev {
#endif #endif
}; };
/* Retrieve/return osd_dev(s) for use by Kernel clients */ /* Unique Identification of an OSD device */
struct osd_dev *osduld_path_lookup(const char *dev_name); /*Use IS_ERR/ERR_PTR*/ 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); void osduld_put_device(struct osd_dev *od);
const struct osd_dev_info *osduld_device_info(struct osd_dev *od);
/* Add/remove test ioctls from external modules */ /* Add/remove test ioctls from external modules */
typedef int (do_test_fn)(struct osd_dev *od, unsigned cmd, unsigned long arg); 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); int osduld_register_test(unsigned ioctl, do_test_fn *do_test);
...@@ -69,8 +82,24 @@ void osduld_unregister_test(unsigned ioctl); ...@@ -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_init(struct osd_dev *od, struct scsi_device *scsi_device);
void osd_dev_fini(struct osd_dev *od); 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) static inline struct request_queue *osd_request_queue(struct osd_dev *od)
{ {
return od->scsi_device->request_queue; 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) ...@@ -84,6 +113,15 @@ static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v)
#endif #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; struct osd_request;
typedef void (osd_req_done_fn)(struct osd_request *or, void *private); typedef void (osd_req_done_fn)(struct osd_request *or, void *private);
...@@ -120,14 +158,9 @@ struct osd_request { ...@@ -120,14 +158,9 @@ struct osd_request {
int async_error; int async_error;
}; };
/* OSD Version control */
static inline bool osd_req_is_ver1(struct osd_request *or) static inline bool osd_req_is_ver1(struct osd_request *or)
{ {
#ifdef OSD_VER1_SUPPORT return osd_dev_is_ver1(or->osd_dev);
return or->osd_dev->version == OSD_VER1;
#else
return false;
#endif
} }
/* /*
......
...@@ -255,6 +255,9 @@ enum osdv2_cdb_field_offset { ...@@ -255,6 +255,9 @@ enum osdv2_cdb_field_offset {
OSD_CFO_STARTING_BYTE = OSD_CDB_OFFSET(v2.start_address), OSD_CFO_STARTING_BYTE = OSD_CDB_OFFSET(v2.start_address),
OSD_CFO_PARTITION_ID = OSD_CDB_OFFSET(partition), OSD_CFO_PARTITION_ID = OSD_CDB_OFFSET(partition),
OSD_CFO_OBJECT_ID = OSD_CDB_OFFSET(object), 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__ */ #endif /* ndef __OSD_SENSE_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment