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

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