/[linux-patches]/genpatches-2.6/historical/2.6.2/401_supermount-2.0.4-2.6.2_rc1.patch
Gentoo

Contents of /genpatches-2.6/historical/2.6.2/401_supermount-2.0.4-2.6.2_rc1.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download) (as text)
Sat Jun 11 23:16:54 2005 UTC (15 years ago) by dsd
File MIME type: text/x-diff
File size: 173911 byte(s)
Import historical releases
1 diff -ruN linux-2.6.2-rc1.old/Documentation/filesystems/00-INDEX linux-2.6.2-rc1/Documentation/filesystems/00-INDEX
2 --- linux-2.6.2-rc1.old/Documentation/filesystems/00-INDEX 2004-01-24 10:55:27.000000000 -0500
3 +++ linux-2.6.2-rc1/Documentation/filesystems/00-INDEX 2004-01-24 11:46:38.893348304 -0500
4 @@ -36,6 +36,8 @@
5 - Description of the ROMFS filesystem.
6 smbfs.txt
7 - info on using filesystems with the SMB protocol (Windows 3.11 and NT)
8 +supermount.txt
9 + - info on using supermount for removable media.
10 sysv-fs.txt
11 - info on the SystemV/V7/Xenix/Coherent filesystem.
12 udf.txt
13 diff -ruN linux-2.6.2-rc1.old/Documentation/filesystems/supermount.txt linux-2.6.2-rc1/Documentation/filesystems/supermount.txt
14 --- linux-2.6.2-rc1.old/Documentation/filesystems/supermount.txt 1969-12-31 19:00:00.000000000 -0500
15 +++ linux-2.6.2-rc1/Documentation/filesystems/supermount.txt 2004-01-24 11:46:38.887349216 -0500
16 @@ -0,0 +1,250 @@
17 +Supermount README
18 +=================
19 +
20 +Running supermount
21 +------------------
22 +
23 +To run supermount, compile and install a kernel with the supermount
24 +patches and select "Y" to the question
25 +
26 + Supermount removable media support (CONFIG_SUPERMOUNT) [Y/n/?]
27 +
28 +when you run "make config". You mount a supermount filesystem with
29 +the normal mount command, using the syntax
30 +
31 + mount -t supermount -o <superfs-options>,--,<subfs-options> none <mpt>
32 +
33 +or by adding correpsonding line to /etc/fstab
34 +
35 + none <mpt> supermount <superfs-options>,--,<subfs-options> 0 0
36 +
37 +where
38 +
39 + <superfs-options> are the options you want to pass to supermount
40 + itself. These are described below.
41 +
42 + <subfs-options> are the options you want supermount to pass to the
43 + dismountable filesystem underneath.
44 +
45 + <mpt> is the mount point where you want your removable media to be
46 + mounted.
47 +
48 +WARNING: in the above description `none' is literal word. While device
49 +is ignored by supermount itself, using real files in this place (real
50 +device name or mount point directory name) is known to cause problems.
51 +Some programs - fuser is one of them - will try to descend into filesystem
52 +if dev can be statted, thus making supermount to attempt to access media.
53 +This is annoying at best - in the worst case it can take very long time
54 +during startup or shutdown.
55 +
56 +Notice that you do not directly specify the block device you are going
57 +to mount on the mount command line. This is because the supermount
58 +filesystem is NOT connected to a block device; rather, supermount is
59 +responsible for connecting a separate filesystem to the block device.
60 +You specify the sub-filesystem and block device name by providing the
61 +<superfs-options> field, where the following options are currently
62 +recognised:
63 +
64 +
65 +* fs=<filesystem-type> [default is "auto"]
66 +
67 + Specify the subfilesystem type. Not every filesystem type has
68 +been tested. If you use `auto', it will try the following filesystems
69 +in order:
70 + "udf"
71 + "iso9660"
72 + "ext2"
73 + "vfat"
74 + "msdos"
75 +
76 +It is also possible to give list of types separated by `:', like
77 +
78 + fs=ext2:vfat
79 + - or -
80 + fs=udf:iso9660
81 +
82 +
83 +* dev=<block-device> [no default, mandatory]
84 +
85 + Specify the block device on which the subfs is to be mounted.
86 +
87 +
88 +* tray_lock={always,onwrite,never} [default is "onwrite"]
89 +
90 + Specify when supermount is to prevent media removal. `always' means
91 +on every access (it was default in earlier versions), `onwrite' means only
92 +for write access and `never' means never :) `onwrite' and `never' are the
93 +same for ro media like CD-ROM. It is not clear when `never' is actually useful,
94 +it is presented for completeness only.
95 +
96 +* debug[=<bitmap>] [default is no debug]
97 +
98 + Enable debugging code in the supermount filesystem, if
99 +the debug option was enabled at compile time. By default, debugging
100 +code is compiled into the kernel but is disabled until a debug mount
101 +option is seen. <bitmap> is the combination of debug flags, following
102 +flags are possible:
103 +
104 + 0x001 - "generic" debug (used by supermount_debug) - default
105 + 0x002 - trace dentry.c
106 + 0x004 - trace file.c
107 + 0x008 - trace filemap.c
108 + 0x010 - trace mediactl.c
109 + 0x020 - trace namei.c
110 + 0x040 - trace subfs.c
111 + 0x080 - trace super.c
112 +
113 +Trace flags turn on tracing of functions in correpsonding files.
114 +"Generic" debug flag is tested in supermount_debug; for compatibility,
115 +if no flags are specified, this flag is set.
116 +
117 +
118 +* '--'
119 +
120 + All options after the option string '--' will be passed
121 +directly to the subfilesystem when it gets mounted.
122 +
123 +Errors
124 +------
125 +
126 +In addition to "normal" errors during file operations supermount may
127 +return following error codes:
128 +
129 +* No medium found
130 +
131 + You attempt to access supermounted filesystem when there is no
132 +medium inserted
133 +
134 +* Wrong medium type
135 +
136 + (Not really generated by supermount) You attempt to mount CD
137 +without data tracks
138 +
139 +* Stale NFS file handle
140 +
141 + You attempt to use file handle after medium has been changed.
142 +
143 +* No such device or address
144 +
145 + (Not really generated by supermount) device specified in
146 +dev=<device> option does not exist. Also some drivers return this
147 +error instead of "No medium found", one example being floppy driver.
148 +
149 +* Device or resource busy
150 +
151 + (Not really generated by supermount) device is already mounted.
152 +Supermount prevents double mount even if kernel otherwise would make it
153 +possible.
154 +
155 +* No such file or directory
156 +
157 + (Not really generated by supermount) file name specified by
158 +dev=<device> option does not exist
159 +
160 +* Operation not permitted
161 +
162 + You attempt to access subfs that is currently disabled
163 +
164 +/proc support
165 +-------------
166 +
167 +If kernel has been compiled with procfs support, supermount will provide
168 +/proc interface to read subfs status and to control some aspects of subfs.
169 +The following files are created under /proc/fs/supermount:
170 +
171 +* version (ro)
172 + Shows supermount version.
173 +
174 +* subfs (rw)
175 +
176 + Reading this file returns list of all subfs status. One line for
177 +every subfs is returned; the format is
178 +
179 + <devname> disabled
180 + - or -
181 + <devname> unmounted
182 + - or -
183 + <devname> mounted readcount writecount
184 +
185 +where <devname> is the string passed in `dev=' parameter during mount.
186 +`readcount' is number of current subfs "users" needing ro access; `writecount'
187 +is the number of "users" needing rw mode. It is mostly the number of open
188 +files, but inode operations also add to these counts. Those operations
189 +are normally short-lived to be seen.
190 +
191 + Writing this file changes subfs status; the following commands are
192 +suported:
193 +
194 + <devname> [disable|enable] [release [force]]
195 +
196 +`disable' will disable subfs (i.e. any futher attempt to mount is rejected).
197 +Subfs must be unmounted; use `disable release' or `disable release force' to
198 +unmount and disable at the same time.
199 +
200 +`enable' will enable disabled subfs, it has no effect if subfs is already
201 +enabled.
202 +
203 +`release' will unmount subfs unless it is busy (opencount > 0). To unmount
204 +busy subfs add `force'; the effect is very much as if media change has been
205 +detected (with the difference that subfs will be cleanly unmounted).
206 +
207 +Some basic sanity checks are performed, i.e. it is impossible to specify
208 +both `enable' and `disable' or `force' without `release'.
209 +
210 +Internals/Locking
211 +-----------------
212 +
213 +THIS SECTION IS PROBABLY INCOMPLETE. CORRECTIONS ARE WELCOME.
214 +
215 +Supermount itself is using two locks and relies on two more locking rules
216 +as implemented by kernel.
217 +
218 +* supermount_proc_sem
219 +
220 + Global mutex used to protect list of sbi during access to
221 +/proc/fs/supermount/subfs
222 +
223 +* sbi->sem
224 +
225 + Per-filesystem mutex that protects subfs state (mounted/unmounted).
226 +Any changes to subfs state (mounting, unmouting, adding or removing file,
227 +dentry or inode) happen under this mutex.
228 +
229 +* inode->i_sem (see Documentation/filesystem/Locking)
230 +
231 + Per-inode mutex used by VFS to serialize inode unlink operation.
232 +Supermount relies on the fact that link/unlink for an inode are mutually
233 +locked and thus inode->i_nlink is atomic inside of fs method.
234 +
235 +* BKL
236 +
237 + Used to protect device usage count. It is changed in open/release
238 +and referenced in ioctl all of which run under BKL. Supermount adds mediactl
239 +and internally wraps it in BKL as well.
240 +
241 +Caveats/BUGS
242 +------------
243 +
244 +Inode times are believed to be correctly updated; still it is possible that
245 +I missed some point.
246 +
247 +If subfs is not yet mounted, find /mnt/cdrom fails with "find: /mnt/cdrom
248 +changed during execution of find". It is unlikely it can be fixed in
249 +supermount; much more simple is to provide wrapper that will check if subfs
250 +is mounted and do simple "touch /mnt/cdrom" if not to make sure it is.
251 +
252 +Supermount attempts to check for changed media at every operation and
253 +invalidate and umount old subfs to avoid new media corruption in rw case.
254 +Still it is possible that kernel will write out stale information and
255 +it is outside of supermount control.
256 +
257 +By default cdrom driver does not check media type i.e. supermount will
258 +try all configured fs types in turn that may be quite time consuming.
259 +Use sysctl -w dev.cdrom.check_media=1 to enable it. Comments in cdrom.c
260 +indicate that some (non conforming) software may have problems with this
261 +settings. YMMV
262 +
263 +atime management does not work for special files. There is no hooks from
264 +VFS into fs to indicate when it gets updated
265 +
266 +$Id: 401_supermount-2.0.4-2.6.2_rc1.patch,v 1.1 2004/01/26 22:15:04 johnm Exp $
267 diff -ruN linux-2.6.2-rc1.old/drivers/cdrom/cdrom.c linux-2.6.2-rc1/drivers/cdrom/cdrom.c
268 --- linux-2.6.2-rc1.old/drivers/cdrom/cdrom.c 2004-01-24 10:55:27.000000000 -0500
269 +++ linux-2.6.2-rc1/drivers/cdrom/cdrom.c 2004-01-24 11:56:57.172355608 -0500
270 @@ -275,6 +275,7 @@
271 #include <linux/fcntl.h>
272 #include <linux/blkdev.h>
273 #include <linux/times.h>
274 +#include <linux/supermount_media.h>
275
276 #include <asm/uaccess.h>
277
278 @@ -333,7 +334,7 @@
279 #define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) return ret
280
281 /* Not-exported routines. */
282 -static int open_for_data(struct cdrom_device_info * cdi);
283 +static int open_for_data(struct cdrom_device_info * cdi, struct block_device *bdev);
284 static int check_for_audio_disc(struct cdrom_device_info * cdi,
285 struct cdrom_device_ops * cdo);
286 static void sanitize_format(union cdrom_addr *addr,
287 @@ -752,7 +753,7 @@
288 if (cdrom_open_write(cdi))
289 goto err;
290 }
291 - ret = open_for_data(cdi);
292 + ret = open_for_data(cdi, ip->i_bdev);
293 }
294
295 if (ret)
296 @@ -770,7 +771,7 @@
297 }
298
299 static
300 -int open_for_data(struct cdrom_device_info * cdi)
301 +int open_for_data(struct cdrom_device_info * cdi, struct block_device *bdev)
302 {
303 int ret;
304 struct cdrom_device_ops *cdo = cdi->ops;
305 @@ -853,7 +854,8 @@
306 cdinfo(CD_OPEN, "open device failed.\n");
307 goto clean_up_and_return;
308 }
309 - if (CDROM_CAN(CDC_LOCK) && (cdi->options & CDO_LOCK)) {
310 + if (CDROM_CAN(CDC_LOCK) && (cdi->options & CDO_LOCK) &&
311 + supermount_usage_count(bdev, cdi->use_count) > 0) {
312 cdo->lock_door(cdi, 1);
313 cdinfo(CD_OPEN, "door locked.\n");
314 }
315 @@ -866,7 +868,7 @@
316 This ensures that the drive gets unlocked after a mount fails. This
317 is a goto to avoid bloating the driver with redundant code. */
318 clean_up_and_return:
319 - cdinfo(CD_WARNING, "open failed.\n");
320 + cdinfo(CD_OPEN, "open failed.\n");
321 if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
322 cdo->lock_door(cdi, 0);
323 cdinfo(CD_OPEN, "door unlocked.\n");
324 @@ -943,7 +945,7 @@
325 cdi->use_count--;
326 if (cdi->use_count == 0)
327 cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
328 - if (cdi->use_count == 0 &&
329 + if (supermount_usage_count(fp ? fp->f_dentry->d_inode->i_bdev : 0, cdi->use_count) == 0 &&
330 (cdo->capability & CDC_LOCK) && !keeplocked) {
331 cdinfo(CD_CLOSE, "Unlocking door!\n");
332 cdo->lock_door(cdi, 0);
333 @@ -1215,6 +1217,38 @@
334 tracks->cdi, tracks->xa);
335 }
336
337 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
338 +/*
339 + * MEDIA_LOCK, MEDIA_UNLOCK
340 + * optarg == 0 - do not adjust usage count (compatibility)
341 + * optarg == 1 - adjust usage count
342 + */
343 +int cdrom_mediactl(struct cdrom_device_info *cdi, struct block_device *bdev, int op, int optarg)
344 +{
345 + struct cdrom_device_ops *cdo = cdi->ops;
346 +
347 + switch (op) {
348 + case MEDIA_LOCK:
349 + case MEDIA_UNLOCK:
350 + if (op == MEDIA_UNLOCK && optarg) {
351 + cdi->use_count--;
352 + if (cdi->use_count < 0)
353 + cdi->use_count = 0;
354 + }
355 + if (cdo->capability & ~cdi->mask & CDC_LOCK &&
356 + cdi->options & CDO_LOCK &&
357 + supermount_usage_count(bdev, cdi->use_count) == 0)
358 + cdo->lock_door(cdi, (op == MEDIA_LOCK));
359 + if (op == MEDIA_LOCK && optarg)
360 + cdi->use_count++;
361 + break;
362 + default:
363 + return -EINVAL;
364 + }
365 + return 0;
366 +}
367 +#endif
368 +
369 /* Requests to the low-level drivers will /always/ be done in the
370 following format convention:
371
372 @@ -1806,8 +1840,9 @@
373 cdinfo(CD_DO_IOCTL, "entering CDROMEJECT\n");
374 if (!CDROM_CAN(CDC_OPEN_TRAY))
375 return -ENOSYS;
376 - if (cdi->use_count != 1 || keeplocked)
377 - return -EBUSY;
378 + if (keeplocked ||
379 + (supermount_usage_count(ip->i_bdev,cdi->use_count) != 1))
380 + return -EBUSY;
381 if (CDROM_CAN(CDC_LOCK))
382 if ((ret=cdo->lock_door(cdi, 0)))
383 return ret;
384 @@ -2639,6 +2674,9 @@
385 EXPORT_SYMBOL(cdrom_release);
386 EXPORT_SYMBOL(cdrom_ioctl);
387 EXPORT_SYMBOL(cdrom_media_changed);
388 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
389 +EXPORT_SYMBOL(cdrom_mediactl);
390 +#endif
391 EXPORT_SYMBOL(cdrom_number_of_slots);
392 EXPORT_SYMBOL(cdrom_mode_select);
393 EXPORT_SYMBOL(cdrom_mode_sense);
394 diff -ruN linux-2.6.2-rc1.old/drivers/cdrom/cdu31a.c linux-2.6.2-rc1/drivers/cdrom/cdu31a.c
395 --- linux-2.6.2-rc1.old/drivers/cdrom/cdu31a.c 2004-01-24 10:55:27.000000000 -0500
396 +++ linux-2.6.2-rc1/drivers/cdrom/cdu31a.c 2004-01-24 11:46:38.898347544 -0500
397 @@ -3174,6 +3174,25 @@
398
399 static int scd_block_release(struct inode *inode, struct file *file)
400 {
401 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
402 + /*
403 + * This is the same sort of clockload as use in blkdev_get.
404 + * We need information whether device is supermounted inside
405 + * of cdrom_release to decide if tray must be unlocked.
406 + * This information so far is available only by looking
407 + * up superblock but it needs struct *bdev and it is not
408 + * available in cdrom_release anymore
409 + */
410 + struct dentry t_dentry;
411 + struct file t_file;
412 +
413 + if (!file) {
414 + t_file.f_dentry = &t_dentry;
415 + t_dentry.d_inode = inode;
416 + file = &t_file;
417 + }
418 +#endif
419 +
420 return cdrom_release(&scd_info, file);
421 }
422
423 @@ -3188,6 +3207,13 @@
424 return cdrom_media_changed(&scd_info);
425 }
426
427 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
428 +static int scd_block_mediactl(struct block_device *bdev, int op, int arg)
429 +{
430 + return cdrom_mediactl(&scd_info, bdev, op, arg);
431 +}
432 +#endif
433 +
434 struct block_device_operations scd_bdops =
435 {
436 .owner = THIS_MODULE,
437 @@ -3195,6 +3221,9 @@
438 .release = scd_block_release,
439 .ioctl = scd_block_ioctl,
440 .media_changed = scd_block_media_changed,
441 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
442 + .mediactl = scd_block_mediactl,
443 +#endif
444 };
445
446 static struct gendisk *scd_gendisk;
447 diff -ruN linux-2.6.2-rc1.old/drivers/cdrom/cm206.c linux-2.6.2-rc1/drivers/cdrom/cm206.c
448 --- linux-2.6.2-rc1.old/drivers/cdrom/cm206.c 2004-01-24 10:55:27.000000000 -0500
449 +++ linux-2.6.2-rc1/drivers/cdrom/cm206.c 2004-01-24 11:46:38.898347544 -0500
450 @@ -1357,6 +1357,25 @@
451
452 static int cm206_block_release(struct inode *inode, struct file *file)
453 {
454 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
455 + /*
456 + * This is the same sort of clockload as use in blkdev_get.
457 + * We need information whether device is supermounted inside
458 + * of cdrom_release to decide if tray must be unlocked.
459 + * This information so far is available only by looking
460 + * up superblock but it needs struct *bdev and it is not
461 + * available in cdrom_release anymore
462 + */
463 + struct dentry t_dentry;
464 + struct file t_file;
465 +
466 + if (!file) {
467 + t_file.f_dentry = &t_dentry;
468 + t_dentry.d_inode = inode;
469 + file = &t_file;
470 + }
471 +#endif
472 +
473 return cdrom_release(&cm206_info, file);
474 }
475
476 @@ -1371,6 +1390,13 @@
477 return cdrom_media_changed(&cm206_info);
478 }
479
480 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
481 +static int cm206_block_mediactl(struct block_device *bdev, int op, int arg)
482 +{
483 + return cdrom_mediactl(&cm206_info, bdev, op, arg);
484 +}
485 +#endif
486 +
487 static struct block_device_operations cm206_bdops =
488 {
489 .owner = THIS_MODULE,
490 @@ -1378,6 +1404,9 @@
491 .release = cm206_block_release,
492 .ioctl = cm206_block_ioctl,
493 .media_changed = cm206_block_media_changed,
494 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
495 + .mediactl = cm206_block_mediactl,
496 +#endif
497 };
498
499 static struct gendisk *cm206_gendisk;
500 diff -ruN linux-2.6.2-rc1.old/drivers/cdrom/mcd.c linux-2.6.2-rc1/drivers/cdrom/mcd.c
501 --- linux-2.6.2-rc1.old/drivers/cdrom/mcd.c 2004-01-24 10:55:27.000000000 -0500
502 +++ linux-2.6.2-rc1/drivers/cdrom/mcd.c 2004-01-24 11:46:38.899347392 -0500
503 @@ -221,6 +221,25 @@
504
505 static int mcd_block_release(struct inode *inode, struct file *file)
506 {
507 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
508 + /*
509 + * This is the same sort of clockload as use in blkdev_get.
510 + * We need information whether device is supermounted inside
511 + * of cdrom_release to decide if tray must be unlocked.
512 + * This information so far is available only by looking
513 + * up superblock but it needs struct *bdev and it is not
514 + * available in cdrom_release anymore
515 + */
516 + struct dentry t_dentry;
517 + struct file t_file;
518 +
519 + if (!file) {
520 + t_file.f_dentry = &t_dentry;
521 + t_dentry.d_inode = inode;
522 + file = &t_file;
523 + }
524 +#endif
525 +
526 return cdrom_release(&mcd_info, file);
527 }
528
529 @@ -235,6 +254,13 @@
530 return cdrom_media_changed(&mcd_info);
531 }
532
533 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
534 +static int mcd_block_mediactl(struct block_device *bdev, int op, int arg)
535 +{
536 + return cdrom_mediactl(&mcd_info, bdev, op, arg);
537 +}
538 +#endif
539 +
540 static struct block_device_operations mcd_bdops =
541 {
542 .owner = THIS_MODULE,
543 @@ -242,6 +268,9 @@
544 .release = mcd_block_release,
545 .ioctl = mcd_block_ioctl,
546 .media_changed = mcd_block_media_changed,
547 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
548 + .mediactl = mcd_block_mediactl,
549 +#endif
550 };
551
552 static struct gendisk *mcd_gendisk;
553 diff -ruN linux-2.6.2-rc1.old/drivers/cdrom/mcdx.c linux-2.6.2-rc1/drivers/cdrom/mcdx.c
554 --- linux-2.6.2-rc1.old/drivers/cdrom/mcdx.c 2004-01-24 10:55:27.000000000 -0500
555 +++ linux-2.6.2-rc1/drivers/cdrom/mcdx.c 2004-01-24 11:46:38.900347240 -0500
556 @@ -230,6 +230,25 @@
557 static int mcdx_block_release(struct inode *inode, struct file *file)
558 {
559 struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
560 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
561 + /*
562 + * This is the same sort of clockload as use in blkdev_get.
563 + * We need information whether device is supermounted inside
564 + * of cdrom_release to decide if tray must be unlocked.
565 + * This information so far is available only by looking
566 + * up superblock but it needs struct *bdev and it is not
567 + * available in cdrom_release anymore
568 + */
569 + struct dentry t_dentry;
570 + struct file t_file;
571 +
572 + if (!file) {
573 + t_file.f_dentry = &t_dentry;
574 + t_dentry.d_inode = inode;
575 + file = &t_file;
576 + }
577 +#endif
578 +
579 return cdrom_release(&p->info, file);
580 }
581
582 @@ -246,6 +265,14 @@
583 return cdrom_media_changed(&p->info);
584 }
585
586 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
587 +static int mcdx_block_mediactl(struct block_device *bdev, int op, int arg)
588 +{
589 + struct s_drive_stuff *p = bdev->bd_disk->private_data;
590 + return cdrom_mediactl(&p->info, bdev, op, arg);
591 +}
592 +#endif
593 +
594 static struct block_device_operations mcdx_bdops =
595 {
596 .owner = THIS_MODULE,
597 @@ -253,6 +280,9 @@
598 .release = mcdx_block_release,
599 .ioctl = mcdx_block_ioctl,
600 .media_changed = mcdx_block_media_changed,
601 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
602 + .mediactl = mcdx_block_mediactl,
603 +#endif
604 };
605
606
607 diff -ruN linux-2.6.2-rc1.old/drivers/cdrom/sbpcd.c linux-2.6.2-rc1/drivers/cdrom/sbpcd.c
608 --- linux-2.6.2-rc1.old/drivers/cdrom/sbpcd.c 2004-01-24 10:55:27.000000000 -0500
609 +++ linux-2.6.2-rc1/drivers/cdrom/sbpcd.c 2004-01-24 11:46:38.902346936 -0500
610 @@ -5365,6 +5365,25 @@
611 static int sbpcd_block_release(struct inode *inode, struct file *file)
612 {
613 struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
614 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
615 + /*
616 + * This is the same sort of clockload as use in blkdev_get.
617 + * We need information whether device is supermounted inside
618 + * of cdrom_release to decide if tray must be unlocked.
619 + * This information so far is available only by looking
620 + * up superblock but it needs struct *bdev and it is not
621 + * available in cdrom_release anymore
622 + */
623 + struct dentry t_dentry;
624 + struct file t_file;
625 +
626 + if (!file) {
627 + t_file.f_dentry = &t_dentry;
628 + t_dentry.d_inode = inode;
629 + file = &t_file;
630 + }
631 +#endif
632 +
633 return cdrom_release(p->sbpcd_infop, file);
634 }
635
636 @@ -5381,6 +5400,14 @@
637 return cdrom_media_changed(p->sbpcd_infop);
638 }
639
640 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
641 +static int sbpcd_block_mediactl(struct block_device *bdev, int op, int arg)
642 +{
643 + struct sbpcd_drive *p = bdev->bd_disk->private_data;
644 + return cdrom_mediactl(p->sbpcd_infop, bdev, op, arg);
645 +}
646 +#endif
647 +
648 static struct block_device_operations sbpcd_bdops =
649 {
650 .owner = THIS_MODULE,
651 @@ -5388,6 +5415,9 @@
652 .release = sbpcd_block_release,
653 .ioctl = sbpcd_block_ioctl,
654 .media_changed = sbpcd_block_media_changed,
655 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
656 + .mediactl = sbpcd_block_mediactl,
657 +#endif
658 };
659 /*==========================================================================*/
660 /*
661 diff -ruN linux-2.6.2-rc1.old/drivers/ide/ide-cd.c linux-2.6.2-rc1/drivers/ide/ide-cd.c
662 --- linux-2.6.2-rc1.old/drivers/ide/ide-cd.c 2004-01-24 10:55:27.000000000 -0500
663 +++ linux-2.6.2-rc1/drivers/ide/ide-cd.c 2004-01-24 11:46:38.903346784 -0500
664 @@ -3421,6 +3421,24 @@
665 {
666 ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
667 struct cdrom_info *info = drive->driver_data;
668 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
669 + /*
670 + * This is the same sort of clockload as use in blkdev_get.
671 + * We need information whether device is supermounted inside
672 + * of cdrom_release to decide if tray must be unlocked.
673 + * This information so far is available only by looking
674 + * up superblock but it needs struct *bdev and it is not
675 + * available in cdrom_release anymore
676 + */
677 + struct dentry t_dentry;
678 + struct file t_file;
679 +
680 + if (!file) {
681 + t_file.f_dentry = &t_dentry;
682 + t_dentry.d_inode = inode;
683 + file = &t_file;
684 + }
685 +#endif
686
687 cdrom_release (&info->devinfo, file);
688 drive->usage--;
689 @@ -3455,13 +3473,26 @@
690 return 0;
691 }
692
693 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
694 +static int idecd_mediactl(struct block_device *bdev, int op, int arg)
695 +{
696 + struct gendisk *disk = bdev->bd_disk;
697 + ide_drive_t *drive = disk->private_data;
698 + struct cdrom_info *info = drive->driver_data;
699 + return cdrom_mediactl(&info->devinfo, bdev, op, arg);
700 +}
701 +#endif
702 +
703 static struct block_device_operations idecd_ops = {
704 .owner = THIS_MODULE,
705 .open = idecd_open,
706 .release = idecd_release,
707 .ioctl = idecd_ioctl,
708 .media_changed = idecd_media_changed,
709 - .revalidate_disk= idecd_revalidate_disk
710 + .revalidate_disk= idecd_revalidate_disk,
711 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
712 + .mediactl = idecd_mediactl,
713 +#endif
714 };
715
716 /* options */
717 diff -ruN linux-2.6.2-rc1.old/drivers/ide/ide-floppy.c linux-2.6.2-rc1/drivers/ide/ide-floppy.c
718 --- linux-2.6.2-rc1.old/drivers/ide/ide-floppy.c 2004-01-24 10:55:27.000000000 -0500
719 +++ linux-2.6.2-rc1/drivers/ide/ide-floppy.c 2004-01-24 11:46:38.904346632 -0500
720 @@ -98,6 +98,8 @@
721 #include <linux/cdrom.h>
722 #include <linux/ide.h>
723
724 +#include <linux/supermount_media.h>
725 +
726 #include <asm/byteorder.h>
727 #include <asm/irq.h>
728 #include <asm/uaccess.h>
729 @@ -1876,7 +1878,7 @@
730
731 debug_log(KERN_INFO "Reached idefloppy_open\n");
732
733 - if (drive->usage == 1) {
734 + if (supermount_usage_count(inode->i_bdev, drive->usage) == 1) {
735 clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
736 /* Just in case */
737
738 @@ -1923,7 +1925,7 @@
739
740 debug_log(KERN_INFO "Reached idefloppy_release\n");
741
742 - if (drive->usage == 1) {
743 + if (supermount_usage_count(inode->i_bdev, drive->usage) == 1) {
744 idefloppy_floppy_t *floppy = drive->driver_data;
745
746 /* IOMEGA Clik! drives do not support lock/unlock commands */
747 @@ -1955,7 +1957,7 @@
748 prevent = 0;
749 /* fall through */
750 case CDROM_LOCKDOOR:
751 - if (drive->usage > 1)
752 + if (supermount_usage_count(bdev, drive->usage) > 1)
753 return -EBUSY;
754
755 /* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */
756 @@ -2023,13 +2025,47 @@
757 return 0;
758 }
759
760 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
761 +static int idefloppy_mediactl (struct block_device *bdev, int op, int optarg)
762 +{
763 + ide_drive_t *drive = bdev->bd_disk->private_data;
764 + idefloppy_floppy_t *floppy = drive->driver_data;
765 + idefloppy_pc_t pc;
766 +
767 + switch (op) {
768 + case MEDIA_LOCK:
769 + case MEDIA_UNLOCK:
770 + if (op == MEDIA_UNLOCK && optarg) {
771 + drive->usage--;
772 + if (drive->usage < 0)
773 + drive->usage = 0;
774 + }
775 + /* IOMEGA Clik! drives do not support lock/unlock commands */
776 + if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)
777 + && supermount_usage_count(bdev, drive->usage) == 0) {
778 + idefloppy_create_prevent_cmd(&pc, (op == MEDIA_LOCK));
779 + (void) idefloppy_queue_pc_tail(drive, &pc);
780 + }
781 + if (op == MEDIA_LOCK && optarg)
782 + drive->usage++;
783 + break;
784 + default:
785 + return -EINVAL;
786 + }
787 + return 0;
788 +}
789 +#endif
790 +
791 static struct block_device_operations idefloppy_ops = {
792 .owner = THIS_MODULE,
793 .open = idefloppy_open,
794 .release = idefloppy_release,
795 .ioctl = idefloppy_ioctl,
796 .media_changed = idefloppy_media_changed,
797 - .revalidate_disk= idefloppy_revalidate_disk
798 + .revalidate_disk= idefloppy_revalidate_disk,
799 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
800 + .mediactl = idefloppy_mediactl,
801 +#endif
802 };
803
804 static int idefloppy_attach (ide_drive_t *drive)
805 diff -ruN linux-2.6.2-rc1.old/drivers/scsi/sd.c linux-2.6.2-rc1/drivers/scsi/sd.c
806 --- linux-2.6.2-rc1.old/drivers/scsi/sd.c 2004-01-24 10:55:27.000000000 -0500
807 +++ linux-2.6.2-rc1/drivers/scsi/sd.c 2004-01-24 11:46:38.905346480 -0500
808 @@ -47,6 +47,8 @@
809 #include <linux/blkpg.h>
810 #include <asm/uaccess.h>
811
812 +#include <linux/supermount_media.h>
813 +
814 #include "scsi.h"
815 #include "hosts.h"
816
817 @@ -430,7 +432,7 @@
818 if (!sdev->online)
819 goto error_out;
820
821 - if (!sdkp->openers++ && sdev->removable) {
822 + if (supermount_usage_count(inode->i_bdev, sdkp->openers++) == 0 && sdev->removable) {
823 if (scsi_block_when_processing_errors(sdev))
824 scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT);
825 }
826 @@ -461,7 +463,7 @@
827
828 SCSI_LOG_HLQUEUE(3, printk("sd_release: disk=%s\n", disk->disk_name));
829
830 - if (!--sdkp->openers && sdev->removable) {
831 + if (supermount_usage_count(inode->i_bdev, --sdkp->openers) == 0 && sdev->removable) {
832 if (scsi_block_when_processing_errors(sdev))
833 scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW);
834 }
835 @@ -620,6 +622,16 @@
836 goto not_present;
837
838 /*
839 + * FIXME HACK
840 + * busy device that is unplugged is SDEV_DEL but online and ioctl
841 + * does not return any error. Oh well, it is likely layering
842 + * violation but for now it enables media checks for supermount
843 + */
844 +
845 + if (sdp->sdev_state == SDEV_DEL)
846 + goto not_present;
847 +
848 + /*
849 * For removable scsi disk we have to recognise the presence
850 * of a disk in the drive. This is kept in the struct scsi_disk
851 * struct and tested at open ! Daniel Roche (dan@lectra.fr)
852 @@ -642,6 +654,51 @@
853 sd_revalidate_disk(sdkp->disk);
854 }
855
856 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
857 +/*
858 + * This function performs media control operations. Currently the
859 + * only functions used are MEDIA_LOCK and MEDIA_UNLOCK, to lock and
860 + * unlock the drive door.
861 + */
862 +
863 +static int sd_mediactl(struct block_device *bdev, int op, int optarg)
864 +{
865 + struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
866 + struct scsi_device *sdp = sdkp->device;
867 + int rc = 0;
868 +
869 + SCSI_LOG_HLQUEUE(3, printk("sd_mediactl: disk=%s\n",
870 + bdev->bd_disk->disk_name));
871 +
872 + if (!sdp->removable)
873 + return 0;
874 +
875 + if (!scsi_block_when_processing_errors(sdp))
876 + return -ENODEV;
877 +
878 + switch (op) {
879 + case MEDIA_LOCK:
880 + if (supermount_usage_count(bdev, sdkp->openers) == 0)
881 + rc = scsi_set_medium_removal(sdp, SCSI_REMOVAL_PREVENT);
882 + /* FIXME is it the right way? */
883 + if (optarg)
884 + sdkp->openers++;
885 + break;
886 + case MEDIA_UNLOCK:
887 + if (optarg && sdkp->openers > 0)
888 + sdkp->openers--;
889 + if (supermount_usage_count(bdev, sdkp->openers) == 0)
890 + rc = scsi_set_medium_removal(sdp, SCSI_REMOVAL_ALLOW);
891 + break;
892 + default:
893 + rc = -EINVAL;
894 + break;
895 + }
896 +
897 + return rc;
898 +}
899 +#endif
900 +
901 static struct block_device_operations sd_fops = {
902 .owner = THIS_MODULE,
903 .open = sd_open,
904 @@ -649,6 +706,9 @@
905 .ioctl = sd_ioctl,
906 .media_changed = sd_media_changed,
907 .revalidate_disk = sd_revalidate_disk,
908 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
909 + .mediactl = sd_mediactl,
910 +#endif
911 };
912
913 /**
914 diff -ruN linux-2.6.2-rc1.old/drivers/scsi/sr.c linux-2.6.2-rc1/drivers/scsi/sr.c
915 --- linux-2.6.2-rc1.old/drivers/scsi/sr.c 2004-01-24 10:55:27.000000000 -0500
916 +++ linux-2.6.2-rc1/drivers/scsi/sr.c 2004-01-24 11:46:38.906346328 -0500
917 @@ -423,6 +423,24 @@
918 static int sr_block_release(struct inode *inode, struct file *file)
919 {
920 struct scsi_cd *cd = scsi_cd(inode->i_bdev->bd_disk);
921 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
922 + /*
923 + * This is the same sort of clockload as use in blkdev_get.
924 + * We need information whether device is supermounted inside
925 + * of cdrom_release to decide if tray must be unlocked.
926 + * This information so far is available only by looking
927 + * up superblock but it needs struct *bdev and it is not
928 + * available in cdrom_release anymore
929 + */
930 + struct dentry t_dentry;
931 + struct file t_file;
932 +
933 + if (!file) {
934 + t_file.f_dentry = &t_dentry;
935 + t_dentry.d_inode = inode;
936 + file = &t_file;
937 + }
938 +#endif
939 return cdrom_release(&cd->cdi, file);
940 }
941
942 @@ -450,6 +468,15 @@
943 return cdrom_media_changed(&cd->cdi);
944 }
945
946 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
947 +static int sr_block_mediactl(struct block_device *bdev, int op, int arg)
948 +{
949 + struct gendisk *disk = bdev->bd_disk;
950 + struct scsi_cd *cd = scsi_cd(disk);
951 + return cdrom_mediactl(&cd->cdi, bdev, op, arg);
952 +}
953 +#endif
954 +
955 struct block_device_operations sr_bdops =
956 {
957 .owner = THIS_MODULE,
958 @@ -457,6 +484,9 @@
959 .release = sr_block_release,
960 .ioctl = sr_block_ioctl,
961 .media_changed = sr_block_media_changed,
962 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
963 + .mediactl = sr_block_mediactl,
964 +#endif
965 };
966
967 static int sr_open(struct cdrom_device_info *cdi, int purpose)
968 diff -ruN linux-2.6.2-rc1.old/fs/Kconfig linux-2.6.2-rc1/fs/Kconfig
969 --- linux-2.6.2-rc1.old/fs/Kconfig 2004-01-24 10:55:27.000000000 -0500
970 +++ linux-2.6.2-rc1/fs/Kconfig 2004-01-24 11:46:38.906346328 -0500
971 @@ -897,6 +897,8 @@
972 To compile this as a module, choose M here: the module will be called
973 ramfs.
974
975 +source "fs/supermount/Kconfig"
976 +
977 endmenu
978
979 menu "Miscellaneous filesystems"
980 diff -ruN linux-2.6.2-rc1.old/fs/Makefile linux-2.6.2-rc1/fs/Makefile
981 --- linux-2.6.2-rc1.old/fs/Makefile 2004-01-24 10:55:27.000000000 -0500
982 +++ linux-2.6.2-rc1/fs/Makefile 2004-01-24 11:46:38.907346176 -0500
983 @@ -91,3 +91,4 @@
984 obj-$(CONFIG_XFS_FS) += xfs/
985 obj-$(CONFIG_AFS_FS) += afs/
986 obj-$(CONFIG_BEFS_FS) += befs/
987 +obj-$(CONFIG_SUPERMOUNT) += supermount/
988 diff -ruN linux-2.6.2-rc1.old/fs/block_dev.c linux-2.6.2-rc1/fs/block_dev.c
989 --- linux-2.6.2-rc1.old/fs/block_dev.c 2004-01-24 10:55:27.000000000 -0500
990 +++ linux-2.6.2-rc1/fs/block_dev.c 2004-01-24 11:46:38.907346176 -0500
991 @@ -504,12 +504,45 @@
992 {
993 struct gendisk *disk = bdev->bd_disk;
994 struct block_device_operations * bdops = disk->fops;
995 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
996 + struct super_block *sb = NULL;
997 + int supermounted = 0;
998 +#endif
999
1000 if (!bdops->media_changed)
1001 return 0;
1002 if (!bdops->media_changed(bdev->bd_disk))
1003 return 0;
1004
1005 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
1006 + sb = get_super(bdev);
1007 + if (sb) {
1008 + atomic_set(&sb->s_media_changed, 1);
1009 + supermounted = sb->s_flags & MS_SUPERMOUNTED;
1010 + drop_super(sb);
1011 + }
1012 +
1013 + /*
1014 + * Supermount used to did invalidate_device followed by
1015 + * destroy_buffers. invalidate_device hardly does anything
1016 + * useful here as it won't really invalidate "busy" inodes
1017 + * and every inode in subfs is busy (at least one reference
1018 + * from superfs exists). So now it just flushes
1019 + * buffers so they do not accidentally overwrite newly
1020 + * inserted media
1021 + *
1022 + * FIXME unfortunately during umount VFS may write on its
1023 + * own, like write_super. Those writes will go to a wrong
1024 + * media thus corrupting it :(
1025 + *
1026 + * There is no error print because supermount warns user
1027 + * itself.
1028 + */
1029 +
1030 + if (supermounted) {
1031 + invalidate_bdev(bdev, 1);
1032 + } else
1033 +#endif
1034 if (__invalidate_device(bdev, 0))
1035 printk("VFS: busy inodes on changed media.\n");
1036
1037 diff -ruN linux-2.6.2-rc1.old/fs/ext2/super.c linux-2.6.2-rc1/fs/ext2/super.c
1038 --- linux-2.6.2-rc1.old/fs/ext2/super.c 2004-01-24 10:55:27.000000000 -0500
1039 +++ linux-2.6.2-rc1/fs/ext2/super.c 2004-01-24 11:46:38.909345872 -0500
1040 @@ -303,6 +303,12 @@
1041 {Opt_ignore, "noquota"},
1042 {Opt_ignore, "quota"},
1043 {Opt_ignore, "usrquota"},
1044 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
1045 + /* Silently ignore NLS options */
1046 + {Opt_ignore, "iocharset=%s"},
1047 + {Opt_ignore, "codepage=%s"},
1048 + {Opt_ignore, "umask=%o"},
1049 +#endif
1050 {Opt_err, NULL}
1051 };
1052
1053 diff -ruN linux-2.6.2-rc1.old/fs/isofs/inode.c linux-2.6.2-rc1/fs/isofs/inode.c
1054 --- linux-2.6.2-rc1.old/fs/isofs/inode.c 2004-01-24 10:55:27.000000000 -0500
1055 +++ linux-2.6.2-rc1/fs/isofs/inode.c 2004-01-24 11:46:38.910345720 -0500
1056 @@ -368,6 +368,10 @@
1057 {Opt_ignore, "conv=auto"},
1058 {Opt_ignore, "conv=a"},
1059 {Opt_nocompress, "nocompress"},
1060 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
1061 + {Opt_ignore, "codepage=%s"},
1062 + {Opt_ignore, "umask=%s"},
1063 +#endif
1064 {Opt_err, NULL}
1065 };
1066
1067 diff -ruN linux-2.6.2-rc1.old/fs/namespace.c linux-2.6.2-rc1/fs/namespace.c
1068 --- linux-2.6.2-rc1.old/fs/namespace.c 2004-01-24 10:55:27.000000000 -0500
1069 +++ linux-2.6.2-rc1/fs/namespace.c 2004-01-24 11:46:38.908346024 -0500
1070 @@ -773,6 +773,15 @@
1071 if (retval)
1072 goto dput_out;
1073
1074 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
1075 + if (!(flags & (MS_REMOUNT | MS_MOVE)) &&
1076 + (nd.mnt->mnt_sb->s_type->fs_flags & FS_NO_SUBMNT)) {
1077 + retval = -EPERM;
1078 + path_release(&nd);
1079 + return retval;
1080 + }
1081 +#endif
1082 +
1083 if (flags & MS_REMOUNT)
1084 retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
1085 data_page);
1086 diff -ruN linux-2.6.2-rc1.old/fs/super.c linux-2.6.2-rc1/fs/super.c
1087 --- linux-2.6.2-rc1.old/fs/super.c 2004-01-24 10:55:27.000000000 -0500
1088 +++ linux-2.6.2-rc1/fs/super.c 2004-01-24 11:46:38.909345872 -0500
1089 @@ -79,6 +79,9 @@
1090 s->dq_op = sb_dquot_ops;
1091 s->s_qcop = sb_quotactl_ops;
1092 s->s_op = &default_op;
1093 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
1094 + atomic_set(&s->s_media_changed, 0);
1095 +#endif
1096 }
1097 out:
1098 return s;
1099 @@ -499,6 +502,10 @@
1100 return 0;
1101 }
1102
1103 +#ifdef CONFIG_SUPERMOUNT_MODULE
1104 +EXPORT_SYMBOL(do_remount_sb);
1105 +#endif
1106 +
1107 static void do_emergency_remount(unsigned long foo)
1108 {
1109 struct super_block *sb;
1110 @@ -605,11 +612,18 @@
1111 goto out;
1112
1113 if (s->s_root) {
1114 - if ((flags ^ s->s_flags) & MS_RDONLY) {
1115 + if (((flags ^ s->s_flags) & MS_RDONLY)
1116 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
1117 + /* disallow double mounting for supermounted device */
1118 + || ((flags | s->s_flags) & MS_SUPERMOUNTED)
1119 +#endif
1120 + )
1121 + {
1122 up_write(&s->s_umount);
1123 deactivate_super(s);
1124 s = ERR_PTR(-EBUSY);
1125 }
1126 +
1127 goto out;
1128 } else {
1129 char b[BDEVNAME_SIZE];
1130 @@ -712,6 +726,17 @@
1131 if (!type)
1132 return ERR_PTR(-ENODEV);
1133
1134 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
1135 + /* sanity checks; supermount relies on these assumptions */
1136 + if (flags & MS_SUPERMOUNTED) {
1137 + sb = ERR_PTR(-EINVAL);
1138 + if (type->fs_flags & FS_ODD_RENAME)
1139 + goto out;
1140 + if (!(type->fs_flags & FS_REQUIRES_DEV))
1141 + goto out;
1142 + sb = ERR_PTR(-ENOMEM);
1143 + }
1144 +#endif
1145 mnt = alloc_vfsmnt(name);
1146 if (!mnt)
1147 goto out;
1148 @@ -739,6 +764,10 @@
1149 return (struct vfsmount *)sb;
1150 }
1151
1152 +#ifdef CONFIG_SUPERMOUNT_MODULE
1153 +EXPORT_SYMBOL(do_kern_mount);
1154 +#endif
1155 +
1156 struct vfsmount *kern_mount(struct file_system_type *type)
1157 {
1158 return do_kern_mount(type->name, 0, type->name, NULL);
1159 diff -ruN linux-2.6.2-rc1.old/fs/supermount/Kconfig linux-2.6.2-rc1/fs/supermount/Kconfig
1160 --- linux-2.6.2-rc1.old/fs/supermount/Kconfig 1969-12-31 19:00:00.000000000 -0500
1161 +++ linux-2.6.2-rc1/fs/supermount/Kconfig 2004-01-24 11:46:38.888349064 -0500
1162 @@ -0,0 +1,26 @@
1163 +config SUPERMOUNT
1164 + tristate "Supermount removable media support"
1165 + help
1166 + Supermount gives you the ability to access CD-ROMs and Floppies
1167 + without mounting/unmounting them every time you want to access
1168 + a different disk/floppy. Just eject the media, insert a new one
1169 + and you are able to access it.
1170 +
1171 + Read Documentation/filesystems/supermount.txt for more information.
1172 +
1173 + If you want to compile the Supermount support as a module ( = code
1174 + which can be inserted in and removed from the running kernel whenever
1175 + you want), say M here and read Documentation/modules.txt. The module
1176 + will be called supermount.o.
1177 +
1178 + If unsure, say N.
1179 +
1180 +config SUPERMOUNT_DEBUG
1181 + bool "Enable supermount debug code"
1182 + depends on SUPERMOUNT
1183 + help
1184 + If you set this to Y, additional debug code will be compiled in.
1185 + Debug output is controlled with debug=N mount option. Possible
1186 + values are listed in Documentation/filesystems/supermount.txt.
1187 +
1188 + If unsure, say Y.
1189 diff -ruN linux-2.6.2-rc1.old/fs/supermount/Makefile linux-2.6.2-rc1/fs/supermount/Makefile
1190 --- linux-2.6.2-rc1.old/fs/supermount/Makefile 1969-12-31 19:00:00.000000000 -0500
1191 +++ linux-2.6.2-rc1/fs/supermount/Makefile 2004-01-24 11:46:38.888349064 -0500
1192 @@ -0,0 +1,15 @@
1193 +#
1194 +# Makefile for the linux supermounting routines.
1195 +#
1196 +
1197 +supermount-objs := dentry.o \
1198 + file.o \
1199 + filemap.o \
1200 + init.o \
1201 + mediactl.o \
1202 + namei.o \
1203 + proc.o \
1204 + subfs.o \
1205 + super.o
1206 +
1207 +obj-$(CONFIG_SUPERMOUNT) += supermount.o
1208 diff -ruN linux-2.6.2-rc1.old/fs/supermount/changelog linux-2.6.2-rc1/fs/supermount/changelog
1209 --- linux-2.6.2-rc1.old/fs/supermount/changelog 1969-12-31 19:00:00.000000000 -0500
1210 +++ linux-2.6.2-rc1/fs/supermount/changelog 2004-01-24 11:46:38.888349064 -0500
1211 @@ -0,0 +1,462 @@
1212 +* ? ? ? Andrey Borzenkov <arvidjaar@mail.ru> ?.?.?
1213 +
1214 +* Sun 18 Jan 2004 Andrey Borzenkov <arvidjaar@mail.ru> 2.0.4
1215 +
1216 + - yet another attempt to fix detection of USB drive removale
1217 + (explicitly check for SDVE_DEL state in sd.c:sd_media_changed)
1218 +
1219 + - fixed i18n patch for ext2 and udf (ignored options)
1220 +
1221 + - ->nopage prototype changed; it makes it incompatible with
1222 + kernel < 2.6.1 (I wonder how it compiled - or did I miss
1223 + warning). Add comments about ->populate and why it won't be
1224 + implemented
1225 +
1226 + - fix "auto" option. Simplification of option processing turned
1227 + out to be a mess :( Reported by Bart
1228 +
1229 +* Mon 12 Jan 2004 Andrey Borzenkov <arvidjaar@mail.ru> 2.0.3b
1230 +
1231 + - Fix compilation problem in subfs.c with older GCC - declaration
1232 + after statement in clear_inodes(bug 875009). Pointed by Adrian Punga.
1233 +
1234 +* Wed 07 Jan 2004 Andrey Borzenkov <arvidjaar@mail.ru> 2.0.3a
1235 +
1236 + - fix Oops during options parsing if no subfs option is
1237 + given after "--" (bug 869863)
1238 +
1239 +* Mon 29 Dec 2003 Andrey Borzenkov <arvidjaar@mail.ru> 2.0.3
1240 +
1241 + - move test for device offline in sd.c to the top in attempt
1242 + to fix USB removale problem
1243 +
1244 + - simplify options procesing
1245 +
1246 + - remove cdrom "open failed" message (it is now under
1247 + CDROM_OPEN flag like all others in cdrom_open).
1248 +
1249 + - rewrote option parsing to use new lib/parse library
1250 +
1251 +* Sun 26 Oct 2003 Andrey Borzenkov <arvidjaar@mail.ru> 2.0.2a
1252 +
1253 + - remove some obsolete files that are not used anymore from CVS
1254 + (i.e. from patch)
1255 +
1256 + - isofs needs extra ignored options now. It rurns out it silently
1257 + ignored any unknown option before new and shiny option parsing
1258 + code
1259 +
1260 + - consistently use "kernel 2.6" in version print
1261 +
1262 + - updates for -test8. Change ext2/udf patches to match new options
1263 + parsing code.
1264 +
1265 +* Wed 10 Sep 2003 Andrey Borzenkov <arvidjaar@mail.ru> 2.0.2
1266 +
1267 + - NODEV is gone, use MKDEV(UNNAMED_MAJOR, 0) instead, it is just
1268 + as good as anything else
1269 +
1270 +* Sat 23 Aug 2003 Andrey Borzenkov <arvidjaar@mail.ru> 2.0.1d
1271 +
1272 + - rediff against 2.6.0-test4
1273 +
1274 +* Mon 18 Aug 2003 Andrey Borzenkov <arvidjaar@mail.ru> 2.0.1c
1275 +
1276 + - fix compilation without CONFIG_SUPERMOUNT. Reported by
1277 + Igor Strygin
1278 +
1279 +* Sun 10 Aug 2003 Andrey Borzenkov <arvidjaar@mail.ru> 2.0.1b
1280 +
1281 + - /proc/fs/supermount/version is read-only, do not set permissions to
1282 + rw
1283 +
1284 + - remove generic_unplug_queue from ide_do_drive_cmd, apparently
1285 + it is redundant now (fixes bug 785691)
1286 +
1287 + - rediff for 2.6.0-test3
1288 +
1289 +* Sun 27 Jul 2003 Andrey Borzenkov <arvidjaar@mail.ru> 2.0.1a
1290 +
1291 + - rediff for 2.6.0-test2
1292 +
1293 +* Sun 13 Jul 2003 Andrey Borzenkov <arvidjaar@mail.ru> 2.0.1
1294 +
1295 + - hush most unused variables warnings with CONFIG_DEBUG (idea
1296 + suggested by Jeff Garzik)
1297 +
1298 + - replace ugly SUPERMOUNT_TARCE_{ENTER,LEAVE}[_ARGS] with ENTER/LEAVE
1299 + Use %p throughout for pointer output.
1300 +
1301 + - send DN_CREATE for root on mount
1302 +
1303 + - allow open and readdir on mountpoint even if subfs is unmounted.
1304 + This provides for active monitoring by FAM/dnotify and is overall
1305 + less surprising - ls /mnt/cdrom just returns empty directory now
1306 + instead of error. For technical reasons ->flush and ->permissions
1307 + need be aware about it too.
1308 +
1309 + Files opened while subfs is unmounted are NOT usable for anything
1310 + except readdir even AFTER subfs gets mounted. So application
1311 + has to reopen directory to rescan it. AFAIK all of them do it :)
1312 +
1313 +* Sat 12 Jul 2003 Andrey Borzenkov <arvidjaar@mail.ru> 2.0.0a
1314 +
1315 + - add struct nameidata * goes into d_revalidate as well
1316 +
1317 + - add struct nameidata * to some inode methods (introduced in
1318 + 2.5.75). Currently it is just passed along - it is not clear if
1319 + local subfs-specific nameidata has to be constructed. Apparently
1320 + it existed in follow_link all the time without any evil done.
1321 +
1322 + - fix small races in supermount_getattr - do not attempt to
1323 + get subdent if prevent_umount failed
1324 +
1325 +* Mon 23 Jun 2003 Andrey Borzenkov <arvidjaar@mail.ru> 2.0.0
1326 +
1327 + - added ->getattr; it never fails on both unmounted mountpoint
1328 + and stale open files - to ensure fuser -m /mnt/cdrom still finds them
1329 +
1330 + - merge 2.5.73; update sd.c to new refcount interface in sd.c
1331 +
1332 + - fix SUPERMOUNT_BUG_ON_LOCKED without SUPERMOUNT_DEBUG
1333 +
1334 + - add media management to ide-floppy and those CD-ROM drivers that
1335 + are using standard cdrom_* calls (cdu31a, cm206, mcd, mcdx, sbpcd).
1336 + Testdrive revealed that none of them builds for other reasons :)
1337 +
1338 + - add (un)mark_media_supermounted; mark after mount, unmark
1339 + before umount. These functions just manipulate bd_disk->scount
1340 +
1341 + - add scount to struct gendisk to serve as count of total
1342 + supermounted partitions; use everywhere to check if device
1343 + is supermounted
1344 +
1345 +* Tue 17 Jun 2003 Andrey Borzenkov <arvidjaar@mail.ru> 2.0.0test2
1346 +
1347 + - update kernel patch for 2.5.72 (there was a reject in
1348 + drivers/ide/ide-io.c)
1349 +
1350 + - move init_inode_info into alloc_inode; use iget_locked
1351 + instead of iget to skip ->read_inode with intent to move
1352 + inode init under if (inode->i_state & I_NEW)
1353 +
1354 + - polish dentry.c a bit while I am on it
1355 +
1356 + - ->d_compare is not run under dcache_lock anymore. Pointed by
1357 + Maneesh Soni. As we can't sleep in d_compare, use rwlock to
1358 + protect against races with supermount_clean_dentries until
1359 + I find better solution.
1360 +
1361 + - remove new_subfs_dentry - it is not used anymore and comments
1362 + there were wrong anyway
1363 +
1364 +* Sun 01 Jun 2003 Andrey Borzenkov <arvidjaar@mail.ru> 2.0.0test1
1365 +
1366 + - add sr and sd support
1367 +
1368 + - update sb s_blocksize and s_blocksize_bits on subfs mount
1369 +
1370 + - use BKL around chek_disk_change; it is not garanteed by VFS now
1371 +
1372 + - llseek no more updates file readahead pointer
1373 +
1374 + - used bdev not gendisk in mediactl - it needs it for
1375 + supermount_usage_count. It probably needs redesign. Also some minor
1376 + changes on the way.
1377 +
1378 + - 2.5 changes. supermount_get_sb, inode alloc/dealloc, use bdev instead
1379 + of dev, Makefile change, add CONFIG_SUPERMOUNT_DEBUG, do_remount_sb
1380 + prototype change, mknod prototype change, UPDATE_ATIME dead,
1381 + dnotify_parent is now true function
1382 +
1383 +* Tue 27 May 2003 Andrey Borzenkov <arvidjaar@mail.ru> 1.2.7
1384 +
1385 + - (re-)set root inode flags after unmounting subfs
1386 +
1387 + - fix mounting of ro media on rw filesystem. It was broken by fix
1388 + in 1.2.4. Remove saved s_mflags and just use real sb->s_flags.
1389 + Reported by Con Kolivas
1390 +
1391 + - do not use MS_MGC_VAL in subfs_real_mount - it is not used anywhere
1392 + in kernel and all lower bits are already taken in 2.5
1393 +
1394 + - configure help from Marc-Christian Petersen
1395 +
1396 + - use subsb->s_bdev instead of looking up using s_dev. This also
1397 + fixes problem with O(1) patch (bug 737783)
1398 +
1399 +* Wed 14 May 2003 Andrey Borzenkov <arvidjaar@mail.ru> 1.2.6
1400 +
1401 + - check for correct inode in attach_subfs_inode - if super inode
1402 + has subinode attached it must be the same as is currently
1403 + resuested. Else it is a bug.
1404 +
1405 + - use lookup_one_len to lookup subfs dentry in cache; check if
1406 + subfs did not change name and lookup "real" dentry in parent
1407 + cache in this case. This finally puts an end to the attempt to
1408 + control subfs dcache. The only thing we rely upon now is that
1409 + nothing can change directory contents while in lookup method.
1410 +
1411 + - implement d_hash and d_compare to properly support case-
1412 + insensitive filesystems (vfat & Co).
1413 +
1414 + - reset super inode i_mapping so it does not point to freed
1415 + subinode mapping when unmounting subfs
1416 +
1417 + - send dnotify_parent on dentry cleanup, not on inode
1418 +
1419 + - use write_inode_now in ->write_inode. Reading intricated flags
1420 + manipulations in fs/inode.c was just too intimidating. It is not as
1421 + much overhead as it looks like - it is called from sync_one only
1422 + so all dirty pages are scheduled to be flushed anyway.
1423 +
1424 +* Sun 04 May 2003 Andrey Borzenkov <arvidjaar@mail.ru> 1.2.5
1425 +
1426 + - enable dentries caching; properly use d_add when dentry is first
1427 + looked up and d_instantiate when inode is finally available.
1428 +
1429 + - first stab at sending notifications on media umount/mount
1430 +
1431 + - more caveats :(
1432 +
1433 +* Sat 26 Apr 2003 Andrey Borzenkov <arvidjaar@mail.ru> 1.2.4
1434 +
1435 + - fix write_inode/prepare_inode deadlock. It looked like
1436 + set I_LOCK
1437 + down(&sbi->sem);
1438 + iget4 -> wait_on_inode
1439 + down(&sbi->sem)
1440 +
1441 + - MS_ACTIVE was reset on subfs remount
1442 +
1443 + - print process PID in trace
1444 +
1445 + - adjust directory structure to make patch generation easier
1446 +
1447 +* Sun 20 Apr 2003 Andrey Borzenkov <arvidjaar@mail.ru> 1.2.3
1448 +
1449 + - dummy version due to script problems
1450 +
1451 +* Sun 20 Apr 2003 Andrey Borzenkov <arvidjaar@mail.ru> 1.2.2
1452 +
1453 + - remove #ifdef CONFIG_PROC_FS from init.c, it already exists in
1454 + supermount.h
1455 +
1456 + - no_tray_lock -> TRAY_LOCK_NEVER. Just to make sure it remains
1457 + compatible (even if it is very unlikely anybody is using it).
1458 +
1459 + - backout kernel stat patch; remove getattr alltogether. It fixed
1460 + fuser -m for stale files. getattr remains uniplemented because
1461 + it does not seem to be used anywhere in kernel at all so I am not
1462 + actually sure how to implement it
1463 +
1464 + It also backouts 10_readlik and 30_lseek as they are not used
1465 + anymore for a long time.
1466 +
1467 + - remove bogus check for sub- and superinodes i_count. i_count is
1468 + outside of supermount control; the only thing that we must be
1469 + sure in - inode is free on umount.
1470 +
1471 + - reset root inode attributes and operations on umount. This fixes
1472 + the problem of attempt to mount media on ls -l /mnt after subfs
1473 + has been mounted once.
1474 +
1475 + - remove ->stale. For all practical purposes an entity is stale iff
1476 + it does not (yet) have associated subfs entity. Creating yet another
1477 + field that just mirrors this condition does not add a single bit
1478 + of useful information.
1479 +
1480 + - subfs_is_busy iff subfs mnt_count > 1
1481 +
1482 +* Sat 05 Apr 2003 Andrey Borzenkov <arvidjaar@mail.ru> 1.2.1
1483 +
1484 + - fixed stupid thinko in mediactl methods (the effect was it was
1485 + impossible to manually eject ro media). It was exposed by recent
1486 + changes. No changes in supermount itself only in driver code
1487 +
1488 + - replace no_tray_lock with tray_lock={never,onwrite,always} with
1489 + "onwrite" being default. I stil do not quite like resulting code
1490 + but it will do for now.
1491 +
1492 + - simplified subfs_(get|put)_(write|read) interface; merge both
1493 + read/write in one function; remove subfs_get_atime. To my surprise
1494 + it resulted on more clean interface in the rest of supermount even
1495 + if subfs_(get|put)_access does look a bit weird.
1496 +
1497 +* Sun 30 Mar 2003 Andrey Borzenkov <arvidjaar@mail.ru> 1.2.0
1498 +
1499 + - changed proc command format to
1500 + <devname> [enable|disable] [release [force]]
1501 +
1502 + - add /proc/fs/supermount/version; printk version on starup only
1503 + if procfs is not configured.
1504 +
1505 + - unify media lock rules for thosed drivers using implementing
1506 + mediactl (cdrom, sd, ide-floppy as of this writing). Lock
1507 + media for both manual and software eject; do not unlock media
1508 + that is in used by something else.
1509 +
1510 + - added show_options method to super.c
1511 +
1512 + - implemented /proc/fs/supermount/subfs read as seq_file
1513 +
1514 +* Sat 29 Mar 2003 Andrey Borzenkov <arvidjaar@mail.ru> 1.1.4
1515 +
1516 + - supermount_rename leftover - it does not need new_subfs_dentry.
1517 + It still worked because new dentry was destroyed immediately, but
1518 + let's do it the right way. Also mark target rw if exists
1519 +
1520 + - propagate S_IMMUTABLE, S_NOATIME and S_APPEND flags from subfs
1521 + to super inode. Filesystems usually rely on VFS to check these
1522 + flags which means it was possible to overwrite immutable file. Also
1523 + needed for atime management (to be added).
1524 +
1525 + - added atime management. It is based on grep UPDATE_ATIME so it may
1526 + be incomplete; still it gives right results in most obvious cases :)
1527 + It respects no(dir)atime mount flag.
1528 +
1529 + - Make sure super inode times and sizes are updated to reflect subfs
1530 + inode. Done in preparation to remove stat kernel patch. Only those
1531 + fields needed by stat are updated.
1532 +
1533 + - remove assertion subi->i_count == 1 from clear_inode. Subfs icache
1534 + is managed independently and there is no lock (as opposed to dentry
1535 + case where we never do cached lookup for subfs).
1536 +
1537 + - use inode cache for supermount inodes to avoid linear search. This
1538 + moves almost the whole inode creation task into read_inode2 - the
1539 + only place where inode needs to be created is root inode.
1540 +
1541 + We use inode numbers from subfs; root inode is never cached until
1542 + subfs has been mounted. Stale inodes are removed from cache in
1543 + clean_inodes (just like dentries are in clean_dentries) so aliasing
1544 + problem is solved.
1545 +
1546 + - add "disabled" state - prevent any attempt to mount media
1547 +
1548 + - add procfs support. Reading /proc/fs/supermount/subfs will return
1549 + list of subfs and their status. Writing into it allows you to
1550 + control status of subfs (mounted/unmounted, enabled/dusabled)
1551 +
1552 + - fix race in clear_inode. It was possible that subfs was umounted
1553 + after inode has been removed from list but before its access
1554 + counters were cleared. The code that checkes for that exists only
1555 + for debugging still I'd like it to be useful.
1556 +
1557 +* Sun 16 Mar 2003 Andrey Borzenkov <arvidjaar@mail.ru> 1.1.3
1558 +
1559 + - add CVS verion Id's to files
1560 +
1561 + - finally get rid of ugly generation number. It is enough to just
1562 + mark entity obsolete; we do not care actually when it happened.
1563 + Now every entity starts out stale; stale flag is reset when subfs
1564 + object is attached; stale flag is set again for the rest of life
1565 + in subfs_umount
1566 +
1567 + - as a side effect read/write count is associated with inodes
1568 + exclusively
1569 +
1570 + - clear_inode and d_iput need prevent/allow umount to avoid "stealing"
1571 + subfs while holding active entities. File release is safe as VFS does
1572 + nou put mnt until _release is finished.
1573 +
1574 + - subfs_prevent_umount does not need validator. The worst thing that
1575 + can happen is that newly mounted subfs is accessed. That does not
1576 + matter, access to subfs object is checked for validity separately in
1577 + every case.
1578 +
1579 + - finally clarify dcache management. As we cannot garantee coherency
1580 + between sub- and super- fs caches we ignore subfs cache entirely.
1581 + Super dentry is instantiated in supermount_lookup and passed around
1582 + with subfs dentry attached. It does not matter if it is positive or
1583 + negative. Currently dentries are forced to be deleted in
1584 + supermount_d_delete but I believe it is not really needed.
1585 +
1586 + - print version number on registering filesystem to facilitate debugging
1587 +
1588 + - umount subfs as soon as possible in check_disk_change. This eliminates
1589 + zombie state (mounted but inactive due to media change detected).
1590 +
1591 + - kill subfs_is_active, it is the same as subfs_is_mounted now.
1592 +
1593 + - kill translations.c it does not do anything special now; move functions
1594 + in file/dentry/namei
1595 +
1596 + - fix stupid bug in get_supermount_inode again - super inode must
1597 + be inited and attached just once not every time.
1598 + Praise assertions again :)
1599 +
1600 +* 10 Mar 2003 Andrey Borzenkov <arvidjaar@mail.ru> 1.1.2
1601 +
1602 + - allow fs=type1:type2:...
1603 +
1604 + - remove supermount_drop_dentries (no more used)
1605 +
1606 + - add some more assertions to subfs_umount
1607 +
1608 +* 10 Mar 2003 Andrey Borzenkov <arvidjaar@mail.ru> 1.1.1
1609 +
1610 + - fix stupid bug in subfs inode refcounting. It was visible with
1611 + hardlinks only so CD-ROM users would not ever see it.
1612 +
1613 + - fix even more stupid bug in unlink - subi was used instead of superi
1614 +
1615 +* 8 Mar 2003 Andrey Borzenkov <arvidjaar@mail.ru> 1.1.0
1616 +
1617 + - files cannot use inode obsolete flag - it does not work for
1618 + root inodes
1619 +
1620 + - make file system structure exact mirror of subfs - now there
1621 + is 1-to-1 correspondence between super- and subfs files, dentries
1622 + and inodes. This is needed to properly manage write access without
1623 + too much locking
1624 +
1625 + - finally realized that subfs cannot be obsolete; use either file
1626 + or inode pointer in all calls into subfs.c to check for freshness
1627 +
1628 + - debug is now per-mount; added trace of all functions
1629 +
1630 + - move setting of SUPERMOUNT_DEBUG to Makefile instead of supermount_i.h
1631 +
1632 +* 1 Mar 2003 Andrey Borzenkov <arvidjaar@mail.ru> 1.0.0
1633 +
1634 + - make sure it is always possible umount subfs. It does it by
1635 + keeping list of opened files (in addition to inodes) and closing
1636 + them if media change is detected.
1637 +
1638 + - make sure subfs can't go away while it is being in use. For
1639 + files it get_file for subfile to ensure subfs mnt is not freed. For
1640 + inode operation it increments usage counter of submnt for duration
1641 + of operation.
1642 +
1643 + - make sure supermounted device can't be mounted twice (that is
1644 + allowed by kernel) because it relies on being the only "owner" of
1645 + subfs. It does it by checking for MS_SUPERMOUNTED flag on mount.
1646 +
1647 + - make sure you can't mount over supermounted directory. Allowing
1648 + it is a nightmare and I cannot see any reason for it (if you can
1649 + provide valid one - I may reconsider this part). It does so by
1650 + adding fstype flag and checking it on mounting.
1651 +
1652 + - reject mount -o remount for the time being (until we can deal
1653 + with it properly)
1654 +
1655 + - completely change implementation of individual inode methods.
1656 + Instead of calling VFS recursively it calls subfs methods directly.
1657 + It is to ensure we are in full control of subfs (assuming it behaves
1658 + properly :)
1659 +
1660 + - properly implement VM methods. Currently changing media would
1661 + leave you with vm_area pointing to no more existing inode ...
1662 +
1663 + - remove many obsolete pieces like flags that just duplicate
1664 + existing information.
1665 +
1666 + - ensure coherency between super- and subfs dentries. Either we
1667 + have both active in dcache or do not have them at all.
1668 +
1669 + - fixe the problem with media ejection after direct access to CD-ROM
1670 +
1671 + - add "just disc change" to all operations to detect media change
1672 + as soon as possible. It is possible to add option to do it just
1673 + for writable media or to completely turn it off.
1674 diff -ruN linux-2.6.2-rc1.old/fs/supermount/dentry.c linux-2.6.2-rc1/fs/supermount/dentry.c
1675 --- linux-2.6.2-rc1.old/fs/supermount/dentry.c 1969-12-31 19:00:00.000000000 -0500
1676 +++ linux-2.6.2-rc1/fs/supermount/dentry.c 2004-01-24 11:46:38.889348912 -0500
1677 @@ -0,0 +1,282 @@
1678 +/*
1679 + * linux/fs/supermount/dentry.c
1680 + *
1681 + * Original version:
1682 + * Copyright (C) 1995
1683 + * Stephen Tweedie (sct@dcs.ed.ac.uk)
1684 + *
1685 + * Rewriten for kernel 2.2 & 2.4. (C) 1999, 2000 Alexis Mikhailov
1686 + * (alexis@abc.cap.ru)
1687 + * Rewritten for kernel 2.4.21 (C) 2003 Andrey Borzenkov
1688 + * (arvidjaar@mail.ru)
1689 + * Rewritten for kernel 2.5.70 (C) 2003 Andrey Borzenkov
1690 + * (arvidjaar@mail.ru)
1691 + *
1692 + * $Id: 401_supermount-2.0.4-2.6.2_rc1.patch,v 1.1 2004/01/26 22:15:04 johnm Exp $
1693 + */
1694 +
1695 +#define S_DBG_TRACE_CURRENT S_DBG_TRACE_DENTRY
1696 +#include "supermount.h"
1697 +
1698 +int
1699 +init_dentry_info(struct dentry *dentry)
1700 +{
1701 + struct super_block *sb = dentry->d_sb;
1702 + struct supermount_dentry_info *sdi;
1703 + int rc;
1704 +
1705 + ENTER(sb, "dentry=%s", dentry->d_name.name);
1706 +
1707 + rc = 1;
1708 + sdi = kmalloc(sizeof(*sdi), GFP_KERNEL);
1709 + if (!sdi)
1710 + goto out;
1711 +
1712 + memset(sdi, 0, sizeof(*sdi));
1713 +
1714 + INIT_LIST_HEAD(&sdi->list);
1715 + sdi->dentry = 0;
1716 + sdi->host = dentry;
1717 +
1718 + dentry->d_fsdata = sdi;
1719 + dentry->d_op = &supermount_dops;
1720 +
1721 + rc = 0;
1722 +out:
1723 + LEAVE(sb, "dentry=%s rc=%d", dentry->d_name.name, rc);
1724 +
1725 + return rc;
1726 +
1727 +}
1728 +
1729 +void
1730 +attach_subfs_dentry(struct dentry *dentry, struct dentry *subdent)
1731 +{
1732 + struct super_block *sb = dentry->d_sb;
1733 + struct supermount_sb_info *sbi = supermount_sbi(sb);
1734 + struct supermount_dentry_info *sdi;
1735 +
1736 + ENTER(sb, "dentry=%s subd=%p", dentry->d_name.name, subdent);
1737 +
1738 + sdi = supermount_d(dentry);
1739 + SUPERMOUNT_BUG_LOCKED_ON(sb, sdi->dentry);
1740 + sdi->dentry = dget(subdent);
1741 + list_add(&sdi->list, &sbi->s_dentries);
1742 +
1743 + LEAVE(sb, "dentry=%s", dentry->d_name.name);
1744 +}
1745 +
1746 +
1747 +struct dentry *
1748 +get_subfs_dentry(struct dentry *dentry)
1749 +{
1750 + struct super_block *sb = dentry->d_sb;
1751 + struct dentry *err;
1752 + struct supermount_dentry_info *sdi = supermount_d(dentry);
1753 +
1754 + ENTER(sb, "dentry=%s", dentry->d_name.name);
1755 +
1756 + subfs_lock(sb);
1757 +
1758 + err = ERR_PTR(-ENOMEDIUM);
1759 + if (!subfs_is_mounted(sb))
1760 + goto out;
1761 +
1762 + err = ERR_PTR(-ESTALE);
1763 + if (is_dentry_obsolete(dentry))
1764 + goto out;
1765 +
1766 + err = dget(sdi->dentry);
1767 + SUPERMOUNT_BUG_LOCKED_ON(sb, !err);
1768 + SUPERMOUNT_BUG_LOCKED_ON(sb, (dentry->d_inode == 0) ^ (err->d_inode == 0));
1769 +
1770 +out:
1771 + subfs_unlock(sb);
1772 +
1773 + LEAVE(sb, "dentry=%s subd=%p", dentry->d_name.name, err);
1774 +
1775 + return err;
1776 +}
1777 +
1778 +static int
1779 +supermount_d_revalidate(struct dentry *dentry, struct nameidata *nd)
1780 +{
1781 + struct super_block *sb = dentry->d_sb;
1782 + struct dentry *subd;
1783 + int rc;
1784 + struct vfsmount *mnt;
1785 +
1786 + ENTER(sb, "dentry=%s", dentry->d_name.name);
1787 +
1788 + rc = 0;
1789 + mnt = subfs_prevent_umount(sb);
1790 + if (!mnt)
1791 + goto out;
1792 +
1793 + subd = get_subfs_dentry(dentry);
1794 +
1795 + if (IS_ERR(subd))
1796 + goto allow_umount;
1797 +
1798 + rc = 1;
1799 + /* FIXME do we need to build proper subfs nd? */
1800 + if (subd->d_op && subd->d_op->d_revalidate)
1801 + rc = subd->d_op->d_revalidate(subd, nd);
1802 +
1803 + dput(subd);
1804 +allow_umount:
1805 + subfs_allow_umount(sb, mnt);
1806 +out:
1807 +
1808 + LEAVE(sb, "dentry=%s rc=%d", dentry->d_name.name, rc);
1809 +
1810 + return rc;
1811 +}
1812 +
1813 +static int
1814 +supermount_d_hash(struct dentry *dentry, struct qstr *name)
1815 +{
1816 + struct super_block *sb = dentry->d_sb;
1817 + struct dentry *subd;
1818 + int rc;
1819 + struct vfsmount *mnt;
1820 +
1821 + ENTER(sb, "dentry=%s name=%s", dentry->d_name.name, name->name);
1822 +
1823 + rc = -ENOMEDIUM;
1824 + mnt = subfs_prevent_umount(sb);
1825 + if (!mnt)
1826 + goto out;
1827 +
1828 + subd = get_subfs_dentry(dentry);
1829 + rc = PTR_ERR(subd);
1830 + if (IS_ERR(subd))
1831 + goto allow_umount;
1832 +
1833 + rc = 0;
1834 + if (subd->d_op && subd->d_op && subd->d_op->d_hash)
1835 + rc = subd->d_op->d_hash(subd, name);
1836 +
1837 + dput(subd);
1838 +allow_umount:
1839 + subfs_allow_umount(sb, mnt);
1840 +out:
1841 + LEAVE(sb, "dentry=%s rc=%d", dentry->d_name.name, rc);
1842 +
1843 + return rc;
1844 +}
1845 +
1846 +
1847 +rwlock_t d_compare_lock = RW_LOCK_UNLOCKED;
1848 +
1849 +static int
1850 +supermount_d_compare(struct dentry *dentry, struct qstr *name1, struct qstr *name2)
1851 +{
1852 + struct super_block *sb = dentry->d_sb;
1853 + struct supermount_dentry_info *sdi;
1854 + struct dentry *subd;
1855 + int rc;
1856 +
1857 + ENTER(sb, "dentry=%s name1=%s name2=%s", dentry->d_name.name, name1->name, name2->name);
1858 +
1859 + rc = 1; /* fail by default */
1860 + sdi = dentry->d_fsdata;
1861 + SUPERMOUNT_BUG_ON(!sdi);
1862 +
1863 + /*
1864 + * HACK - FIXME
1865 + * this protects against races with supermount_clean_dentries
1866 + * I cannot use blocking calls (i.e. sbi->sem) here and it is not
1867 + * protected by dcache_lock anymore
1868 + */
1869 + read_lock(&d_compare_lock);
1870 + subd = sdi->dentry;
1871 + if (!subd) {
1872 + read_unlock(&d_compare_lock);
1873 + goto out;
1874 + }
1875 +
1876 + if (subd->d_op && subd->d_op->d_compare)
1877 + rc = subd->d_op->d_compare(subd, name1, name2);
1878 + else { /* based on fs/dcache.c:d_lookup */
1879 + if (name1->len == name2->len)
1880 + rc = memcmp(name1->name, name2->name, name1->len);
1881 + }
1882 + read_unlock(&d_compare_lock);
1883 +
1884 +out:
1885 + LEAVE(sb, "dentry=%s rc=%d", dentry->d_name.name, rc);
1886 + return rc;
1887 +}
1888 +
1889 +static inline void
1890 +handle_subdent(struct dentry *dentry)
1891 +{
1892 + struct super_block *sb = dentry->d_sb;
1893 + struct vfsmount *mnt;
1894 + struct supermount_dentry_info *sdi = supermount_d(dentry);
1895 + struct dentry *subd = 0;
1896 +
1897 + mnt = subfs_prevent_umount(sb);
1898 + if (!mnt)
1899 + goto out;
1900 +
1901 + subfs_lock(sb);
1902 + if (sdi) {
1903 + subd = sdi->dentry;
1904 + list_del_init(&sdi->list);
1905 + sdi->dentry = 0;
1906 + }
1907 + subfs_unlock(sb);
1908 +
1909 + if (subd)
1910 + dput(subd);
1911 +
1912 + subfs_allow_umount(sb, mnt);
1913 +out:
1914 + return;
1915 +}
1916 +
1917 +/*
1918 + * in case of active dentry we must be sure subfs dentry is released
1919 + * before subfs inode to correctly maintain write state
1920 + */
1921 +static void
1922 +supermount_d_iput(struct dentry *dentry, struct inode *inode)
1923 +{
1924 + struct super_block *sb = dentry->d_sb;
1925 +
1926 + ENTER(sb, "dentry=%s inode=%p", dentry->d_name.name, inode);
1927 +
1928 + handle_subdent(dentry);
1929 + iput(inode);
1930 +
1931 + LEAVE(sb, "dentry=%s", dentry->d_name.name);
1932 +}
1933 +
1934 +
1935 +/*
1936 + * this duplicated code is due to the lack of common "destroy" method
1937 + * for both negative and positive dentries
1938 + */
1939 +static void
1940 +supermount_d_release(struct dentry *dentry)
1941 +{
1942 + struct super_block *sb = dentry->d_sb;
1943 + struct supermount_dentry_info *sdi = supermount_d(dentry);
1944 +
1945 + ENTER(sb, "dentry=%s", dentry->d_name.name);
1946 +
1947 + handle_subdent(dentry);
1948 + kfree(sdi);
1949 +
1950 + LEAVE(sb, "dentry=%s", dentry->d_name.name);
1951 +}
1952 +
1953 +struct dentry_operations supermount_dops = {
1954 + .d_revalidate = supermount_d_revalidate,
1955 + .d_hash = supermount_d_hash,
1956 + .d_compare = supermount_d_compare,
1957 + .d_iput = supermount_d_iput,
1958 + .d_release = supermount_d_release,
1959 +};
1960 diff -ruN linux-2.6.2-rc1.old/fs/supermount/file.c linux-2.6.2-rc1/fs/supermount/file.c
1961 --- linux-2.6.2-rc1.old/fs/supermount/file.c 1969-12-31 19:00:00.000000000 -0500
1962 +++ linux-2.6.2-rc1/fs/supermount/file.c 2004-01-24 11:46:38.889348912 -0500
1963 @@ -0,0 +1,689 @@
1964 +/*
1965 + * linux/fs/supermount/file.c
1966 + *
1967 + * Original version:
1968 + * Copyright (C) 1995, 1997
1969 + * Stephen Tweedie (sct@dcs.ed.ac.uk)
1970 + *
1971 + * from
1972 + *
1973 + * linux/fs/minix/dir.c
1974 + * Copyright (C) 1991, 1992 Linus Torvalds
1975 + *
1976 + * and
1977 + *
1978 + * linux/fs/ext2/dir.c
1979 + * Copyright (C) 1992, 1993, 1994, 1995 Remy Card
1980 + *
1981 + * Rewriten for kernel 2.2 & 2.4. (C) 1999, 2000 Alexis Mikhailov
1982 + * (alexis@abc.cap.ru)
1983 + * Rewriten for kernel 2.4. (C) 2001 MandrakeSoft Inc.
1984 + * Juan Quintela (quintela@mandrakesoft.com)
1985 + * Rewritten for kernel 2.4.21 (C) 2003 Andrey Borzenkov
1986 + * (arvidjaar@mail.ru)
1987 + * Rewritten for kernel 2.5.70 (C) 2003 Andrey Borzenkov
1988 + * (arvidjaar@mail.ru)
1989 + *
1990 + * $Id: 401_supermount-2.0.4-2.6.2_rc1.patch,v 1.1 2004/01/26 22:15:04 johnm Exp $
1991 + */
1992 +
1993 +#define S_DBG_TRACE_CURRENT S_DBG_TRACE_FILE
1994 +#include "supermount.h"
1995 +
1996 +#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
1997 +
1998 +static inline int
1999 +init_file_info(struct file *file, unsigned int fake)
2000 +{
2001 + struct super_block *sb = file->f_dentry->d_sb;
2002 + struct supermount_file_info *sfi;
2003 + int rc;
2004 +
2005 + ENTER(sb, "file=%p fake=%d", file, fake);
2006 +
2007 + rc = 1;
2008 + sfi = kmalloc(sizeof(*sfi), GFP_KERNEL);
2009 + if (!sfi)
2010 + goto out;
2011 +
2012 + memset(sfi, 0, sizeof(*sfi));
2013 +
2014 + INIT_LIST_HEAD(&sfi->list);
2015 + sfi->host = file;
2016 + sfi->owner = current->pid;
2017 + sfi->vm_ops = 0;
2018 + sfi->file = 0;
2019 + sfi->fake = fake;
2020 +
2021 + file->f_supermount = sfi;
2022 +
2023 + rc = 0;
2024 +out:
2025 + LEAVE(sb, "file=%p fake=%d rc=%d", file, fake, rc);
2026 +
2027 + return rc;
2028 +}
2029 +
2030 +static inline void
2031 +attach_subfs_file(struct file *file, struct file *subfile)
2032 +{
2033 + struct super_block *sb = file->f_dentry->d_sb;
2034 + struct supermount_sb_info *sbi = supermount_sbi(sb);
2035 + struct supermount_file_info *sfi;
2036 +
2037 + ENTER(sb, "file=%p subfile=%p", file, subfile);
2038 +
2039 + sfi = supermount_f(file);
2040 + sfi->file = subfile;
2041 + list_add(&sfi->list, &sbi->s_files);
2042 +
2043 + LEAVE(sb, "file=%p subfile=%p", file, subfile);
2044 +}
2045 +
2046 +static inline int
2047 +prepare_file(struct file *file, struct file *subfile)
2048 +{
2049 + struct super_block *sb = file->f_dentry->d_sb;
2050 + int rc;
2051 +
2052 + ENTER(sb, "file=%p subfile=%p", file, subfile);
2053 +
2054 + subfs_lock(sb);
2055 +
2056 + rc = -ENOMEDIUM;
2057 + if (!subfs_is_mounted(sb))
2058 + goto out;
2059 +
2060 + rc = -ESTALE;
2061 + if (is_dentry_obsolete(file->f_dentry))
2062 + goto out;
2063 +
2064 + rc = -ENOMEM;
2065 + if (init_file_info(file, 0))
2066 + goto out;
2067 +
2068 + attach_subfs_file(file, subfile);
2069 + rc = 0;
2070 +
2071 +out:
2072 + subfs_unlock(sb);
2073 +
2074 + LEAVE(sb, "file=%p subfile=%p", file, subfile);
2075 +
2076 + return rc;
2077 +}
2078 +
2079 +struct file *
2080 +get_subfs_file(struct file *file)
2081 +{
2082 + struct super_block *sb = file->f_dentry->d_sb;
2083 + struct supermount_file_info *sfi = supermount_f(file);
2084 + struct file *err;
2085 +
2086 + ENTER(sb, "file=%p", file);
2087 +
2088 + subfs_lock(sb);
2089 +
2090 + err = ERR_PTR(-ENOMEDIUM);
2091 + if (!subfs_is_mounted(sb))
2092 + goto out;
2093 +
2094 + err = ERR_PTR(-ESTALE);
2095 + if (is_file_fake(file) || is_file_obsolete(file))
2096 + goto out;
2097 +
2098 + err = sfi->file;
2099 + SUPERMOUNT_BUG_LOCKED_ON(sb, !err->f_dentry);
2100 + SUPERMOUNT_BUG_LOCKED_ON(sb, !err->f_dentry->d_inode);
2101 + get_file(err);
2102 +
2103 +out:
2104 + subfs_unlock(sb);
2105 +
2106 + LEAVE(sb, "file=%p subfile=%p", file, err);
2107 +
2108 + return err;
2109 +}
2110 +
2111 +static loff_t
2112 +supermount_llseek(struct file *file, loff_t offset, int origin)
2113 +{
2114 + struct super_block *sb = file->f_dentry->d_sb;
2115 + struct file *subfile;
2116 + loff_t rc;
2117 +
2118 + ENTER(sb, "file=%p offset=%lld origin=%d", file, offset, origin);
2119 +
2120 + rc = -ESTALE;
2121 + if (subfs_check_disk_change(sb))
2122 + goto out;
2123 +
2124 + subfile = get_subfs_file(file);
2125 + rc = PTR_ERR(subfile);
2126 + if (IS_ERR(subfile))
2127 + goto out;
2128 +
2129 + if (subfile->f_op && subfile->f_op->llseek)
2130 + rc = subfile->f_op->llseek(subfile, offset, origin);
2131 + else
2132 + rc = default_llseek(subfile, offset, origin);
2133 + file->f_pos = subfile->f_pos;
2134 + file->f_version = subfile->f_version;
2135 +
2136 + fput(subfile);
2137 +out:
2138 + LEAVE(sb, "file=%p rc=%lld", file, rc);
2139 +
2140 + return rc;
2141 +}
2142 +
2143 +static ssize_t
2144 +supermount_read(struct file *file, char *buf, size_t count, loff_t * ppos)
2145 +{
2146 + struct super_block *sb = file->f_dentry->d_sb;
2147 + struct inode *inode = file->f_dentry->d_inode;
2148 + struct file *subfile;
2149 + int write_on = NEED_WRITE_ATIME(inode);
2150 + int rc;
2151 +
2152 + ENTER(sb, "file=%p", file);
2153 +
2154 + rc = -ESTALE;
2155 + if (subfs_check_disk_change(sb))
2156 + goto out;
2157 +
2158 + subfile = get_subfs_file(file);
2159 + rc = PTR_ERR(subfile);
2160 + if (IS_ERR(subfile))
2161 + goto out;
2162 +
2163 + rc = -EINVAL;
2164 + if (!subfile->f_op || !subfile->f_op->read)
2165 + goto put_subfile;
2166 +
2167 + rc = subfs_get_access(inode, write_on);
2168 + if (rc)
2169 + goto put_subfile;
2170 +
2171 + rc = subfile->f_op->read(subfile, buf, count, ppos);
2172 + subfs_put_access(inode, write_on);
2173 + if (rc < 0)
2174 + goto put_subfile;
2175 +
2176 + inode->i_atime = subfile->f_dentry->d_inode->i_atime;
2177 +
2178 + if (rc > 0)
2179 + file->f_pos = subfile->f_pos = *ppos;
2180 +
2181 +put_subfile:
2182 + fput(subfile);
2183 +out:
2184 + LEAVE(sb, "file=%p rc=%d", file, rc);
2185 +
2186 + return rc;
2187 +}
2188 +
2189 +static ssize_t
2190 +supermount_write(struct file *file, const char *buf,
2191 + size_t count, loff_t * ppos)
2192 +{
2193 + struct super_block *sb = file->f_dentry->d_sb;
2194 + struct file *subfile;
2195 + int rc;
2196 +
2197 + ENTER(sb, "file=%p", file);
2198 +
2199 + rc = -ESTALE;
2200 + if (subfs_check_disk_change(sb))
2201 + goto out;
2202 +
2203 + subfile = get_subfs_file(file);
2204 + rc = PTR_ERR(subfile);
2205 + if (IS_ERR(subfile))
2206 + goto out;
2207 +
2208 + rc = 0;
2209 + if (subfile->f_op && subfile->f_op->write)
2210 + rc = subfile->f_op->write(subfile, buf, count, ppos);
2211 + if (rc > 0) {
2212 + struct inode *subinode = subfile->f_dentry->d_inode;
2213 +
2214 + file->f_pos = subfile->f_pos = *ppos;
2215 + file->f_mode = subfile->f_mode;
2216 + file->f_dentry->d_inode->i_size = subinode->i_size;
2217 + file->f_dentry->d_inode->i_blocks = subinode->i_blocks;
2218 + file->f_dentry->d_inode->i_mode = subinode->i_mode;
2219 + file->f_dentry->d_inode->i_ctime = subinode->i_ctime;
2220 + file->f_dentry->d_inode->i_mtime = subinode->i_mtime;
2221 + }
2222 +
2223 + fput(subfile);
2224 +out:
2225 + LEAVE(sb, "file=%p rc=%d", file, rc);
2226 +
2227 + return rc;
2228 +}
2229 +
2230 +int
2231 +supermount_readdir(struct file *file, void *buf, filldir_t fill_fn)
2232 +{
2233 + struct super_block *sb = file->f_dentry->d_sb;
2234 + struct inode *inode = file->f_dentry->d_inode;
2235 + struct file *subfile;
2236 + int write_on = NEED_WRITE_ATIME(inode);
2237 + int fake_readdir = 1;
2238 + int rc;
2239 +
2240 + ENTER(sb, "file=%p", file);
2241 +
2242 + rc = -ESTALE;
2243 + if (subfs_check_disk_change(sb))
2244 + goto out;
2245 +
2246 + subfile = get_subfs_file(file);
2247 + rc = PTR_ERR(subfile);
2248 + if (IS_ERR(subfile))
2249 + goto out;
2250 +
2251 + rc = -ENOTDIR;
2252 + if (!subfile->f_op || !subfile->f_op->readdir)
2253 + goto put_subfile;
2254 +
2255 + rc = subfs_get_access(inode, write_on);
2256 + if (rc)
2257 + goto put_subfile;
2258 +
2259 + /* FIXME should it go before get_access? */
2260 + fake_readdir = 0;
2261 + rc = subfile->f_op->readdir(subfile, buf, fill_fn);
2262 + subfs_put_access(inode, write_on);
2263 + if (rc)
2264 + goto put_subfile;
2265 +
2266 + inode->i_atime = subfile->f_dentry->d_inode->i_atime;
2267 + file->f_pos = subfile->f_pos;
2268 +
2269 +put_subfile:
2270 + fput(subfile);
2271 +out:
2272 + if (fake_readdir && is_file_fake(file)) {
2273 + /* cf. supermount_open */
2274 + rc = 0;
2275 + }
2276 + LEAVE(sb, "file=%p rc=%d fpos=%lld", file, rc, file->f_pos);
2277 +
2278 + return rc;
2279 +}
2280 +
2281 +static unsigned int
2282 +supermount_poll(struct file *file, struct poll_table_struct *table)
2283 +{
2284 + struct super_block *sb = file->f_dentry->d_sb;
2285 + struct file *subfile;
2286 + int rc;
2287 +
2288 + ENTER(sb, "file=%p", file);
2289 +
2290 + rc = -ESTALE;
2291 + if (subfs_check_disk_change(sb))
2292 + goto out;
2293 +
2294 + subfile = get_subfs_file(file);
2295 + rc = PTR_ERR(subfile);
2296 + if (IS_ERR(subfile))
2297 + goto out;
2298 +
2299 + rc = DEFAULT_POLLMASK;
2300 + if (subfile->f_op && subfile->f_op->poll)
2301 + rc = subfile->f_op->poll(subfile, table);
2302 +
2303 + fput(subfile);
2304 +out:
2305 + LEAVE(sb, "file=%p rc=%d", file, rc);
2306 +
2307 + return rc;
2308 +}
2309 +
2310 +static int
2311 +supermount_ioctl(struct inode *inode, struct file *file,
2312 + unsigned int cmd, unsigned long arg)
2313 +{
2314 + struct super_block *sb = file->f_dentry->d_sb;
2315 + struct file *subfile;
2316 + struct inode *subinode;
2317 + int rc;
2318 +
2319 + ENTER(sb, "file=%p cmd=%u arg=%lu", file, cmd, arg);
2320 +
2321 + rc = -ESTALE;
2322 + if (subfs_check_disk_change(sb))
2323 + goto out;
2324 +
2325 + subfile = get_subfs_file(file);
2326 + rc = PTR_ERR(subfile);
2327 + if (IS_ERR(subfile))
2328 + goto out;
2329 +
2330 + rc = -ENOTTY;
2331 + subinode = subfile->f_dentry->d_inode;
2332 + if (subfile->f_op && subfile->f_op->ioctl)
2333 + rc = subfile->f_op->ioctl(subinode, subfile, cmd, arg);
2334 +
2335 + /* flags may have been changed by ioctl */
2336 + if (!rc)
2337 + set_inode_flags(file->f_dentry->d_inode, subinode);
2338 +
2339 + fput(subfile);
2340 +out:
2341 + LEAVE(sb, "file=%p rc=%d", file, rc);
2342 +
2343 + return rc;
2344 +}
2345 +
2346 +int
2347 +supermount_open(struct inode *inode, struct file *file)
2348 +{
2349 + struct super_block *sb = inode->i_sb;
2350 + struct dentry *subdent;
2351 + struct file *subfile = 0;
2352 + struct vfsmount *submnt;
2353 + int write_on = file->f_mode & FMODE_WRITE;
2354 + int fake_open = 1;
2355 + int rc;
2356 +
2357 + ENTER(sb, "inode=%p file=%p", inode, file);
2358 +
2359 + rc = -ESTALE;
2360 + if (subfs_check_disk_change(sb))
2361 + goto out;
2362 +
2363 + submnt = subfs_get_mnt(sb);
2364 + if (!submnt)
2365 + goto out;
2366 +
2367 + subdent = get_subfs_dentry(file->f_dentry);
2368 + rc = PTR_ERR(subdent);
2369 + if (IS_ERR(subdent))
2370 + goto put_submnt;
2371 +
2372 + rc = subfs_get_access(inode, write_on);
2373 + if (rc)
2374 + goto put_subdent;
2375 +
2376 + /*
2377 + * the following is used to simplify error processing. dentry_open
2378 + * automatically does mntput and dput in error case, this may result
2379 + * in subfs being destroyed
2380 + * We just make sure we need to do mntput exactly once here;
2381 + * additionally it guards against accidental remounting of subfs
2382 + * until we has cleaned up
2383 + */
2384 + submnt = mntget(submnt);
2385 + subdent = dget(subdent);
2386 +
2387 + subfile = dentry_open(subdent, submnt, file->f_flags);
2388 + rc = PTR_ERR(subfile);
2389 + if (IS_ERR(subfile))
2390 + goto put_access;
2391 + /*
2392 + * no need to do extra mntput and dput, it is done automatically in
2393 + * dentry_open on error
2394 + */
2395 +
2396 + rc = prepare_file(file, subfile);
2397 + if (rc)
2398 + goto put_subfile;
2399 +
2400 + subfile->f_mode = file->f_mode;
2401 + /*
2402 + * this is needed for mmap to work. In current model vm_area
2403 + * is associated with superfile; we never explicitly call
2404 + * any vm method with subfile as pointer. But many drivers
2405 + * attach private structures to this field and mmap of special
2406 + * files on supermount fs won't work without it
2407 + */
2408 + file->private_data = subfile->private_data;
2409 + /*
2410 + * we have real subfile now, do not fake anything
2411 + */
2412 + fake_open = 0;
2413 +
2414 + /*
2415 + * Now get rid of extra mntget and dget
2416 + */
2417 + goto put_subdent;
2418 +
2419 + /*
2420 + * error cleanup
2421 + */
2422 +
2423 +put_subfile:
2424 + fput(subfile);
2425 + subfile = 0;
2426 +put_access:
2427 + subfs_put_access(inode, write_on);
2428 +put_subdent:
2429 + dput(subdent);
2430 +put_submnt:
2431 + mntput(submnt);
2432 +out:
2433 + if (fake_open && inode == sb->s_root->d_inode) {
2434 + /*
2435 + * always appear to succeed for root open. It allows active
2436 + * monitoring of mountpoint using FAM/dnotify and also is less
2437 + * surprising for other programs
2438 + */
2439 + rc = init_file_info(file, 1);
2440 + if (rc)
2441 + rc = -ENOMEM;
2442 + }
2443 + LEAVE(sb, "inode=%p file=%p rc=%d subfile=0x%p", inode, file, rc, subfile);
2444 +
2445 + return rc;
2446 +}
2447 +
2448 +static int
2449 +supermount_flush(struct file *file)
2450 +{
2451 + struct super_block *sb = file->f_dentry->d_sb;
2452 + struct file *subfile;
2453 + int fake_flush = 1;
2454 + int rc;
2455 +
2456 + ENTER(sb, "file=%p", file);
2457 +
2458 + rc = -ESTALE;
2459 + if (subfs_check_disk_change(sb))
2460 + goto out;
2461 +
2462 + subfile = get_subfs_file(file);
2463 + rc = PTR_ERR(subfile);
2464 + if (IS_ERR(subfile))
2465 + goto out;
2466 +
2467 + rc = 0;
2468 + fake_flush = 0;
2469 + if (subfile->f_op && subfile->f_op->flush)
2470 + rc = subfile->f_op->flush(subfile);
2471 +
2472 + fput(subfile);
2473 +out:
2474 + if (fake_flush && is_file_fake(file)) {
2475 + /* cf. supermount_open */
2476 + rc = 0;
2477 + }
2478 + LEAVE(sb, "file=%p rc=%d fake=%d", file, rc, fake_flush);
2479 +
2480 + return rc;
2481 +}
2482 +
2483 +/*
2484 + * if subfile is NULL it has already been released in supermount_clean_files
2485 + * together with adjusting open/write counters. Else we do it here.
2486 + *
2487 + * The reason is, it may be called long after media has been changed
2488 + * and we definitely do not want this function to mess up the
2489 + * new subfs state.
2490 + */
2491 +static int
2492 +supermount_release(struct inode *inode, struct file *file)
2493 +{
2494 + struct file *subfile = 0;
2495 + struct super_block *sb = inode->i_sb;
2496 + struct supermount_file_info *sfi = file->f_supermount;
2497 +
2498 + ENTER(sb, "inode=%p file=%p", inode, file);
2499 +
2500 + subfs_lock(sb);
2501 + /*
2502 + * FIXME
2503 + * this sucks. But there does not seem to be any way
2504 + * to distinguish between ENOMEM on _open (legitimate
2505 + * case) and anything else (plain bug)
2506 + */
2507 + if (sfi) {
2508 + list_del(&sfi->list);
2509 + subfile = sfi->file;
2510 + sfi->file = 0;
2511 + } else
2512 + supermount_warning(sb, "no supermount file info attached");
2513 + subfs_unlock(sb);
2514 +
2515 + if (subfile) {
2516 + int bug = atomic_read(&subfile->f_count) != 1;
2517 + fput(subfile);
2518 + subfs_put_access(inode, file->f_mode & FMODE_WRITE);
2519 + SUPERMOUNT_BUG_ON(bug);
2520 + }
2521 +
2522 + if (sfi)
2523 + kfree(sfi);
2524 +
2525 + LEAVE(sb, "inode=%p file=%p", inode, file);
2526 +
2527 + return 0;
2528 +
2529 +}
2530 +
2531 +static int
2532 +supermount_fsync(struct file *file, struct dentry *dentry, int datasync)
2533 +{
2534 + struct super_block *sb = file->f_dentry->d_sb;
2535 + struct file *subfile;
2536 + int rc;
2537 +
2538 + ENTER(sb, "file=%p dentry=%s sync=%d", file, dentry->d_name.name, datasync);
2539 +
2540 + rc = -ESTALE;
2541 + if (subfs_check_disk_change(sb))
2542 + goto out;
2543 +
2544 + subfile = get_subfs_file(file);
2545 + rc = PTR_ERR(subfile);
2546 + if (IS_ERR(subfile))
2547 + goto out;
2548 +
2549 + rc = -EINVAL;
2550 + if (subfile->f_op && subfile->f_op->fsync)
2551 + rc = subfile->f_op->fsync(subfile, subfile->f_dentry, datasync);
2552 +
2553 + fput(subfile);
2554 +out:
2555 + ENTER(sb, "file=%p dentry=%s rc=%d", file, dentry->d_name.name, rc);
2556 +
2557 + return rc;
2558 +}
2559 +
2560 +static int
2561 +supermount_fasync(int fd, struct file *file, int on)
2562 +{
2563 + struct super_block *sb = file->f_dentry->d_sb;
2564 + struct file *subfile;
2565 + int rc;
2566 +
2567 + ENTER(sb, "fd=%d file=%p on=%d", fd, file, on);
2568 +
2569 + rc = -ESTALE;
2570 + if (subfs_check_disk_change(sb))
2571 + goto out;
2572 +
2573 + subfile = get_subfs_file(file);
2574 + rc = PTR_ERR(subfile);
2575 + if (IS_ERR(subfile))
2576 + goto out;
2577 +
2578 + rc = -EINVAL;
2579 + if (subfile->f_op && subfile->f_op->fasync)
2580 + rc = subfile->f_op->fasync(fd, subfile, on);
2581 +
2582 + fput(subfile);
2583 +out:
2584 + LEAVE(sb, "fd=%d file=%p rc=%d", fd, file, rc);
2585 +
2586 + return rc;
2587 +}
2588 +
2589 +static int
2590 +supermount_lock(struct file *file, int cmd, struct file_lock *fl)
2591 +{
2592 + struct super_block *sb = file->f_dentry->d_sb;
2593 + struct file *subfile;
2594 + int rc;
2595 +
2596 + ENTER(sb, "file=%p cmd=%d", file, cmd);
2597 +
2598 + rc = -ESTALE;
2599 + if (subfs_check_disk_change(sb))
2600 + goto out;
2601 +
2602 + subfile = get_subfs_file(file);
2603 + rc = PTR_ERR(subfile);
2604 + if (IS_ERR(subfile))
2605 + goto out;
2606 +
2607 + rc = 0;
2608 + if (subfile->f_op && subfile->f_op->lock)
2609 + rc = subfile->f_op->lock(subfile, cmd, fl);
2610 + else if (cmd == F_GETLK)
2611 + posix_test_lock(file, fl);
2612 +
2613 + fput(subfile);
2614 +out:
2615 + LEAVE(sb, "file=%p rc=%d", file, rc);
2616 +
2617 + return rc;
2618 +}
2619 +
2620 +/* Fixme:
2621 + * readv: easy, export churnk from vfs
2622 + * writev: easy, export churnk from vfs
2623 + * sendpage: only used for networking, not needed
2624 + * get_unmmapped_area: only used for devices, not needed
2625 + */
2626 +
2627 +struct file_operations supermount_dir_operations = {
2628 + .llseek = supermount_llseek,
2629 + .read = supermount_read,
2630 + .readdir = supermount_readdir,
2631 + .ioctl = supermount_ioctl,
2632 + .open = supermount_open,
2633 + .flush = supermount_flush,
2634 + .release = supermount_release,
2635 + .fsync = supermount_fsync,
2636 + .fasync = supermount_fasync,
2637 +};
2638 +
2639 +struct file_operations supermount_file_operations = {
2640 + .llseek = supermount_llseek,
2641 + .read = supermount_read,
2642 + .write = supermount_write,
2643 + .poll = supermount_poll,
2644 + .ioctl = supermount_ioctl,
2645 + .mmap = supermount_file_mmap, /* from filemap.c */
2646 + .open = supermount_open,
2647 + .flush = supermount_flush,
2648 + .release = supermount_release,
2649 + .fsync = supermount_fsync,
2650 + .fasync = supermount_fasync,
2651 + .lock = supermount_lock,
2652 +};
2653 diff -ruN linux-2.6.2-rc1.old/fs/supermount/filemap.c linux-2.6.2-rc1/fs/supermount/filemap.c
2654 --- linux-2.6.2-rc1.old/fs/supermount/filemap.c 1969-12-31 19:00:00.000000000 -0500
2655 +++ linux-2.6.2-rc1/fs/supermount/filemap.c 2004-01-24 11:46:38.890348760 -0500
2656 @@ -0,0 +1,182 @@
2657 +/*
2658 + * linux/fs/supermount/filemap.c
2659 + *
2660 + * Initial version for kernel 2.4.21 (C) 2003 Andrey Borzenkov
2661 + * (arvidjaar@mail.ru)
2662 + *
2663 + * $Id: 401_supermount-2.0.4-2.6.2_rc1.patch,v 1.1 2004/01/26 22:15:04 johnm Exp $
2664 + */
2665 +
2666 +#define S_DBG_TRACE_CURRENT S_DBG_TRACE_FILEMAP
2667 +#include "supermount.h"
2668 +
2669 +/*
2670 + * Some rationale and justification for this file
2671 + *
2672 + * We play dirty tricks with mm management for mmaped files on supermount.
2673 + * Address space points to subinode but vm area is associated with superfile.
2674 + * When media change is detected, subinode together with all associated
2675 + * pages goes away as well (at least, I hope so ...) Now we must prevent
2676 + * any attempt to access no more existing address space. To do so we save
2677 + * original vm_ops in private field and replace them with vm_ops in this file.
2678 + * They check if file is stale, if yes, they try to return sensible error.
2679 + * There is some doubt about possibility to block here ... OTOH any write
2680 + * lock on subfs is hold in context where no mm lock is expected.
2681 + */
2682 +static void
2683 +supermount_vm_open(struct vm_area_struct *area)
2684 +{
2685 + struct file *file = area->vm_file, *subfile;
2686 + struct super_block *sb = file->f_dentry->d_sb;
2687 + struct supermount_file_info *sfi;
2688 +
2689 + ENTER(sb, "vm=%p", area);
2690 +
2691 + if (subfs_check_disk_change(sb))
2692 + goto out;
2693 +
2694 + subfile = get_subfs_file(file);
2695 + if (IS_ERR(subfile))
2696 + goto out;
2697 +
2698 + sfi = supermount_f(file);
2699 + if (sfi->vm_ops && sfi->vm_ops->open)
2700 + sfi->vm_ops->open(area);
2701 +
2702 + fput(subfile);
2703 +out:
2704 + LEAVE(sb, "vm=%p", area);
2705 +
2706 + return;
2707 +}
2708 +
2709 +static void
2710 +supermount_vm_close(struct vm_area_struct *area)
2711 +{
2712 + struct file *file = area->vm_file, *subfile;
2713 + struct super_block *sb = file->f_dentry->d_sb;
2714 + struct supermount_file_info *sfi;
2715 +
2716 + ENTER(sb, "vm=%p", area);
2717 +
2718 + if (subfs_check_disk_change(sb))
2719 + goto out;
2720 +
2721 + subfile = get_subfs_file(file);
2722 + if (IS_ERR(subfile))
2723 + goto out;
2724 +
2725 + sfi = supermount_f(file);
2726 + if (sfi->vm_ops && sfi->vm_ops->close)
2727 + sfi->vm_ops->close(area);
2728 +
2729 + fput(subfile);
2730 +out:
2731 + LEAVE(sb, "vm=%p", area);
2732 +
2733 + return;
2734 +}
2735 +
2736 +static struct page *
2737 +supermount_vm_nopage(struct vm_area_struct *area, unsigned long address, int *type)
2738 +{
2739 + struct file *file = area->vm_file, *subfile;
2740 + struct super_block *sb = file->f_dentry->d_sb;
2741 + struct supermount_file_info *sfi;
2742 + struct page *page = 0;
2743 +
2744 + ENTER(sb, "vm=%p addr=%lx", area, address);
2745 +
2746 + /*
2747 + * this is called with mm semaphore down read and pagetable
2748 + * spinlock released. So it _appears_ safe to sleep ...
2749 + */
2750 + if (subfs_check_disk_change(sb))
2751 + goto out;
2752 +
2753 + subfile = get_subfs_file(file);
2754 + if (IS_ERR(subfile))
2755 + goto out;
2756 +
2757 + sfi = supermount_f(file);
2758 + page = sfi->vm_ops->nopage(area, address, type);
2759 +
2760 + fput(subfile);
2761 +out:
2762 + LEAVE(sb, "vm=%p page=%p", area, page);
2763 +
2764 + return page;
2765 +}
2766 +
2767 +int
2768 +supermount_file_mmap(struct file *file, struct vm_area_struct *vma)
2769 +{
2770 +
2771 + struct super_block *sb = file->f_dentry->d_sb;
2772 + struct inode *inode = file->f_dentry->d_inode;
2773 + struct supermount_file_info *sfi;
2774 + struct file *subfile;
2775 + int write_on = NEED_WRITE_ATIME(inode);
2776 + int rc;
2777 +
2778 + ENTER(sb, "file=%p vm=%p", file, vma);
2779 +
2780 + rc = -ESTALE;
2781 + if (subfs_check_disk_change(sb))
2782 + goto out;
2783 +
2784 + subfile = get_subfs_file(file);
2785 + rc = PTR_ERR(subfile);
2786 + if (IS_ERR(subfile))
2787 + goto out;
2788 +
2789 + sfi = supermount_f(file);
2790 +
2791 + rc = -ENODEV;
2792 + if (!subfile->f_op || !subfile->f_op->mmap)
2793 + goto put_subfile;
2794 +
2795 + rc = subfs_get_access(inode, write_on);
2796 + if (rc)
2797 + goto put_subfile;
2798 +
2799 + rc = subfile->f_op->mmap(subfile, vma);
2800 + subfs_put_access(inode, write_on);
2801 + if (rc)
2802 + goto put_subfile;
2803 + /*
2804 + * we cannot deal with anonymous mapping
2805 + */
2806 + if (!vma->vm_ops || !vma->vm_ops->nopage) {
2807 + rc = -ENOSYS;
2808 + goto put_subfile;
2809 + }
2810 +
2811 + /*
2812 + * now do the nasty trick
2813 + */
2814 + sfi->vm_ops = vma->vm_ops;
2815 + vma->vm_ops = &supermount_vm_ops;
2816 +
2817 +put_subfile:
2818 + fput(subfile);
2819 +out:
2820 + LEAVE(sb, "file=%p vm=%p rc=%d", file, vma, rc);
2821 +
2822 + return rc;
2823 +}
2824 +
2825 +/*
2826 + * ->populate: to properly implement it it should call do_no_page if
2827 + * subfs does not provide its own ->populate. Unfortunately
2828 + * populate gets different parameters. Translating them into
2829 + * what ->nopage expects just does not worth it - currently
2830 + * supermount is slow enough to bother about this imaginary
2831 + * speed up even if it was possible (which probably is not
2832 + * due to how locking is done; see mm/memory.c).
2833 + */
2834 +struct vm_operations_struct supermount_vm_ops = {
2835 + .open = supermount_vm_open,
2836 + .close = supermount_vm_close,
2837 + .nopage = supermount_vm_nopage,
2838 +};
2839 diff -ruN linux-2.6.2-rc1.old/fs/supermount/init.c linux-2.6.2-rc1/fs/supermount/init.c
2840 --- linux-2.6.2-rc1.old/fs/supermount/init.c 1969-12-31 19:00:00.000000000 -0500
2841 +++ linux-2.6.2-rc1/fs/supermount/init.c 2004-01-24 11:46:38.890348760 -0500
2842 @@ -0,0 +1,48 @@
2843 +/*
2844 + * linux/fs/supermount/init.c
2845 + *
2846 + * (C) Copyright 2001-2002 Juan Quintela <quintela@mandrakesoft.com>
2847 + * Released unde GPL v2.
2848 + * Rewritten for kernel 2.4.21 (C) 2003 Andrey Borzenkov
2849 + * (arvidjaar@mail.ru)
2850 + * Rewritten for kernel 2.5.70 (C) 2003 Andrey Borzenkov
2851 + * (arvidjaar@mail.ru)
2852 + *
2853 + * $Id: 401_supermount-2.0.4-2.6.2_rc1.patch,v 1.1 2004/01/26 22:15:04 johnm Exp $
2854 + */
2855 +
2856 +#include "supermount.h"
2857 +
2858 +struct file_system_type supermount_fs_type = {
2859 + .owner = THIS_MODULE,
2860 + .name = "supermount",
2861 + .get_sb = supermount_get_sb,
2862 + .kill_sb = kill_anon_super,
2863 + .fs_flags = FS_NO_SUBMNT,
2864 +};
2865 +
2866 +static int __init
2867 +init_supermount_fs(void)
2868 +{
2869 + int rc = register_filesystem(&supermount_fs_type);
2870 +
2871 + if (!rc) {
2872 + printk(KERN_INFO "Supermount version %s for kernel 2.6\n", SUPERMOUNT_VERSION);
2873 + supermount_proc_register();
2874 + }
2875 +
2876 + return rc;
2877 +}
2878 +
2879 +static void __exit
2880 +exit_supermount_fs(void)
2881 +{
2882 + supermount_proc_unregister();
2883 + unregister_filesystem(&supermount_fs_type);
2884 +}
2885 +
2886 +MODULE_AUTHOR("Stephen Tweedie, Alexis Mikhailov, Juan Quintela, Andrey Borzenkov and others");
2887 +MODULE_DESCRIPTION("Transparent removable media support");
2888 +MODULE_LICENSE("GPL");
2889 +module_init(init_supermount_fs);
2890 +module_exit(exit_supermount_fs);
2891 diff -ruN linux-2.6.2-rc1.old/fs/supermount/mediactl.c linux-2.6.2-rc1/fs/supermount/mediactl.c
2892 --- linux-2.6.2-rc1.old/fs/supermount/mediactl.c 1969-12-31 19:00:00.000000000 -0500
2893 +++ linux-2.6.2-rc1/fs/supermount/mediactl.c 2004-01-24 11:46:38.890348760 -0500
2894 @@ -0,0 +1,69 @@
2895 +/*
2896 + * linux/fs/supermount/mediactl.c
2897 + *
2898 + * Original version:
2899 + * Copyright (C) 1995, 1997
2900 + * Stephen Tweedie (sct@dcs.ed.ac.uk)
2901 + *
2902 + * Rewriten for kernel 2.2, 2.4. (C) 1999, 2000 Alexis Mikhailov
2903 + * (alexis@abc.cap.ru)
2904 + * Rewritten for kernel 2.4.21 (C) 2003 Andrey Borzenkov
2905 + * (arvidjaar@mail.ru)
2906 + * Rewritten for kernel 2.5.70 (C) 2003 Andrey Borzenkov
2907 + * (arvidjaar@mail.ru)
2908 + *
2909 + * $Id: 401_supermount-2.0.4-2.6.2_rc1.patch,v 1.1 2004/01/26 22:15:04 johnm Exp $
2910 + */
2911 +
2912 +#define S_DBG_TRACE_CURRENT S_DBG_TRACE_MEDIACTL
2913 +#include "supermount.h"
2914 +
2915 +/*
2916 + * Try to lock the drive door. This is not guaranteed to work on all
2917 + * hardware, but we try any tricks we know of anyway.
2918 + */
2919 +void
2920 +supermount_mediactl(struct super_block *sb, int operation, int opt)
2921 +{
2922 + struct block_device *bdev;
2923 + struct super_block *subsb;
2924 + struct block_device_operations *fops = 0;
2925 +
2926 + if (!subfs_is_mounted(sb))
2927 + return;
2928 +
2929 + subsb = subfs_sb(sb);
2930 + bdev = subsb->s_bdev;
2931 + if (!bdev->bd_disk)
2932 + return;
2933 +
2934 + /* FIXME is it enough to use bd_sem here? */
2935 + switch (operation) {
2936 + case SUPERMOUNT_INC_COUNT:
2937 + lock_kernel();
2938 + SUPERMOUNT_BUG_ON(bdev->bd_disk->scount < 0);
2939 + bdev->bd_disk->scount++;
2940 + unlock_kernel();
2941 + return;
2942 + case SUPERMOUNT_DEC_COUNT:
2943 + lock_kernel();
2944 + SUPERMOUNT_BUG_ON(bdev->bd_disk->scount <= 0);
2945 + bdev->bd_disk->scount--;
2946 + unlock_kernel();
2947 + return;
2948 + }
2949 +
2950 + fops = bdev->bd_disk->fops;
2951 + if (!fops || !fops->mediactl)
2952 + return;
2953 + /*
2954 + * tray is (un-)locked in open (BKL for bdev), release (BKL for bdev)
2955 + * and ioctl (BKL). We are in good company.
2956 + * This must be changed if block devices ever stop using BKL
2957 + * for open/release. Unfortunately, using just bdev->bd_sem is not
2958 + * enough due to ioctl.
2959 + */
2960 + lock_kernel();
2961 + fops->mediactl(bdev, operation, opt);
2962 + unlock_kernel();
2963 +}
2964 diff -ruN linux-2.6.2-rc1.old/fs/supermount/namei.c linux-2.6.2-rc1/fs/supermount/namei.c
2965 --- linux-2.6.2-rc1.old/fs/supermount/namei.c 1969-12-31 19:00:00.000000000 -0500
2966 +++ linux-2.6.2-rc1/fs/supermount/namei.c 2004-01-24 11:46:38.891348608 -0500
2967 @@ -0,0 +1,1143 @@
2968 +/*
2969 + * linux/fs/supermount/namei.c
2970 + *
2971 + * Original version:
2972 + * Copyright (C) 1995
2973 + * Stephen Tweedie (sct@dcs.ed.ac.uk)
2974 + *
2975 + * from
2976 + *
2977 + * linux/fs/minix/namei.c
2978 + * Copyright (C) 1991, 1992 Linus Torvalds
2979 + *
2980 + * and
2981 + *
2982 + * linux/fs/ext2/namei.c
2983 + * Copyright (C) 1992, 1993, 1994, 1995 Remy Card
2984 + *
2985 + * Rewriten for kernel 2.2 & 2.4. (C) 1999, 2000 Alexis Mikhailov
2986 + * (alexis@abc.cap.ru)
2987 + * Rewritten for kernel 2.4.21 (C) 2003 Andrey Borzenkov
2988 + * (arvidjaar@mail.ru)
2989 + * Rewritten for kernel 2.5.70 (C) 2003 Andrey Borzenkov
2990 + * (arvidjaar@mail.ru)
2991 + *
2992 + * $Id: 401_supermount-2.0.4-2.6.2_rc1.patch,v 1.1 2004/01/26 22:15:04 johnm Exp $
2993 + */
2994 +
2995 +#define S_DBG_TRACE_CURRENT S_DBG_TRACE_NAMEI
2996 +#include "supermount.h"
2997 +
2998 +/**
2999 + * Attach super dentry to sub dentry
3000 + *
3001 + * @dentry: super dentry that is being created
3002 + * @subd: subfs dentry that just has been found
3003 + *
3004 + * It checks whether subfs is still valid using @dentry->d_parent;
3005 + * new supermount_dentry_info is created and set to point to @subd.
3006 + *
3007 + * It is possible that @subd actually has different name (ntfs, vfat or
3008 + * in general any case-insensitive filesystems). Search @dentry->d_parent
3009 + * for a child matching == @subd->d_name. If found, discard @dentry and child
3010 + * (after some validity checks) is returned. Check that child actually points
3011 + * to @subd
3012 + *
3013 + * d_lookup relies on the fact that hash is properly initialized in
3014 + * @subd->d_name and that superfs is using the same compare method as subfs.
3015 + *
3016 + * About ref counting. @subd is dput in supermount_lookup. I.e. in case of
3017 + * error or if we find out it is already connected to superfs the excessive
3018 + * counter gets decremented. @dentry is finally dput in caller of ->lookup
3019 + * if ->lookup returns something != 0.
3020 + */
3021 +
3022 +static struct dentry *
3023 +prepare_dentry(struct dentry *dentry, struct dentry *subd)
3024 +{
3025 + struct super_block *sb = dentry->d_sb;
3026 + struct dentry *rc;
3027 +
3028 + ENTER(sb, "dentry=%s subd=%s", dentry->d_name.name, subd->d_name.name);
3029 +
3030 + subfs_lock(sb);
3031 +
3032 + SUPERMOUNT_BUG_LOCKED_ON(sb, !subd);
3033 + SUPERMOUNT_BUG_LOCKED_ON(sb, dentry->d_fsdata);
3034 +
3035 + rc = ERR_PTR(-ENOMEDIUM);
3036 + if (!subfs_is_mounted(sb))
3037 + goto out;
3038 +
3039 + rc = ERR_PTR(-ESTALE);
3040 + if (is_dentry_obsolete(dentry->d_parent))
3041 + goto out;
3042 +
3043 + rc = d_lookup(dentry->d_parent, &subd->d_name);
3044 + if (IS_ERR(rc))
3045 + goto out;
3046 +
3047 + if (rc) {
3048 + SUPERMOUNT_BUG_LOCKED_ON(sb, !rc->d_fsdata);
3049 + SUPERMOUNT_BUG_LOCKED_ON(sb,
3050 + ((struct supermount_dentry_info *)rc->d_fsdata)->dentry != subd);
3051 + } else {
3052 + /*
3053 + * this is theoretically possible. We cannot garantee full
3054 + * coherency between subfs and superfs cache; i.e. entry
3055 + * may have been left in one cache but removed from another
3056 + */
3057 + rc = ERR_PTR(-ENOMEM);
3058 + if (init_dentry_info(dentry))
3059 + goto out;
3060 + attach_subfs_dentry(dentry, subd);
3061 + d_add(dentry, 0);
3062 + rc = 0;
3063 + }
3064 +
3065 +out:
3066 + subfs_unlock(sb);
3067 +
3068 + LEAVE(sb, "dentry=%p subd=%p rc=%p", dentry, subd, rc);
3069 +
3070 + return rc;
3071 + /*
3072 + * subdent is implicitly freed on return if we skip dget here
3073 + */
3074 +}
3075 +
3076 +
3077 +/**
3078 + * Attach superfs inode to subfs inode
3079 + *
3080 + * @dentry: superfs dentry
3081 + * @subd: subfs dentry
3082 + *
3083 + * This is expected to be called only in cointext that requires
3084 + * negative dentry.
3085 + *
3086 + * FIXME
3087 + * Holding sbi->sem during iget4 creates deadlock with write_inode -
3088 + * write_inode sets I_LOCK abd calls supermount_write_inode at the
3089 + * same moment as iget4 sleeps waiting for I_LOCK to be cleared. So
3090 + * it first acquires inode and then checks if subfs is still valid.
3091 + */
3092 +
3093 +static int
3094 +prepare_inode(struct dentry *dentry, struct dentry *subd)
3095 +{
3096 + struct super_block *sb = dentry->d_sb;
3097 + struct inode *inode = dentry->d_inode;
3098 + struct inode *subi = subd->d_inode;
3099 + int rc;
3100 +
3101 + ENTER(sb, "dentry=%s", dentry->d_name.name);
3102 +
3103 + SUPERMOUNT_BUG_ON(inode);
3104 + SUPERMOUNT_BUG_ON(!subi);
3105 +
3106 + rc = -ENOMEM;
3107 + inode = iget_locked(sb, subi->i_ino);
3108 + if (!inode)
3109 + goto out;
3110 + else if (inode->i_state & I_NEW)
3111 + unlock_new_inode(inode);
3112 +
3113 + rc = 0;
3114 +
3115 + subfs_lock(sb);
3116 + if (!subfs_is_mounted(sb))
3117 + rc = -ENOMEDIUM;
3118 + else if (is_dentry_obsolete(dentry))
3119 + rc = -ESTALE;
3120 + else {
3121 + attach_subfs_inode(inode, subi);
3122 + d_instantiate(dentry, inode);
3123 + }
3124 + subfs_unlock(sb);
3125 +
3126 + if (rc)
3127 + iput(inode);
3128 +
3129 +out:
3130 + LEAVE(sb, "dentry=%s inode=%p rc=%d", dentry->d_name.name, inode, rc);
3131 +
3132 + return rc;
3133 +}
3134 +
3135 +struct inode *
3136 +get_subfs_inode(struct inode *inode)
3137 +{
3138 + struct super_block *sb = inode->i_sb;
3139 + struct inode *err;
3140 + struct supermount_inode_info *sii = supermount_i(inode);
3141 +
3142 + ENTER(sb, "inode=%p", inode);
3143 +
3144 + subfs_lock(sb);
3145 +
3146 + err = ERR_PTR(-ENOMEDIUM);
3147 + if (!subfs_is_mounted(sb))
3148 + goto out;
3149 +
3150 + err = ERR_PTR(-ESTALE);
3151 + if (is_inode_obsolete(inode))
3152 + goto out;
3153 +
3154 + err = igrab(sii->inode);
3155 + SUPERMOUNT_BUG_LOCKED_ON(sb, !err);
3156 +
3157 +out:
3158 + subfs_unlock(sb);
3159 +
3160 + LEAVE(sb, "inode=%p subi=%p", inode, err);
3161 +
3162 + return err;
3163 +}
3164 +
3165 +/* inode methods */
3166 +
3167 +static int
3168 +supermount_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
3169 +{
3170 + struct super_block *sb = dir->i_sb;
3171 + struct dentry *subdent;
3172 + struct inode *subdir;
3173 + int rc;
3174 + struct vfsmount *mnt;
3175 +
3176 + ENTER(sb, "dir=%p dentry=%s", dir, dentry->d_name.name);
3177 +
3178 + mnt = subfs_go_online(sb);
3179 + rc = PTR_ERR(mnt);
3180 + if (IS_ERR(mnt))
3181 + goto out;
3182 +
3183 + subdir = get_subfs_inode(dir);
3184 + rc = PTR_ERR(subdir);
3185 + if (IS_ERR(subdir))
3186 + goto go_offline;
3187 +
3188 + rc = -EACCES;
3189 + if (!subdir->i_op || !subdir->i_op->create)
3190 + goto put_subdir;
3191 +
3192 + subdent = get_subfs_dentry(dentry);
3193 + rc = PTR_ERR(subdent);
3194 + if (IS_ERR(subdent))
3195 + goto put_subdir;
3196 +
3197 + rc = subfs_get_access(dir, 1);
3198 + if (rc)
3199 + goto put_subdent;
3200 +
3201 + /* FIXME build proper nd struct */
3202 + rc = subdir->i_op->create(subdir, subdent, mode, nd);
3203 + subfs_put_access(dir, 1);
3204 + if (rc)
3205 + goto put_subdent;
3206 +
3207 + rc = prepare_inode(dentry, subdent);
3208 + if (rc)
3209 + goto put_subdent;
3210 +
3211 + dir->i_mtime = subdir->i_mtime;
3212 + dir->i_ctime = subdir->i_ctime;
3213 + dir->i_nlink = subdir->i_nlink;
3214 + dir->i_size = subdir->i_size;
3215 + dir->i_blocks = subdir->i_blocks;
3216 +
3217 +put_subdent:
3218 + dput(subdent);
3219 +put_subdir:
3220 + iput(subdir);
3221 +go_offline:
3222 + subfs_go_offline(sb, mnt);
3223 +out:
3224 + LEAVE(sb, "dir=%p dentry=%s rc=%d", dir, dentry->d_name.name, rc);
3225 +
3226 + return rc;
3227 +}
3228 +
3229 +/**
3230 + * Search directory for a matching name
3231 + *
3232 + * @dir: directory that is being searched
3233 + * @dentry: name to search for (in dentry->d_name)
3234 + *
3235 + * This is (currently :) the only method where we do not call subfs
3236 + * directly. The reason is coherency between subfs and superfs dentry
3237 + * caches. It is impossible to ensure it without modifying the very
3238 + * guts of fs/dcache.c; so we check cache before doing actual lookup.
3239 + * lookup_one_len just avoids duplicating of code.
3240 + *
3241 + * Supermount is in exclusive control of subfs so it is garanteed that
3242 + * dentry cannot magically appear in the middle of lookup.
3243 + *
3244 + * There are filesystems that support multiple forms of file name, like
3245 + * case-insensitive or short-long names on NTFS. In this case cache lookup
3246 + * fails but filesystem may return dentry for different name. In this case
3247 + * we check if dentry with matching name exists in parent and reuse it.
3248 + */
3249 +static struct dentry *
3250 +supermount_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
3251 +{
3252 + struct super_block *sb = dir->i_sb;
3253 + struct dentry *rc, *subdent, *subparent;
3254 + struct inode *subdir;
3255 + struct vfsmount *mnt;
3256 + int ret;
3257 +
3258 + ENTER(sb, "dir=%p dentry=%s", dir, dentry->d_name.name);
3259 +
3260 + mnt = subfs_go_online(sb);
3261 + rc = (struct dentry *)mnt;
3262 + if (IS_ERR(mnt))
3263 + goto out;
3264 +
3265 + subdir = get_subfs_inode(dir);
3266 + rc = (struct dentry *)subdir;
3267 + if (IS_ERR(subdir))
3268 + goto go_offline;
3269 +
3270 + subparent = get_subfs_dentry(dentry->d_parent);
3271 + rc = subparent;
3272 + if (IS_ERR(subparent))
3273 + goto put_subdir;
3274 +
3275 + ret = subfs_get_access(dir, 0);
3276 + rc = ERR_PTR(ret);
3277 + if (ret)
3278 + goto put_subparent;
3279 +
3280 + SUPERMOUNT_BUG_ON(subparent->d_inode != subdir);
3281 +
3282 + /* FIXME usually lookup_one_len is called under i_sem */
3283 + /* FIXME what to do with nd? */
3284 + subdent = lookup_one_len(dentry->d_name.name, subparent,
3285 + dentry->d_name.len);
3286 +
3287 + subfs_put_access(dir, 0);
3288 + rc = subdent;
3289 + if (IS_ERR(rc))
3290 + goto put_subparent;
3291 +
3292 + rc = prepare_dentry(dentry, subdent);
3293 + if (IS_ERR(rc))
3294 + goto put_subdent;
3295 +
3296 + if (!rc && subdent->d_inode) {
3297 + ret = prepare_inode(dentry, subdent);
3298 + if (ret < 0)
3299 + rc = ERR_PTR(ret);
3300 + }
3301 +
3302 +put_subdent:
3303 + dput(subdent);
3304 +put_subparent:
3305 + dput(subparent);
3306 +put_subdir:
3307 + iput(subdir);
3308 +go_offline:
3309 + subfs_go_offline(sb, mnt);
3310 +out:
3311 + LEAVE(sb, "dir=%p dentry=%s rc=%p", dir, dentry->d_name.name, rc);
3312 +
3313 + return rc;
3314 +}
3315 +
3316 +static int
3317 +supermount_link(struct dentry *old_dentry, struct inode *dir,
3318 + struct dentry *new_dentry)
3319 +{
3320 + struct super_block *sb = dir->i_sb;
3321 + struct dentry *old_subdent, *new_subdent;
3322 + struct inode *subdir;
3323 + int rc;
3324 + struct vfsmount *mnt;
3325 +
3326 + ENTER(sb, "from=%s dir=%p to=%s", old_dentry->d_name.name, dir, new_dentry->d_name.name);
3327 +
3328 + SUPERMOUNT_BUG_ON(new_dentry->d_inode);
3329 +
3330 + mnt = subfs_go_online(sb);
3331 + rc = PTR_ERR(mnt);
3332 + if (IS_ERR(mnt))
3333 + goto out;
3334 +
3335 + subdir = get_subfs_inode(dir);
3336 + rc = PTR_ERR(subdir);
3337 + if (IS_ERR(subdir))
3338 + goto go_offline;
3339 +
3340 + rc = -EPERM;
3341 + if (!subdir->i_op || !subdir->i_op->link)
3342 + goto put_subdir;
3343 +
3344 + old_subdent = get_subfs_dentry(old_dentry);
3345 + rc = PTR_ERR(old_subdent);
3346 + if (IS_ERR(old_subdent))
3347 + goto put_subdir;
3348 +
3349 + new_subdent = get_subfs_dentry(new_dentry);
3350 + rc = PTR_ERR(new_subdent);
3351 + if (IS_ERR(new_subdent))
3352 + goto put_old_subdent;
3353 +
3354 + rc = subfs_get_access(dir, 1);
3355 + if (rc)
3356 + goto put_new_subdent;
3357 +
3358 + rc = subdir->i_op->link(old_subdent, subdir, new_subdent);
3359 + subfs_put_access(dir, 1);
3360 + if (rc)
3361 + goto put_new_subdent;
3362 +
3363 + rc = prepare_inode(new_dentry, new_subdent);
3364 + if (rc)
3365 + goto put_new_subdent;
3366 +
3367 + dir->i_mtime = subdir->i_mtime;
3368 + dir->i_ctime = subdir->i_ctime;
3369 + dir->i_nlink = subdir->i_nlink;
3370 + dir->i_size = subdir->i_size;
3371 + dir->i_blocks = subdir->i_blocks;
3372 +
3373 +put_new_subdent:
3374 + dput(new_subdent);
3375 +put_old_subdent:
3376 + dput(old_subdent);
3377 +put_subdir:
3378 + iput(subdir);
3379 +go_offline:
3380 + subfs_go_offline(sb, mnt);
3381 +out:
3382 + LEAVE(sb, "from=%s dir=%p to=%s rc=%d", old_dentry->d_name.name, dir, new_dentry->d_name.name, rc);
3383 +
3384 + return rc;
3385 +}
3386 +
3387 +static int
3388 +supermount_unlink(struct inode *dir, struct dentry *dentry)
3389 +{
3390 + struct super_block *sb = dir->i_sb;
3391 + struct dentry *subdent;
3392 + struct inode *subdir;
3393 + int rc;
3394 + struct vfsmount *mnt;
3395 +
3396 + ENTER(sb, "dir=%p dentry=%s", dir, dentry->d_name.name);
3397 +
3398 + mnt = subfs_go_online(sb);
3399 + rc = PTR_ERR(mnt);
3400 + if (IS_ERR(mnt))
3401 + goto out;
3402 +
3403 + subdir = get_subfs_inode(dir);
3404 + rc = PTR_ERR(subdir);
3405 + if (IS_ERR(subdir))
3406 + goto go_offline;
3407 +
3408 + rc = -EPERM;
3409 + if (!subdir->i_op || !subdir->i_op->unlink)
3410 + goto put_subdir;
3411 +
3412 + subdent = get_subfs_dentry(dentry);
3413 + rc = PTR_ERR(subdent);
3414 + if (IS_ERR(subdent))
3415 + goto put_subdir;
3416 +
3417 + /*
3418 + * below is not a typo. We have to mark _deleted_ inode
3419 + * for possible later delete in clear_inode
3420 + */
3421 + rc = subfs_get_access(dentry->d_inode, 1);
3422 + if (rc)
3423 + goto put_subdent;
3424 +
3425 + rc = subdir->i_op->unlink(subdir, subdent);
3426 + if (rc)
3427 + goto put_write_access;
3428 +
3429 + dir->i_mtime = subdir->i_mtime;
3430 + dir->i_ctime = subdir->i_ctime;
3431 + dir->i_nlink = subdir->i_nlink;
3432 + dir->i_size = subdir->i_size;
3433 + dir->i_blocks = subdir->i_blocks;
3434 +
3435 + dentry->d_inode->i_nlink = subdent->d_inode->i_nlink;
3436 + dentry->d_inode->i_ctime = subdent->d_inode->i_ctime;
3437 +
3438 +put_write_access:
3439 + /*
3440 + * we can't put write access if there are pending deletes
3441 + * so we leave it on and let it be put in clear_inode for
3442 + * i_nlink == 0
3443 + *
3444 + * While i_nlink is believed to be atomic here i_count not,
3445 + * so we cannot check && i_count == 0. It is expected that
3446 + * deleted files are kept open only rarely.
3447 + */
3448 + if (dentry->d_inode->i_nlink)
3449 + subfs_put_access(dentry->d_inode, 1);
3450 +put_subdent:
3451 + dput(subdent);
3452 +put_subdir:
3453 + iput(subdir);
3454 +go_offline:
3455 + subfs_go_offline(sb, mnt);
3456 +out:
3457 + LEAVE(sb, "dir=%p dentry=%s rc=%d", dir, dentry->d_name.name, rc);
3458 +
3459 + return rc;
3460 +}
3461 +
3462 +static int
3463 +supermount_symlink(struct inode *dir, struct dentry *dentry,
3464 + const char *symname)
3465 +{
3466 + struct super_block *sb = dir->i_sb;
3467 + struct dentry *subdent;
3468 + struct inode *subdir;
3469 + int rc;
3470 + struct vfsmount *mnt;
3471 +
3472 + ENTER(sb, "dir=%p dentry=%s", dir, dentry->d_name.name);
3473 +
3474 + mnt = subfs_go_online(sb);
3475 + rc = PTR_ERR(mnt);
3476 + if (IS_ERR(mnt))
3477 + goto out;
3478 +
3479 + subdir = get_subfs_inode(dir);
3480 + rc = PTR_ERR(subdir);
3481 + if (IS_ERR(subdir))
3482 + goto go_offline;
3483 +
3484 + rc = -EPERM;
3485 + if (!subdir->i_op || !subdir->i_op->symlink)
3486 + goto put_subdir;
3487 +
3488 + subdent = get_subfs_dentry(dentry);
3489 + rc = PTR_ERR(subdent);
3490 + if (IS_ERR(subdent))
3491 + goto put_subdir;
3492 +
3493 + rc = subfs_get_access(dir, 1);
3494 + if (rc)
3495 + goto put_subdent;
3496 +
3497 + rc = subdir->i_op->symlink(subdir, subdent, symname);
3498 + subfs_put_access(dir, 1);
3499 + if (rc)
3500 + goto put_subdent;
3501 +
3502 + rc = prepare_inode(dentry, subdent);
3503 + if (rc)
3504 + goto put_subdent;
3505 +
3506 + dir->i_mtime = subdir->i_mtime;
3507 + dir->i_ctime = subdir->i_ctime;
3508 + dir->i_nlink = subdir->i_nlink;
3509 + dir->i_size = subdir->i_size;
3510 + dir->i_blocks = subdir->i_blocks;
3511 +
3512 +put_subdent:
3513 + dput(subdent);
3514 +put_subdir:
3515 + iput(subdir);
3516 +go_offline:
3517 + subfs_go_offline(sb, mnt);
3518 +out:
3519 + LEAVE(sb, "dir=%p dentry=%s rc=%d", dir, dentry->d_name.name, rc);
3520 +
3521 + return rc;
3522 +}
3523 +
3524 +static int
3525 +supermount_mkdir(struct inode *dir, struct dentry *dentry, int mode)
3526 +{
3527 + struct super_block *sb = dir->i_sb;
3528 + struct dentry *subdent;
3529 + struct inode *subdir;
3530 + int rc;
3531 + struct vfsmount *mnt;
3532 +
3533 + ENTER(sb, "dir=%p dentry=%s", dir, dentry->d_name.name);
3534 +
3535 + mnt = subfs_go_online(sb);
3536 + rc = PTR_ERR(mnt);
3537 + if (IS_ERR(mnt))
3538 + goto out;
3539 +
3540 + subdir = get_subfs_inode(dir);
3541 + rc = PTR_ERR(subdir);
3542 + if (IS_ERR(subdir))
3543 + goto go_offline;
3544 +
3545 + rc = -EPERM;
3546 + if (!subdir->i_op || !subdir->i_op->mkdir)
3547 + goto put_subdir;
3548 +
3549 + subdent = get_subfs_dentry(dentry);
3550 + rc = PTR_ERR(subdent);
3551 + if (IS_ERR(subdent))
3552 + goto put_subdir;
3553 +
3554 + rc = subfs_get_access(dir, 1);
3555 + if (rc)
3556 + goto put_subdent;
3557 +
3558 + rc = subdir->i_op->mkdir(subdir, subdent, mode);
3559 + subfs_put_access(dir, 1);
3560 + if (rc)
3561 + goto put_subdent;
3562 +
3563 + rc = prepare_inode(dentry, subdent);
3564 + if (rc)
3565 + goto put_subdent;
3566 +
3567 + dir->i_mtime = subdir->i_mtime;
3568 + dir->i_ctime = subdir->i_ctime;
3569 + dir->i_nlink = subdir->i_nlink;
3570 + dir->i_size = subdir->i_size;
3571 + dir->i_blocks = subdir->i_blocks;
3572 +
3573 +put_subdent:
3574 + dput(subdent);
3575 +put_subdir:
3576 + iput(subdir);
3577 +go_offline:
3578 + subfs_go_offline(sb, mnt);
3579 +out:
3580 + LEAVE(sb, "dir=%p dentry=%s rc=%d", dir, dentry->d_name.name, rc);
3581 +
3582 + return rc;
3583 +}
3584 +
3585 +static int
3586 +supermount_rmdir(struct inode *dir, struct dentry *dentry)
3587 +{
3588 + struct super_block *sb = dir->i_sb;
3589 + struct dentry *subdent;
3590 + struct inode *subdir;
3591 + int rc;
3592 + struct vfsmount *mnt;
3593 +
3594 + ENTER(sb, "dir=%p dentry=%s", dir, dentry->d_name.name);
3595 +
3596 + mnt = subfs_go_online(sb);
3597 + rc = PTR_ERR(mnt);
3598 + if (IS_ERR(mnt))
3599 + goto out;
3600 +
3601 + subdir = get_subfs_inode(dir);
3602 + rc = PTR_ERR(subdir);
3603 + if (IS_ERR(subdir))
3604 + goto go_offline;
3605 +
3606 + rc = -EPERM;
3607 + if (!subdir->i_op || !subdir->i_op->rmdir)
3608 + goto put_subdir;
3609 +
3610 + subdent = get_subfs_dentry(dentry);
3611 + rc = PTR_ERR(subdent);
3612 + if (IS_ERR(subdent))
3613 + goto put_subdir;
3614 +
3615 + /* cf. supermount_unlink */
3616 + rc = subfs_get_access(dentry->d_inode, 1);
3617 + if (rc)
3618 + goto put_subdent;
3619 +
3620 + rc = subdir->i_op->rmdir(subdir, subdent);
3621 + if (rc)
3622 + goto put_write_access;
3623 +
3624 + dir->i_mtime = subdir->i_mtime;
3625 + dir->i_ctime = subdir->i_ctime;
3626 + dir->i_nlink = subdir->i_nlink;
3627 + dir->i_size = subdir->i_size;
3628 + dir->i_blocks = subdir->i_blocks;
3629 +
3630 + /* hmm ... hard links to directories are not allowed, are they? */
3631 + dentry->d_inode->i_nlink = subdent->d_inode->i_nlink;
3632 + dentry->d_inode->i_ctime = subdent->d_inode->i_ctime;
3633 +
3634 +put_write_access:
3635 + /* cf. supermount_unlink */
3636 + if (dentry->d_inode->i_nlink)
3637 + subfs_put_access(dentry->d_inode, 1);
3638 +put_subdent:
3639 + dput(subdent);
3640 +put_subdir:
3641 + iput(subdir);
3642 +go_offline:
3643 + subfs_go_offline(sb, mnt);
3644 +out:
3645 + LEAVE(sb, "dir=%p dentry=%s rc=%d", dir, dentry->d_name.name, rc);
3646 +
3647 + return rc;
3648 +}
3649 +
3650 +static int
3651 +supermount_mknod(struct inode *dir, struct dentry *dentry, int
3652 + mode, dev_t dev)
3653 +{
3654 + struct super_block *sb = dir->i_sb;
3655 + struct dentry *subdent;
3656 + struct inode *subdir;
3657 + int rc;
3658 + struct vfsmount *mnt;
3659 +
3660 + ENTER(sb, "dir=%p dentry=%s", dir, dentry->d_name.name);
3661 +
3662 + mnt = subfs_go_online(sb);
3663 + rc = PTR_ERR(mnt);
3664 + if (IS_ERR(mnt))
3665 + goto out;
3666 +
3667 + subdir = get_subfs_inode(dir);
3668 + rc = PTR_ERR(subdir);
3669 + if (IS_ERR(subdir))
3670 + goto go_offline;
3671 +
3672 + rc = -EPERM;
3673 + if (!subdir->i_op || !subdir->i_op->mknod)
3674 + goto put_subdir;
3675 +
3676 + subdent = get_subfs_dentry(dentry);
3677 + rc = PTR_ERR(subdent);
3678 + if (IS_ERR(subdent))
3679 + goto put_subdir;
3680 +
3681 + rc = subfs_get_access(dir, 1);
3682 + if (rc)
3683 + goto put_subdent;
3684 +
3685 + rc = subdir->i_op->mknod(subdir, subdent, mode, dev);
3686 + subfs_put_access(dir, 1);
3687 + if (rc)
3688 + goto put_subdent;
3689 +
3690 + rc = prepare_inode(dentry, subdent);
3691 + if (rc)
3692 + goto put_subdent;
3693 +
3694 + dir->i_mtime = subdir->i_mtime;
3695 + dir->i_ctime = subdir->i_ctime;
3696 + dir->i_nlink = subdir->i_nlink;
3697 + dir->i_size = subdir->i_size;
3698 + dir->i_blocks = subdir->i_blocks;
3699 +
3700 +put_subdent:
3701 + dput(subdent);
3702 +put_subdir:
3703 + iput(subdir);
3704 +go_offline:
3705 + subfs_go_offline(sb, mnt);
3706 +out:
3707 + LEAVE(sb, "dir=%p dentry=%s rc=%d", dir, dentry->d_name.name, rc);
3708 +
3709 + return rc;
3710 +}
3711 +
3712 +static int
3713 +supermount_rename(struct inode *olddir, struct dentry *olddentry,
3714 + struct inode *newdir, struct dentry *newdentry)
3715 +{
3716 + struct super_block *sb = olddir->i_sb;
3717 + struct dentry *oldsubdent, *newsubdent;
3718 + struct inode *oldsubdir, *newsubdir;
3719 + int rc;
3720 + struct vfsmount *mnt;
3721 +
3722 + ENTER(sb, "olddir=%p olddentry=%s newdir=%p newdentry=%s", olddir, olddentry->d_name.name, newdir, newdentry->d_name.name);
3723 +
3724 + mnt = subfs_go_online(sb);
3725 + rc = PTR_ERR(mnt);
3726 + if (IS_ERR(mnt))
3727 + goto out;
3728 +
3729 + oldsubdir = get_subfs_inode(olddir);
3730 + rc = PTR_ERR(oldsubdir);
3731 + if (IS_ERR(oldsubdir))
3732 + goto go_offline;
3733 +
3734 + rc = -EPERM;
3735 + if (!oldsubdir->i_op || !oldsubdir->i_op->rename)
3736 + goto put_old_subdir;
3737 +
3738 + oldsubdent = get_subfs_dentry(olddentry);
3739 + rc = PTR_ERR(oldsubdent);
3740 + if (IS_ERR(oldsubdent))
3741 + goto put_old_subdir;
3742 +
3743 + newsubdir = get_subfs_inode(newdir);
3744 + rc = PTR_ERR(newsubdir);
3745 + if (IS_ERR(newsubdir))
3746 + goto put_old_subdent;
3747 +
3748 + newsubdent = get_subfs_dentry(newdentry);
3749 + rc = PTR_ERR(newsubdent);
3750 + if (IS_ERR(newsubdent))
3751 + goto put_new_subdir;
3752 +
3753 + /*
3754 + * If new file exists it will be implcitly unlinked so
3755 + * behave like in unlink case.
3756 + * If it does not exist we have two write accesses - for
3757 + * both old and new directory, I guess it does not matter
3758 + * which one is used in this case
3759 + */
3760 + if (newdentry->d_inode)
3761 + rc = subfs_get_access(newdentry->d_inode, 1);
3762 + else
3763 + rc = subfs_get_access(olddir, 1);
3764 + if (rc)
3765 + goto put_new_subdent;
3766 +
3767 + rc = oldsubdir->i_op->rename(oldsubdir, oldsubdent,
3768 + newsubdir, newsubdent);
3769 + if (rc)
3770 + goto put_write_access;
3771 +
3772 + /*
3773 + * this is strictly speaking conditional on FS_ODD_RENAME
3774 + * flag, but as of this writing this flag is set only
3775 + * for NFS or intermezzo and it hopefully goes away sometimes ...
3776 + *
3777 + * Supermount patch adds code to do_kern_mount that checks
3778 + * for this flag and refuses mounting
3779 + */
3780 + d_move(oldsubdent, newsubdent);
3781 +
3782 + olddir->i_mtime = oldsubdir->i_mtime;
3783 + olddir->i_ctime = oldsubdir->i_ctime;
3784 + olddir->i_nlink = oldsubdir->i_nlink;
3785 + olddir->i_size = oldsubdir->i_size;
3786 + olddir->i_blocks = oldsubdir->i_blocks;
3787 +
3788 + newdir->i_mtime = newsubdir->i_mtime;
3789 + newdir->i_ctime = newsubdir->i_ctime;
3790 + newdir->i_nlink = newsubdir->i_nlink;
3791 + newdir->i_size = newsubdir->i_size;
3792 + newdir->i_blocks = newsubdir->i_blocks;
3793 +
3794 + olddentry->d_inode->i_nlink = oldsubdent->d_inode->i_nlink;
3795 + olddentry->d_inode->i_ctime = oldsubdent->d_inode->i_ctime;
3796 +
3797 + if (newdentry->d_inode) {
3798 + newdentry->d_inode->i_nlink = newsubdent->d_inode->i_nlink;
3799 + newdentry->d_inode->i_ctime = newsubdent->d_inode->i_ctime;
3800 + }
3801 +
3802 +put_write_access:
3803 + if (newdentry->d_inode) {
3804 + /* cf. supermount_unlink */
3805 + if (newdentry->d_inode->i_nlink)
3806 + subfs_put_access(newdentry->d_inode, 1);
3807 + } else
3808 + subfs_put_access(olddir, 1);
3809 +put_new_subdent:
3810 + dput(newsubdent);
3811 +put_new_subdir:
3812 + iput(newsubdir);
3813 +put_old_subdent:
3814 + dput(oldsubdent);
3815 +put_old_subdir:
3816 + iput(oldsubdir);
3817 +go_offline:
3818 + subfs_go_offline(sb, mnt);
3819 +out:
3820 + LEAVE(sb, "olddentry=%s newdentry=%s rc=%d", olddentry->d_name.name, newdentry->d_name.name, rc);
3821 +
3822 + return rc;
3823 +}
3824 +
3825 +static int
3826 +supermount_readlink(struct dentry *dentry, char *buffer , int buflen)
3827 +{
3828 + struct super_block *sb = dentry->d_sb;
3829 + struct inode *inode = dentry->d_inode;
3830 + struct dentry *subdent;
3831 + int write_on = NEED_WRITE_ATIME(inode);
3832 + int rc;
3833 + struct vfsmount *mnt;
3834 +
3835 + ENTER(sb, "dentry=%s", dentry->d_name.name);
3836 +
3837 + mnt = subfs_go_online(sb);
3838 + rc = PTR_ERR(mnt);
3839 + if (IS_ERR(mnt))
3840 + goto out;
3841 +
3842 + subdent = get_subfs_dentry(dentry);
3843 + rc = PTR_ERR(subdent);
3844 + if (IS_ERR(subdent))
3845 + goto go_offline;
3846 +
3847 + rc = -EINVAL;
3848 + if (!subdent->d_inode->i_op || !subdent->d_inode->i_op->readlink)
3849 + goto put_subdent;
3850 +
3851 + rc = subfs_get_access(inode, write_on);
3852 + if (rc)
3853 + goto put_subdent;
3854 +
3855 + update_atime(subdent->d_inode);
3856 + rc = subdent->d_inode->i_op->readlink(subdent, buffer, buflen);
3857 + subfs_put_access(inode, write_on);
3858 + inode->i_atime = subdent->d_inode->i_atime;
3859 +
3860 +put_subdent:
3861 + dput(subdent);
3862 +go_offline:
3863 + subfs_go_offline(sb, mnt);
3864 +out:
3865 + LEAVE(sb, "dentry=%s rc=%d", dentry->d_name.name, rc);
3866 +
3867 + return rc;
3868 +}
3869 +
3870 +static int
3871 +supermount_follow_link(struct dentry *dentry, struct nameidata *nd)
3872 +{
3873 + struct super_block *sb = dentry->d_sb;
3874 + struct inode *inode = dentry->d_inode;
3875 + struct dentry *subdent;
3876 + int write_on = NEED_WRITE_ATIME(inode);
3877 + int rc;
3878 + struct vfsmount *mnt;
3879 +
3880 + ENTER(sb, "dentry=%s", dentry->d_name.name);
3881 +
3882 + mnt = subfs_go_online(sb);
3883 + rc = PTR_ERR(mnt);
3884 + if (IS_ERR(mnt))
3885 + goto out;
3886 +
3887 + subdent = get_subfs_dentry(dentry);
3888 + rc = PTR_ERR(subdent);
3889 + if (IS_ERR(subdent))
3890 + goto go_offline;
3891 +
3892 + rc = subfs_get_access(inode, write_on);
3893 + if (rc)
3894 + goto put_subdent;
3895 +
3896 + update_atime(subdent->d_inode);
3897 + /* FIXME do we need proper subfs nd here? */
3898 + rc = subdent->d_inode->i_op->follow_link(subdent, nd);
3899 + subfs_put_access(inode, write_on);
3900 + inode->i_atime = subdent->d_inode->i_atime;
3901 +
3902 +put_subdent:
3903 + dput(subdent);
3904 +go_offline:
3905 + subfs_go_offline(sb, mnt);
3906 +out:
3907 + LEAVE(sb, "dentry=%s rc=%d", dentry->d_name.name, rc);
3908 +
3909 + return rc;
3910 +}
3911 +
3912 +static int
3913 +supermount_permission(struct inode *inode, int mask, struct nameidata *nd)
3914 +{
3915 + struct super_block *sb = inode->i_sb;
3916 + struct inode *subi;
3917 + int rc;
3918 + int write_on = !IS_RDONLY(inode) && (mask & MAY_WRITE);
3919 + struct vfsmount *mnt;
3920 + int fake_permissions = 1;
3921 +
3922 + ENTER(sb, "inode=%p", inode);
3923 +
3924 + mnt = subfs_go_online(sb);
3925 + rc = PTR_ERR(mnt);
3926 + if (IS_ERR(mnt))
3927 + goto out;
3928 +
3929 + subi = get_subfs_inode(inode);
3930 + rc = PTR_ERR(subi);
3931 + if (IS_ERR(subi))
3932 + goto go_offline;
3933 +
3934 + rc = subfs_get_access(inode, write_on);
3935 + if (rc)
3936 + goto put_subi;
3937 +
3938 + fake_permissions = 0;
3939 + /* FIXME do we need proper subfs nd here */
3940 + if (subi->i_op && subi->i_op->permission)
3941 + rc = subi->i_op->permission(subi, mask, nd);
3942 + else
3943 + rc = vfs_permission(subi, mask);
3944 +
3945 + subfs_put_access(inode, write_on);
3946 +
3947 +put_subi:
3948 + iput(subi);
3949 +go_offline:
3950 + subfs_go_offline(sb, mnt);
3951 +out:
3952 + if (fake_permissions && inode == sb->s_root->d_inode) {
3953 + /* cf. file.c:supermount_open() */
3954 + rc = vfs_permission(inode, mask);
3955 + }
3956 +
3957 + LEAVE(sb, "inode=%p rc=%d fake=%d", inode, rc, fake_permissions);
3958 +
3959 + return rc;
3960 +}
3961 +
3962 +static int
3963 +supermount_setattr(struct dentry *dentry, struct iattr *attr)
3964 +{
3965 + struct super_block *sb = dentry->d_sb;
3966 + struct inode *subi;
3967 + struct dentry *subdent;
3968 + int rc;
3969 + struct vfsmount *mnt;
3970 +
3971 + ENTER(sb, "dentry=%s", dentry->d_name.name);
3972 +
3973 + mnt = subfs_go_online(sb);
3974 + rc = PTR_ERR(mnt);
3975 + if (IS_ERR(mnt))
3976 + goto out;
3977 +
3978 + subdent = get_subfs_dentry(dentry);
3979 + rc = PTR_ERR(subdent);
3980 + if (IS_ERR(subdent))
3981 + goto go_offline;
3982 +
3983 + rc = subfs_get_access(dentry->d_inode, 1);
3984 + if (rc)
3985 + goto put_subdent;
3986 +
3987 + subi = subdent->d_inode;
3988 + if (subi->i_op && subi->i_op->setattr)
3989 + rc = subi->i_op->setattr(subdent, attr);
3990 + else {
3991 + rc = inode_change_ok(subi, attr);
3992 + /*
3993 + * FIXME
3994 + * What to do with quota?
3995 + */
3996 + if (!rc)
3997 + rc = inode_setattr(subi, attr);
3998 + }
3999 + subfs_put_access(dentry->d_inode, 1);
4000 + if (rc)
4001 + goto put_subdent;
4002 +
4003 + /*
4004 + * If it worked, then we need to mark the modification
4005 + * to the subfs, and we also need to propogate the
4006 + * change up to the shadowing inode.
4007 + */
4008 + attr->ia_mode = subi->i_mode;
4009 + attr->ia_uid = subi->i_uid;
4010 + attr->ia_gid = subi->i_gid;
4011 + attr->ia_size = subi->i_size;
4012 + attr->ia_atime = subi->i_atime;
4013 + attr->ia_mtime = subi->i_mtime;
4014 + attr->ia_ctime = subi->i_ctime;
4015 + attr->ia_valid =
4016 + ATTR_UID | ATTR_GID | ATTR_MODE | ATTR_SIZE |
4017 + ATTR_ATIME | ATTR_MTIME | ATTR_CTIME;
4018 + inode_setattr(dentry->d_inode, attr);
4019 +
4020 +put_subdent:
4021 + dput(subdent);
4022 +go_offline:
4023 + subfs_go_offline(sb, mnt);
4024 +out:
4025 + LEAVE(sb, "dentry=%s rc=%d", dentry->d_name.name, rc);
4026 +
4027 + return rc;
4028 +}
4029 +
4030 +static int
4031 +supermount_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
4032 +{
4033 + struct super_block *sb = dentry->d_sb;
4034 + struct vfsmount *submnt;
4035 + struct dentry *subdent = 0;
4036 + int rc;
4037 +
4038 + ENTER(sb, "dentry=%s", dentry->d_name.name);
4039 +
4040 + /*
4041 + * do not use subfs_go_online - it will result in ls /mnt
4042 + * attempting to mount all supermounted directories
4043 + */
4044 + submnt = subfs_prevent_umount(sb);
4045 + if (submnt)
4046 + subdent = get_subfs_dentry(dentry);
4047 +
4048 + /*
4049 + * do not fail stat for stale files - it is needed to
4050 + * make sure fuser -m /mnt/cdrom lists all processes still
4051 + * having any (obsolete) file open
4052 + */
4053 + if (submnt && subdent && !IS_ERR(subdent)) {
4054 + rc = vfs_getattr(submnt, subdent, stat);
4055 + stat->dev = sb->s_dev;
4056 + } else {
4057 + subfs_lock(sb);
4058 + generic_fillattr(dentry->d_inode, stat);
4059 + subfs_unlock(sb);
4060 + rc = 0;
4061 + }
4062 +
4063 + if (subdent && !IS_ERR(subdent))
4064 + dput(subdent);
4065 + if (submnt)
4066 + subfs_allow_umount(sb, submnt);
4067 +
4068 + LEAVE(sb, "dentry=%s rc=%d", dentry->d_name.name, rc);
4069 +
4070 + return rc;
4071 +}
4072 +
4073 +/*
4074 + * directories can handle most operations... supermount/namei.c just
4075 + * passes them through to the underlying subfs, except for lookup().
4076 + */
4077 +
4078 +/* truncate: is not necesary, handled with setattr
4079 + * revalidate: only needed by nfs
4080 + * ->getattr: FIXME is not appeared to be used anywhere in kernel; so I am
4081 + * not sure how to implement it or what to return
4082 + * FIXME: implement accl functions
4083 + */
4084 +
4085 +struct inode_operations supermount_dir_iops = {
4086 + .create = supermount_create,
4087 + .lookup = supermount_lookup,
4088 + .link = supermount_link,
4089 + .unlink = supermount_unlink,
4090 + .symlink = supermount_symlink,
4091 + .mkdir = supermount_mkdir,
4092 + .rmdir = supermount_rmdir,
4093 + .mknod = supermount_mknod,
4094 + .rename = supermount_rename,
4095 + .permission = supermount_permission,
4096 + .setattr = supermount_setattr,
4097 + .getattr = supermount_getattr,
4098 +};
4099 +
4100 +struct inode_operations supermount_symlink_iops = {
4101 + .readlink = supermount_readlink,
4102 + .follow_link = supermount_follow_link,
4103 + .setattr = supermount_setattr,
4104 + .getattr = supermount_getattr,
4105 +};
4106 +
4107 +struct inode_operations supermount_file_iops = {
4108 + .setattr = supermount_setattr,
4109 + .getattr = supermount_getattr,
4110 +};
4111 diff -ruN linux-2.6.2-rc1.old/fs/supermount/proc.c linux-2.6.2-rc1/fs/supermount/proc.c
4112 --- linux-2.6.2-rc1.old/fs/supermount/proc.c 1969-12-31 19:00:00.000000000 -0500
4113 +++ linux-2.6.2-rc1/fs/supermount/proc.c 2004-01-24 11:46:38.891348608 -0500
4114 @@ -0,0 +1,289 @@
4115 +/*
4116 + * linux/fs/supermount/proc.c
4117 + *
4118 + * Initial version for kernel 2.4.21 (C) 2003 Andrey Borzenkov
4119 + * (arvidjaar@mail.ru)
4120 + * Rewritten for kernel 2.5.70 (C) 2003 Andrey Borzenkov
4121 + * (arvidjaar@mail.ru)
4122 + *
4123 + * $Id: 401_supermount-2.0.4-2.6.2_rc1.patch,v 1.1 2004/01/26 22:15:04 johnm Exp $
4124 + */
4125 +
4126 +#include "supermount.h"
4127 +
4128 +#ifdef CONFIG_PROC_FS
4129 +
4130 +/*
4131 + * we use semaphore because we have to lock subfs inside and it can
4132 + * sleep. Unlocking procfs list would mean adding generic usage count
4133 + * management to sbi and this is far too fetching
4134 + */
4135 +
4136 +static DECLARE_MUTEX(supermount_proc_sem);
4137 +static struct proc_dir_entry *supermount_proc_root;
4138 +static struct proc_dir_entry *supermount_proc_subfs;
4139 +static struct proc_dir_entry *supermount_proc_version;
4140 +static struct supermount_sb_info *supermount_list_head;
4141 +
4142 +#define SKIP_BLANKS(s) while(*s == ' ' || *s == '\t' || *s == '\n') s++
4143 +#define CHECK_COUNT do { \
4144 + size += n; \
4145 + count -= n; \
4146 + if (count <= 0) { \
4147 + subfs_unlock(sbi->host); \
4148 + break; \
4149 + } \
4150 +} while (0)
4151 +
4152 +/* iterator; shamelessly copied over from pci.c */
4153 +static void *supermount_seq_start(struct seq_file *sf, loff_t *pos)
4154 +{
4155 + struct supermount_sb_info *sbi;
4156 + loff_t n = *pos;
4157 +
4158 + down(&supermount_proc_sem);
4159 +
4160 + sbi = supermount_list_head;
4161 + while (n-- && sbi)
4162 + sbi = sbi->next;
4163 +
4164 + return sbi;
4165 +}
4166 +
4167 +static void *supermount_seq_next(struct seq_file *sf, void *v, loff_t *pos)
4168 +{
4169 + struct supermount_sb_info *sbi = v;
4170 + (*pos)++;
4171 + return sbi->next;
4172 +}
4173 +
4174 +static void supermount_seq_stop(struct seq_file *sf, void *v)
4175 +{
4176 + up(&supermount_proc_sem);
4177 +}
4178 +
4179 +
4180 +static int
4181 +supermount_show_sbi(struct seq_file *sf, void *v)
4182 +{
4183 + struct supermount_sb_info *sbi = v;
4184 +
4185 +
4186 + subfs_lock(sbi->host);
4187 + seq_puts(sf, sbi->devname);
4188 + if (sbi->disabled)
4189 + seq_puts(sf, " disabled\n");
4190 + else if (subfs_is_mounted(sbi->host))
4191 + seq_printf(sf, " mounted %d %d\n",
4192 + sbi->readcount, sbi->writecount);
4193 + else
4194 + seq_puts(sf, " unmounted\n");
4195 + subfs_unlock(sbi->host);
4196 +
4197 + return 0;
4198 +}
4199 +
4200 +static struct seq_operations supermount_proc_subfs_op = {
4201 + start: supermount_seq_start,
4202 + next: supermount_seq_next,
4203 + stop: supermount_seq_stop,
4204 + show: supermount_show_sbi
4205 +};
4206 +
4207 +static int supermount_proc_subfs_open(struct inode *inode, struct file *file)
4208 +{
4209 + return seq_open(file, &supermount_proc_subfs_op);
4210 +}
4211 +
4212 +/*
4213 + * mostly copied over from drivers/scsi/scsi.c:proc_scsi_gen_write()
4214 + */
4215 +static int
4216 +supermount_proc_subfs_write(struct file *file, const char *buf, size_t length, loff_t *offset)
4217 +{
4218 + char *buffer, *s, *dev = 0;
4219 + int disable = 0, enable = 0, release = 0, force = 0;
4220 + struct supermount_sb_info *sbi;
4221 + size_t rc;
4222 +
4223 + rc = -EINVAL;
4224 + if (!buf || length > PAGE_SIZE)
4225 + goto out;
4226 +
4227 + rc = -ENOMEM;
4228 + if (!(s = buffer = (char *)__get_free_page(GFP_KERNEL)))
4229 + goto out;
4230 +
4231 + rc =-EFAULT;
4232 + if(copy_from_user(buffer, buf, length))
4233 + goto free_buffer;
4234 +
4235 + rc = -EINVAL;
4236 + if (length < PAGE_SIZE)
4237 + buffer[length] = '\0';
4238 + else if (buffer[PAGE_SIZE-1])
4239 + goto free_buffer;
4240 +
4241 + /*
4242 + * echo "/dev/cdrom [enable|disable] [release [force]]" > \
4243 + * /proc/fs/supermount/subfs
4244 + */
4245 +
4246 + do {
4247 + char *p;
4248 +
4249 + SKIP_BLANKS(s);
4250 + p = strpbrk(s, " \t\n");
4251 + if (p)
4252 + *p++ = '\0';
4253 + if (!dev)
4254 + dev = s;
4255 + else if (!strcmp(s, "disable"))
4256 + disable = 1;
4257 + else if (!strcmp(s, "enable"))
4258 + enable = 1;
4259 + else if (!strcmp(s, "release"))
4260 + release = 1;
4261 + else if (!strcmp(s, "force"))
4262 + force = 1;
4263 + else
4264 + goto free_buffer;
4265 +
4266 + s = p;
4267 + } while (s && *s);
4268 +
4269 + if ((enable && disable) || (force && !release))
4270 + goto free_buffer;
4271 +
4272 + down(&supermount_proc_sem);
4273 + for(sbi = supermount_list_head; sbi; sbi = sbi->next) {
4274 + if (strcmp(sbi->devname, dev))
4275 + continue;
4276 +
4277 + subfs_lock(sbi->host);
4278 +
4279 + rc = length;
4280 + if (release && subfs_is_mounted(sbi->host)) {
4281 + if (!subfs_is_busy(sbi->host) || force)
4282 + subfs_umount(sbi->host, SUBFS_UMNT_USER);
4283 + else
4284 + rc = -EBUSY;
4285 + }
4286 +
4287 + if (disable && subfs_is_mounted(sbi->host))
4288 + rc = -EBUSY;
4289 +
4290 + if (rc >= 0) {
4291 + if (disable)
4292 + sbi->disabled = 1;
4293 + else if (enable)
4294 + sbi->disabled = 0;
4295 + }
4296 +
4297 + subfs_unlock(sbi->host);
4298 + break;
4299 + }
4300 + up(&supermount_proc_sem);
4301 +
4302 +free_buffer:
4303 + free_page((unsigned long)buffer);
4304 +out:
4305 + return rc;
4306 +
4307 +}
4308 +
4309 +static struct file_operations supermount_proc_subfs_operations = {
4310 + open: supermount_proc_subfs_open,
4311 + read: seq_read,
4312 + llseek: seq_lseek,
4313 + release: seq_release,
4314 + write: supermount_proc_subfs_write,
4315 +};
4316 +
4317 +static int
4318 +supermount_proc_version_read(char *page, char **start, off_t pos, int count, int *eof, void *data)
4319 +{
4320 + int rc;
4321 +
4322 + rc = snprintf(page, count, "Supermount version %s for kernel 2.6\n",
4323 + SUPERMOUNT_VERSION);
4324 + *eof = 1;
4325 + return rc;
4326 +}
4327 +
4328 +void
4329 +supermount_proc_register(void)
4330 +{
4331 + supermount_proc_root = proc_mkdir("fs/supermount", 0);
4332 + if (!supermount_proc_root) {
4333 + printk(KERN_ERR "SUPERMOUNT failed to create /proc/fs/supermount");
4334 + return;
4335 + }
4336 + supermount_proc_root->owner = THIS_MODULE;
4337 +
4338 + supermount_proc_version = create_proc_read_entry("version",
4339 + S_IFREG | S_IRUGO,
4340 + supermount_proc_root,
4341 + supermount_proc_version_read,
4342 + 0);
4343 +
4344 + if (supermount_proc_version)
4345 + supermount_proc_version->owner = THIS_MODULE;
4346 + else
4347 + printk(KERN_ERR
4348 + "SUPERMOUNT failed to create /proc/fs/supermount/version");
4349 +
4350 + supermount_proc_subfs = create_proc_entry("subfs",
4351 + S_IFREG | S_IRUGO | S_IWUSR,
4352 + supermount_proc_root);
4353 +
4354 + if (supermount_proc_subfs) {
4355 + supermount_proc_subfs->proc_fops =
4356 + &supermount_proc_subfs_operations;
4357 + supermount_proc_subfs->owner = THIS_MODULE;
4358 + } else
4359 + printk(KERN_ERR
4360 + "SUPERMOUNT failed to create /proc/fs/supermount/subfs");
4361 +
4362 +}
4363 +
4364 +void
4365 +supermount_proc_unregister(void)
4366 +{
4367 + remove_proc_entry("fs/supermount/subfs", 0);
4368 + remove_proc_entry("fs/supermount/version", 0);
4369 + remove_proc_entry("fs/supermount", 0);
4370 +}
4371 +
4372 +void
4373 +supermount_proc_insert(struct supermount_sb_info *sbi)
4374 +{
4375 +
4376 + down(&supermount_proc_sem);
4377 +
4378 + sbi->next = supermount_list_head;
4379 + supermount_list_head = sbi;
4380 +
4381 + up(&supermount_proc_sem);
4382 +}
4383 +
4384 +void
4385 +supermount_proc_remove(struct supermount_sb_info *sbi)
4386 +{
4387 + struct supermount_sb_info **p, *q;
4388 +
4389 + down(&supermount_proc_sem);
4390 +
4391 + for(p = &supermount_list_head, q = supermount_list_head;
4392 + q; p = &q->next, q = q->next)
4393 + if (q == sbi)
4394 + break;
4395 +
4396 + if (q)
4397 + *p = q->next;
4398 +
4399 + up(&supermount_proc_sem);
4400 +
4401 + SUPERMOUNT_BUG_ON(!q);
4402 +}
4403 +#endif /* CONFIG_PROC_FS */
4404 diff -ruN linux-2.6.2-rc1.old/fs/supermount/subfs.c linux-2.6.2-rc1/fs/supermount/subfs.c
4405 --- linux-2.6.2-rc1.old/fs/supermount/subfs.c 1969-12-31 19:00:00.000000000 -0500
4406 +++ linux-2.6.2-rc1/fs/supermount/subfs.c 2004-01-24 11:46:38.892348456 -0500
4407 @@ -0,0 +1,742 @@
4408 +/*
4409 + * linux/fs/supermount/subfs.c
4410 + *
4411 + * Original version:
4412 + * Copyright (C) 1995, 1997
4413 + * Stephen Tweedie (sct@dcs.ed.ac.uk)
4414 + *
4415 + * from
4416 + *
4417 + * linux/fs/minix/inode.c
4418 + * Copyright (C) 1991, 1992 Linus Torvalds
4419 + *
4420 + * and
4421 + *
4422 + * linux/fs/ext2/super.c
4423 + * Copyright (C) 1992, 1993, 1994, 1995 Remy Card
4424 + *
4425 + * Rewriten for kernel 2.2, 2.4. (C) 1999, 2000 Alexis Mikhailov
4426 + * (alexis@abc.cap.ru)
4427 + * Rewritten for kernel 2.4.21 (C) 2003 Andrey Borzenkov
4428 + * (arvidjaar@mail.ru)
4429 + * Rewritten for kernel 2.5.70 (C) 2003 Andrey Borzenkov
4430 + * (arvidjaar@mail.ru)
4431 + *
4432 + * $Id: 401_supermount-2.0.4-2.6.2_rc1.patch,v 1.1 2004/01/26 22:15:04 johnm Exp $
4433 + */
4434 +
4435 +#define S_DBG_TRACE_CURRENT S_DBG_TRACE_SUBFS
4436 +#include "supermount.h"
4437 +
4438 +/*
4439 + * close all open files on subfs
4440 + */
4441 +static void
4442 +supermount_clean_files(struct super_block *sb)
4443 +{
4444 + struct supermount_sb_info *sbi = supermount_sbi(sb);
4445 + struct list_head *ptr, *n;
4446 +
4447 + ENTER(sb);
4448 +
4449 + list_for_each_safe(ptr, n, &sbi->s_files) {
4450 + struct supermount_file_info *sfi;
4451 + struct file *subfile;
4452 +
4453 + sfi = list_entry(ptr, struct supermount_file_info, list);
4454 +
4455 + subfile = sfi->file;
4456 + sfi->file = 0;
4457 + list_del_init(&sfi->list);
4458 +
4459 + SUPERMOUNT_BUG_LOCKED_ON(sb, !subfile);
4460 +
4461 + fput(subfile);
4462 + }
4463 +
4464 + LEAVE(sb);
4465 +
4466 +}
4467 +
4468 +/*
4469 + * close all open dentries on subfs
4470 + */
4471 +static void
4472 +supermount_clean_dentries(struct super_block *sb)
4473 +{
4474 + struct supermount_sb_info *sbi = supermount_sbi(sb);
4475 + struct list_head *ptr, *n;
4476 +
4477 + ENTER(sb);
4478 +
4479 + list_for_each_safe(ptr, n, &sbi->s_dentries) {
4480 + struct supermount_dentry_info *sdi;
4481 + struct dentry *subdent;
4482 +
4483 + sdi = list_entry(ptr, struct supermount_dentry_info, list);
4484 + /*
4485 + * HACK - FIXME
4486 + * see dentry.c:supermount_d_compare
4487 + */
4488 + write_lock(&d_compare_lock);
4489 + subdent = sdi->dentry;
4490 + sdi->dentry = 0;
4491 + write_unlock(&d_compare_lock);
4492 +
4493 + list_del_init(&sdi->list);
4494 + d_drop(sdi->host);
4495 + dnotify_parent(sdi->host, DN_DELETE);
4496 +
4497 + SUPERMOUNT_BUG_LOCKED_ON(sb, !subdent);
4498 +
4499 + dput(subdent);
4500 + }
4501 +
4502 + LEAVE(sb);
4503 +
4504 +}
4505 +
4506 +/*
4507 + * close all open inodes on subfs
4508 + */
4509 +static void
4510 +supermount_clean_inodes(struct super_block *sb)
4511 +{
4512 + struct supermount_sb_info *sbi = supermount_sbi(sb);
4513 + struct list_head *ptr, *n;
4514 +
4515 + ENTER(sb);
4516 +
4517 + list_for_each_safe(ptr, n, &sbi->s_inodes) {
4518 + struct supermount_inode_info *sii;
4519 + struct inode *host;
4520 + struct inode *subi;
4521 +
4522 + sii = list_entry(ptr, struct supermount_inode_info, list);
4523 + host = &sii->vfs_inode;
4524 +
4525 + subi = sii->inode;
4526 + sii->inode = NULL;
4527 + list_del_init(&sii->list);
4528 + remove_inode_hash(host);
4529 + host->i_mapping = &host->i_data;
4530 +
4531 + /*
4532 + * it is possible to have no subi here. clear_inode does
4533 + * release lock after removing subi but before unlinking
4534 + * it
4535 + */
4536 + if (subi)
4537 + iput(subi);
4538 +
4539 + SUPERMOUNT_BUG_LOCKED_ON(sb, sii->writecount < 0);
4540 + SUPERMOUNT_BUG_LOCKED_ON(sb, sii->readcount < 0);
4541 + while (sii->writecount) {
4542 + sii->writecount--;
4543 + sbi->writecount--;
4544 + }
4545 + while (sii->readcount) {
4546 + sii->readcount--;
4547 + sbi->readcount--;
4548 + }
4549 + }
4550 +
4551 + LEAVE(sb);
4552 +}
4553 +
4554 +/*
4555 + * reason can be
4556 + * SUBFS_UMNT_NORMAL - normal umount, do not try to release subfs
4557 + * SUBFS_UMNT_MEDIA - media change detected, release subfs,
4558 + * do not remount ro (as media is already gone)
4559 + * SUBFS_UMNT_USER - user request, release subfs, remount ro before
4560 + * releasing tray lock
4561 + *
4562 + * unlock_door is always needed to keep device usage count correct
4563 + */
4564 +static inline int subfs_remount_ro(struct super_block *sb);
4565 +void
4566 +subfs_umount(struct super_block *sb, int reason)
4567 +{
4568 + struct supermount_sb_info *sbi = supermount_sbi(sb);
4569 + int writecount = sbi->writecount;
4570 +
4571 + ENTER(sb);
4572 +
4573 + if (reason != SUBFS_UMNT_NORMAL) {
4574 + /*
4575 + * we used to did shrink_dcache here. It compicates locking
4576 + * (clear_inode is called under sbi->sem thus requiring either
4577 + * recursive lock or separate lock just for inode list).
4578 + * This is not needed any more to ensure subfs can be umounted
4579 + * so we let dentries die and rely on dentry_revalidate to
4580 + * reject stale dentries
4581 + */
4582 +
4583 + if (subfs_is_busy(sb))
4584 + supermount_warning(sb, "opened files during media change");
4585 +
4586 + supermount_clean_files(sb);
4587 + supermount_clean_dentries(sb);
4588 + supermount_clean_inodes(sb);
4589 +
4590 + if (reason == SUBFS_UMNT_USER && writecount > 0)
4591 + subfs_remount_ro(sb);
4592 + if (sbi->lockcount > 0)
4593 + supermount_unlock_door(sb);
4594 + /*
4595 + * this is quite ugly but so far I have no idea how to
4596 + * do it cleanly
4597 + */
4598 + sbi->lockcount = 0;
4599 + }
4600 +
4601 + /*
4602 + * all files are expected to be closed
4603 + */
4604 + SUPERMOUNT_BUG_LOCKED_ON(sb, sbi->writecount);
4605 + SUPERMOUNT_BUG_LOCKED_ON(sb, sbi->readcount);
4606 + SUPERMOUNT_BUG_LOCKED_ON(sb, sbi->lockcount);
4607 + SUPERMOUNT_BUG_LOCKED_ON(sb, !list_empty(&sbi->s_files));
4608 + SUPERMOUNT_BUG_LOCKED_ON(sb, !list_empty(&sbi->s_dentries));
4609 + SUPERMOUNT_BUG_LOCKED_ON(sb, !list_empty(&sbi->s_inodes));
4610 +
4611 + unmark_media_supermounted(sb);
4612 + mntput(sbi->s_undermount);
4613 + sbi->s_undermount = NULL;
4614 + if (sbi->rw)
4615 + sb->s_flags &= ~MS_RDONLY;
4616 + sb->s_blocksize = 1024;
4617 + sb->s_blocksize_bits = 10;
4618 +
4619 + /*
4620 + * FIXME
4621 + * again the problem of unmounting subfs from inside of put_super
4622 + */
4623 + if (sb->s_root)
4624 + supermount_init_root_inode(sb->s_root->d_inode);
4625 +
4626 + LEAVE(sb);
4627 +}
4628 +
4629 +static inline int
4630 +subfs_remount_ro(struct super_block *sb)
4631 +{
4632 + struct super_block *subsb = subfs_sb(sb);
4633 + int rc;
4634 +
4635 + ENTER(sb);
4636 +
4637 + rc = do_remount_sb(subsb, subsb->s_flags | MS_RDONLY, NULL, 0);
4638 +
4639 + LEAVE(sb);
4640 +
4641 + return rc;
4642 +}
4643 +
4644 +static inline int
4645 +subfs_remount_rw(struct super_block *sb)
4646 +{
4647 + struct super_block *subsb = subfs_sb(sb);
4648 + int rc;
4649 +
4650 + ENTER(sb);
4651 +
4652 + rc = do_remount_sb(subsb, subsb->s_flags & ~MS_RDONLY, NULL, 0);
4653 +
4654 + LEAVE(sb);
4655 +
4656 + return rc;
4657 +}
4658 +
4659 +static struct vfsmount *
4660 +subfs_real_mount(struct super_block *sb, char *type)
4661 +{
4662 + struct supermount_sb_info *sbi = supermount_sbi(sb);
4663 + struct vfsmount *mnt;
4664 + char *opts = NULL;
4665 +
4666 + ENTER(sb, "type=%s", type);
4667 +
4668 + if (sbi->s_data) {
4669 + opts = strdup(sbi->s_data);
4670 + if (!opts) {
4671 + mnt = ERR_PTR(-ENOMEM);
4672 + goto fail;
4673 + }
4674 + }
4675 +
4676 + mnt = do_kern_mount(type,
4677 + (sb->s_flags & MS_RMT_MASK) | MS_SUPERMOUNTED,
4678 + sbi->devname, opts);
4679 + if (opts)
4680 + kfree(opts);
4681 +
4682 +fail:
4683 + LEAVE(sb, "submnt=%p", mnt);
4684 +
4685 + return mnt;
4686 +}
4687 +
4688 +static int
4689 +subfs_real_mount2(struct super_block *sb, char *type)
4690 +{
4691 + struct supermount_sb_info *sbi = supermount_sbi(sb);
4692 + struct vfsmount *mnt;
4693 + struct super_block *subsb;
4694 + int rc = 0;
4695 +
4696 + ENTER(sb, "type=%s", type);
4697 +
4698 + mnt = subfs_real_mount(sb, type);
4699 +
4700 + if (IS_ERR(mnt) && PTR_ERR(mnt) == -EROFS) {
4701 + sb->s_flags |= MS_RDONLY;
4702 + mnt = subfs_real_mount(sb, type);
4703 + }
4704 + rc = PTR_ERR(mnt);
4705 + if (IS_ERR(mnt))
4706 + goto out;
4707 +
4708 + /* paranoid check for double-mounting */
4709 + SUPERMOUNT_BUG_LOCKED_ON(sb, atomic_read(&mnt->mnt_sb->s_active) != 1);
4710 +
4711 + sbi->s_undermount = mnt;
4712 +
4713 + if (!(sb->s_flags & MS_RDONLY)) {
4714 + rc = subfs_remount_ro(sb);
4715 + if (rc)
4716 + goto mntput;
4717 + }
4718 +
4719 + subsb = mnt->mnt_sb;
4720 + sb->s_blocksize = subsb->s_blocksize;
4721 + sb->s_blocksize_bits = subsb->s_blocksize_bits;
4722 + attach_subfs_dentry(sb->s_root, mnt->mnt_root);
4723 + attach_subfs_inode(sb->s_root->d_inode, mnt->mnt_root->d_inode);
4724 + insert_inode_hash(sb->s_root->d_inode);
4725 + dnotify_parent(sb->s_root, DN_CREATE);
4726 + rc = 0;
4727 + goto out;
4728 +
4729 + /*
4730 + * error clean up
4731 + */
4732 +mntput:
4733 + sbi->s_undermount = 0;
4734 + mntput(mnt);
4735 +out:
4736 + LEAVE(sb, "type=%s rc=%d", type, rc);
4737 +
4738 + return rc;
4739 +}
4740 +
4741 +/*
4742 + * Error values from mount
4743 + * ENOENT - no device file (quite possible with devfs)
4744 + * ENXIO - device does not exist
4745 + * ENOMEDIUM - no medium inserted (surprise, surprise :)
4746 + * EBUSY - attempt to mount on already mounted device
4747 + * we specifically disallow it even when both
4748 + * file system and mode (ro/rw) are the same
4749 + */
4750 +static int
4751 +subfs_mount(struct super_block *sb)
4752 +{
4753 + struct supermount_sb_info *sbi = supermount_sbi(sb);
4754 + int retval = -ENODEV;
4755 + char *types = strdup(sbi->s_type);
4756 +
4757 + ENTER(sb);
4758 +
4759 + if (sbi->disabled)
4760 + retval = -EPERM;
4761 + else if (!types)
4762 + retval = -ENOMEM;
4763 + else {
4764 + char *p = types, *fs;
4765 +
4766 + while ((fs = strsep(&p, ":")) != NULL && retval
4767 + && retval != -ENXIO
4768 + && retval != -ENOMEDIUM
4769 + && retval != -ENOENT
4770 + && retval != -EBUSY)
4771 + retval = subfs_real_mount2(sb, fs);
4772 + }
4773 +
4774 + if (types)
4775 + kfree(types);
4776 +
4777 + if (!retval)
4778 + mark_media_supermounted(sb);
4779 +
4780 + LEAVE(sb, "rc=%d", retval);
4781 +
4782 + return retval;
4783 +}
4784 +
4785 +static int
4786 +__subfs_check_disk_change(struct super_block *sb)
4787 +{
4788 + struct super_block *subsb = subfs_sb(sb);
4789 + int rc;
4790 + struct block_device *dev = subsb->s_bdev;
4791 +
4792 + ENTER(sb);
4793 +
4794 + rc = atomic_read(&subsb->s_media_changed);
4795 + if (!rc) {
4796 + lock_kernel();
4797 + rc = check_disk_change(dev);
4798 + unlock_kernel();
4799 + }
4800 +
4801 + if (rc)
4802 + subfs_umount(sb, SUBFS_UMNT_MEDIA);
4803 +
4804 + LEAVE(sb, "rc=%d", rc);
4805 +
4806 + return rc;
4807 +}
4808 +
4809 +/*
4810 + * this must really be called subfs_active ...
4811 + */
4812 +int
4813 +subfs_check_disk_change(struct super_block *sb)
4814 +{
4815 + int rc;
4816 +
4817 + ENTER(sb);
4818 +
4819 + subfs_lock(sb);
4820 + if (subfs_is_mounted(sb))
4821 + rc = __subfs_check_disk_change(sb);
4822 + else
4823 + rc = 1;
4824 + subfs_unlock(sb);
4825 +
4826 +
4827 + LEAVE(sb, "rc=%d", rc);
4828 +
4829 + return rc;
4830 +}
4831 +
4832 +static int
4833 +check_and_remount_subfs(struct super_block *sb)
4834 +{
4835 + int rc;
4836 +
4837 + ENTER(sb);
4838 +
4839 + if (subfs_is_mounted(sb) && !__subfs_check_disk_change(sb)) {
4840 + rc = 0;
4841 + goto out;
4842 + }
4843 +
4844 + rc = subfs_mount(sb);
4845 +
4846 +out:
4847 + LEAVE(sb, "rc=%d", rc);
4848 +
4849 + return rc;
4850 +}
4851 +
4852 +static inline void
4853 +subfs_tray_lock(struct super_block *sb)
4854 +{
4855 + struct supermount_sb_info *sbi = supermount_sbi(sb);
4856 +
4857 + ENTER(sb);
4858 +
4859 + SUPERMOUNT_BUG_LOCKED_ON(sb, sbi->lockcount < 0);
4860 +
4861 + if (!sbi->lockcount++)
4862 + supermount_lock_door(sb);
4863 +
4864 + LEAVE(sb);
4865 +}
4866 +
4867 +static inline void
4868 +subfs_tray_unlock(struct super_block *sb)
4869 +{
4870 + struct supermount_sb_info *sbi = supermount_sbi(sb);
4871 +
4872 + ENTER(sb);
4873 +
4874 + SUPERMOUNT_BUG_LOCKED_ON(sb, sbi->lockcount <= 0);
4875 +
4876 + if (!--sbi->lockcount)
4877 + supermount_unlock_door(sb);
4878 +
4879 + LEAVE(sb);
4880 +}
4881 +
4882 +static void
4883 +subfs_get_read_access(struct super_block *sb)
4884 +{
4885 + struct supermount_sb_info *sbi = supermount_sbi(sb);
4886 +
4887 + ENTER(sb);
4888 +
4889 + SUPERMOUNT_BUG_LOCKED_ON(sb, sbi->readcount < 0);
4890 +
4891 + if (!sbi->readcount++ && sbi->tray_lock == TRAY_LOCK_ALWAYS)
4892 + subfs_tray_lock(sb);
4893 +
4894 + LEAVE(sb);
4895 +}
4896 +
4897 +static int
4898 +subfs_get_write_access(struct super_block *sb)
4899 +{
4900 + struct supermount_sb_info *sbi = supermount_sbi(sb);
4901 + int rc;
4902 +
4903 + ENTER(sb);
4904 +
4905 + SUPERMOUNT_BUG_LOCKED_ON(sb, sbi->writecount < 0);
4906 +
4907 + rc = 0;
4908 + if (!sbi->writecount) {
4909 + if (sb->s_flags & MS_RDONLY)
4910 + rc = -EROFS;
4911 + else
4912 + rc = subfs_remount_rw(sb);
4913 + }
4914 +
4915 + if (!rc && !sbi->writecount++ && sbi->tray_lock != TRAY_LOCK_NEVER)
4916 + subfs_tray_lock(sb);
4917 +
4918 + LEAVE(sb, "rc=%d", rc);
4919 +
4920 + return rc;
4921 +}
4922 +
4923 +static void
4924 +subfs_put_read_access(struct super_block *sb)
4925 +{
4926 + struct supermount_sb_info *sbi = supermount_sbi(sb);
4927 +
4928 + ENTER(sb);
4929 +
4930 + SUPERMOUNT_BUG_LOCKED_ON(sb, sbi->readcount <= 0);
4931 +
4932 + if (!--sbi->readcount && sbi->tray_lock == TRAY_LOCK_ALWAYS)
4933 + subfs_tray_unlock(sb);
4934 +
4935 + LEAVE(sb);
4936 +}
4937 +
4938 +static void
4939 +subfs_put_write_access(struct super_block *sb)
4940 +{
4941 + struct supermount_sb_info *sbi = supermount_sbi(sb);
4942 +
4943 + ENTER(sb);
4944 +
4945 + SUPERMOUNT_BUG_LOCKED_ON(sb, sbi->writecount <= 0);
4946 +
4947 + if (!--sbi->writecount) {
4948 + /*
4949 + * no need to fsync, it is done automatically on remount
4950 + */
4951 + int rc = subfs_remount_ro(sb);
4952 + if (rc)
4953 + supermount_error(sb, "failed to remount ro, error = %d", rc);
4954 + if (sbi->tray_lock != TRAY_LOCK_NEVER)
4955 + subfs_tray_unlock(sb);
4956 + }
4957 +
4958 + LEAVE(sb);
4959 +}
4960 +
4961 +int
4962 +subfs_get_access(struct inode *inode, int rw)
4963 +{
4964 + struct super_block *sb = inode->i_sb;
4965 + int rc = 0;
4966 +
4967 + ENTER(sb);
4968 +
4969 + subfs_lock(sb);
4970 + if (is_inode_obsolete(inode))
4971 + rc = -ESTALE;
4972 + else {
4973 + struct supermount_inode_info *sii = supermount_i(inode);
4974 +
4975 + if (rw) {
4976 + SUPERMOUNT_BUG_LOCKED_ON(sb, sii->writecount < 0);
4977 + rc = subfs_get_write_access(sb);
4978 + if (!rc)
4979 + sii->writecount++;
4980 + } else {
4981 + SUPERMOUNT_BUG_LOCKED_ON(sb, sii->readcount < 0);
4982 + subfs_get_read_access(sb);
4983 + sii->readcount++;
4984 + }
4985 + }
4986 + subfs_unlock(sb);
4987 +
4988 + LEAVE(sb, "rc=%d", rc);
4989 +
4990 + return rc;
4991 +}
4992 +
4993 +void
4994 +subfs_put_access(struct inode *inode, int rw)
4995 +{
4996 + struct super_block *sb = inode->i_sb;
4997 +
4998 + ENTER(sb);
4999 +
5000 + subfs_lock(sb);
5001 + if (!is_inode_obsolete(inode)) {
5002 + struct supermount_inode_info *sii = supermount_i(inode);
5003 +
5004 + if (rw) {
5005 + SUPERMOUNT_BUG_LOCKED_ON(sb, sii->writecount <= 0);
5006 + sii->writecount--;
5007 + subfs_put_write_access(sb);
5008 + } else {
5009 + SUPERMOUNT_BUG_LOCKED_ON(sb, sii->readcount <= 0);
5010 + sii->readcount--;
5011 + subfs_put_read_access(sb);
5012 + }
5013 +
5014 + }
5015 + subfs_unlock(sb);
5016 +
5017 + LEAVE(sb);
5018 +}
5019 +
5020 +struct vfsmount *
5021 +subfs_go_online(struct super_block *sb)
5022 +{
5023 + int rc;
5024 + struct vfsmount *mnt;
5025 +
5026 + ENTER(sb);
5027 +
5028 + subfs_lock(sb);
5029 +
5030 + rc = check_and_remount_subfs(sb);
5031 + mnt = ERR_PTR(rc);
5032 + if (!rc)
5033 + mnt = mntget(subfs_mnt(sb));
5034 + subfs_unlock(sb);
5035 +
5036 + LEAVE(sb, "mnt=%p", mnt);
5037 +
5038 + return mnt;
5039 +}
5040 +
5041 +void
5042 +subfs_go_offline(struct super_block *sb, struct vfsmount *mnt)
5043 +{
5044 + ENTER(sb);
5045 +
5046 + SUPERMOUNT_BUG_ON(!mnt);
5047 + mntput(mnt);
5048 +
5049 + LEAVE(sb);
5050 +
5051 +}
5052 +
5053 +struct vfsmount *
5054 +subfs_prevent_umount(struct super_block *sb)
5055 +{
5056 + struct vfsmount *mnt;
5057 +
5058 + ENTER(sb);
5059 +
5060 + subfs_lock(sb);
5061 + mnt = subfs_mnt(sb);
5062 + if (mnt)
5063 + mnt = mntget(mnt);
5064 + subfs_unlock(sb);
5065 +
5066 + LEAVE(sb, "mnt=%p", mnt);
5067 +
5068 + return mnt;
5069 +}
5070 +
5071 +void
5072 +subfs_allow_umount(struct super_block *sb, struct vfsmount *mnt)
5073 +{
5074 + ENTER(sb);
5075 +
5076 + SUPERMOUNT_BUG_ON(!mnt);
5077 + mntput(mnt);
5078 +
5079 + LEAVE(sb);
5080 +
5081 +}
5082 +
5083 +struct vfsmount *
5084 +subfs_get_mnt(struct super_block *sb)
5085 +{
5086 + struct vfsmount *mnt = NULL;
5087 +
5088 + ENTER(sb);
5089 +
5090 + subfs_lock(sb);
5091 + if (subfs_is_mounted(sb))
5092 + mnt = mntget(subfs_mnt(sb));
5093 + subfs_unlock(sb);
5094 +
5095 + LEAVE(sb, "mnt=%p", mnt);
5096 +
5097 + return mnt;
5098 +}
5099 +
5100 +struct super_block *
5101 +subfs_get_sb(struct super_block *sb)
5102 +{
5103 + struct super_block *subsb = NULL;
5104 +
5105 + ENTER(sb);
5106 +
5107 + subfs_lock(sb);
5108 + if (subfs_is_mounted(sb))
5109 + subsb = subfs_sb(sb);
5110 + subfs_unlock(sb);
5111 +
5112 + LEAVE(sb, "subsb=%p", subsb);
5113 +
5114 + return subsb;
5115 +}
5116 +
5117 +/*
5118 + * contrary to its name this function deals with _supermount_ inode
5119 + */
5120 +void
5121 +subfs_clear_inode(struct inode *inode)
5122 +{
5123 + struct super_block *sb = inode->i_sb;
5124 + struct supermount_inode_info *sii = supermount_i(inode);
5125 +
5126 + ENTER(sb, "inode=%p", inode);
5127 +
5128 + subfs_lock(sb);
5129 +
5130 + /*
5131 + * this is safe. If subfs has been unmounted, counters has been
5132 + * set to 0 already
5133 + */
5134 + while(sii->writecount > 0) {
5135 + sii->writecount--;
5136 + subfs_put_write_access(sb);
5137 + }
5138 +
5139 + while(sii->readcount > 0) {
5140 + sii->readcount--;
5141 + subfs_put_read_access(sb);
5142 + }
5143 +
5144 + list_del(&sii->list);
5145 +
5146 + subfs_unlock(sb);
5147 +
5148 + LEAVE(sb, "inode=%p", inode);
5149 +}
5150 diff -ruN linux-2.6.2-rc1.old/fs/supermount/super.c linux-2.6.2-rc1/fs/supermount/super.c
5151 --- linux-2.6.2-rc1.old/fs/supermount/super.c 1969-12-31 19:00:00.000000000 -0500
5152 +++ linux-2.6.2-rc1/fs/supermount/super.c 2004-01-24 11:46:38.893348304 -0500
5153 @@ -0,0 +1,646 @@
5154 +/*
5155 + * linux/fs/supermount/super.c
5156 + *
5157 + * Original version:
5158 + * Copyright (C) 1995, 1997
5159 + * Stephen Tweedie (sct@@dcs.ed.ac.uk)
5160 + *
5161 + * from
5162 + *
5163 + * linux/fs/minix/inode.c
5164 + * Copyright (C) 1991, 1992 Linus Torvalds
5165 + *
5166 + * and
5167 + *
5168 + * linux/fs/ext2/super.c
5169 + * Copyright (C) 1992, 1993, 1994, 1995 Remy Card
5170 + *
5171 + * Rewriten for kernel 2.2, 2.4. (C) 1999, 2000 Alexis Mikhailov
5172 + * (alexis@@abc.cap.ru)
5173 + * Rewritten for kernel 2.4.21 (C) 2003 Andrey Borzenkov
5174 + * (arvidjaar@@mail.ru)
5175 + * Rewritten for kernel 2.5.70 (C) 2003 Andrey Borzenkov
5176 + * (arvidjaar@@mail.ru)
5177 + *
5178 + * $Id: 401_supermount-2.0.4-2.6.2_rc1.patch,v 1.1 2004/01/26 22:15:04 johnm Exp $
5179 + */
5180 +
5181 +#define S_DBG_TRACE_CURRENT S_DBG_TRACE_SUPER
5182 +
5183 +#include <linux/statfs.h>
5184 +#include <linux/parser.h>
5185 +#include "supermount.h"
5186 +
5187 +/*
5188 + * vfat and msdos do not have any valididty checks for superblock and must
5189 + * be the last entries!
5190 + */
5191 +
5192 +static char *default_fs_types = "udf:iso9660:ext2:vfat:msdos";
5193 +
5194 +static struct super_operations supermount_sops;
5195 +
5196 +/* ========================= helpers ================================= */
5197 +
5198 +static inline void
5199 +supermount_update_inode(struct inode *superi, struct inode *subi)
5200 +{
5201 + struct super_block *sb = superi->i_sb;
5202 +
5203 + ENTER(sb, "superi=%p subi=%p", superi, subi);
5204 +
5205 + superi->i_ino = subi->i_ino;
5206 + superi->i_mode = subi->i_mode;
5207 + superi->i_uid = subi->i_uid;
5208 + superi->i_gid = subi->i_gid;
5209 + superi->i_nlink = subi->i_nlink;
5210 + superi->i_size = subi->i_size;
5211 + superi->i_atime = subi->i_atime;
5212 + superi->i_ctime = subi->i_ctime;
5213 + superi->i_mtime = subi->i_mtime;
5214 + superi->i_blksize = subi->i_blksize;
5215 + superi->i_blocks = subi->i_blocks;
5216 + superi->i_rdev = subi->i_rdev;
5217 + superi->i_version++;
5218 + set_inode_flags(superi, subi);
5219 +
5220 + if (S_ISDIR(superi->i_mode)) {
5221 + superi->i_op = &supermount_dir_iops;
5222 + superi->i_fop = &supermount_dir_operations;
5223 + } else if (S_ISLNK(superi->i_mode)) {
5224 + superi->i_op = &supermount_symlink_iops;
5225 + superi->i_mapping = subi->i_mapping;
5226 + } else {
5227 + superi->i_op = &supermount_file_iops;
5228 + superi->i_fop = &supermount_file_operations;
5229 + superi->i_mapping = subi->i_mapping;
5230 + }
5231 +
5232 + LEAVE(sb, "superi=%p subi=%p", superi, subi);
5233 +}
5234 +
5235 +/* this is also called from subfs_mount to reinstantiate root inode */
5236 +void
5237 +attach_subfs_inode(struct inode *inode, struct inode *subi)
5238 +{
5239 + struct super_block *sb = inode->i_sb;
5240 + struct supermount_sb_info *sbi = supermount_sbi(sb);
5241 + struct supermount_inode_info *sii;
5242 +
5243 + ENTER(sb, "inode=%p subi=%p", inode, subi);
5244 +
5245 + sii = supermount_i(inode);
5246 + if (!sii->inode) {
5247 + /*
5248 + * this can be run concurrently. It is executed under
5249 + * sbi->sem so only one task would actually instantate
5250 + * inode. See namei.c:prepare_inode
5251 + * Another user is subfs.c:subfs_real_mount2
5252 + */
5253 + sii->inode = igrab(subi);
5254 + supermount_update_inode(inode, subi);
5255 + list_add(&sii->list, &sbi->s_inodes);
5256 + } else
5257 + SUPERMOUNT_BUG_LOCKED_ON(sb, sii->inode != subi);
5258 +
5259 + LEAVE(sb, "inode=%p subi=%p", inode, subi);
5260 +}
5261 +
5262 +char *
5263 +strdup(const char *val)
5264 +{
5265 + char *tmp;
5266 + tmp = kmalloc(1 + strlen(val), GFP_KERNEL);
5267 + if (tmp)
5268 + strcpy(tmp, val);
5269 + return tmp;
5270 +}
5271 +
5272 +static struct supermount_sb_info *
5273 +create_sbi(struct super_block *sb)
5274 +{
5275 + struct supermount_sb_info *sbi = kmalloc(sizeof (*sbi), GFP_KERNEL);
5276 +
5277 + if (!sbi)
5278 + return NULL;
5279 +
5280 + memset(sbi, 0, sizeof (*sbi));
5281 +
5282 + sbi->s_undermount = NULL;
5283 + sbi->s_type = sbi->devname = sbi->s_data = NULL;
5284 + INIT_LIST_HEAD(&sbi->s_inodes);
5285 + INIT_LIST_HEAD(&sbi->s_files);
5286 + INIT_LIST_HEAD(&sbi->s_dentries);
5287 + init_MUTEX(&sbi->sem);
5288 + sbi->host = sb;
5289 + sbi->tray_lock = TRAY_LOCK_ONWRITE;
5290 + sbi->rw = !(sb->s_flags & MS_RDONLY);
5291 +
5292 + return sbi;
5293 +}
5294 +
5295 +static void
5296 +free_sbi(struct supermount_sb_info *sbi)
5297 +{
5298 + if (sbi->s_type && sbi->s_type != default_fs_types)
5299 + kfree(sbi->s_type);
5300 + if (sbi->devname)
5301 + kfree(sbi->devname);
5302 + if (sbi->s_data)
5303 + kfree(sbi->s_data);
5304 + kfree(sbi);
5305 +}
5306 +
5307 +enum {
5308 + Opt_fs, Opt_fs_auto, Opt_dev, Opt_debug, Opt_debug_old, Opt_subfsopts,
5309 + Opt_tray_lock_always, Opt_tray_lock_never, Opt_tray_lock_onwrite,
5310 + Opt_ignore, Opt_err
5311 +};
5312 +
5313 +static match_table_t tokens = {
5314 + {Opt_fs_auto, "fs=auto"},
5315 + {Opt_fs, "fs=%s"},
5316 + {Opt_dev, "dev=%s"},
5317 + {Opt_debug, "debug=%u"},
5318 + {Opt_debug_old, "debug"},
5319 + {Opt_subfsopts, "--"},
5320 + {Opt_tray_lock_always, "tray_lock=always"},
5321 + {Opt_tray_lock_never, "tray_lock=never"},
5322 + {Opt_tray_lock_onwrite, "tray_lock=onwrite"},
5323 + {Opt_ignore, "no_tray_lock"},
5324 + {Opt_ignore, "fail_statfs_until_mount"},
5325 + {Opt_err, NULL}
5326 +};
5327 +
5328 +static int
5329 +parse_options(char *options, struct super_block *sb)
5330 +{
5331 + struct supermount_sb_info *sbi = supermount_sbi(sb);
5332 + int rc;
5333 + char *p;
5334 +
5335 + if (!options)
5336 + return 0;
5337 +
5338 + while ((p = strsep(&options, ",")) != NULL) {
5339 + int token;
5340 + substring_t args[MAX_OPT_ARGS];
5341 + int n;
5342 +
5343 + /* empty option means start of subfs options */
5344 + if (!*p)
5345 + goto copy_subfs_options;
5346 +
5347 + token = match_token(p, tokens, args);
5348 + switch(token) {
5349 + case Opt_fs:
5350 + sbi->s_type = match_strdup(&args[0]);
5351 + if (!sbi->s_type)
5352 + return -ENOMEM;
5353 + break;
5354 + case Opt_fs_auto:
5355 + sbi->s_type = default_fs_types;
5356 + break;
5357 + case Opt_dev:
5358 + sbi->devname = match_strdup(&args[0]);
5359 + if (!sbi->devname)
5360 + return -ENOMEM;
5361 + break;
5362 + case Opt_debug:
5363 + if ((rc = match_int(&args[0], &n)))
5364 + return rc;
5365 + sbi->s_debug = n;
5366 + break;
5367 + case Opt_debug_old:
5368 + sbi->s_debug = S_DBG_DEBUG;
5369 + break;
5370 + case Opt_tray_lock_always:
5371 + sbi->tray_lock = TRAY_LOCK_ALWAYS;
5372 + break;
5373 + case Opt_tray_lock_onwrite:
5374 + sbi->tray_lock = TRAY_LOCK_ONWRITE;
5375 + break;
5376 + case Opt_tray_lock_never:
5377 + sbi->tray_lock = TRAY_LOCK_NEVER;
5378 + break;
5379 + case Opt_subfsopts:
5380 +copy_subfs_options:
5381 + /* mount may have removed options after -- */
5382 + if (options && *options) {
5383 + sbi->s_data = strdup(options);
5384 + if (!sbi->s_data)
5385 + return -ENOMEM;
5386 + }
5387 + return 0;
5388 + break;
5389 + case Opt_ignore:
5390 + break;
5391 + default:
5392 + supermount_error(sb, "Unrecognized mount option \"%s\"",
5393 + p);
5394 + return -EINVAL;
5395 + break;
5396 + }
5397 + }
5398 +
5399 + return 0;
5400 +}
5401 +
5402 +void
5403 +supermount_init_root_inode(struct inode *inode)
5404 +{
5405 + inode->i_mode = 0777 | S_IFDIR;
5406 + inode->i_uid = current->fsuid;
5407 + inode->i_gid = current->fsgid;
5408 + inode->i_blksize = inode->i_sb->s_blocksize;
5409 + inode->i_rdev = MKDEV(UNNAMED_MAJOR, 0);
5410 + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
5411 + inode->i_size = 0;
5412 + inode->i_blocks = 0;
5413 + inode->i_ino = 0;
5414 + inode->i_nlink = 0;
5415 +
5416 + set_inode_flags(inode, 0);
5417 +
5418 + inode->i_op = &supermount_dir_iops;
5419 + inode->i_fop = &supermount_dir_operations;
5420 +}
5421 +
5422 +static struct inode *
5423 +supermount_root_inode(struct super_block *sb)
5424 +{
5425 + struct inode *inode = new_inode(sb);
5426 +
5427 + ENTER(sb);
5428 +
5429 + if (inode) {
5430 + inode->i_version = 0;
5431 + supermount_init_root_inode(inode);
5432 + }
5433 +
5434 + LEAVE(sb, "inode=%p", inode);
5435 +
5436 + return inode;
5437 +}
5438 +
5439 +/* ========================== used in fstype declaration ================*/
5440 +
5441 +/* read_super: the main mount() entry point into the VFS layer. */
5442 +static int
5443 +supermount_read_super(struct super_block *sb, void *data, int silent)
5444 +{
5445 + struct inode *root_inode;
5446 + struct dentry *root;
5447 + struct supermount_sb_info *sbi = create_sbi(sb);
5448 + int rc = -ENOMEM;
5449 +
5450 + if (!sbi)
5451 + goto fail_no_memory;
5452 +
5453 + sb->s_fs_info = sbi;
5454 +
5455 + rc = parse_options((char *) data, sb);
5456 + if (rc)
5457 + goto fail_parsing;
5458 +
5459 + rc = -EINVAL;
5460 + if (!sbi->devname) {
5461 + supermount_error(sb, "no dev=<device> option");
5462 + goto fail_parsing;
5463 + }
5464 +
5465 + if (!sbi->s_type) {
5466 + sbi->s_type = default_fs_types;
5467 + supermount_warning(sb, "no fs=<filesystem> option, assuming fs=auto");
5468 + }
5469 +
5470 + rc = -ENOMEM;
5471 +
5472 + sb->s_blocksize = 1024;
5473 + sb->s_blocksize_bits = 10;
5474 + sb->s_magic = SUPERMOUNT_SUPER_MAGIC;
5475 + sb->s_op = &supermount_sops;
5476 +
5477 + root_inode = supermount_root_inode(sb);
5478 + if (!root_inode)
5479 + goto fail_allocating_root_inode;
5480 +
5481 + root = d_alloc_root(root_inode);
5482 + if (!root)
5483 + goto fail_allocating_root_dentry;
5484 + if (init_dentry_info(root))
5485 + goto fail_init_root_info;
5486 +
5487 + sb->s_root = root;
5488 +
5489 + supermount_proc_insert(sbi);
5490 +
5491 + return 0;
5492 +
5493 +fail_init_root_info:
5494 + dput(root);
5495 +fail_allocating_root_dentry:
5496 + iput(root_inode);
5497 +fail_parsing:
5498 +fail_allocating_root_inode:
5499 + free_sbi(sbi);
5500 +
5501 +fail_no_memory:
5502 + return rc;
5503 +}
5504 +
5505 +struct super_block *supermount_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
5506 +{
5507 + return get_sb_nodev(fs_type, flags, data, supermount_read_super);
5508 +}
5509 +
5510 +/* ======================= super_operations methods ==================== */
5511 +
5512 +static struct inode *
5513 +supermount_alloc_inode(struct super_block *sb)
5514 +{
5515 + struct supermount_inode_info *sii = kmalloc(sizeof(*sii), GFP_KERNEL);
5516 + struct inode *inode = 0;
5517 +
5518 + ENTER(sb);
5519 +
5520 + if (sii) {
5521 + INIT_LIST_HEAD(&sii->list);
5522 + sii->inode = 0;
5523 + sii->readcount = 0;
5524 + sii->writecount = 0;
5525 + inode = &sii->vfs_inode;
5526 + inode_init_once(inode);
5527 + }
5528 +
5529 + LEAVE(sb, "inode=%p", inode);
5530 +
5531 + return inode;
5532 +}
5533 +
5534 +static void
5535 +supermount_destroy_inode(struct inode *inode)
5536 +{
5537 + struct super_block *sb = inode->i_sb;
5538 + struct supermount_inode_info *sii = supermount_i(inode);
5539 +
5540 + ENTER(sb, "inode=%p", inode);
5541 +
5542 + kfree(sii);
5543 +
5544 + ENTER(sb, "inode=%p", inode);
5545 +}
5546 +
5547 +/*
5548 + * FIXME
5549 + * I am still unsure if (or why) this functions is needed; it is likely
5550 + * to go away. So far the only _real_ user seems to be knfsd.
5551 + */
5552 +static void
5553 +supermount_write_inode(struct inode *inode, int sync)
5554 +{
5555 + struct super_block *sb = inode->i_sb;
5556 + struct super_block *subsb;
5557 + struct inode *subi;
5558 + struct vfsmount *submnt;
5559 +
5560 + ENTER(sb);
5561 +
5562 + if (subfs_check_disk_change(sb))
5563 + goto out;
5564 +
5565 + submnt = subfs_prevent_umount(sb);
5566 + if (!submnt)
5567 + goto out;
5568 +
5569 + subi = get_subfs_inode(inode);
5570 + if (IS_ERR(subi))
5571 + goto allow_umount;
5572 +
5573 + subsb = subfs_get_sb(sb);
5574 + if (!sb)
5575 + goto put_subi;
5576 +
5577 + if (subsb->s_op && subsb->s_op->write_inode) {
5578 + if (subfs_get_access(inode, 1))
5579 + goto put_subi;
5580 +
5581 + write_inode_now(subi, sync);
5582 +
5583 + subfs_put_access(inode, 1);
5584 + }
5585 +put_subi:
5586 + iput(subi);
5587 +allow_umount:
5588 + subfs_allow_umount(sb, submnt);
5589 +out:
5590 + LEAVE(sb);
5591 +
5592 + return;
5593 +}
5594 +
5595 +/*
5596 + * FIXME
5597 + * subfs_umount has no business here
5598 + * it should be moved into umount_begin; in this case force umount will
5599 + * free subfs (and give false No medium as error ... oh, well)
5600 + */
5601 +static void
5602 +supermount_put_super(struct super_block *sb)
5603 +{
5604 + struct supermount_sb_info *sbi = supermount_sbi(sb);
5605 +
5606 + ENTER(sb);
5607 +
5608 + subfs_lock(sb);
5609 + if (subfs_is_mounted(sb))
5610 + subfs_umount(sb, SUBFS_UMNT_NORMAL);
5611 + subfs_unlock(sb);
5612 +
5613 + supermount_proc_remove(sbi);
5614 +
5615 + LEAVE(sb);
5616 +
5617 + sb->s_fs_info = 0;
5618 + free_sbi(sbi);
5619 +}
5620 +
5621 +/*
5622 + * Th