diff options
author | Boaz Harrosh <bharrosh@panasas.com> | 2009-05-24 13:05:05 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-06-10 10:00:25 -0400 |
commit | 021e2230d6c04d80289fceb2d21c9ce93a615b32 (patch) | |
tree | f8a4eeb7be9aa2ea65bf343680893e30d02ead92 /drivers | |
parent | fc2fac5b5f11e2bee3bf37215c8746236f5ea188 (diff) |
[SCSI] osduld: use filp_open() when looking up an osd-device
This patch was inspired by Al Viro, for simplifying and fixing the
retrieval of osd-devices by in-kernel users, eg: file systems.
In-Kernel users, now, go through the same path user-mode does by
opening a file on the osd char-device and though holding a reference
to both the device and the Module.
A file pointer was added to the osd_dev structure which is now
allocated for each user. The internal osd_dev is no longer exposed
outside of the uld. I wanted to do that for a long time so each
libosd user can have his own defaults on the device.
The API is left the same, so user code need not change.
It is no longer needed to open/close a file handle on the osd
char-device from user-mode, before mounting an exofs on it.
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
CC: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/osd/osd_uld.c | 66 |
1 files changed, 30 insertions, 36 deletions
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c index 22b59e13ba83..0bdef3390902 100644 --- a/drivers/scsi/osd/osd_uld.c +++ b/drivers/scsi/osd/osd_uld.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/device.h> | 49 | #include <linux/device.h> |
50 | #include <linux/idr.h> | 50 | #include <linux/idr.h> |
51 | #include <linux/major.h> | 51 | #include <linux/major.h> |
52 | #include <linux/file.h> | ||
52 | 53 | ||
53 | #include <scsi/scsi.h> | 54 | #include <scsi/scsi.h> |
54 | #include <scsi/scsi_driver.h> | 55 | #include <scsi/scsi_driver.h> |
@@ -175,10 +176,9 @@ static const struct file_operations osd_fops = { | |||
175 | 176 | ||
176 | struct osd_dev *osduld_path_lookup(const char *name) | 177 | struct osd_dev *osduld_path_lookup(const char *name) |
177 | { | 178 | { |
178 | struct path path; | 179 | struct osd_uld_device *oud; |
179 | struct inode *inode; | 180 | struct osd_dev *od; |
180 | struct cdev *cdev; | 181 | struct file *file; |
181 | struct osd_uld_device *uninitialized_var(oud); | ||
182 | int error; | 182 | int error; |
183 | 183 | ||
184 | if (!name || !*name) { | 184 | if (!name || !*name) { |
@@ -186,52 +186,46 @@ struct osd_dev *osduld_path_lookup(const char *name) | |||
186 | return ERR_PTR(-EINVAL); | 186 | return ERR_PTR(-EINVAL); |
187 | } | 187 | } |
188 | 188 | ||
189 | error = kern_path(name, LOOKUP_FOLLOW, &path); | 189 | od = kzalloc(sizeof(*od), GFP_KERNEL); |
190 | if (error) { | 190 | if (!od) |
191 | OSD_ERR("path_lookup of %s failed=>%d\n", name, error); | 191 | return ERR_PTR(-ENOMEM); |
192 | return ERR_PTR(error); | ||
193 | } | ||
194 | 192 | ||
195 | inode = path.dentry->d_inode; | 193 | file = filp_open(name, O_RDWR, 0); |
196 | error = -EINVAL; /* Not the right device e.g osd_uld_device */ | 194 | if (IS_ERR(file)) { |
197 | if (!S_ISCHR(inode->i_mode)) { | 195 | error = PTR_ERR(file); |
198 | OSD_DEBUG("!S_ISCHR()\n"); | 196 | goto free_od; |
199 | goto out; | ||
200 | } | 197 | } |
201 | 198 | ||
202 | cdev = inode->i_cdev; | 199 | if (file->f_op != &osd_fops){ |
203 | if (!cdev) { | 200 | error = -EINVAL; |
204 | OSD_ERR("Before mounting an OSD Based filesystem\n"); | 201 | goto close_file; |
205 | OSD_ERR(" user-mode must open+close the %s device\n", name); | ||
206 | OSD_ERR(" Example: bash: echo < %s\n", name); | ||
207 | goto out; | ||
208 | } | 202 | } |
209 | 203 | ||
210 | /* The Magic wand. Is it our char-dev */ | 204 | oud = file->private_data; |
211 | /* TODO: Support sg devices */ | ||
212 | if (cdev->owner != THIS_MODULE) { | ||
213 | OSD_ERR("Error mounting %s - is not an OSD device\n", name); | ||
214 | goto out; | ||
215 | } | ||
216 | 205 | ||
217 | oud = container_of(cdev, struct osd_uld_device, cdev); | 206 | *od = oud->od; |
207 | od->file = file; | ||
218 | 208 | ||
219 | __uld_get(oud); | 209 | return od; |
220 | error = 0; | ||
221 | 210 | ||
222 | out: | 211 | close_file: |
223 | path_put(&path); | 212 | fput(file); |
224 | return error ? ERR_PTR(error) : &oud->od; | 213 | free_od: |
214 | kfree(od); | ||
215 | return ERR_PTR(error); | ||
225 | } | 216 | } |
226 | EXPORT_SYMBOL(osduld_path_lookup); | 217 | EXPORT_SYMBOL(osduld_path_lookup); |
227 | 218 | ||
228 | void osduld_put_device(struct osd_dev *od) | 219 | void osduld_put_device(struct osd_dev *od) |
229 | { | 220 | { |
230 | if (od) { | ||
231 | struct osd_uld_device *oud = container_of(od, | ||
232 | struct osd_uld_device, od); | ||
233 | 221 | ||
234 | __uld_put(oud); | 222 | if (od && !IS_ERR(od)) { |
223 | struct osd_uld_device *oud = od->file->private_data; | ||
224 | |||
225 | BUG_ON(od->scsi_device != oud->od.scsi_device); | ||
226 | |||
227 | fput(od->file); | ||
228 | kfree(od); | ||
235 | } | 229 | } |
236 | } | 230 | } |
237 | EXPORT_SYMBOL(osduld_put_device); | 231 | EXPORT_SYMBOL(osduld_put_device); |