diff options
| author | Boaz Harrosh <bharrosh@panasas.com> | 2009-01-25 09:58:03 -0500 |
|---|---|---|
| committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-03-12 13:58:07 -0400 |
| commit | b799bc7da0ce5ba4a988c521a8fb10452eb419f0 (patch) | |
| tree | 47f1c70c15419a6da81cb718329326f4c1a7e246 | |
| parent | 95b05a7db5865855c32e0bb8b244c3a7aac1cfeb (diff) | |
[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>
| -rw-r--r-- | drivers/scsi/osd/osd_uld.c | 63 | ||||
| -rw-r--r-- | include/scsi/osd_initiator.h | 4 |
2 files changed, 67 insertions, 0 deletions
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c index f6f9a99adaa6..cd4ca7cd9f75 100644 --- a/drivers/scsi/osd/osd_uld.c +++ b/drivers/scsi/osd/osd_uld.c | |||
| @@ -173,6 +173,69 @@ static const struct file_operations osd_fops = { | |||
| 173 | .unlocked_ioctl = osd_uld_ioctl, | 173 | .unlocked_ioctl = osd_uld_ioctl, |
| 174 | }; | 174 | }; |
| 175 | 175 | ||
| 176 | struct osd_dev *osduld_path_lookup(const char *path) | ||
| 177 | { | ||
| 178 | struct nameidata nd; | ||
| 179 | struct inode *inode; | ||
| 180 | struct cdev *cdev; | ||
| 181 | struct osd_uld_device *uninitialized_var(oud); | ||
| 182 | int error; | ||
| 183 | |||
| 184 | if (!path || !*path) { | ||
| 185 | OSD_ERR("Mount with !path || !*path\n"); | ||
| 186 | return ERR_PTR(-EINVAL); | ||
| 187 | } | ||
| 188 | |||
| 189 | error = path_lookup(path, LOOKUP_FOLLOW, &nd); | ||
| 190 | if (error) { | ||
| 191 | OSD_ERR("path_lookup of %s faild=>%d\n", path, error); | ||
| 192 | return ERR_PTR(error); | ||
| 193 | } | ||
| 194 | |||
| 195 | inode = nd.path.dentry->d_inode; | ||
| 196 | error = -EINVAL; /* Not the right device e.g osd_uld_device */ | ||
| 197 | if (!S_ISCHR(inode->i_mode)) { | ||
| 198 | OSD_DEBUG("!S_ISCHR()\n"); | ||
| 199 | goto out; | ||
| 200 | } | ||
| 201 | |||
| 202 | cdev = inode->i_cdev; | ||
| 203 | if (!cdev) { | ||
| 204 | OSD_ERR("Before mounting an OSD Based filesystem\n"); | ||
| 205 | OSD_ERR(" user-mode must open+close the %s device\n", path); | ||
| 206 | OSD_ERR(" Example: bash: echo < %s\n", path); | ||
| 207 | goto out; | ||
| 208 | } | ||
| 209 | |||
| 210 | /* The Magic wand. Is it our char-dev */ | ||
| 211 | /* TODO: Support sg devices */ | ||
| 212 | if (cdev->owner != THIS_MODULE) { | ||
| 213 | OSD_ERR("Error mounting %s - is not an OSD device\n", path); | ||
| 214 | goto out; | ||
| 215 | } | ||
| 216 | |||
| 217 | oud = container_of(cdev, struct osd_uld_device, cdev); | ||
| 218 | |||
| 219 | __uld_get(oud); | ||
| 220 | error = 0; | ||
| 221 | |||
| 222 | out: | ||
| 223 | path_put(&nd.path); | ||
| 224 | return error ? ERR_PTR(error) : &oud->od; | ||
| 225 | } | ||
| 226 | EXPORT_SYMBOL(osduld_path_lookup); | ||
| 227 | |||
| 228 | void osduld_put_device(struct osd_dev *od) | ||
| 229 | { | ||
| 230 | if (od) { | ||
| 231 | struct osd_uld_device *oud = container_of(od, | ||
| 232 | struct osd_uld_device, od); | ||
| 233 | |||
| 234 | __uld_put(oud); | ||
| 235 | } | ||
| 236 | } | ||
| 237 | EXPORT_SYMBOL(osduld_put_device); | ||
| 238 | |||
| 176 | /* | 239 | /* |
| 177 | * Scsi Device operations | 240 | * Scsi Device operations |
| 178 | */ | 241 | */ |
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h index a5dbbddcf73b..e84dc7aa5e34 100644 --- a/include/scsi/osd_initiator.h +++ b/include/scsi/osd_initiator.h | |||
| @@ -33,6 +33,10 @@ struct osd_dev { | |||
| 33 | unsigned def_timeout; | 33 | unsigned def_timeout; |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | /* Retrieve/return osd_dev(s) for use by Kernel clients */ | ||
| 37 | struct osd_dev *osduld_path_lookup(const char *dev_name); /*Use IS_ERR/ERR_PTR*/ | ||
| 38 | void osduld_put_device(struct osd_dev *od); | ||
| 39 | |||
| 36 | /* Add/remove test ioctls from external modules */ | 40 | /* Add/remove test ioctls from external modules */ |
| 37 | typedef int (do_test_fn)(struct osd_dev *od, unsigned cmd, unsigned long arg); | 41 | typedef int (do_test_fn)(struct osd_dev *od, unsigned cmd, unsigned long arg); |
| 38 | int osduld_register_test(unsigned ioctl, do_test_fn *do_test); | 42 | int osduld_register_test(unsigned ioctl, do_test_fn *do_test); |
