mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 11:46:19 +00:00
[SCSI] osd_uld: API for retrieving osd devices from Kernel
Kernel clients like exofs can retrieve struct osd_dev(s) by means of below API. + osduld_path_lookup() - given a path (e.g "/dev/osd0") locks and returns the corresponding struct osd_dev, which is then needed for subsequent libosd use. + osduld_put_device() - free up use of an osd_dev. Devices can be shared by multiple clients. The osd_uld_device's life time is governed by an embedded kref structure. The osd_uld_device holds an extra reference to both it's char-device and it's scsi_device, and will release these just before the final deallocation. There are three possible lock sources of the osd_uld_device 1. First and for most is the probe() function called by scsi-ml upon a successful login into a target. Released in release() when logout. 2. Second by user-mode file handles opened on the char-dev. 3. Third is here by Kernel users. All three locks must be removed before the osd_uld_device is freed. The MODULE has three lock sources as well: 1. scsi-ml at probe() time, removed after release(). (login/logout) 2. The user-mode file handles open/close. 3. Import symbols by client modules like exofs. TODO: This API is not enough for the pNFS-objects LD. A more versatile API will be needed. Proposed API could be: struct osd_dev *osduld_sysid_lookup(const char id[OSD_SYSTEMID_LEN]); Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
parent
95b05a7db5
commit
b799bc7da0
2 changed files with 67 additions and 0 deletions
|
@ -173,6 +173,69 @@ static const struct file_operations osd_fops = {
|
|||
.unlocked_ioctl = osd_uld_ioctl,
|
||||
};
|
||||
|
||||
struct osd_dev *osduld_path_lookup(const char *path)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct inode *inode;
|
||||
struct cdev *cdev;
|
||||
struct osd_uld_device *uninitialized_var(oud);
|
||||
int error;
|
||||
|
||||
if (!path || !*path) {
|
||||
OSD_ERR("Mount with !path || !*path\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
error = path_lookup(path, LOOKUP_FOLLOW, &nd);
|
||||
if (error) {
|
||||
OSD_ERR("path_lookup of %s faild=>%d\n", path, error);
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
inode = nd.path.dentry->d_inode;
|
||||
error = -EINVAL; /* Not the right device e.g osd_uld_device */
|
||||
if (!S_ISCHR(inode->i_mode)) {
|
||||
OSD_DEBUG("!S_ISCHR()\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
cdev = inode->i_cdev;
|
||||
if (!cdev) {
|
||||
OSD_ERR("Before mounting an OSD Based filesystem\n");
|
||||
OSD_ERR(" user-mode must open+close the %s device\n", path);
|
||||
OSD_ERR(" Example: bash: echo < %s\n", path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* The Magic wand. Is it our char-dev */
|
||||
/* TODO: Support sg devices */
|
||||
if (cdev->owner != THIS_MODULE) {
|
||||
OSD_ERR("Error mounting %s - is not an OSD device\n", path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
oud = container_of(cdev, struct osd_uld_device, cdev);
|
||||
|
||||
__uld_get(oud);
|
||||
error = 0;
|
||||
|
||||
out:
|
||||
path_put(&nd.path);
|
||||
return error ? ERR_PTR(error) : &oud->od;
|
||||
}
|
||||
EXPORT_SYMBOL(osduld_path_lookup);
|
||||
|
||||
void osduld_put_device(struct osd_dev *od)
|
||||
{
|
||||
if (od) {
|
||||
struct osd_uld_device *oud = container_of(od,
|
||||
struct osd_uld_device, od);
|
||||
|
||||
__uld_put(oud);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(osduld_put_device);
|
||||
|
||||
/*
|
||||
* Scsi Device operations
|
||||
*/
|
||||
|
|
|
@ -33,6 +33,10 @@ struct osd_dev {
|
|||
unsigned def_timeout;
|
||||
};
|
||||
|
||||
/* 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*/
|
||||
void osduld_put_device(struct osd_dev *od);
|
||||
|
||||
/* 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);
|
||||
|
|
Loading…
Reference in a new issue