]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-supermount.patch
- [2.4.2x, 2.6.x] don't recursively crash in die() on CHRP/PReP machines
[packages/kernel.git] / kernel-supermount.patch
1 diff -Naurp linux-2.4.20-ck4/arch/ia64/kernel/sys_ia64.c linux-2.4.20-ck5/arch/ia64/kernel/sys_ia64.c
2 --- linux-2.4.20-ck4/arch/ia64/kernel/sys_ia64.c        2002-11-30 17:02:01.000000000 +1100
3 +++ linux-2.4.20-ck5/arch/ia64/kernel/sys_ia64.c        2003-04-08 10:52:50.000000000 +1000
4 @@ -280,120 +280,55 @@ ia64_create_module (const char *name_use
5   * call - it will be removed later once everybody migrates to the new
6   * kernel stat structure that matches the glibc one - Jes
7   */
8 -static __inline__ int
9 -do_revalidate (struct dentry *dentry)
10 -{
11 -       struct inode * inode = dentry->d_inode;
12 -       if (inode->i_op && inode->i_op->revalidate)
13 -               return inode->i_op->revalidate(dentry);
14 -       return 0;
15 -}
16  
17  static int
18 -cp_ia64_old_stat (struct inode *inode, struct ia64_oldstat *statbuf)
19 +cp_ia64_old_stat (struct kstat *stat, struct ia64_oldstat *statbuf)
20  {
21         struct ia64_oldstat tmp;
22 -       unsigned int blocks, indirect;
23  
24         memset(&tmp, 0, sizeof(tmp));
25 -       tmp.st_dev = kdev_t_to_nr(inode->i_dev);
26 -       tmp.st_ino = inode->i_ino;
27 -       tmp.st_mode = inode->i_mode;
28 -       tmp.st_nlink = inode->i_nlink;
29 -       SET_STAT_UID(tmp, inode->i_uid);
30 -       SET_STAT_GID(tmp, inode->i_gid);
31 -       tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
32 -       tmp.st_size = inode->i_size;
33 -       tmp.st_atime = inode->i_atime;
34 -       tmp.st_mtime = inode->i_mtime;
35 -       tmp.st_ctime = inode->i_ctime;
36 -/*
37 - * st_blocks and st_blksize are approximated with a simple algorithm if
38 - * they aren't supported directly by the filesystem. The minix and msdos
39 - * filesystems don't keep track of blocks, so they would either have to
40 - * be counted explicitly (by delving into the file itself), or by using
41 - * this simple algorithm to get a reasonable (although not 100% accurate)
42 - * value.
43 - */
44 -
45 -/*
46 - * Use minix fs values for the number of direct and indirect blocks.  The
47 - * count is now exact for the minix fs except that it counts zero blocks.
48 - * Everything is in units of BLOCK_SIZE until the assignment to
49 - * tmp.st_blksize.
50 - */
51 -#define D_B   7
52 -#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
53 -
54 -       if (!inode->i_blksize) {
55 -               blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
56 -               if (blocks > D_B) {
57 -                       indirect = (blocks - D_B + I_B - 1) / I_B;
58 -                       blocks += indirect;
59 -                       if (indirect > 1) {
60 -                               indirect = (indirect - 1 + I_B - 1) / I_B;
61 -                               blocks += indirect;
62 -                               if (indirect > 1)
63 -                                       blocks++;
64 -                       }
65 -               }
66 -               tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
67 -               tmp.st_blksize = BLOCK_SIZE;
68 -       } else {
69 -               tmp.st_blocks = inode->i_blocks;
70 -               tmp.st_blksize = inode->i_blksize;
71 -       }
72 +       tmp.st_dev = stat->dev;
73 +       tmp.st_ino = stat->ino;
74 +       tmp.st_mode = stat->mode;
75 +       tmp.st_nlink = stat->nlink;
76 +       SET_STAT_UID(tmp, stat->uid);
77 +       SET_STAT_GID(tmp, stat->gid);
78 +       tmp.st_rdev = stat->rdev;
79 +       tmp.st_size = stat->size;
80 +       tmp.st_atime = stat->atime;
81 +       tmp.st_mtime = stat->mtime;
82 +       tmp.st_ctime = stat->ctime;
83 +       tmp.st_blocks = stat->blocks;
84 +       tmp.st_blksize = stat->blksize;
85         return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
86  }
87  
88  asmlinkage long
89  ia64_oldstat (char *filename, struct ia64_oldstat *statbuf)
90  {
91 -       struct nameidata nd;
92 -       int error;
93 +       struct kstat stat;
94 +       int error = vfs_stat(filename, &stat);
95  
96 -       error = user_path_walk(filename, &nd);
97 -       if (!error) {
98 -               error = do_revalidate(nd.dentry);
99 -               if (!error)
100 -               error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf);
101 -               path_release(&nd);
102 -       }
103 -       return error;
104 +       return error ? error : cp_ia64_old_stat(&stat, statbuf);
105  }
106  
107  
108  asmlinkage long
109 -ia64_oldlstat (char *filename, struct ia64_oldstat *statbuf) {
110 -       struct nameidata nd;
111 -       int error;
112 -
113 -       error = user_path_walk_link(filename, &nd);
114 -       if (!error) {
115 -               error = do_revalidate(nd.dentry);
116 -               if (!error)
117 -                       error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf);
118 -               path_release(&nd);
119 -       }
120 -       return error;
121 +ia64_oldlstat (char *filename, struct ia64_oldstat *statbuf)
122 +{
123 +       struct kstat stat;
124 +       int error = vfs_lstat(filename, &stat);
125 +
126 +       return error ? error : cp_ia64_old_stat(&stat, statbuf);
127  }
128  
129  asmlinkage long
130  ia64_oldfstat (unsigned int fd, struct ia64_oldstat *statbuf)
131  {
132 -       struct file * f;
133 -       int err = -EBADF;
134 +       struct kstat stat;
135 +       int error = vfs_fstat(fd, &stat);
136  
137 -       f = fget(fd);
138 -       if (f) {
139 -               struct dentry * dentry = f->f_dentry;
140 -
141 -               err = do_revalidate(dentry);
142 -               if (!err)
143 -                       err = cp_ia64_old_stat(dentry->d_inode, statbuf);
144 -               fput(f);
145 -       }
146 -       return err;
147 +       return error ? error : cp_ia64_old_stat(&stat, statbuf);
148  }
149  
150  #endif
151 diff -Naurp linux-2.4.20-ck4/arch/mips/kernel/sysirix.c linux-2.4.20-ck5/arch/mips/kernel/sysirix.c
152 --- linux-2.4.20-ck4/arch/mips/kernel/sysirix.c 2002-11-30 17:02:01.000000000 +1100
153 +++ linux-2.4.20-ck5/arch/mips/kernel/sysirix.c 2003-04-08 10:52:50.000000000 +1000
154 @@ -1178,8 +1178,9 @@ linux_to_irix_dev_t (dev_t t)
155         return MAJOR (t) << 18 | MINOR (t);
156  }
157  
158 -static inline int irix_xstat32_xlate(struct stat *kb, void *ubuf)
159 +static inline int irix_xstat32_xlate(struct kstat *kb, void *ubuf)
160  {
161 +       /*  XXX_SIZE */
162         struct xstat32 {
163                 u32 st_dev, st_pad1[3], st_ino, st_mode, st_nlink, st_uid, st_gid;
164                 u32 st_rdev, st_pad2[2], st_size, st_pad3;
165 @@ -1191,29 +1192,30 @@ static inline int irix_xstat32_xlate(str
166                 u32 st_pad4[8];
167         } ub;
168  
169 -       ub.st_dev     = linux_to_irix_dev_t (kb->st_dev);
170 -       ub.st_ino     = kb->st_ino;
171 -       ub.st_mode    = kb->st_mode;
172 -       ub.st_nlink   = kb->st_nlink;
173 -       ub.st_uid     = kb->st_uid;
174 -       ub.st_gid     = kb->st_gid;
175 -       ub.st_rdev    = linux_to_irix_dev_t (kb->st_rdev);
176 -       ub.st_size    = kb->st_size;
177 -       ub.st_atime0  = kb->st_atime;
178 +       ub.st_dev     = linux_to_irix_dev_t (kb->dev);
179 +       ub.st_ino     = kb->ino;
180 +       ub.st_mode    = kb->mode;
181 +       ub.st_nlink   = kb->nlink;
182 +       ub.st_uid     = kb->uid;
183 +       ub.st_gid     = kb->gid;
184 +       ub.st_rdev    = linux_to_irix_dev_t (kb->rdev);
185 +       ub.st_size    = kb->size;
186 +       ub.st_atime0  = kb->atime;
187         ub.st_atime1  = 0;
188 -       ub.st_mtime0  = kb->st_mtime;
189 +       ub.st_mtime0  = kb->mtime;
190         ub.st_mtime1  = 0;
191 -       ub.st_ctime0  = kb->st_ctime;
192 +       ub.st_ctime0  = kb->ctime;
193         ub.st_ctime1  = 0;
194 -       ub.st_blksize = kb->st_blksize;
195 -       ub.st_blocks  = kb->st_blocks;
196 +       ub.st_blksize = kb->blksize;
197 +       ub.st_blocks  = kb->blocks;
198         strcpy (ub.st_fstype, "efs");
199  
200         return copy_to_user(ubuf, &ub, sizeof(ub)) ? -EFAULT : 0;
201  }
202  
203 -static inline void irix_xstat64_xlate(struct stat *sb)
204 +static inline int irix_xstat64_xlate(struct kstat *sb, void *ubuf)
205  {
206 +       /*  XXX_SIZE */
207         struct xstat64 {
208                 u32 st_dev; s32 st_pad1[3];
209                 unsigned long long st_ino;
210 @@ -1229,38 +1231,37 @@ static inline void irix_xstat64_xlate(st
211                 s32 st_pad4[8];
212         } ks;
213  
214 -       ks.st_dev = linux_to_irix_dev_t (sb->st_dev);
215 +       ks.st_dev = sb->dev;
216         ks.st_pad1[0] = ks.st_pad1[1] = ks.st_pad1[2] = 0;
217 -       ks.st_ino = (unsigned long long) sb->st_ino;
218 -       ks.st_mode = (u32) sb->st_mode;
219 -       ks.st_nlink = (u32) sb->st_nlink;
220 -       ks.st_uid = (s32) sb->st_uid;
221 -       ks.st_gid = (s32) sb->st_gid;
222 -       ks.st_rdev = linux_to_irix_dev_t (sb->st_rdev);
223 +       ks.st_ino = (unsigned long long) sb->ino;
224 +       ks.st_mode = (u32) sb->mode;
225 +       ks.st_nlink = (u32) sb->nlink;
226 +       ks.st_uid = (s32) sb->uid;
227 +       ks.st_gid = (s32) sb->gid;
228 +       ks.st_rdev = linux_to_irix_dev_t (sb->rdev);
229         ks.st_pad2[0] = ks.st_pad2[1] = 0;
230 -       ks.st_size = (long long) sb->st_size;
231 +       ks.st_size = (long long) sb->size;
232         ks.st_pad3 = 0;
233  
234         /* XXX hackety hack... */
235 -       ks.st_atime.tv_sec = (s32) sb->st_atime; ks.st_atime.tv_nsec = 0;
236 -       ks.st_mtime.tv_sec = (s32) sb->st_atime; ks.st_mtime.tv_nsec = 0;
237 -       ks.st_ctime.tv_sec = (s32) sb->st_atime; ks.st_ctime.tv_nsec = 0;
238 +       ks.st_atime.tv_sec = (s32) sb->atime; ks.st_atime.tv_nsec = 0;
239 +       ks.st_mtime.tv_sec = (s32) sb->atime; ks.st_mtime.tv_nsec = 0;
240 +       ks.st_ctime.tv_sec = (s32) sb->atime; ks.st_ctime.tv_nsec = 0;
241  
242 -       ks.st_blksize = (s32) sb->st_blksize;
243 -       ks.st_blocks = (long long) sb->st_blocks;
244 +       ks.st_blksize = (s32) sb->blksize;
245 +       ks.st_blocks = (long long) sb->blocks;
246         memset(ks.st_fstype, 0, 16);
247         ks.st_pad4[0] = ks.st_pad4[1] = ks.st_pad4[2] = ks.st_pad4[3] = 0;
248         ks.st_pad4[4] = ks.st_pad4[5] = ks.st_pad4[6] = ks.st_pad4[7] = 0;
249  
250         /* Now write it all back. */
251 -       copy_to_user(sb, &ks, sizeof(struct xstat64));
252 +       copy_to_user(ubuf, &ks, sizeof(struct xstat64));
253  }
254  
255 -extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf);
256 -
257  asmlinkage int irix_xstat(int version, char *filename, struct stat *statbuf)
258  {
259         int retval;
260 +       struct kstat kb;
261  
262  #ifdef DEBUG_XSTAT
263         printk("[%s:%d] Wheee.. irix_xstat(%d,%s,%p) ",
264 @@ -1268,12 +1269,7 @@ asmlinkage int irix_xstat(int version, c
265  #endif
266         switch(version) {
267         case 2: {
268 -               struct stat kb;
269 -               mm_segment_t old_fs;
270 -
271 -               old_fs = get_fs(); set_fs(get_ds());
272 -               retval = sys_newstat(filename, &kb);
273 -               set_fs(old_fs);
274 +               retval = vfs_stat(filename, &kb);
275  #ifdef DEBUG_XSTAT
276                 printk("retval[%d]\n", retval);
277  #endif
278 @@ -1284,16 +1280,14 @@ asmlinkage int irix_xstat(int version, c
279         }
280  
281         case 3: {
282 -               retval = sys_newstat(filename, statbuf);
283 +               retval = vfs_stat(filename, &kb);
284  #ifdef DEBUG_XSTAT
285                 printk("retval[%d]\n", retval);
286  #endif
287                 if(retval)
288                         goto out;
289 -
290 -               irix_xstat64_xlate(statbuf);
291 -               retval = 0;
292 -               break;
293 +               retval = irix_xstat64_xlate(&kb, statbuf);
294 +               goto out;
295         }
296  
297         default:
298 @@ -1305,11 +1299,10 @@ out:
299         return retval;
300  }
301  
302 -extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf);
303 -
304  asmlinkage int irix_lxstat(int version, char *filename, struct stat *statbuf)
305  {
306         int error;
307 +       struct kstat kb;
308  
309  #ifdef DEBUG_XSTAT
310         printk("[%s:%d] Wheee.. irix_lxstat(%d,%s,%p) ",
311 @@ -1317,12 +1310,7 @@ asmlinkage int irix_lxstat(int version, 
312  #endif
313         switch(version) {
314         case 2: {
315 -               struct stat kb;
316 -               mm_segment_t old_fs;
317 -
318 -               old_fs = get_fs(); set_fs(get_ds());
319 -               error = sys_newlstat(filename, &kb);
320 -               set_fs(old_fs);
321 +               error = vfs_lstat(filename, &kb);
322  #ifdef DEBUG_XSTAT
323                 printk("error[%d]\n", error);
324  #endif
325 @@ -1333,18 +1321,15 @@ asmlinkage int irix_lxstat(int version, 
326         }
327  
328         case 3: {
329 -               error = sys_newlstat(filename, statbuf);
330 +               error = vfs_lstat(filename, &kb);
331  #ifdef DEBUG_XSTAT
332                 printk("error[%d]\n", error);
333  #endif
334                 if(error)
335                         goto out;
336 -
337 -               irix_xstat64_xlate(statbuf);
338 -               error = 0;
339 +               error = irix_xstat64_xlate(&kb, statbuf);
340                 goto out;
341         }
342 -
343         default:
344                 error = -EINVAL;
345                 goto out;
346 @@ -1354,11 +1339,10 @@ out:
347         return error;
348  }
349  
350 -extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf);
351 -
352  asmlinkage int irix_fxstat(int version, int fd, struct stat *statbuf)
353  {
354         int error;
355 +       struct stat kb;
356  
357  #ifdef DEBUG_XSTAT
358         printk("[%s:%d] Wheee.. irix_fxstat(%d,%d,%p) ",
359 @@ -1366,12 +1350,7 @@ asmlinkage int irix_fxstat(int version, 
360  #endif
361         switch(version) {
362         case 2: {
363 -               struct stat kb;
364 -               mm_segment_t old_fs;
365 -
366 -               old_fs = get_fs(); set_fs(get_ds());
367 -               error = sys_newfstat(fd, &kb);
368 -               set_fs(old_fs);
369 +               error = vfs_fstat(fd, &kb);
370  #ifdef DEBUG_XSTAT
371                 printk("error[%d]\n", error);
372  #endif
373 @@ -1382,15 +1361,13 @@ asmlinkage int irix_fxstat(int version, 
374         }
375  
376         case 3: {
377 -               error = sys_newfstat(fd, statbuf);
378 +               error = vfs_fstat(fd, &kb);
379  #ifdef DEBUG_XSTAT
380                 printk("error[%d]\n", error);
381  #endif
382                 if(error)
383                         goto out;
384 -
385 -               irix_xstat64_xlate(statbuf);
386 -               error = 0;
387 +               error = irix_xstat64_xlate(&kb, statbuf);
388                 goto out;
389         }
390  
391 diff -Naurp linux-2.4.20-ck4/arch/mips64/kernel/linux32.c linux-2.4.20-ck5/arch/mips64/kernel/linux32.c
392 --- linux-2.4.20-ck4/arch/mips64/kernel/linux32.c       2002-11-30 17:02:02.000000000 +1100
393 +++ linux-2.4.20-ck5/arch/mips64/kernel/linux32.c       2003-04-08 10:52:50.000000000 +1000
394 @@ -55,128 +55,51 @@
395  #define merge_64(r1,r2)        ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL))
396  #endif
397  
398 -/*
399 - * Revalidate the inode. This is required for proper NFS attribute caching.
400 - */
401 -static __inline__ int
402 -do_revalidate(struct dentry *dentry)
403 -{
404 -       struct inode * inode = dentry->d_inode;
405 -
406 -       if (inode->i_op && inode->i_op->revalidate)
407 -               return inode->i_op->revalidate(dentry);
408 -
409 -       return 0;
410 -}
411 -
412 -static int cp_new_stat32(struct inode * inode, struct stat32 * statbuf)
413 +static int cp_new_stat32(struct kstat *stat, struct stat32 * statbuf)
414  {
415 +       /* XXX_SIZE */
416         struct stat32 tmp;
417 -       unsigned int blocks, indirect;
418  
419         memset(&tmp, 0, sizeof(tmp));
420 -       tmp.st_dev = kdev_t_to_nr(inode->i_dev);
421 -       tmp.st_ino = inode->i_ino;
422 -       tmp.st_mode = inode->i_mode;
423 -       tmp.st_nlink = inode->i_nlink;
424 -       SET_STAT_UID(tmp, inode->i_uid);
425 -       SET_STAT_GID(tmp, inode->i_gid);
426 -       tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
427 -       tmp.st_size = inode->i_size;
428 -       tmp.st_atime = inode->i_atime;
429 -       tmp.st_mtime = inode->i_mtime;
430 -       tmp.st_ctime = inode->i_ctime;
431 -
432 -       /*
433 -        * st_blocks and st_blksize are approximated with a simple algorithm if
434 -        * they aren't supported directly by the filesystem. The minix and msdos
435 -        * filesystems don't keep track of blocks, so they would either have to
436 -        * be counted explicitly (by delving into the file itself), or by using
437 -        * this simple algorithm to get a reasonable (although not 100%
438 -        * accurate) value.
439 -        */
440 -
441 -       /*
442 -        * Use minix fs values for the number of direct and indirect blocks.
443 -        * The count is now exact for the minix fs except that it counts zero
444 -        * blocks.  Everything is in units of BLOCK_SIZE until the assignment
445 -        * to tmp.st_blksize.
446 -        */
447 -#define D_B   7
448 -#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
449 -
450 -       if (!inode->i_blksize) {
451 -               blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
452 -               if (blocks > D_B) {
453 -                       indirect = (blocks - D_B + I_B - 1) / I_B;
454 -                       blocks += indirect;
455 -                       if (indirect > 1) {
456 -                               indirect = (indirect - 1 + I_B - 1) / I_B;
457 -                               blocks += indirect;
458 -                               if (indirect > 1)
459 -                                       blocks++;
460 -                       }
461 -               }
462 -               tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
463 -               tmp.st_blksize = BLOCK_SIZE;
464 -       } else {
465 -               tmp.st_blocks = inode->i_blocks;
466 -               tmp.st_blksize = inode->i_blksize;
467 -       }
468 +       tmp.st_dev = stat->dev;
469 +       tmp.st_ino = stat->ino;
470 +       tmp.st_mode = stat->mode;
471 +       tmp.st_nlink = stat->nlink;
472 +       SET_STAT_UID(tmp, stat->uid);
473 +       SET_STAT_GID(tmp, stat->gid);
474 +       tmp.st_rdev = stat->rdev;
475 +       tmp.st_size = stat->size;
476 +       tmp.st_atime = stat->atime;
477 +       tmp.st_mtime = stat->mtime;
478 +       tmp.st_ctime = stat->ctime;
479 +       tmp.st_blocks = stat->blocks;
480 +       tmp.st_blksize = stat->blksize;
481  
482         return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
483  }
484  
485  asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
486  {
487 -       struct nameidata nd;
488 -       int error;
489 +       struct kstat stat;
490 +       int error = vfs_stat(filename, &stat);
491  
492 -       error = user_path_walk(filename, &nd);
493 -       if (!error) {
494 -               error = do_revalidate(nd.dentry);
495 -               if (!error)
496 -                       error = cp_new_stat32(nd.dentry->d_inode, statbuf);
497 -
498 -               path_release(&nd);
499 -       }
500 -
501 -       return error;
502 +       return error ? cp_new_stat32(&stat, statbuf);
503  }
504  
505  asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
506  {
507 -       struct nameidata nd;
508 -       int error;
509 -
510 -       error = user_path_walk_link(filename, &nd);
511 -       if (!error) {
512 -               error = do_revalidate(nd.dentry);
513 -               if (!error)
514 -                       error = cp_new_stat32(nd.dentry->d_inode, statbuf);
515 -
516 -               path_release(&nd);
517 -       }
518 +       struct kstat stat;
519 +       int error = vfs_lstat(filename, &stat);
520  
521 -       return error;
522 +       return error ? cp_new_stat32(&stat, statbuf);
523  }
524  
525  asmlinkage long sys32_newfstat(unsigned int fd, struct stat32 * statbuf)
526  {
527 -       struct file * f;
528 -       int err = -EBADF;
529 -
530 -       f = fget(fd);
531 -       if (f) {
532 -               struct dentry * dentry = f->f_dentry;
533 -
534 -               err = do_revalidate(dentry);
535 -               if (!err)
536 -                       err = cp_new_stat32(dentry->d_inode, statbuf);
537 -               fput(f);
538 -       }
539 +       struct kstat stat;
540 +       int error = vfs_fstat(fd, &stat);
541  
542 -       return err;
543 +       return error ? cp_new_stat32(&stat, statbuf);
544  }
545  
546  asmlinkage int sys_mmap2(void) {return 0;}
547 diff -Naurp linux-2.4.20-ck4/arch/parisc/hpux/fs.c linux-2.4.20-ck5/arch/parisc/hpux/fs.c
548 --- linux-2.4.20-ck4/arch/parisc/hpux/fs.c      2002-11-30 17:02:02.000000000 +1100
549 +++ linux-2.4.20-ck5/arch/parisc/hpux/fs.c      2003-04-08 10:52:50.000000000 +1000
550 @@ -120,110 +120,47 @@ int hpux_mount(const char *fs, const cha
551         return -ENOSYS;
552  }
553  
554 -static int cp_hpux_stat(struct inode * inode, struct hpux_stat64 * statbuf)
555 +static int cp_hpux_stat(struct kstat *stat, struct hpux_stat64 * statbuf)
556  {
557         struct hpux_stat64 tmp;
558 -       unsigned int blocks, indirect;
559  
560         memset(&tmp, 0, sizeof(tmp));
561 -       tmp.st_dev = kdev_t_to_nr(inode->i_dev);
562 -       tmp.st_ino = inode->i_ino;
563 -       tmp.st_mode = inode->i_mode;
564 -       tmp.st_nlink = inode->i_nlink;
565 -       tmp.st_uid = inode->i_uid;
566 -       tmp.st_gid = inode->i_gid;
567 -       tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
568 -       tmp.st_size = inode->i_size;
569 -       tmp.st_atime = inode->i_atime;
570 -       tmp.st_mtime = inode->i_mtime;
571 -       tmp.st_ctime = inode->i_ctime;
572 -
573 -#define D_B   7
574 -#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
575 -
576 -       if (!inode->i_blksize) {
577 -               blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
578 -               if (blocks > D_B) {
579 -                       indirect = (blocks - D_B + I_B - 1) / I_B;
580 -                       blocks += indirect;
581 -                       if (indirect > 1) {
582 -                               indirect = (indirect - 1 + I_B - 1) / I_B;
583 -                               blocks += indirect;
584 -                               if (indirect > 1)
585 -                                       blocks++;
586 -                       }
587 -               }
588 -               tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
589 -               tmp.st_blksize = BLOCK_SIZE;
590 -       } else {
591 -               tmp.st_blocks = inode->i_blocks;
592 -               tmp.st_blksize = inode->i_blksize;
593 -       }
594 +       tmp.st_dev = stat->dev;
595 +       tmp.st_ino = stat->ino;
596 +       tmp.st_mode = stat->mode;
597 +       tmp.st_nlink = stat->nlink;
598 +       tmp.st_uid = stat->uid;
599 +       tmp.st_gid = stat->gid;
600 +       tmp.st_rdev = stat->rdev;
601 +       tmp.st_size = stat->size;
602 +       tmp.st_atime = stat->atime;
603 +       tmp.st_mtime = stat->mtime;
604 +       tmp.st_ctime = stat->ctime;
605 +       tmp.st_blocks = stat->blocks;
606 +       tmp.st_blksize = stat->blksize;
607         return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
608  }
609  
610 -/*
611 - * Revalidate the inode. This is required for proper NFS attribute caching.
612 - * Blatently copied wholesale from fs/stat.c
613 - */
614 -static __inline__ int
615 -do_revalidate(struct dentry *dentry)
616 -{
617 -       struct inode * inode = dentry->d_inode;
618 -       if (inode->i_op && inode->i_op->revalidate)
619 -               return inode->i_op->revalidate(dentry);
620 -       return 0;
621 -}
622 -
623  long hpux_stat64(const char *path, struct hpux_stat64 *buf)
624  {
625 -       struct nameidata nd;
626 -       int error;
627 +       struct kstat stat;
628 +       int error = vfs_stat(path, &stat);
629  
630 -       lock_kernel();
631 -       error = user_path_walk(path, &nd);
632 -       if (!error) {
633 -               error = do_revalidate(nd.dentry);
634 -               if (!error)
635 -                       error = cp_hpux_stat(nd.dentry->d_inode, buf);
636 -               path_release(&nd);
637 -       }
638 -       unlock_kernel();
639 -       return error;
640 +       return error ? error : cp_hpux_stat(&stat, buf);
641  }
642  
643  long hpux_fstat64(unsigned int fd, struct hpux_stat64 *statbuf)
644  {
645 -       struct file * f;
646 -       int err = -EBADF;
647 +       struct kstat stat;
648 +       int error = vfs_fstat(fd, &stat);
649  
650 -       lock_kernel();
651 -       f = fget(fd);
652 -       if (f) {
653 -               struct dentry * dentry = f->f_dentry;
654 -
655 -               err = do_revalidate(dentry);
656 -               if (!err)
657 -                       err = cp_hpux_stat(dentry->d_inode, statbuf);
658 -               fput(f);
659 -       }
660 -       unlock_kernel();
661 -       return err;
662 +       return error ? error : cp_hpux_stat(&stat, buf);
663  }
664  
665  long hpux_lstat64(char *filename, struct hpux_stat64 *statbuf)
666  {
667 -       struct nameidata nd;
668 -       int error;
669 +       struct kstat stat;
670 +       int error = vfs_lstat(path, &stat);
671  
672 -       lock_kernel();
673 -       error = user_path_walk_link(filename, &nd);
674 -       if (!error) {
675 -               error = do_revalidate(nd.dentry);
676 -               if (!error)
677 -                       error = cp_hpux_stat(nd.dentry->d_inode, statbuf);
678 -               path_release(&nd);
679 -       }
680 -       unlock_kernel();
681 -       return error;
682 +       return error ? error : cp_hpux_stat(&stat, buf);
683  }
684 diff -Naurp linux-2.4.20-ck4/arch/s390x/kernel/linux32.c linux-2.4.20-ck5/arch/s390x/kernel/linux32.c
685 --- linux-2.4.20-ck4/arch/s390x/kernel/linux32.c        2002-08-03 13:14:44.000000000 +1000
686 +++ linux-2.4.20-ck5/arch/s390x/kernel/linux32.c        2003-04-08 10:52:50.000000000 +1000
687 @@ -1486,76 +1486,27 @@ out_nofds:
688         return ret;
689  }
690  
691 -static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf)
692 +static int cp_new_stat32(struct kstat *stat, struct stat32 *statbuf)
693  {
694 -       unsigned long ino, blksize, blocks;
695 -       kdev_t dev, rdev;
696 -       umode_t mode;
697 -       nlink_t nlink;
698 -       uid_t uid;
699 -       gid_t gid;
700 -       off_t size;
701 -       time_t atime, mtime, ctime;
702 +       /* XXX_SIZE */
703         int err;
704  
705 -       /* Stream the loads of inode data into the load buffer,
706 -        * then we push it all into the store buffer below.  This
707 -        * should give optimal cache performance.
708 -        */
709 -       ino = inode->i_ino;
710 -       dev = inode->i_dev;
711 -       mode = inode->i_mode;
712 -       nlink = inode->i_nlink;
713 -       uid = inode->i_uid;
714 -       gid = inode->i_gid;
715 -       rdev = inode->i_rdev;
716 -       size = inode->i_size;
717 -       atime = inode->i_atime;
718 -       mtime = inode->i_mtime;
719 -       ctime = inode->i_ctime;
720 -       blksize = inode->i_blksize;
721 -       blocks = inode->i_blocks;
722 -
723 -       err  = put_user(kdev_t_to_nr(dev), &statbuf->st_dev);
724 -       err |= put_user(ino, &statbuf->st_ino);
725 -       err |= put_user(mode, &statbuf->st_mode);
726 -       err |= put_user(nlink, &statbuf->st_nlink);
727 -       err |= put_user(high2lowuid(uid), &statbuf->st_uid);
728 -       err |= put_user(high2lowgid(gid), &statbuf->st_gid);
729 -       err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev);
730 -       err |= put_user(size, &statbuf->st_size);
731 -       err |= put_user(atime, &statbuf->st_atime);
732 +       err  = put_user(stat->dev, &statbuf->st_dev);
733 +       err |= put_user(stat->ino, &statbuf->st_ino);
734 +       err |= put_user(stat->mode, &statbuf->st_mode);
735 +       err |= put_user(stat->nlink, &statbuf->st_nlink);
736 +       err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
737 +       err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
738 +       err |= put_user(stat->rdev, &statbuf->st_rdev);
739 +       err |= put_user(stat->size, &statbuf->st_size);
740 +       err |= put_user(stat->atime, &statbuf->st_atime);
741         err |= put_user(0, &statbuf->__unused1);
742 -       err |= put_user(mtime, &statbuf->st_mtime);
743 +       err |= put_user(stat->mtime, &statbuf->st_mtime);
744         err |= put_user(0, &statbuf->__unused2);
745 -       err |= put_user(ctime, &statbuf->st_ctime);
746 +       err |= put_user(stat->ctime, &statbuf->st_ctime);
747         err |= put_user(0, &statbuf->__unused3);
748 -       if (blksize) {
749 -               err |= put_user(blksize, &statbuf->st_blksize);
750 -               err |= put_user(blocks, &statbuf->st_blocks);
751 -       } else {
752 -               unsigned int tmp_blocks;
753 -
754 -#define D_B   7
755 -#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
756 -               tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
757 -               if (tmp_blocks > D_B) {
758 -                       unsigned int indirect;
759 -
760 -                       indirect = (tmp_blocks - D_B + I_B - 1) / I_B;
761 -                       tmp_blocks += indirect;
762 -                       if (indirect > 1) {
763 -                               indirect = (indirect - 1 + I_B - 1) / I_B;
764 -                               tmp_blocks += indirect;
765 -                               if (indirect > 1)
766 -                                       tmp_blocks++;
767 -                       }
768 -               }
769 -               err |= put_user(BLOCK_SIZE, &statbuf->st_blksize);
770 -               err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks);
771 -#undef D_B
772 -#undef I_B
773 -       }
774 +       err |= put_user(stat->blksize, &statbuf->st_blksize);
775 +       err |= put_user(stat->blocks, &statbuf->st_blocks);
776  /* fixme
777         err |= put_user(0, &statbuf->__unused4[0]);
778         err |= put_user(0, &statbuf->__unused4[1]);
779 @@ -1564,62 +1515,28 @@ static int cp_new_stat32(struct inode *i
780         return err;
781  }
782  
783 -/* Perhaps this belongs in fs.h or similar. -DaveM */
784 -static __inline__ int
785 -do_revalidate(struct dentry *dentry)
786 -{
787 -       struct inode * inode = dentry->d_inode;
788 -       if (inode->i_op && inode->i_op->revalidate)
789 -               return inode->i_op->revalidate(dentry);
790 -       return 0;
791 -}
792 -
793  asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
794  {
795 -       struct nameidata nd;
796 -       int error;
797 +       struct kstat stat;
798 +       int error = vfs_stat(filename, &stat);
799  
800 -       error = user_path_walk(filename, &nd);
801 -       if (!error) {
802 -               error = do_revalidate(nd.dentry);
803 -               if (!error)
804 -                       error = cp_new_stat32(nd.dentry->d_inode, statbuf);
805 -               path_release(&nd);
806 -       }
807 -       return error;
808 +       return error ? error : cp_new_stat32(&stat, statbuf);
809  }
810  
811  asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
812  {
813 -       struct nameidata nd;
814 -       int error;
815 +       struct kstat stat;
816 +       int error = vfs_lstat(filename, &stat);
817  
818 -       error = user_path_walk_link(filename, &nd);
819 -       if (!error) {
820 -               error = do_revalidate(nd.dentry);
821 -               if (!error)
822 -                       error = cp_new_stat32(nd.dentry->d_inode, statbuf);
823 -
824 -               path_release(&nd);
825 -       }
826 -       return error;
827 +       return error ? error : cp_new_stat32(&stat, statbuf);
828  }
829  
830  asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
831  {
832 -       struct file *f;
833 -       int err = -EBADF;
834 -
835 -       f = fget(fd);
836 -       if (f) {
837 -               struct dentry * dentry = f->f_dentry;
838 +       struct kstat stat;
839 +       int error = vfs_fstat(fd, &stat);
840  
841 -               err = do_revalidate(dentry);
842 -               if (!err)
843 -                       err = cp_new_stat32(dentry->d_inode, statbuf);
844 -               fput(f);
845 -       }
846 -       return err;
847 +       return error ? error : cp_new_stat32(&stat, statbuf);
848  }
849  
850  extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
851 @@ -4080,89 +3997,55 @@ struct stat64_emu31 {
852  };     
853  
854  static inline int
855 -putstat64 (struct stat64_emu31 *ubuf, struct stat *kbuf)
856 +putstat64 (struct stat64_emu31 *ubuf, struct kstat *kbuf)
857  {
858      struct stat64_emu31 tmp;
859     
860      memset(&tmp, 0, sizeof(tmp));
861  
862 -    tmp.st_dev = (unsigned short)kbuf->st_dev;
863 -    tmp.st_ino = kbuf->st_ino;
864 -    tmp.__st_ino = (u32)kbuf->st_ino;
865 -    tmp.st_mode = kbuf->st_mode;
866 -    tmp.st_nlink = (unsigned int)kbuf->st_nlink;
867 -    tmp.st_uid = kbuf->st_uid;
868 -    tmp.st_gid = kbuf->st_gid;
869 -    tmp.st_rdev = (unsigned short)kbuf->st_rdev;
870 -    tmp.st_size = kbuf->st_size;
871 -    tmp.st_blksize = (u32)kbuf->st_blksize;
872 -    tmp.st_blocks = (u32)kbuf->st_blocks;
873 -    tmp.st_atime = (u32)kbuf->st_atime;
874 -    tmp.st_mtime = (u32)kbuf->st_mtime;
875 -    tmp.st_ctime = (u32)kbuf->st_ctime;
876 +    tmp.st_dev = (unsigned short)kbuf->dev;
877 +    tmp.st_ino = kbuf->ino;
878 +    tmp.__st_ino = (u32)kbuf->ino;
879 +    tmp.st_mode = kbuf->mode;
880 +    tmp.st_nlink = (unsigned int)kbuf->nlink;
881 +    tmp.st_uid = kbuf->uid;
882 +    tmp.st_gid = kbuf->gid;
883 +    tmp.st_rdev = (unsigned short)kbuf->rdev;
884 +    tmp.st_size = kbuf->size;
885 +    tmp.st_blksize = (u32)kbuf->blksize;
886 +    tmp.st_blocks = (u32)kbuf->blocks;
887 +    tmp.st_atime = (u32)kbuf->atime;
888 +    tmp.st_mtime = (u32)kbuf->mtime;
889 +    tmp.st_ctime = (u32)kbuf->ctime;
890  
891      return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; 
892  }
893  
894 -extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
895 -
896  asmlinkage long sys32_stat64(char * filename, struct stat64_emu31 * statbuf, long flags)
897  {
898 -    int ret;
899 -    struct stat s;
900 -    char * tmp;
901 -    int err;
902 -    mm_segment_t old_fs = get_fs();
903 -    
904 -    tmp = getname(filename);
905 -    err = PTR_ERR(tmp);
906 -    if (IS_ERR(tmp))   
907 -           return err;
908 -
909 -    set_fs (KERNEL_DS);
910 -    ret = sys_newstat(tmp, &s);
911 -    set_fs (old_fs);
912 -    putname(tmp);
913 +    struct kstat s;
914 +    int ret = vfs_stat(filename, &s);
915 +
916      if (putstat64 (statbuf, &s)) 
917             return -EFAULT;
918      return ret;
919  }
920  
921 -extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
922 -
923  asmlinkage long sys32_lstat64(char * filename, struct stat64_emu31 * statbuf, long flags)
924  {
925 -    int ret;
926 -    struct stat s;
927 -    char * tmp;
928 -    int err;
929 -    mm_segment_t old_fs = get_fs();
930 -    
931 -    tmp = getname(filename);
932 -    err = PTR_ERR(tmp);
933 -    if (IS_ERR(tmp))   
934 -           return err;
935 -
936 -    set_fs (KERNEL_DS);
937 -    ret = sys_newlstat(tmp, &s);
938 -    set_fs (old_fs);
939 -    putname(tmp);
940 +    struct kstat s;
941 +    int ret = vfs_lstat(filename, &s);
942 +
943      if (putstat64 (statbuf, &s)) 
944             return -EFAULT;
945      return ret;
946  }
947  
948 -extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
949 -
950  asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 * statbuf, long flags)
951  {
952 -    int ret;
953 -    struct stat s;
954 -    mm_segment_t old_fs = get_fs();
955 -    
956 -    set_fs (KERNEL_DS);
957 -    ret = sys_newfstat(fd, &s);
958 -    set_fs (old_fs);
959 +    struct kstat s;
960 +    int ret = vfs_fstat(fd, &s);
961 +
962      if (putstat64 (statbuf, &s))
963             return -EFAULT;
964      return ret;
965 diff -Naurp linux-2.4.20-ck4/arch/sparc64/kernel/sys_sparc32.c linux-2.4.20-ck5/arch/sparc64/kernel/sys_sparc32.c
966 --- linux-2.4.20-ck4/arch/sparc64/kernel/sys_sparc32.c  2002-11-30 17:02:06.000000000 +1100
967 +++ linux-2.4.20-ck5/arch/sparc64/kernel/sys_sparc32.c  2003-04-08 10:52:50.000000000 +1000
968 @@ -1475,138 +1475,54 @@ out_nofds:
969         return ret;
970  }
971  
972 -static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf)
973 +static int cp_new_stat32(struct kstat *stat, struct stat32 *statbuf)
974  {
975 -       unsigned long ino, blksize, blocks;
976 -       kdev_t dev, rdev;
977 -       umode_t mode;
978 -       nlink_t nlink;
979 -       uid_t uid;
980 -       gid_t gid;
981 -       off_t size;
982 -       time_t atime, mtime, ctime;
983 +       /* XXX_SIZE */
984         int err;
985 -
986 -       /* Stream the loads of inode data into the load buffer,
987 -        * then we push it all into the store buffer below.  This
988 -        * should give optimal cache performance.
989 -        */
990 -       ino = inode->i_ino;
991 -       dev = inode->i_dev;
992 -       mode = inode->i_mode;
993 -       nlink = inode->i_nlink;
994 -       uid = inode->i_uid;
995 -       gid = inode->i_gid;
996 -       rdev = inode->i_rdev;
997 -       size = inode->i_size;
998 -       atime = inode->i_atime;
999 -       mtime = inode->i_mtime;
1000 -       ctime = inode->i_ctime;
1001 -       blksize = inode->i_blksize;
1002 -       blocks = inode->i_blocks;
1003 -
1004 -       err  = put_user(kdev_t_to_nr(dev), &statbuf->st_dev);
1005 -       err |= put_user(ino, &statbuf->st_ino);
1006 -       err |= put_user(mode, &statbuf->st_mode);
1007 -       err |= put_user(nlink, &statbuf->st_nlink);
1008 -       err |= put_user(high2lowuid(uid), &statbuf->st_uid);
1009 -       err |= put_user(high2lowgid(gid), &statbuf->st_gid);
1010 -       err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev);
1011 -       err |= put_user(size, &statbuf->st_size);
1012 -       err |= put_user(atime, &statbuf->st_atime);
1013 +       err  = put_user(stat->dev, &statbuf->st_dev);
1014 +       err |= put_user(stat->ino, &statbuf->st_ino);
1015 +       err |= put_user(stat->mode, &statbuf->st_mode);
1016 +       err |= put_user(stat->nlink, &statbuf->st_nlink);
1017 +       err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
1018 +       err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
1019 +       err |= put_user(kdev_t_to_nr(stat->rdev), &statbuf->st_rdev);
1020 +       err |= put_user(stat->size, &statbuf->st_size);
1021 +       err |= put_user(stat->atime, &statbuf->st_atime);
1022         err |= put_user(0, &statbuf->__unused1);
1023 -       err |= put_user(mtime, &statbuf->st_mtime);
1024 +       err |= put_user(stat->mtime, &statbuf->st_mtime);
1025         err |= put_user(0, &statbuf->__unused2);
1026 -       err |= put_user(ctime, &statbuf->st_ctime);
1027 +       err |= put_user(stat->ctime, &statbuf->st_ctime);
1028         err |= put_user(0, &statbuf->__unused3);
1029 -       if (blksize) {
1030 -               err |= put_user(blksize, &statbuf->st_blksize);
1031 -               err |= put_user(blocks, &statbuf->st_blocks);
1032 -       } else {
1033 -               unsigned int tmp_blocks;
1034 -
1035 -#define D_B   7
1036 -#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
1037 -               tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
1038 -               if (tmp_blocks > D_B) {
1039 -                       unsigned int indirect;
1040 -
1041 -                       indirect = (tmp_blocks - D_B + I_B - 1) / I_B;
1042 -                       tmp_blocks += indirect;
1043 -                       if (indirect > 1) {
1044 -                               indirect = (indirect - 1 + I_B - 1) / I_B;
1045 -                               tmp_blocks += indirect;
1046 -                               if (indirect > 1)
1047 -                                       tmp_blocks++;
1048 -                       }
1049 -               }
1050 -               err |= put_user(BLOCK_SIZE, &statbuf->st_blksize);
1051 -               err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks);
1052 -#undef D_B
1053 -#undef I_B
1054 -       }
1055 +       err |= put_user(stat->blksize, &statbuf->st_blksize);
1056 +       err |= put_user(stat->blocks, &statbuf->st_blocks);
1057         err |= put_user(0, &statbuf->__unused4[0]);
1058         err |= put_user(0, &statbuf->__unused4[1]);
1059  
1060         return err;
1061  }
1062  
1063 -/* Perhaps this belongs in fs.h or similar. -DaveM */
1064 -static __inline__ int
1065 -do_revalidate(struct dentry *dentry)
1066 -{
1067 -       struct inode * inode = dentry->d_inode;
1068 -       if (inode->i_op && inode->i_op->revalidate)
1069 -               return inode->i_op->revalidate(dentry);
1070 -       return 0;
1071 -}
1072 -
1073  asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
1074  {
1075 -       struct nameidata nd;
1076 -       int error;
1077 -
1078 -       error = user_path_walk(filename, &nd);
1079 -       if (!error) {
1080 -               error = do_revalidate(nd.dentry);
1081 -               if (!error)
1082 -                       error = cp_new_stat32(nd.dentry->d_inode, statbuf);
1083 -               path_release(&nd);
1084 -       }
1085 -       return error;
1086 +       struct kstat stat;
1087 +       int error = vfs_stat(filename, &stat);
1088 +  
1089 +       return error ? error : cp_new_stat32(&stat, statbuf);
1090  }
1091  
1092  asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
1093  {
1094 -       struct nameidata nd;
1095 -       int error;
1096 +       struct kstat stat;
1097 +       int error = vfs_lstat(filename, &stat);
1098  
1099 -       error = user_path_walk_link(filename, &nd);
1100 -       if (!error) {
1101 -               error = do_revalidate(nd.dentry);
1102 -               if (!error)
1103 -                       error = cp_new_stat32(nd.dentry->d_inode, statbuf);
1104 -
1105 -               path_release(&nd);
1106 -       }
1107 -       return error;
1108 +       return error ? error : cp_new_stat32(&stat, statbuf);
1109  }
1110  
1111  asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
1112  {
1113 -       struct file *f;
1114 -       int err = -EBADF;
1115 -
1116 -       f = fget(fd);
1117 -       if (f) {
1118 -               struct dentry * dentry = f->f_dentry;
1119 -
1120 -               err = do_revalidate(dentry);
1121 -               if (!err)
1122 -                       err = cp_new_stat32(dentry->d_inode, statbuf);
1123 -               fput(f);
1124 -       }
1125 -       return err;
1126 +       struct kstat stat;
1127 +       int error = vfs_fstat(fd, &stat);
1128 +  
1129 +       return error ? error : cp_new_stat32(&stat, statbuf);
1130  }
1131  
1132  extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
1133 diff -Naurp linux-2.4.20-ck4/arch/sparc64/solaris/fs.c linux-2.4.20-ck5/arch/sparc64/solaris/fs.c
1134 --- linux-2.4.20-ck4/arch/sparc64/solaris/fs.c  2001-09-21 07:11:57.000000000 +1000
1135 +++ linux-2.4.20-ck5/arch/sparc64/solaris/fs.c  2003-04-08 10:52:50.000000000 +1000
1136 @@ -79,47 +79,49 @@ struct sol_stat64 {
1137  
1138  #define UFSMAGIC (((unsigned)'u'<<24)||((unsigned)'f'<<16)||((unsigned)'s'<<8))
1139  
1140 -static inline int putstat(struct sol_stat *ubuf, struct stat *kbuf)
1141 +static inline int putstat(struct sol_stat *ubuf, struct kstat *kbuf)
1142  {
1143 -       if (put_user (R4_DEV(kbuf->st_dev), &ubuf->st_dev)      ||
1144 -           __put_user (kbuf->st_ino, &ubuf->st_ino)            ||
1145 -           __put_user (kbuf->st_mode, &ubuf->st_mode)          ||
1146 -           __put_user (kbuf->st_nlink, &ubuf->st_nlink)        ||
1147 -           __put_user (kbuf->st_uid, &ubuf->st_uid)            ||
1148 -           __put_user (kbuf->st_gid, &ubuf->st_gid)            ||
1149 -           __put_user (R4_DEV(kbuf->st_rdev), &ubuf->st_rdev)  ||
1150 -           __put_user (kbuf->st_size, &ubuf->st_size)          ||
1151 -           __put_user (kbuf->st_atime, &ubuf->st_atime.tv_sec) ||
1152 +       /* XXX_UID, XXX_SIZE */
1153 +       if (put_user (R4_DEV(kbuf->dev), &ubuf->st_dev) ||
1154 +           __put_user (kbuf->ino, &ubuf->st_ino)               ||
1155 +           __put_user (kbuf->mode, &ubuf->st_mode)             ||
1156 +           __put_user (kbuf->nlink, &ubuf->st_nlink)   ||
1157 +           __put_user (kbuf->uid, &ubuf->st_uid)               ||
1158 +           __put_user (kbuf->gid, &ubuf->st_gid)               ||
1159 +           __put_user (R4_DEV(kbuf->rdev), &ubuf->st_rdev)     ||
1160 +           __put_user (kbuf->size, &ubuf->st_size)             ||
1161 +           __put_user (kbuf->atime, &ubuf->st_atime.tv_sec)    ||
1162             __put_user (0, &ubuf->st_atime.tv_nsec)             ||
1163 -           __put_user (kbuf->st_mtime, &ubuf->st_mtime.tv_sec) ||
1164 +           __put_user (kbuf->mtime, &ubuf->st_mtime.tv_sec)    ||
1165             __put_user (0, &ubuf->st_mtime.tv_nsec)             ||
1166 -           __put_user (kbuf->st_ctime, &ubuf->st_ctime.tv_sec) ||
1167 +           __put_user (kbuf->ctime, &ubuf->st_ctime.tv_sec)    ||
1168             __put_user (0, &ubuf->st_ctime.tv_nsec)             ||
1169 -           __put_user (kbuf->st_blksize, &ubuf->st_blksize)    ||
1170 -           __put_user (kbuf->st_blocks, &ubuf->st_blocks)      ||
1171 +           __put_user (kbuf->blksize, &ubuf->st_blksize)       ||
1172 +           __put_user (kbuf->blocks, &ubuf->st_blocks) ||
1173             __put_user (UFSMAGIC, (unsigned *)ubuf->st_fstype))
1174                 return -EFAULT;
1175         return 0;
1176  }
1177  
1178 -static inline int putstat64(struct sol_stat64 *ubuf, struct stat *kbuf)
1179 +static inline int putstat64(struct sol_stat64 *ubuf, struct kstat *kbuf)
1180  {
1181 -       if (put_user (R4_DEV(kbuf->st_dev), &ubuf->st_dev)      ||
1182 -           __put_user (kbuf->st_ino, &ubuf->st_ino)            ||
1183 -           __put_user (kbuf->st_mode, &ubuf->st_mode)          ||
1184 -           __put_user (kbuf->st_nlink, &ubuf->st_nlink)        ||
1185 -           __put_user (kbuf->st_uid, &ubuf->st_uid)            ||
1186 -           __put_user (kbuf->st_gid, &ubuf->st_gid)            ||
1187 -           __put_user (R4_DEV(kbuf->st_rdev), &ubuf->st_rdev)  ||
1188 -           __put_user (kbuf->st_size, &ubuf->st_size)          ||
1189 -           __put_user (kbuf->st_atime, &ubuf->st_atime.tv_sec) ||
1190 +       /* XXX_UID, XXX_SIZE */
1191 +       if (put_user (R4_DEV(kbuf->dev), &ubuf->st_dev) ||
1192 +           __put_user (kbuf->ino, &ubuf->st_ino)               ||
1193 +           __put_user (kbuf->mode, &ubuf->st_mode)             ||
1194 +           __put_user (kbuf->nlink, &ubuf->st_nlink)   ||
1195 +           __put_user (kbuf->uid, &ubuf->st_uid)               ||
1196 +           __put_user (kbuf->gid, &ubuf->st_gid)               ||
1197 +           __put_user (R4_DEV(kbuf->rdev), &ubuf->st_rdev)     ||
1198 +           __put_user (kbuf->size, &ubuf->st_size)             ||
1199 +           __put_user (kbuf->atime, &ubuf->st_atime.tv_sec)    ||
1200             __put_user (0, &ubuf->st_atime.tv_nsec)             ||
1201 -           __put_user (kbuf->st_mtime, &ubuf->st_mtime.tv_sec) ||
1202 +           __put_user (kbuf->mtime, &ubuf->st_mtime.tv_sec)    ||
1203             __put_user (0, &ubuf->st_mtime.tv_nsec)             ||
1204 -           __put_user (kbuf->st_ctime, &ubuf->st_ctime.tv_sec) ||
1205 +           __put_user (kbuf->ctime, &ubuf->st_ctime.tv_sec)    ||
1206             __put_user (0, &ubuf->st_ctime.tv_nsec)             ||
1207 -           __put_user (kbuf->st_blksize, &ubuf->st_blksize)    ||
1208 -           __put_user (kbuf->st_blocks, &ubuf->st_blocks)      ||
1209 +           __put_user (kbuf->blksize, &ubuf->st_blksize)       ||
1210 +           __put_user (kbuf->blocks, &ubuf->st_blocks) ||
1211             __put_user (UFSMAGIC, (unsigned *)ubuf->st_fstype))
1212                 return -EFAULT;
1213         return 0;
1214 @@ -127,23 +129,11 @@ static inline int putstat64(struct sol_s
1215  
1216  asmlinkage int solaris_stat(u32 filename, u32 statbuf)
1217  {
1218 -       int ret;
1219 -       struct stat s;
1220 -       char *filenam;
1221 -       mm_segment_t old_fs = get_fs();
1222 -       int (*sys_newstat)(char *,struct stat *) = 
1223 -               (int (*)(char *,struct stat *))SYS(stat);
1224 -       
1225 -       filenam = getname ((char *)A(filename));
1226 -       ret = PTR_ERR(filenam);
1227 -       if (!IS_ERR(filenam)) {
1228 -               set_fs (KERNEL_DS);
1229 -               ret = sys_newstat(filenam, &s);
1230 -               set_fs (old_fs);
1231 -               putname (filenam);
1232 -               if (putstat ((struct sol_stat *)A(statbuf), &s))
1233 -                       return -EFAULT;
1234 -       }
1235 +       struct kstat s;
1236 +       int ret = vfs_stat((char*)A(filename), &s);
1237 +
1238 +       if (putstat ((struct sol_stat *)A(statbuf), &s))
1239 +               return -EFAULT;
1240         return ret;
1241  }
1242  
1243 @@ -155,45 +145,21 @@ asmlinkage int solaris_xstat(int vers, u
1244  
1245  asmlinkage int solaris_stat64(u32 filename, u32 statbuf)
1246  {
1247 -       int ret;
1248 -       struct stat s;
1249 -       char *filenam;
1250 -       mm_segment_t old_fs = get_fs();
1251 -       int (*sys_newstat)(char *,struct stat *) = 
1252 -               (int (*)(char *,struct stat *))SYS(stat);
1253 -       
1254 -       filenam = getname ((char *)A(filename));
1255 -       ret = PTR_ERR(filenam);
1256 -       if (!IS_ERR(filenam)) {
1257 -               set_fs (KERNEL_DS);
1258 -               ret = sys_newstat(filenam, &s);
1259 -               set_fs (old_fs);
1260 -               putname (filenam);
1261 -               if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
1262 -                       return -EFAULT;
1263 -       }
1264 +       struct kstat s;
1265 +       int ret = vfs_stat((char*)A(filename), &s);
1266 +
1267 +       if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
1268 +               return -EFAULT;
1269         return ret;
1270  }
1271  
1272  asmlinkage int solaris_lstat(u32 filename, u32 statbuf)
1273  {
1274 -       int ret;
1275 -       struct stat s;
1276 -       char *filenam;
1277 -       mm_segment_t old_fs = get_fs();
1278 -       int (*sys_newlstat)(char *,struct stat *) = 
1279 -               (int (*)(char *,struct stat *))SYS(lstat);
1280 -       
1281 -       filenam = getname ((char *)A(filename));
1282 -       ret = PTR_ERR(filenam);
1283 -       if (!IS_ERR(filenam)) {
1284 -               set_fs (KERNEL_DS);
1285 -               ret = sys_newlstat(filenam, &s);
1286 -               set_fs (old_fs);
1287 -               putname (filenam);
1288 -               if (putstat ((struct sol_stat *)A(statbuf), &s))
1289 -                       return -EFAULT;
1290 -       }
1291 +       struct kstat s;
1292 +       int ret = vfs_lstat((char*)A(filename), &s);
1293 +
1294 +       if (putstat ((struct sol_stat *)A(statbuf), &s))
1295 +               return -EFAULT;
1296         return ret;
1297  }
1298  
1299 @@ -204,37 +170,19 @@ asmlinkage int solaris_lxstat(int vers, 
1300  
1301  asmlinkage int solaris_lstat64(u32 filename, u32 statbuf)
1302  {
1303 -       int ret;
1304 -       struct stat s;
1305 -       char *filenam;
1306 -       mm_segment_t old_fs = get_fs();
1307 -       int (*sys_newlstat)(char *,struct stat *) = 
1308 -               (int (*)(char *,struct stat *))SYS(lstat);
1309 -       
1310 -       filenam = getname ((char *)A(filename));
1311 -       ret = PTR_ERR(filenam);
1312 -       if (!IS_ERR(filenam)) {
1313 -               set_fs (KERNEL_DS);
1314 -               ret = sys_newlstat(filenam, &s);
1315 -               set_fs (old_fs);
1316 -               putname (filenam);
1317 -               if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
1318 -                       return -EFAULT;
1319 -       }
1320 +       struct kstat s;
1321 +       int ret = vfs_lstat((char*)A(filename), &s);
1322 +
1323 +       if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
1324 +               return -EFAULT;
1325         return ret;
1326  }
1327  
1328  asmlinkage int solaris_fstat(unsigned int fd, u32 statbuf)
1329  {
1330 -       int ret;
1331 -       struct stat s;
1332 -       mm_segment_t old_fs = get_fs();
1333 -       int (*sys_newfstat)(unsigned,struct stat *) = 
1334 -               (int (*)(unsigned,struct stat *))SYS(fstat);
1335 -       
1336 -       set_fs (KERNEL_DS);
1337 -       ret = sys_newfstat(fd, &s);
1338 -       set_fs (old_fs);
1339 +       struct kstat s;
1340 +       int ret = vfs_fstat(fd, &s);
1341 +
1342         if (putstat ((struct sol_stat *)A(statbuf), &s))
1343                 return -EFAULT;
1344         return ret;
1345 @@ -247,15 +195,9 @@ asmlinkage int solaris_fxstat(int vers, 
1346  
1347  asmlinkage int solaris_fstat64(unsigned int fd, u32 statbuf)
1348  {
1349 -       int ret;
1350 -       struct stat s;
1351 -       mm_segment_t old_fs = get_fs();
1352 -       int (*sys_newfstat)(unsigned,struct stat *) = 
1353 -               (int (*)(unsigned,struct stat *))SYS(fstat);
1354 -       
1355 -       set_fs (KERNEL_DS);
1356 -       ret = sys_newfstat(fd, &s);
1357 -       set_fs (old_fs);
1358 +       struct kstat s;
1359 +       int ret = vfs_fstat(fd, &s);
1360 +
1361         if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
1362                 return -EFAULT;
1363         return ret;
1364 diff -Naurp linux-2.4.20-ck4/Documentation/filesystems/00-INDEX linux-2.4.20-ck5/Documentation/filesystems/00-INDEX
1365 --- linux-2.4.20-ck4/Documentation/filesystems/00-INDEX 2002-11-30 17:02:00.000000000 +1100
1366 +++ linux-2.4.20-ck5/Documentation/filesystems/00-INDEX 2003-04-08 10:52:50.000000000 +1000
1367 @@ -36,6 +36,8 @@ romfs.txt
1368         - Description of the ROMFS filesystem.
1369  smbfs.txt
1370         - info on using filesystems with the SMB protocol (Windows 3.11 and NT)
1371 +supermount.txt
1372 +       - info on using supermount for removable media.
1373  sysv-fs.txt
1374         - info on the SystemV/V7/Xenix/Coherent filesystem.
1375  udf.txt
1376 diff -Naurp linux-2.4.20-ck4/Documentation/filesystems/supermount.txt linux-2.4.20-ck5/Documentation/filesystems/supermount.txt
1377 --- linux-2.4.20-ck4/Documentation/filesystems/supermount.txt   1970-01-01 10:00:00.000000000 +1000
1378 +++ linux-2.4.20-ck5/Documentation/filesystems/supermount.txt   2003-04-08 10:52:50.000000000 +1000
1379 @@ -0,0 +1,66 @@
1380 +Supermount README
1381 +=================
1382 +
1383 +Running supermount
1384 +------------------
1385 +
1386 +To run supermount, compile and install a kernel with the supermount
1387 +patches and select "Y" to the question
1388 +
1389 +       Supermount removable media support (CONFIG_SUPERMOUNT) [Y/n/?] 
1390 +
1391 +when you run "make config".  You set up a supermount filesystem with
1392 +the normal mount command, using the syntax:
1393 +
1394 +       mount -t supermount -o <superfs-options>,--,<subfs-options> <mpt> <mpt>
1395 +
1396 +where
1397 +
1398 +       <superfs-options> are the options you want to pass to supermount
1399 +       itself.  These are described below.
1400 +
1401 +       <subfs-options> are the options you want supermount to pass to the
1402 +       dismountable filesystem underneath.
1403 +
1404 +       <mpt> is the mount point where you want your removable media to be
1405 +       mounted. 
1406 +
1407 +Notice that you do not directly specify the block device you are going
1408 +to mount on the mount command line.  This is because the supermount
1409 +filesystem is NOT connected to a block device; rather, supermount is
1410 +responsible for connecting a separate filesystem to the block device.
1411 +You specify the sub-filesystem and block device name by providing the
1412 +<superfs-options> field, where the following options are currently
1413 +recognised:
1414 +
1415 +* fs=<filesystem-type>                 [default is "auto"]
1416 +
1417 +       Specify the subfilesystem type.  "msdos" and "iso9660" have
1418 +        been tested.  If you use auto, it will try the following
1419 +        filesystems in order:
1420 +                       "udf"
1421 +                       "iso9660"
1422 +                       "vfat"
1423 +                       "msdos"
1424 +                       "ext2"
1425
1426 +
1427 +* dev=<block-device>
1428 +
1429 +       Specify the block device on which the subfs is to be mounted.
1430 +
1431 +
1432 +
1433 +* debug
1434 +
1435 +       Enable debugging code in the supermount filesystem, if
1436 +the debug option was enabled at compile time.  By default, debugging
1437 +code is compiled into the kernel but is disabled until a debug mount
1438 +option is seen.
1439 +
1440 +* '--'
1441 +
1442 +       All options after the option string '--' will be passed
1443 +directly to the subfilesystem when it gets mounted.
1444 +
1445 +
1446 diff -Naurp linux-2.4.20-ck4/drivers/block/paride/pcd.c linux-2.4.20-ck5/drivers/block/paride/pcd.c
1447 --- linux-2.4.20-ck4/drivers/block/paride/pcd.c 2002-11-30 17:02:06.000000000 +1100
1448 +++ linux-2.4.20-ck5/drivers/block/paride/pcd.c 2003-04-08 10:52:50.000000000 +1000
1449 @@ -271,6 +271,7 @@ static struct block_device_operations pc
1450         release:                cdrom_release,
1451         ioctl:                  cdrom_ioctl,
1452         check_media_change:     cdrom_media_changed,
1453 +       mediactl:               cdrom_mediactl,
1454  };
1455  
1456  static struct cdrom_device_ops pcd_dops = {
1457 diff -Naurp linux-2.4.20-ck4/drivers/cdrom/cdrom.c linux-2.4.20-ck5/drivers/cdrom/cdrom.c
1458 --- linux-2.4.20-ck4/drivers/cdrom/cdrom.c      2002-11-30 17:02:06.000000000 +1100
1459 +++ linux-2.4.20-ck5/drivers/cdrom/cdrom.c      2003-04-08 10:52:50.000000000 +1000
1460 @@ -908,6 +908,24 @@ void cdrom_count_tracks(struct cdrom_dev
1461                 tracks->cdi, tracks->xa);
1462  }      
1463  
1464 +int cdrom_mediactl (kdev_t dev, int op, int optarg)
1465 +{
1466 +       struct cdrom_device_info *cdi = cdrom_find_device(dev);
1467 +       struct cdrom_device_ops *cdo = cdi->ops;
1468 +
1469 +       switch (op) {
1470 +       case MEDIA_LOCK:
1471 +       case MEDIA_UNLOCK:
1472 +               if (cdo->capability & ~cdi->mask & CDC_LOCK &&
1473 +                           cdi->options & CDO_LOCK)
1474 +                       cdo->lock_door(cdi, (op == MEDIA_LOCK));
1475 +               break;
1476 +       default:
1477 +               return -ENOSYS;
1478 +       }
1479 +       return 0;
1480 +}
1481 +
1482  /* Requests to the low-level drivers will /always/ be done in the
1483     following format convention:
1484  
1485 @@ -1492,10 +1510,26 @@ int cdrom_ioctl(struct inode *ip, struct
1486                 }
1487  
1488         case CDROMEJECT: {
1489 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
1490 +               struct super_block *sb = get_super(dev);
1491 +               int supermounted = sb ? sb->s_flags & MS_SUPERMOUNTED : 0;
1492 +               int usagecount = cdi->use_count;
1493 +
1494 +               if (sb) drop_super(sb);
1495 +               if (supermounted && usagecount < 2)
1496 +                       BUG();
1497 +#endif
1498                 cdinfo(CD_DO_IOCTL, "entering CDROMEJECT\n"); 
1499                 if (!CDROM_CAN(CDC_OPEN_TRAY))
1500                         return -ENOSYS;
1501 -               if (cdi->use_count != 1 || keeplocked)
1502 +               if (keeplocked 
1503 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
1504 +                   || (supermounted && usagecount != 2) 
1505 +                   || (!supermounted && usagecount != 1)
1506 +#else
1507 +                   || (cdi->use_count != 1)
1508 +#endif
1509 +               )
1510                         return -EBUSY;
1511                 if (CDROM_CAN(CDC_LOCK))
1512                         if ((ret=cdo->lock_door(cdi, 0)))
1513 @@ -2364,7 +2398,7 @@ use_last_written:
1514                 *next_writable += 7;
1515                 return 0;
1516         }
1517 -}
1518 +}      
1519  
1520  EXPORT_SYMBOL(cdrom_get_disc_info);
1521  EXPORT_SYMBOL(cdrom_get_track_info);
1522 @@ -2377,6 +2411,7 @@ EXPORT_SYMBOL(cdrom_open);
1523  EXPORT_SYMBOL(cdrom_release);
1524  EXPORT_SYMBOL(cdrom_ioctl);
1525  EXPORT_SYMBOL(cdrom_media_changed);
1526 +EXPORT_SYMBOL(cdrom_mediactl);
1527  EXPORT_SYMBOL(cdrom_number_of_slots);
1528  EXPORT_SYMBOL(cdrom_select_disc);
1529  EXPORT_SYMBOL(cdrom_mode_select);
1530 diff -Naurp linux-2.4.20-ck4/drivers/cdrom/cdu31a.c linux-2.4.20-ck5/drivers/cdrom/cdu31a.c
1531 --- linux-2.4.20-ck4/drivers/cdrom/cdu31a.c     2002-11-30 17:02:06.000000000 +1100
1532 +++ linux-2.4.20-ck5/drivers/cdrom/cdu31a.c     2003-04-08 10:52:50.000000000 +1000
1533 @@ -3188,6 +3188,7 @@ struct block_device_operations scd_bdops
1534         release:                cdrom_release,
1535         ioctl:                  cdrom_ioctl,
1536         check_media_change:     cdrom_media_changed,
1537 +       mediactl:               cdrom_mediactl,
1538  };
1539  
1540  static struct cdrom_device_ops scd_dops = {
1541 diff -Naurp linux-2.4.20-ck4/drivers/cdrom/cm206.c linux-2.4.20-ck5/drivers/cdrom/cm206.c
1542 --- linux-2.4.20-ck4/drivers/cdrom/cm206.c      2001-10-26 06:58:35.000000000 +1000
1543 +++ linux-2.4.20-ck5/drivers/cdrom/cm206.c      2003-04-08 10:52:50.000000000 +1000
1544 @@ -772,6 +772,7 @@ struct block_device_operations cm206_bdo
1545         release:                cdrom_release,
1546         ioctl:                  cdrom_ioctl,
1547         check_media_change:     cdrom_media_changed,
1548 +       mediactl:               cdrom_mediactl,
1549  };
1550  
1551  /* The new open. The real opening strategy is defined in cdrom.c. */
1552 diff -Naurp linux-2.4.20-ck4/drivers/cdrom/mcd.c linux-2.4.20-ck5/drivers/cdrom/mcd.c
1553 --- linux-2.4.20-ck4/drivers/cdrom/mcd.c        2001-10-26 06:58:35.000000000 +1000
1554 +++ linux-2.4.20-ck5/drivers/cdrom/mcd.c        2003-04-08 10:52:51.000000000 +1000
1555 @@ -196,6 +196,7 @@ struct block_device_operations mcd_bdops
1556         release:                cdrom_release,
1557         ioctl:                  cdrom_ioctl,
1558         check_media_change:     cdrom_media_changed,
1559 +       mediactl:               cdrom_mediactl,
1560  };
1561  
1562  static struct timer_list mcd_timer;
1563 diff -Naurp linux-2.4.20-ck4/drivers/cdrom/mcdx.c linux-2.4.20-ck5/drivers/cdrom/mcdx.c
1564 --- linux-2.4.20-ck4/drivers/cdrom/mcdx.c       2001-10-26 06:58:35.000000000 +1000
1565 +++ linux-2.4.20-ck5/drivers/cdrom/mcdx.c       2003-04-08 10:52:51.000000000 +1000
1566 @@ -226,6 +226,7 @@ struct block_device_operations mcdx_bdop
1567         release:                cdrom_release,
1568         ioctl:                  cdrom_ioctl,
1569         check_media_change:     cdrom_media_changed,
1570 +       mediactl:               cdrom_mediactl,
1571  };
1572  
1573  
1574 diff -Naurp linux-2.4.20-ck4/drivers/cdrom/sbpcd.c linux-2.4.20-ck5/drivers/cdrom/sbpcd.c
1575 --- linux-2.4.20-ck4/drivers/cdrom/sbpcd.c      2001-10-26 06:58:35.000000000 +1000
1576 +++ linux-2.4.20-ck5/drivers/cdrom/sbpcd.c      2003-04-08 10:52:51.000000000 +1000
1577 @@ -5426,6 +5426,7 @@ static struct block_device_operations sb
1578         release:                cdrom_release,
1579         ioctl:                  cdrom_ioctl,
1580         check_media_change:     cdrom_media_changed,
1581 +       mediactl:               cdrom_mediactl,
1582  };
1583  /*==========================================================================*/
1584  /*
1585 diff -Naurp linux-2.4.20-ck4/drivers/ide/ide.c linux-2.4.20-ck5/drivers/ide/ide.c
1586 --- linux-2.4.20-ck4/drivers/ide/ide.c  2002-11-30 17:02:07.000000000 +1100
1587 +++ linux-2.4.20-ck5/drivers/ide/ide.c  2003-04-08 10:52:51.000000000 +1000
1588 @@ -2215,6 +2215,18 @@ jump_eight:
1589  #endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
1590  }
1591  
1592 +static int ide_mediactl (kdev_t i_rdev, int op, int optarg)
1593 +{
1594 +       ide_drive_t *drive;
1595 +
1596 +       if ((drive = get_info_ptr(i_rdev)) == NULL)
1597 +               return -ENODEV;
1598 +
1599 +       if (drive->driver != NULL && DRIVER(drive)->mediactl != NULL)
1600 +               return DRIVER(drive)->mediactl(drive, op, optarg);
1601 +       return 0;
1602 +}
1603
1604  void ide_unregister (unsigned int index)
1605  {
1606         struct gendisk *gd;
1607 @@ -3930,7 +3942,8 @@ struct block_device_operations ide_fops[
1608         release:                ide_release,
1609         ioctl:                  ide_ioctl,
1610         check_media_change:     ide_check_media_change,
1611 -       revalidate:             ide_revalidate_disk
1612 +       revalidate:             ide_revalidate_disk,
1613 +       mediactl:               ide_mediactl
1614  }};
1615  
1616  EXPORT_SYMBOL(ide_hwifs);
1617 diff -Naurp linux-2.4.20-ck4/drivers/ide/ide-cd.c linux-2.4.20-ck5/drivers/ide/ide-cd.c
1618 --- linux-2.4.20-ck4/drivers/ide/ide-cd.c       2002-11-30 17:02:07.000000000 +1100
1619 +++ linux-2.4.20-ck5/drivers/ide/ide-cd.c       2003-04-08 10:52:51.000000000 +1000
1620 @@ -2875,6 +2875,18 @@ int ide_cdrom_ioctl (ide_drive_t *drive,
1621         return cdrom_ioctl (inode, file, cmd, arg);
1622  }
1623  
1624 +int ide_cdrom_mediactl (ide_drive_t *drive, int op, int optarg)
1625 +{
1626 +       switch (op) {
1627 +       case MEDIA_LOCK:
1628 +       case MEDIA_UNLOCK:
1629 +               return cdrom_lockdoor (drive, op == MEDIA_LOCK, NULL);
1630 +       default:
1631 +               return -ENOSYS;
1632 +       }
1633 +       return 0;
1634 +}
1635 +
1636  static
1637  int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive)
1638  {
1639 @@ -2989,6 +3001,7 @@ static ide_driver_t ide_cdrom_driver = {
1640         special:                NULL,
1641         proc:                   NULL,
1642         reinit:                 ide_cdrom_reinit,
1643 +       mediactl:               ide_cdrom_mediactl,
1644         ata_prebuilder:         NULL,
1645         atapi_prebuilder:       NULL,
1646  };
1647 diff -Naurp linux-2.4.20-ck4/drivers/scsi/sd.c linux-2.4.20-ck5/drivers/scsi/sd.c
1648 --- linux-2.4.20-ck4/drivers/scsi/sd.c  2002-08-03 13:14:53.000000000 +1000
1649 +++ linux-2.4.20-ck5/drivers/scsi/sd.c  2003-04-08 10:52:51.000000000 +1000
1650 @@ -562,6 +562,32 @@ static int sd_release(struct inode *inod
1651         return 0;
1652  }
1653  
1654 +/*
1655 + * This function performs media control operations.  Currently the
1656 + * only functions used are MEDIA_LOCK and MEDIA_UNLOCK, to lock and
1657 + * unlock the drive door.  
1658 + */
1659 +
1660 +static int sd_mediactl(kdev_t full_dev, int op, int optarg) {
1661 +       int target;
1662 +
1663 +       target =  DEVICE_NR(full_dev);
1664 +
1665 +       if (target >= sd_template.nr_dev) {
1666 +               printk("CD-ROM request error: invalid device.\n");
1667 +               return -ENODEV;
1668 +       };
1669 +
1670 +       switch (op) {
1671 +               case MEDIA_LOCK:
1672 +                               return scsi_ioctl(rscsi_disks[target].device, SCSI_IOCTL_DOORLOCK, 0);
1673 +               case MEDIA_UNLOCK:
1674 +                               return scsi_ioctl(rscsi_disks[target].device, SCSI_IOCTL_DOORUNLOCK, 0);
1675 +               default:
1676 +                               return -ENOSYS;
1677 +       }
1678 +}
1679
1680  static struct block_device_operations sd_fops =
1681  {
1682         owner:                  THIS_MODULE,
1683 @@ -569,7 +595,8 @@ static struct block_device_operations sd
1684         release:                sd_release,
1685         ioctl:                  sd_ioctl,
1686         check_media_change:     check_scsidisk_media_change,
1687 -       revalidate:             fop_revalidate_scsidisk
1688 +       revalidate:             fop_revalidate_scsidisk,
1689 +       mediactl:               sd_mediactl,
1690  };
1691  
1692  /*
1693 diff -Naurp linux-2.4.20-ck4/drivers/scsi/sr.c linux-2.4.20-ck5/drivers/scsi/sr.c
1694 --- linux-2.4.20-ck4/drivers/scsi/sr.c  2002-11-30 17:02:09.000000000 +1100
1695 +++ linux-2.4.20-ck5/drivers/scsi/sr.c  2003-04-08 10:52:51.000000000 +1000
1696 @@ -512,6 +512,7 @@ struct block_device_operations sr_bdops 
1697         release:                cdrom_release,
1698         ioctl:                  cdrom_ioctl,
1699         check_media_change:     cdrom_media_changed,
1700 +       mediactl:               cdrom_mediactl,
1701  };
1702  
1703  static int sr_open(struct cdrom_device_info *cdi, int purpose)
1704 diff -Naurp linux-2.4.20-ck4/fs/block_dev.c linux-2.4.20-ck5/fs/block_dev.c
1705 --- linux-2.4.20-ck4/fs/block_dev.c     2002-08-03 13:14:57.000000000 +1000
1706 +++ linux-2.4.20-ck5/fs/block_dev.c     2003-04-08 10:52:51.000000000 +1000
1707 @@ -508,36 +508,80 @@ int unregister_blkdev(unsigned int major
1708   * People changing diskettes in the middle of an operation deserve
1709   * to lose :-)
1710   */
1711 -int check_disk_change(kdev_t dev)
1712 +const struct block_device_operations *get_block_operations(kdev_t dev)
1713  {
1714 -       int i;
1715 +       int major = MAJOR(dev);
1716         const struct block_device_operations * bdops = NULL;
1717  
1718 -       i = MAJOR(dev);
1719 -       if (i < MAX_BLKDEV)
1720 -               bdops = blkdevs[i].bdops;
1721 +       if (major < MAX_BLKDEV)
1722 +               bdops = blkdevs[major].bdops;
1723         if (bdops == NULL) {
1724                 devfs_handle_t de;
1725  
1726 -               de = devfs_find_handle (NULL, NULL, i, MINOR (dev),
1727 +               de = devfs_find_handle (NULL, NULL, major, MINOR (dev),
1728                                         DEVFS_SPECIAL_BLK, 0);
1729                 if (de) {
1730                         bdops = devfs_get_ops (de);
1731                         devfs_put_ops (de); /* We're running in owner module */
1732                 }
1733         }
1734 -       if (bdops == NULL)
1735 -               return 0;
1736 -       if (bdops->check_media_change == NULL)
1737 -               return 0;
1738 -       if (!bdops->check_media_change(dev))
1739 -               return 0;
1740  
1741 -       if (invalidate_device(dev, 0))
1742 -               printk("VFS: busy inodes on changed media.\n");
1743 +       return bdops;
1744 +}
1745 +
1746 +/*
1747 + * This routine checks whether a removable media has been changed, and
1748 + * (for check_disk_change only) invalidate all buffer-cache-entries in
1749 + * that case. This is a relatively slow routine, so we have to try to
1750 + * minimize using it. Thus it is called only upon a 'mount' or
1751 + * 'open'. This is the best way of combining speed and utility, I
1752 + * think.  People changing diskettes in the middle of an operation
1753 + * deserve to loose :-) 
1754 +*/
1755 +
1756 +int query_disk_change(kdev_t dev)
1757 +{
1758 +       const struct block_device_operations * 
1759 +               bdops = get_block_operations(dev);
1760 +
1761 +       if (bdops && bdops->check_media_change)
1762 +               return (bdops->check_media_change(dev));
1763 +       return 0;
1764 +}
1765 +
1766 +/** 
1767 + *  invalidate_media
1768 + *  destroy all the buffers of this device 
1769 + */
1770  
1771 -       if (bdops->revalidate)
1772 +void invalidate_media(kdev_t dev) 
1773 +{
1774 +       const struct block_device_operations * 
1775 +               bdops = get_block_operations(dev);
1776 +
1777 +       if (destroy_device(dev))
1778 +               printk(KERN_INFO "VFS: busy inodes on changed media.\n");
1779 +
1780 +       if (bdops && bdops->revalidate)
1781                 bdops->revalidate(dev);
1782 +}
1783 +
1784 +int check_disk_change(kdev_t dev)
1785 +{
1786 +       if (!query_disk_change(dev))
1787 +               return 0;
1788 +
1789 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
1790 +       {
1791 +               struct super_block *sb = get_super(dev);
1792 +               if (sb) {
1793 +                       sb->s_media_changed = 1;
1794 +                       drop_super(sb);
1795 +               }
1796 +       }
1797 +#endif
1798
1799 +       invalidate_media(dev);
1800         return 1;
1801  }
1802  
1803 diff -Naurp linux-2.4.20-ck4/fs/Config.in linux-2.4.20-ck5/fs/Config.in
1804 --- linux-2.4.20-ck4/fs/Config.in       2002-11-30 17:02:20.000000000 +1100
1805 +++ linux-2.4.20-ck5/fs/Config.in       2003-04-08 10:52:51.000000000 +1000
1806 @@ -12,6 +12,8 @@ tristate 'Reiserfs support' CONFIG_REISE
1807  dep_mbool '  Enable reiserfs debug mode' CONFIG_REISERFS_CHECK $CONFIG_REISERFS_FS
1808  dep_mbool '  Stats in /proc/fs/reiserfs' CONFIG_REISERFS_PROC_INFO $CONFIG_REISERFS_FS
1809  
1810 +tristate 'Supermount removable media support' CONFIG_SUPERMOUNT
1811 +
1812  dep_tristate 'ADFS file system support (EXPERIMENTAL)' CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
1813  dep_mbool '  ADFS write support (DANGEROUS)' CONFIG_ADFS_FS_RW $CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
1814  
1815 diff -Naurp linux-2.4.20-ck4/fs/ext2/super.c linux-2.4.20-ck5/fs/ext2/super.c
1816 --- linux-2.4.20-ck4/fs/ext2/super.c    2002-11-30 17:02:20.000000000 +1100
1817 +++ linux-2.4.20-ck5/fs/ext2/super.c    2003-04-08 10:52:51.000000000 +1000
1818 @@ -274,6 +274,13 @@ static int parse_options (char * options
1819                          || !strcmp (this_char, "quota")
1820                          || !strcmp (this_char, "usrquota"))
1821                         /* Don't do anything ;-) */ ;
1822 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
1823 +               /* Silently ignore NLS options */
1824 +               else if (!strcmp (this_char, "iocharset")
1825 +                        || !strcmp (this_char, "codepage")
1826 +                        || !strcmp (this_char, "mode"))
1827 +                       /* Don't do anything ;-) */ ;
1828 +#endif
1829                 else {
1830                         printk ("EXT2-fs: Unrecognized mount option %s\n", this_char);
1831                         return 0;
1832 diff -Naurp linux-2.4.20-ck4/fs/fat/file.c linux-2.4.20-ck5/fs/fat/file.c
1833 --- linux-2.4.20-ck4/fs/fat/file.c      2001-08-13 03:56:56.000000000 +1000
1834 +++ linux-2.4.20-ck5/fs/fat/file.c      2003-04-08 10:52:51.000000000 +1000
1835 @@ -117,8 +117,17 @@ void fat_truncate(struct inode *inode)
1836         int cluster;
1837  
1838         /* Why no return value?  Surely the disk could fail... */
1839 +#if 0
1840 +       /*
1841 +        * Why do we need this check? VFS layer should already have
1842 +        * checked user access before we ever get here; and we can 
1843 +        * get here from iput on read-only file system, consider
1844 +        * remounting file system read-only after changing some file.
1845 +        * That is exactly what happens with supermount and breaks it
1846 +        */
1847         if (IS_RDONLY (inode))
1848                 return /* -EPERM */;
1849 +#endif
1850         if (IS_IMMUTABLE(inode))
1851                 return /* -EPERM */;
1852         cluster = 1 << sbi->cluster_bits;
1853 diff -Naurp linux-2.4.20-ck4/fs/inode.c linux-2.4.20-ck5/fs/inode.c
1854 --- linux-2.4.20-ck4/fs/inode.c 2003-04-08 10:50:36.000000000 +1000
1855 +++ linux-2.4.20-ck5/fs/inode.c 2003-04-08 10:52:51.000000000 +1000
1856 @@ -660,6 +660,22 @@ int invalidate_device(kdev_t dev, int do
1857         return res;
1858  }
1859  
1860 +/* 
1861 + * The device is a removable device, the device is not there anymore,
1862 + * we need to remove all its buffers
1863 + */
1864 +
1865 +int destroy_device(kdev_t dev)
1866 +{
1867 +       struct super_block *sb = get_super(dev);
1868 +       int res = 0;
1869 +       if (sb) {
1870 +               res = invalidate_inodes(sb);
1871 +               drop_super(sb);
1872 +       }
1873 +       destroy_buffers(dev);
1874 +       return res;
1875 +}
1876  
1877  /*
1878   * This is called with the inode lock held. It searches
1879 diff -Naurp linux-2.4.20-ck4/fs/Makefile linux-2.4.20-ck5/fs/Makefile
1880 --- linux-2.4.20-ck4/fs/Makefile        2002-11-30 17:02:20.000000000 +1100
1881 +++ linux-2.4.20-ck5/fs/Makefile        2003-04-08 10:52:51.000000000 +1000
1882 @@ -60,6 +60,7 @@ subdir-$(CONFIG_AFFS_FS)      += affs
1883  subdir-$(CONFIG_ROMFS_FS)      += romfs
1884  subdir-$(CONFIG_QNX4FS_FS)     += qnx4
1885  subdir-$(CONFIG_UDF_FS)                += udf
1886 +subdir-$(CONFIG_SUPERMOUNT)    += supermount
1887  subdir-$(CONFIG_AUTOFS_FS)     += autofs
1888  subdir-$(CONFIG_AUTOFS4_FS)    += autofs4
1889  subdir-$(CONFIG_ADFS_FS)       += adfs
1890 diff -Naurp linux-2.4.20-ck4/fs/namespace.c linux-2.4.20-ck5/fs/namespace.c
1891 --- linux-2.4.20-ck4/fs/namespace.c     2002-11-30 17:02:21.000000000 +1100
1892 +++ linux-2.4.20-ck5/fs/namespace.c     2003-04-08 10:52:51.000000000 +1000
1893 @@ -21,8 +21,6 @@
1894  #include <linux/seq_file.h>
1895  #include <linux/namespace.h>
1896  
1897 -struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
1898 -int do_remount_sb(struct super_block *sb, int flags, void * data);
1899  void kill_super(struct super_block *sb);
1900  
1901  static struct list_head *mount_hashtable;
1902 diff -Naurp linux-2.4.20-ck4/fs/read_write.c linux-2.4.20-ck5/fs/read_write.c
1903 --- linux-2.4.20-ck4/fs/read_write.c    2002-08-03 13:14:58.000000000 +1000
1904 +++ linux-2.4.20-ck5/fs/read_write.c    2003-04-08 10:52:51.000000000 +1000
1905 @@ -91,7 +91,7 @@ loff_t default_llseek(struct file *file,
1906         return retval;
1907  }
1908  
1909 -static inline loff_t llseek(struct file *file, loff_t offset, int origin)
1910 +loff_t vfs_llseek(struct file *file, loff_t offset, int origin)
1911  {
1912         loff_t (*fn)(struct file *, loff_t, int);
1913         loff_t retval;
1914 @@ -116,7 +116,7 @@ asmlinkage off_t sys_lseek(unsigned int 
1915                 goto bad;
1916         retval = -EINVAL;
1917         if (origin <= 2) {
1918 -               loff_t res = llseek(file, offset, origin);
1919 +               loff_t res = vfs_llseek(file, offset, origin);
1920                 retval = res;
1921                 if (res != (loff_t)retval)
1922                         retval = -EOVERFLOW;    /* LFS: should only happen on 32 bit platforms */
1923 @@ -143,7 +143,7 @@ asmlinkage long sys_llseek(unsigned int 
1924         if (origin > 2)
1925                 goto out_putf;
1926  
1927 -       offset = llseek(file, ((loff_t) offset_high << 32) | offset_low,
1928 +       offset = vfs_llseek(file, ((loff_t) offset_high << 32) | offset_low,
1929                         origin);
1930  
1931         retval = (int)offset;
1932 diff -Naurp linux-2.4.20-ck4/fs/stat.c linux-2.4.20-ck5/fs/stat.c
1933 --- linux-2.4.20-ck4/fs/stat.c  2001-09-14 09:04:43.000000000 +1000
1934 +++ linux-2.4.20-ck5/fs/stat.c  2003-04-08 10:52:51.000000000 +1000
1935 @@ -25,222 +25,248 @@ do_revalidate(struct dentry *dentry)
1936         return 0;
1937  }
1938  
1939 -
1940 -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__)
1941 -
1942 -/*
1943 - * For backward compatibility?  Maybe this should be moved
1944 - * into arch/i386 instead?
1945 - */
1946 -static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf)
1947 +int getattr_full(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
1948  {
1949 -       static int warncount = 5;
1950 -       struct __old_kernel_stat tmp;
1951 -
1952 -       if (warncount > 0) {
1953 -               warncount--;
1954 -               printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
1955 -                       current->comm);
1956 -       } else if (warncount < 0) {
1957 -               /* it's laughable, but... */
1958 -               warncount = 0;
1959 -       }
1960 -
1961 -       tmp.st_dev = kdev_t_to_nr(inode->i_dev);
1962 -       tmp.st_ino = inode->i_ino;
1963 -       tmp.st_mode = inode->i_mode;
1964 -       tmp.st_nlink = inode->i_nlink;
1965 -       SET_OLDSTAT_UID(tmp, inode->i_uid);
1966 -       SET_OLDSTAT_GID(tmp, inode->i_gid);
1967 -       tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
1968 -#if BITS_PER_LONG == 32
1969 -       if (inode->i_size > MAX_NON_LFS)
1970 -               return -EOVERFLOW;
1971 -#endif 
1972 -       tmp.st_size = inode->i_size;
1973 -       tmp.st_atime = inode->i_atime;
1974 -       tmp.st_mtime = inode->i_mtime;
1975 -       tmp.st_ctime = inode->i_ctime;
1976 -       return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
1977 +       struct inode *inode = dentry->d_inode;
1978 +       stat->dev = kdev_t_to_nr(inode->i_dev);
1979 +       stat->ino = inode->i_ino;
1980 +       stat->mode = inode->i_mode;
1981 +       stat->nlink = inode->i_nlink;
1982 +       stat->uid = inode->i_uid;
1983 +       stat->gid = inode->i_gid;
1984 +       stat->rdev = kdev_t_to_nr(inode->i_rdev);
1985 +       stat->atime = inode->i_atime;
1986 +       stat->mtime = inode->i_mtime;
1987 +       stat->ctime = inode->i_ctime;
1988 +       stat->size = inode->i_size;
1989 +       stat->blocks = inode->i_blocks;
1990 +       stat->blksize = inode->i_blksize;
1991 +       return 0;
1992  }
1993  
1994 -#endif
1995 -
1996 -static int cp_new_stat(struct inode * inode, struct stat * statbuf)
1997 +int getattr_minix(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
1998  {
1999 -       struct stat tmp;
2000 +       struct inode *inode = dentry->d_inode;
2001         unsigned int blocks, indirect;
2002  
2003 -       memset(&tmp, 0, sizeof(tmp));
2004 -       tmp.st_dev = kdev_t_to_nr(inode->i_dev);
2005 -       tmp.st_ino = inode->i_ino;
2006 -       tmp.st_mode = inode->i_mode;
2007 -       tmp.st_nlink = inode->i_nlink;
2008 -       SET_STAT_UID(tmp, inode->i_uid);
2009 -       SET_STAT_GID(tmp, inode->i_gid);
2010 -       tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
2011 -#if BITS_PER_LONG == 32
2012 -       if (inode->i_size > MAX_NON_LFS)
2013 -               return -EOVERFLOW;
2014 -#endif 
2015 -       tmp.st_size = inode->i_size;
2016 -       tmp.st_atime = inode->i_atime;
2017 -       tmp.st_mtime = inode->i_mtime;
2018 -       tmp.st_ctime = inode->i_ctime;
2019 -/*
2020 - * st_blocks and st_blksize are approximated with a simple algorithm if
2021 - * they aren't supported directly by the filesystem. The minix and msdos
2022 - * filesystems don't keep track of blocks, so they would either have to
2023 - * be counted explicitly (by delving into the file itself), or by using
2024 - * this simple algorithm to get a reasonable (although not 100% accurate)
2025 - * value.
2026 - */
2027 -
2028 -/*
2029 - * Use minix fs values for the number of direct and indirect blocks.  The
2030 - * count is now exact for the minix fs except that it counts zero blocks.
2031 - * Everything is in units of BLOCK_SIZE until the assignment to
2032 - * tmp.st_blksize.
2033 - */
2034 +       stat->dev = kdev_t_to_nr(inode->i_dev);
2035 +       stat->ino = inode->i_ino;
2036 +       stat->mode = inode->i_mode;
2037 +       stat->nlink = inode->i_nlink;
2038 +       stat->uid = inode->i_uid;
2039 +       stat->gid = inode->i_gid;
2040 +       stat->rdev = kdev_t_to_nr(inode->i_rdev);
2041 +       stat->atime = inode->i_atime;
2042 +       stat->mtime = inode->i_mtime;
2043 +       stat->ctime = inode->i_ctime;
2044 +       stat->size = inode->i_size;
2045  #define D_B   7
2046  #define I_B   (BLOCK_SIZE / sizeof(unsigned short))
2047  
2048 -       if (!inode->i_blksize) {
2049 -               blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
2050 -               if (blocks > D_B) {
2051 -                       indirect = (blocks - D_B + I_B - 1) / I_B;
2052 +       blocks = (stat->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
2053 +       if (blocks > D_B) {
2054 +               indirect = (blocks - D_B + I_B - 1) / I_B;
2055 +               blocks += indirect;
2056 +               if (indirect > 1) {
2057 +                       indirect = (indirect - 1 + I_B - 1) / I_B;
2058                         blocks += indirect;
2059 -                       if (indirect > 1) {
2060 -                               indirect = (indirect - 1 + I_B - 1) / I_B;
2061 -                               blocks += indirect;
2062 -                               if (indirect > 1)
2063 -                                       blocks++;
2064 -                       }
2065 +                       if (indirect > 1)
2066 +                               blocks++;
2067                 }
2068 -               tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
2069 -               tmp.st_blksize = BLOCK_SIZE;
2070 -       } else {
2071 -               tmp.st_blocks = inode->i_blocks;
2072 -               tmp.st_blksize = inode->i_blksize;
2073         }
2074 -       return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
2075 +       stat->blocks = (BLOCK_SIZE / 512) * blocks;
2076 +       stat->blksize = BLOCK_SIZE;
2077 +       return 0;
2078  }
2079  
2080 -
2081 -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__)
2082 -/*
2083 - * For backward compatibility?  Maybe this should be moved
2084 - * into arch/i386 instead?
2085 - */
2086 -asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
2087 +int vfs_lstat(char * filename, struct kstat *stat)
2088  {
2089         struct nameidata nd;
2090         int error;
2091  
2092 -       error = user_path_walk(filename, &nd);
2093 +       error = user_path_walk_link(filename, &nd);
2094 +       if (error)
2095 +               return error;
2096 +
2097 +       error = do_revalidate(nd.dentry);
2098         if (!error) {
2099 -               error = do_revalidate(nd.dentry);
2100 -               if (!error)
2101 -                       error = cp_old_stat(nd.dentry->d_inode, statbuf);
2102 +               struct inode *inode = nd.dentry->d_inode;
2103 +               if (inode->i_op->getattr)
2104 +                       error = inode->i_op->getattr(nd.mnt, nd.dentry, stat);
2105 +               else
2106 +                       error = getattr_full(nd.mnt, nd.dentry, stat);
2107                 path_release(&nd);
2108         }
2109         return error;
2110  }
2111 -#endif
2112  
2113 -asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
2114 +int vfs_stat(char * filename, struct kstat *stat)
2115  {
2116         struct nameidata nd;
2117         int error;
2118  
2119         error = user_path_walk(filename, &nd);
2120 +       if (error)
2121 +               return error;
2122 +
2123 +       error = do_revalidate(nd.dentry);
2124         if (!error) {
2125 -               error = do_revalidate(nd.dentry);
2126 -               if (!error)
2127 -                       error = cp_new_stat(nd.dentry->d_inode, statbuf);
2128 +               struct inode *inode = nd.dentry->d_inode;
2129 +               if (inode->i_op->getattr)
2130 +                       error = inode->i_op->getattr(nd.mnt, nd.dentry, stat);
2131 +               else
2132 +                       error = getattr_full(nd.mnt, nd.dentry, stat);
2133                 path_release(&nd);
2134         }
2135         return error;
2136  }
2137  
2138 +int vfs_fstat(int fd, struct kstat *stat)
2139 +{
2140 +       struct file *file = fget(fd);
2141 +       int error;
2142 +
2143 +       if (!file)
2144 +               return -EBADF;
2145 +
2146 +       error = do_revalidate(file->f_dentry);
2147 +       if (!error) {
2148 +               struct inode *inode = file->f_dentry->d_inode;
2149 +               if (inode->i_op->getattr)
2150 +                       error = inode->i_op->getattr(file->f_vfsmnt, file->f_dentry, stat);
2151 +               else
2152 +                       error = getattr_full(file->f_vfsmnt, file->f_dentry, stat);
2153 +               fput(file);
2154 +       }
2155 +       return error;
2156 +}
2157 +
2158  #if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__)
2159  
2160  /*
2161   * For backward compatibility?  Maybe this should be moved
2162   * into arch/i386 instead?
2163   */
2164 -asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
2165 +static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat * statbuf)
2166  {
2167 -       struct nameidata nd;
2168 -       int error;
2169 +       static int warncount = 5;
2170 +       struct __old_kernel_stat tmp;
2171  
2172 -       error = user_path_walk_link(filename, &nd);
2173 -       if (!error) {
2174 -               error = do_revalidate(nd.dentry);
2175 -               if (!error)
2176 -                       error = cp_old_stat(nd.dentry->d_inode, statbuf);
2177 -               path_release(&nd);
2178 +       if (warncount > 0) {
2179 +               warncount--;
2180 +               printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
2181 +                       current->comm);
2182 +       } else if (warncount < 0) {
2183 +               /* it's laughable, but... */
2184 +               warncount = 0;
2185         }
2186 -       return error;
2187 -}
2188  
2189 -#endif
2190 +       tmp.st_dev = stat->dev;
2191 +       tmp.st_ino = stat->ino;
2192 +       tmp.st_mode = stat->mode;
2193 +       tmp.st_nlink = stat->nlink;
2194 +       SET_OLDSTAT_UID(tmp, stat->uid);
2195 +       SET_OLDSTAT_GID(tmp, stat->gid);
2196 +       tmp.st_rdev = stat->rdev;
2197 +#if BITS_PER_LONG == 32
2198 +       if (stat->size > MAX_NON_LFS)
2199 +               return -EOVERFLOW;
2200 +#endif 
2201 +       tmp.st_size = stat->size;
2202 +       tmp.st_atime = stat->atime;
2203 +       tmp.st_mtime = stat->mtime;
2204 +       tmp.st_ctime = stat->ctime;
2205 +       return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
2206 +}
2207  
2208 -asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
2209 +asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
2210  {
2211 -       struct nameidata nd;
2212 -       int error;
2213 +       struct kstat stat;
2214 +       int error = vfs_stat(filename, &stat);
2215  
2216 -       error = user_path_walk_link(filename, &nd);
2217 -       if (!error) {
2218 -               error = do_revalidate(nd.dentry);
2219 -               if (!error)
2220 -                       error = cp_new_stat(nd.dentry->d_inode, statbuf);
2221 -               path_release(&nd);
2222 -       }
2223 -       return error;
2224 +       return error ? error : cp_old_stat(&stat, statbuf);
2225  }
2226  
2227 -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__)
2228 +asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
2229 +{
2230 +       struct kstat stat;
2231 +       int error = vfs_lstat(filename, &stat);
2232 +
2233 +       return error ? error : cp_old_stat(&stat, statbuf);
2234 +}
2235  
2236 -/*
2237 - * For backward compatibility?  Maybe this should be moved
2238 - * into arch/i386 instead?
2239 - */
2240  asmlinkage long sys_fstat(unsigned int fd, struct __old_kernel_stat * statbuf)
2241  {
2242 -       struct file * f;
2243 -       int err = -EBADF;
2244 +       struct kstat stat;
2245 +       int error = vfs_fstat(fd, &stat);
2246  
2247 -       f = fget(fd);
2248 -       if (f) {
2249 -               struct dentry * dentry = f->f_dentry;
2250 -
2251 -               err = do_revalidate(dentry);
2252 -               if (!err)
2253 -                       err = cp_old_stat(dentry->d_inode, statbuf);
2254 -               fput(f);
2255 -       }
2256 -       return err;
2257 +       return error ? error : cp_old_stat(&stat, statbuf);
2258  }
2259  
2260  #endif
2261  
2262 +static int cp_new_stat(struct kstat *stat, struct stat * statbuf)
2263 +{
2264 +       struct stat tmp;
2265 +
2266 +       memset(&tmp, 0, sizeof(tmp));
2267 +       tmp.st_dev = stat->dev;
2268 +       tmp.st_ino = stat->ino;
2269 +       tmp.st_mode = stat->mode;
2270 +       tmp.st_nlink = stat->nlink;
2271 +       SET_STAT_UID(tmp, stat->uid);
2272 +       SET_STAT_GID(tmp, stat->gid);
2273 +       tmp.st_rdev = stat->rdev;
2274 +#if BITS_PER_LONG == 32
2275 +       if (stat->size > MAX_NON_LFS)
2276 +               return -EOVERFLOW;
2277 +#endif 
2278 +       tmp.st_size = stat->size;
2279 +       tmp.st_atime = stat->atime;
2280 +       tmp.st_mtime = stat->mtime;
2281 +       tmp.st_ctime = stat->ctime;
2282 +       tmp.st_blocks = stat->blocks;
2283 +       tmp.st_blksize = stat->blksize;
2284 +       return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
2285 +}
2286 +
2287 +asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
2288 +{
2289 +       struct kstat stat;
2290 +       int error = vfs_stat(filename, &stat);
2291 +
2292 +       return error ? error : cp_new_stat(&stat, statbuf);
2293 +}
2294 +
2295 +asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
2296 +{
2297 +       struct kstat stat;
2298 +       int error = vfs_lstat(filename, &stat);
2299 +
2300 +       return error ? error : cp_new_stat(&stat, statbuf);
2301 +}
2302 +
2303  asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf)
2304  {
2305 -       struct file * f;
2306 -       int err = -EBADF;
2307 +       struct kstat stat;
2308 +       int error = vfs_fstat(fd, &stat);
2309 +
2310 +       return error ? error : cp_new_stat(&stat, statbuf);
2311 +}
2312 +/* this function should be callled vfs_readlink & vfs_readlink
2313 +   generic_readlink */
2314 +
2315 +int vfs_readlink_real(struct dentry * dentry, char * buf, int bufsiz)
2316 +{
2317 +       struct inode * inode = dentry->d_inode;
2318 +       int error = -EINVAL;
2319  
2320 -       f = fget(fd);
2321 -       if (f) {
2322 -               struct dentry * dentry = f->f_dentry;
2323 -
2324 -               err = do_revalidate(dentry);
2325 -               if (!err)
2326 -                       err = cp_new_stat(dentry->d_inode, statbuf);
2327 -               fput(f);
2328 +       if (inode->i_op && inode->i_op->readlink &&
2329 +           !(error = do_revalidate(dentry))) {
2330 +               UPDATE_ATIME(inode);
2331 +               error = inode->i_op->readlink(dentry, buf, bufsiz);
2332         }
2333 -       return err;
2334 +       return error;
2335  }
2336  
2337  asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz)
2338 @@ -253,127 +279,60 @@ asmlinkage long sys_readlink(const char 
2339  
2340         error = user_path_walk_link(path, &nd);
2341         if (!error) {
2342 -               struct inode * inode = nd.dentry->d_inode;
2343 -
2344 -               error = -EINVAL;
2345 -               if (inode->i_op && inode->i_op->readlink &&
2346 -                   !(error = do_revalidate(nd.dentry))) {
2347 -                       UPDATE_ATIME(inode);
2348 -                       error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
2349 -               }
2350 +               error = vfs_readlink_real(nd.dentry, buf, bufsiz);
2351                 path_release(&nd);
2352         }
2353         return error;
2354  }
2355  
2356 -
2357  /* ---------- LFS-64 ----------- */
2358  #if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips64) && !defined(__x86_64__) && !defined(CONFIG_ARCH_S390X)
2359  
2360 -static long cp_new_stat64(struct inode * inode, struct stat64 * statbuf)
2361 +static long cp_new_stat64(struct kstat *stat, struct stat64 * statbuf)
2362  {
2363         struct stat64 tmp;
2364 -       unsigned int blocks, indirect;
2365 -
2366         memset(&tmp, 0, sizeof(tmp));
2367 -       tmp.st_dev = kdev_t_to_nr(inode->i_dev);
2368 -       tmp.st_ino = inode->i_ino;
2369 +       tmp.st_dev = stat->dev;
2370 +       tmp.st_ino = stat->ino;
2371  #ifdef STAT64_HAS_BROKEN_ST_INO
2372 -       tmp.__st_ino = inode->i_ino;
2373 +       tmp.__st_ino = stat->ino;
2374  #endif
2375 -       tmp.st_mode = inode->i_mode;
2376 -       tmp.st_nlink = inode->i_nlink;
2377 -       tmp.st_uid = inode->i_uid;
2378 -       tmp.st_gid = inode->i_gid;
2379 -       tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
2380 -       tmp.st_atime = inode->i_atime;
2381 -       tmp.st_mtime = inode->i_mtime;
2382 -       tmp.st_ctime = inode->i_ctime;
2383 -       tmp.st_size = inode->i_size;
2384 -/*
2385 - * st_blocks and st_blksize are approximated with a simple algorithm if
2386 - * they aren't supported directly by the filesystem. The minix and msdos
2387 - * filesystems don't keep track of blocks, so they would either have to
2388 - * be counted explicitly (by delving into the file itself), or by using
2389 - * this simple algorithm to get a reasonable (although not 100% accurate)
2390 - * value.
2391 - */
2392 -
2393 -/*
2394 - * Use minix fs values for the number of direct and indirect blocks.  The
2395 - * count is now exact for the minix fs except that it counts zero blocks.
2396 - * Everything is in units of BLOCK_SIZE until the assignment to
2397 - * tmp.st_blksize.
2398 - */
2399 -#define D_B   7
2400 -#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
2401 -
2402 -       if (!inode->i_blksize) {
2403 -               blocks = (tmp.st_size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
2404 -               if (blocks > D_B) {
2405 -                       indirect = (blocks - D_B + I_B - 1) / I_B;
2406 -                       blocks += indirect;
2407 -                       if (indirect > 1) {
2408 -                               indirect = (indirect - 1 + I_B - 1) / I_B;
2409 -                               blocks += indirect;
2410 -                               if (indirect > 1)
2411 -                                       blocks++;
2412 -                       }
2413 -               }
2414 -               tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
2415 -               tmp.st_blksize = BLOCK_SIZE;
2416 -       } else {
2417 -               tmp.st_blocks = inode->i_blocks;
2418 -               tmp.st_blksize = inode->i_blksize;
2419 -       }
2420 +       tmp.st_mode = stat->mode;
2421 +       tmp.st_nlink = stat->nlink;
2422 +       tmp.st_uid = stat->uid;
2423 +       tmp.st_gid = stat->gid;
2424 +       tmp.st_rdev = stat->rdev;
2425 +       tmp.st_atime = stat->atime;
2426 +       tmp.st_mtime = stat->mtime;
2427 +       tmp.st_ctime = stat->ctime;
2428 +       tmp.st_size = stat->size;
2429 +       tmp.st_blocks = stat->blocks;
2430 +       tmp.st_blksize = stat->blksize;
2431         return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
2432  }
2433  
2434  asmlinkage long sys_stat64(char * filename, struct stat64 * statbuf, long flags)
2435  {
2436 -       struct nameidata nd;
2437 -       int error;
2438 +       struct kstat stat;
2439 +       int error = vfs_stat(filename, &stat);
2440  
2441 -       error = user_path_walk(filename, &nd);
2442 -       if (!error) {
2443 -               error = do_revalidate(nd.dentry);
2444 -               if (!error)
2445 -                       error = cp_new_stat64(nd.dentry->d_inode, statbuf);
2446 -               path_release(&nd);
2447 -       }
2448 -       return error;
2449 +       return error ? error : cp_new_stat64(&stat, statbuf);
2450  }
2451  
2452  asmlinkage long sys_lstat64(char * filename, struct stat64 * statbuf, long flags)
2453  {
2454 -       struct nameidata nd;
2455 -       int error;
2456 +       struct kstat stat;
2457 +       int error = vfs_lstat(filename, &stat);
2458  
2459 -       error = user_path_walk_link(filename, &nd);
2460 -       if (!error) {
2461 -               error = do_revalidate(nd.dentry);
2462 -               if (!error)
2463 -                       error = cp_new_stat64(nd.dentry->d_inode, statbuf);
2464 -               path_release(&nd);
2465 -       }
2466 -       return error;
2467 +       return error ? error : cp_new_stat64(&stat, statbuf);
2468  }
2469  
2470  asmlinkage long sys_fstat64(unsigned long fd, struct stat64 * statbuf, long flags)
2471  {
2472 -       struct file * f;
2473 -       int err = -EBADF;
2474 +       struct kstat stat;
2475 +       int error = vfs_fstat(fd, &stat);
2476  
2477 -       f = fget(fd);
2478 -       if (f) {
2479 -               struct dentry * dentry = f->f_dentry;
2480 -
2481 -               err = do_revalidate(dentry);
2482 -               if (!err)
2483 -                       err = cp_new_stat64(dentry->d_inode, statbuf);
2484 -               fput(f);
2485 -       }
2486 -       return err;
2487 +       return error ? error : cp_new_stat64(&stat, statbuf);
2488  }
2489  
2490  #endif /* LFS-64 */
2491 diff -Naurp linux-2.4.20-ck4/fs/super.c linux-2.4.20-ck5/fs/super.c
2492 --- linux-2.4.20-ck4/fs/super.c 2002-11-30 17:02:22.000000000 +1100
2493 +++ linux-2.4.20-ck5/fs/super.c 2003-04-08 10:59:54.000000000 +1000
2494 @@ -844,10 +844,14 @@ void kill_super(struct super_block *sb)
2495         }
2496  
2497         /* Forget any remaining inodes */
2498 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
2499 +       invalidate_inodes(sb);
2500 +#else
2501         if (invalidate_inodes(sb)) {
2502                 printk(KERN_ERR "VFS: Busy inodes after unmount. "
2503                         "Self-destruct in 5 seconds.  Have a nice day...\n");
2504         }
2505 +#endif
2506  
2507         unlock_kernel();
2508         unlock_super(sb);
2509 diff -Naurp linux-2.4.20-ck4/fs/supermount/changelog linux-2.4.20-ck5/fs/supermount/changelog
2510 --- linux-2.4.20-ck4/fs/supermount/changelog    1970-01-01 10:00:00.000000000 +1000
2511 +++ linux-2.4.20-ck5/fs/supermount/changelog    2003-04-08 10:52:51.000000000 +1000
2512 @@ -0,0 +1 @@
2513 +
2514 diff -Naurp linux-2.4.20-ck4/fs/supermount/dentry_operations.c linux-2.4.20-ck5/fs/supermount/dentry_operations.c
2515 --- linux-2.4.20-ck4/fs/supermount/dentry_operations.c  1970-01-01 10:00:00.000000000 +1000
2516 +++ linux-2.4.20-ck5/fs/supermount/dentry_operations.c  2003-04-08 10:52:51.000000000 +1000
2517 @@ -0,0 +1,54 @@
2518 +/*
2519 + *  linux/fs/supermount/revalidate.c
2520 + *
2521 + *  Original version:
2522 + *      Copyright (C) 1995
2523 + *      Stephen Tweedie (sct@dcs.ed.ac.uk)
2524 + *
2525 + *  Rewriten for kernel 2.2 & 2.4. (C) 1999, 2000 Alexis Mikhailov
2526 + *                                    (alexis@abc.cap.ru)
2527 + *
2528 + */
2529 +
2530 +#include <linux/errno.h>
2531 +#include <linux/fs.h>
2532 +#include <linux/sched.h>
2533 +#include "supermount_i.h"
2534 +
2535 +static int
2536 +supermount_dentry_revalidate(struct dentry *dentry, int flags)
2537 +{
2538 +       struct dentry *subd;
2539 +       int rc = 1;
2540 +
2541 +       if (subfs_go_online(dentry->d_sb))
2542 +               goto bad_dentry;
2543 +       spin_lock(&dcache_lock);
2544 +       if (dentry->d_inode && is_inode_obsolete(dentry->d_inode)) {
2545 +               spin_unlock(&dcache_lock);
2546 +               goto bad_dentry;
2547 +       }
2548 +       spin_unlock(&dcache_lock);
2549 +       subd = get_subfs_dentry(dentry);
2550 +       if (IS_ERR(subd))
2551 +               goto bad_dentry;
2552 +
2553 +       if (subd->d_op && subd->d_op->d_revalidate)
2554 +               rc = subd->d_op->d_revalidate(subd, flags);
2555 +
2556 +       dput(subd);
2557 +out:
2558 +       subfs_go_inactive(dentry->d_sb);
2559 +       return rc;
2560 +bad_dentry:
2561 +       rc = 0;
2562 +       goto out;
2563 +}
2564 +
2565 +struct dentry_operations supermount_dir_dops = {
2566 +       .d_revalidate   = supermount_dentry_revalidate,
2567 +};
2568 +
2569 +struct dentry_operations supermount_file_dops = {
2570 +       .d_revalidate   = supermount_dentry_revalidate,
2571 +};
2572 diff -Naurp linux-2.4.20-ck4/fs/supermount/file_operations.c linux-2.4.20-ck5/fs/supermount/file_operations.c
2573 --- linux-2.4.20-ck4/fs/supermount/file_operations.c    1970-01-01 10:00:00.000000000 +1000
2574 +++ linux-2.4.20-ck5/fs/supermount/file_operations.c    2003-04-08 10:52:51.000000000 +1000
2575 @@ -0,0 +1,289 @@
2576 +/*
2577 + *  linux/fs/supermount/file_operations.c
2578 + *
2579 + *  Original version:
2580 + *      Copyright (C) 1995, 1997
2581 + *      Stephen Tweedie (sct@dcs.ed.ac.uk)
2582 + *
2583 + *      from
2584 + *
2585 + *      linux/fs/minix/dir.c
2586 + *      Copyright (C) 1991, 1992  Linus Torvalds
2587 + *
2588 + *      and
2589 + *
2590 + *      linux/fs/ext2/dir.c
2591 + *      Copyright (C) 1992, 1993, 1994, 1995  Remy Card
2592 + *
2593 + *  Rewriten for kernel 2.2 & 2.4. (C) 1999, 2000 Alexis Mikhailov
2594 + *                                    (alexis@abc.cap.ru)
2595 + *  Rewriten for kernel 2.4. (C) 2001 MandrakeSoft Inc.
2596 + *                                    Juan Quintela (quintela@mandrakesoft.com)
2597 + *
2598 + */
2599 +
2600 +#include <linux/errno.h>
2601 +#include <linux/fs.h>
2602 +#include <linux/sched.h>
2603 +#include <linux/file.h>
2604 +#include <linux/poll.h>
2605 +#include <linux/slab.h>
2606 +
2607 +#include "supermount_i.h"
2608 +
2609 +#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
2610 +
2611 +static loff_t
2612 +supermount_llseek(struct file *file, loff_t offset, int origin)
2613 +{
2614 +       struct file *subfile = get_subfile(file);
2615 +       loff_t retval;
2616 +
2617 +       retval = vfs_llseek(subfile, offset, origin);
2618 +       file->f_pos = subfile->f_pos;
2619 +       file->f_reada = subfile->f_reada;
2620 +       file->f_version = subfile->f_version;
2621 +       return retval;
2622 +}
2623 +
2624 +static ssize_t
2625 +supermount_read(struct file *file, char *buf, size_t count, loff_t * ppos)
2626 +{
2627 +       struct file *subfile = get_subfile(file);
2628 +       int rc;
2629 +
2630 +       rc = -EINVAL;
2631 +       if (subfile->f_op && subfile->f_op->read)
2632 +               rc = subfile->f_op->read(subfile, buf, count, ppos);
2633 +       if (rc > 0)
2634 +               file->f_pos = subfile->f_pos = *ppos;
2635 +       return rc;
2636 +}
2637 +
2638 +static ssize_t
2639 +supermount_write(struct file *file, const char *buf,
2640 +                size_t count, loff_t * ppos)
2641 +{
2642 +       struct file *subfile = get_subfile(file);
2643 +       int rc = 0;
2644 +
2645 +       if (subfile->f_op && subfile->f_op->write)
2646 +               rc = subfile->f_op->write(subfile, buf, count, ppos);
2647 +       if (rc > 0) {
2648 +               struct inode *subinode = subfile->f_dentry->d_inode;
2649 +
2650 +               file->f_pos = subfile->f_pos = *ppos;
2651 +               file->f_mode = subfile->f_mode;
2652 +               file->f_dentry->d_inode->i_size = subinode->i_size;
2653 +               file->f_dentry->d_inode->i_blocks = subinode->i_blocks;
2654 +               file->f_dentry->d_inode->i_mode = subinode->i_mode;
2655 +       }
2656 +       return rc;
2657 +}
2658 +
2659 +int
2660 +supermount_readdir(struct file *file, void *buf, filldir_t fill_fn)
2661 +{
2662 +       struct file *subfile = get_subfile(file);
2663 +       int rc;
2664 +
2665 +       rc = vfs_readdir(subfile, fill_fn, buf);
2666 +       file->f_pos = subfile->f_pos;   /* update position, nfs needs it */
2667 +       UPDATE_ATIME(file->f_dentry->d_inode);
2668 +       return rc;
2669 +}
2670 +
2671 +static unsigned int
2672 +supermount_poll(struct file *file, struct poll_table_struct *table)
2673 +{
2674 +       struct file *subfile = get_subfile(file);
2675 +       int rc = DEFAULT_POLLMASK;
2676 +
2677 +       if (subfile->f_op && subfile->f_op->poll)
2678 +               rc = subfile->f_op->poll(subfile, table);
2679 +
2680 +       return rc;
2681 +}
2682 +
2683 +static int
2684 +supermount_ioctl(struct inode *inode, struct file *file,
2685 +                unsigned int cmd, unsigned long arg)
2686 +{
2687 +       struct file *subfile = get_subfile(file);
2688 +       struct inode *subinode;
2689 +       int rc = -ENOTTY;
2690 +
2691 +       subinode = subfile->f_dentry->d_inode;
2692 +       if (subfile->f_op && subfile->f_op->ioctl)
2693 +               rc = subfile->f_op->ioctl(subinode, subfile, cmd, arg);
2694 +       return rc;
2695 +}
2696 +
2697 +int
2698 +supermount_open(struct inode *inode, struct file *file)
2699 +{
2700 +       struct dentry *subdent;
2701 +       struct file *subfile;
2702 +       struct supermount_sb_info *sbi = supermount_sbi(inode->i_sb);
2703 +       struct vfsmount *mnt;
2704 +       int rc;
2705 +
2706 +       rc = -EIO;
2707 +       if (subfs_go_online(inode->i_sb))
2708 +               goto out;
2709 +
2710 +       subdent = get_subfs_dentry(file->f_dentry);
2711 +       rc = PTR_ERR(subdent);
2712 +       if (IS_ERR(subdent))
2713 +               goto out;
2714 +
2715 +       if (!subdent->d_inode)
2716 +               BUG();
2717 +
2718 +       subfs_get_read_access(inode->i_sb);
2719 +
2720 +       if (file->f_mode & FMODE_WRITE) {
2721 +               rc = subfs_get_write_access(inode->i_sb);
2722 +               if (rc)
2723 +                       goto dput_ret;
2724 +       }
2725 +
2726 +       mnt = mntget(sbi->s_undermount);
2727 +       subfile = dentry_open(subdent, mnt, file->f_flags);
2728 +       rc = PTR_ERR(subfile);
2729 +       if (IS_ERR(subfile))
2730 +               goto close_ret;
2731 +
2732 +       put_subfile(file, subfile);
2733 +       subfile->f_mode = file->f_mode;
2734 +
2735 +       rc = 0;
2736 +out:
2737 +       subfs_go_inactive(inode->i_sb);
2738 +       return rc;
2739 +
2740 +close_ret:
2741 +       subfs_put_write_access(inode->i_sb);
2742 +dput_ret:
2743 +       subfs_put_read_access(inode->i_sb);
2744 +       dput(subdent);
2745 +       goto out;
2746 +}
2747 +
2748 +static int
2749 +supermount_flush(struct file *file)
2750 +{
2751 +       struct file *subfile = get_subfile(file);
2752 +       int rc = 0;
2753 +
2754 +       if (subfile->f_op && subfile->f_op->flush)
2755 +               rc = subfile->f_op->flush(subfile);
2756 +
2757 +       return rc;
2758 +}
2759 +
2760 +/* we want to maintain the numbers right indeed if we have an error 
2761 + */
2762 +
2763 +static int
2764 +supermount_release(struct inode *inode, struct file *file)
2765 +{
2766 +       struct file *subfile = get_subfile(file);
2767 +       struct inode *subinode;
2768 +       int write_on = 0;
2769 +       int rc;
2770 +
2771 +       rc = -EIO;
2772 +       if (subfs_go_online(inode->i_sb))
2773 +               goto out;
2774 +
2775 +       rc = 0;
2776 +       subinode = subfile->f_dentry->d_inode;
2777 +       if (!(file->f_mode & FMODE_WRITE) && subinode->i_nlink == 0) {
2778 +               if (!subfs_get_write_access(inode->i_sb))
2779 +                       write_on = 1;
2780 +
2781 +       }
2782 +
2783 +       filp_close(subfile, current->files);
2784 +       if ((file->f_mode & FMODE_WRITE) || write_on) {
2785 +               mark_subfs_dirty(inode->i_sb);
2786 +               subfs_put_write_access(inode->i_sb);
2787 +       }
2788 +out:
2789 +       subfs_put_read_access(inode->i_sb);
2790 +       subfs_go_inactive(inode->i_sb);
2791 +       return rc;
2792 +
2793 +}
2794 +
2795 +static int
2796 +supermount_fsync(struct file *file, struct dentry *dentry, int datasync)
2797 +{
2798 +       struct file *subfile = get_subfile(file);
2799 +       int rc = -EINVAL;
2800 +
2801 +       if (subfile->f_op && subfile->f_op->fsync)
2802 +               rc = subfile->f_op->fsync(subfile, subfile->f_dentry, datasync);
2803 +
2804 +       return rc;
2805 +}
2806 +
2807 +static int
2808 +supermount_fasync(int fd, struct file *file, int on)
2809 +{
2810 +       struct file *subfile = get_subfile(file);
2811 +       int rc = -EINVAL;
2812 +
2813 +       if (subfile->f_op && subfile->f_op->fasync)
2814 +               rc = subfile->f_op->fasync(fd, subfile, on);
2815 +
2816 +       return rc;
2817 +}
2818 +
2819 +static int
2820 +supermount_lock(struct file *file, int cmd, struct file_lock *fl)
2821 +{
2822 +       struct file *subfile = get_subfile(file);
2823 +       int rc = 0;
2824 +
2825 +       if (subfile->f_op && subfile->f_op->lock)
2826 +               rc = subfile->f_op->lock(subfile, cmd, fl);
2827 +       else if (cmd == F_GETLK)
2828 +               posix_test_lock(file, fl);
2829 +       return rc;
2830 +}
2831 +
2832 +/* Fixme:
2833 + * readv: easy, export churnk from vfs
2834 + * writev: easy, export churnk from vfs
2835 + * sendpage: only used for networking, not needed
2836 + * get_unmmapped_area: only used for devices, not needed
2837 + */
2838 +
2839 +struct file_operations supermount_dir_operations = {
2840 +       .llseek         = supermount_llseek,
2841 +       .read           = supermount_read,
2842 +       .readdir        = supermount_readdir,
2843 +       .ioctl          = supermount_ioctl,
2844 +       .open           = supermount_open,
2845 +       .flush          = supermount_flush,
2846 +       .release        = supermount_release,
2847 +       .fsync          = supermount_fsync,
2848 +       .fasync         = supermount_fasync,
2849 +};
2850 +
2851 +struct file_operations supermount_file_operations = {
2852 +       .llseek         = supermount_llseek,
2853 +       .read           = supermount_read,
2854 +       .write          = supermount_write,
2855 +       .poll           = supermount_poll,
2856 +       .ioctl          = supermount_ioctl,
2857 +       .mmap           = generic_file_mmap,
2858 +       .open           = supermount_open,
2859 +       .flush          = supermount_flush,
2860 +       .release        = supermount_release,
2861 +       .fsync          = supermount_fsync,
2862 +       .fasync         = supermount_fasync,
2863 +       .lock           = supermount_lock,
2864 +};
2865 diff -Naurp linux-2.4.20-ck4/fs/supermount/init.c linux-2.4.20-ck5/fs/supermount/init.c
2866 --- linux-2.4.20-ck4/fs/supermount/init.c       1970-01-01 10:00:00.000000000 +1000
2867 +++ linux-2.4.20-ck5/fs/supermount/init.c       2003-04-08 10:52:51.000000000 +1000
2868 @@ -0,0 +1,36 @@
2869 +/* 
2870 + * linux/fs/supermount/init.c
2871 + *
2872 + *  (C) Copyright 2001-2002 Juan Quintela <quintela@mandrakesoft.com>
2873 + *      Released unde GPL v2.
2874 + *
2875 + */
2876 +
2877 +#include <linux/module.h>
2878 +#include <linux/init.h>
2879 +#include <linux/fs.h>
2880 +
2881 +#include "supermount_i.h"
2882 +
2883 +static DECLARE_FSTYPE(supermount_fs_type, "supermount",
2884 +                     supermount_read_super, 0);
2885 +
2886 +static int __init
2887 +init_supermount_fs(void)
2888 +{
2889 +       return register_filesystem(&supermount_fs_type);
2890 +}
2891 +
2892 +static void __exit
2893 +exit_supermount_fs(void)
2894 +{
2895 +       unregister_filesystem(&supermount_fs_type);
2896 +}
2897 +
2898 +EXPORT_NO_SYMBOLS;
2899 +
2900 +MODULE_AUTHOR("Stephen Tweedie, Alexis Mikhailov, Juan Quintela and others");
2901 +MODULE_DESCRIPTION("Supermount");
2902 +MODULE_LICENSE("GPL");
2903 +module_init(init_supermount_fs);
2904 +module_exit(exit_supermount_fs);
2905 diff -Naurp linux-2.4.20-ck4/fs/supermount/inode_operations.c linux-2.4.20-ck5/fs/supermount/inode_operations.c
2906 --- linux-2.4.20-ck4/fs/supermount/inode_operations.c   1970-01-01 10:00:00.000000000 +1000
2907 +++ linux-2.4.20-ck5/fs/supermount/inode_operations.c   2003-04-08 10:52:51.000000000 +1000
2908 @@ -0,0 +1,893 @@
2909 +/*
2910 + *  linux/fs/supermount/namei.c
2911 + *
2912 + *  Original version:
2913 + *      Copyright (C) 1995
2914 + *      Stephen Tweedie (sct@dcs.ed.ac.uk)
2915 + *
2916 + *      from
2917 + *
2918 + *      linux/fs/minix/namei.c
2919 + *      Copyright (C) 1991, 1992  Linus Torvalds
2920 + *
2921 + *      and
2922 + *
2923 + *      linux/fs/ext2/namei.c
2924 + *      Copyright (C) 1992, 1993, 1994, 1995  Remy Card
2925 + *
2926 + *  Rewriten for kernel 2.2 & 2.4. (C) 1999, 2000 Alexis Mikhailov
2927 + *                                    (alexis@abc.cap.ru)
2928 + *
2929 + */
2930 +
2931 +/* This file handles almost all of the normal filesystem running of
2932 +   supermount.  We don't have to deal to much with the subfs
2933 +   interface, since we just pass subinodes out to the application on
2934 +   demand. */
2935 +
2936 +#include <linux/errno.h>
2937 +#include <linux/fs.h>
2938 +#include <linux/sched.h>
2939 +
2940 +#include "supermount_i.h"
2941 +
2942 +static struct dentry *
2943 +get_subdent(struct dentry *subfs_dir, struct dentry *dentry)
2944 +{
2945 +       struct dentry *subdent = get_subfs_dentry(dentry);
2946 +       if (IS_ERR(subdent)) {
2947 +               subdent = d_alloc(subfs_dir, &dentry->d_name);
2948 +       }
2949 +       if (!subdent)
2950 +               subdent = ERR_PTR(-ENOMEM);
2951 +
2952 +       return subdent;
2953 +}
2954 +
2955 +static void
2956 +supermount_update_super_inode(struct inode *superi, struct inode *subi)
2957 +{
2958 +       superi->i_mode = subi->i_mode;
2959 +       superi->i_uid = subi->i_uid;
2960 +       superi->i_gid = subi->i_gid;
2961 +       superi->i_nlink = subi->i_nlink;
2962 +       superi->i_size = subi->i_size;
2963 +       superi->i_atime = subi->i_atime;
2964 +       superi->i_ctime = subi->i_ctime;
2965 +       superi->i_mtime = subi->i_mtime;
2966 +       superi->i_blksize = subi->i_blksize;
2967 +       superi->i_blocks = subi->i_blocks;
2968 +       superi->i_rdev = subi->i_rdev;
2969 +       superi->i_version++;
2970 +
2971 +       if (S_ISDIR(superi->i_mode)) {
2972 +               superi->i_op = &supermount_dir_iops;
2973 +               superi->i_fop = &supermount_dir_operations;
2974 +       } else if (S_ISLNK(superi->i_mode)) {
2975 +               superi->i_op = &supermount_symlink_iops;
2976 +               superi->i_mapping = subi->i_mapping;
2977 +       } else {
2978 +               superi->i_op = &supermount_file_iops;
2979 +               superi->i_fop = &supermount_file_operations;
2980 +               superi->i_mapping = subi->i_mapping;
2981 +       }
2982 +}
2983 +
2984 +/*
2985 + * Attach superinode to subinode and instantiate dentry with this inode
2986 + */
2987 +
2988 +static void
2989 +attach_and_prepare(struct super_block *sb,
2990 +                  struct dentry *dentry, struct dentry *subd, int create)
2991 +{
2992 +       struct inode *superi, *subi = subd->d_inode;
2993 +
2994 +       if (dentry->d_inode)
2995 +               BUG();
2996 +
2997 +       superi = supermount_create_inode(sb);
2998 +       supermount_update_super_inode(superi, subd->d_inode);
2999 +
3000 +       if (create)
3001 +               d_instantiate(dentry, superi);
3002 +       else
3003 +               d_add(dentry, superi);
3004 +       supermount_i(superi)->i_dentry = dget(subd);
3005 +
3006 +       if (S_ISDIR(subi->i_mode))
3007 +               dentry->d_op = &supermount_dir_dops;
3008 +       else
3009 +               dentry->d_op = &supermount_file_dops;
3010 +
3011 +}
3012 +
3013 +static inline void
3014 +update_nlink(struct inode *superi, struct inode *subi)
3015 +{
3016 +       superi->i_nlink = subi->i_nlink;
3017 +}
3018 +
3019 +static inline void
3020 +update_ctime(struct inode *superi, struct inode *subi)
3021 +{
3022 +       superi->i_ctime = subi->i_ctime;
3023 +}
3024 +
3025 +static inline void
3026 +update_mtime(struct inode *superi, struct inode *subi)
3027 +{
3028 +       superi->i_mtime = subi->i_mtime;
3029 +}
3030 +
3031 +/* inode methods */
3032 +
3033 +static int
3034 +supermount_create(struct inode *dir, struct dentry *dentry, int mode)
3035 +{
3036 +       struct dentry *subdent, *subfs_dir;
3037 +       int rc;
3038 +
3039 +       if (dentry->d_inode)
3040 +               BUG();
3041 +       rc = -EIO;
3042 +       if (subfs_go_online(dir->i_sb))
3043 +               goto out;
3044 +
3045 +       subfs_dir = get_subfs_dentry_by_inode(dir);
3046 +       rc = PTR_ERR(subfs_dir);
3047 +       if (IS_ERR(subfs_dir))
3048 +               goto out;
3049 +
3050 +       rc = -ENOENT;
3051 +       if (!subfs_dir->d_inode)
3052 +               goto dirput_ret;
3053 +
3054 +       subdent = get_subdent(subfs_dir, dentry);
3055 +       rc = PTR_ERR(subdent);
3056 +       if (IS_ERR(subdent))
3057 +               goto dirput_ret;
3058 +
3059 +       rc = -EINVAL;
3060 +       if (subdent->d_inode)
3061 +               goto attach;
3062 +
3063 +       rc = subfs_get_write_access(dir->i_sb);
3064 +       if (rc)
3065 +               goto dput_ret;
3066 +
3067 +       rc = vfs_create(subfs_dir->d_inode, subdent, mode);
3068 +
3069 +       mark_subfs_dirty(dir->i_sb);
3070 +       subfs_put_write_access(dir->i_sb);
3071 +
3072 +       if (rc)
3073 +               goto dput_ret;
3074 +
3075 +       if (!subdent->d_inode) {
3076 +               d_instantiate(dentry, NULL);
3077 +               goto dput_ret;
3078 +       }
3079 +
3080 +       /* It worked, so now create a shadow supermount inode for the
3081 +          result... */
3082 +attach:
3083 +       attach_and_prepare(dir->i_sb, dentry, subdent, 1);
3084 +dput_ret:
3085 +       dput(subdent);
3086 +dirput_ret:
3087 +       dput(subfs_dir);
3088 +out:
3089 +       subfs_go_inactive(dir->i_sb);
3090 +       return rc;
3091 +}
3092 +
3093 +static struct dentry *
3094 +supermount_lookup(struct inode *dir, struct dentry *dentry)
3095 +{
3096 +       struct dentry *err, *subdent, *subfs_dir;
3097 +
3098 +       if (dentry->d_inode)
3099 +               BUG();
3100 +       err = ERR_PTR(-EIO);
3101 +       if (subfs_go_online(dir->i_sb))
3102 +               goto out;
3103 +       subfs_dir = get_subfs_dentry_by_inode(dir);
3104 +       err = subfs_dir;
3105 +       if (IS_ERR(subfs_dir))
3106 +               goto out;
3107 +       err = ERR_PTR(-ENOENT);
3108 +       if (!subfs_dir->d_inode)
3109 +               goto dirput_ret;
3110 +       subdent = lookup_one_len(dentry->d_name.name, subfs_dir,
3111 +                                dentry->d_name.len);
3112 +       err = subdent;
3113 +       if (IS_ERR(subdent))
3114 +               goto dirput_ret;
3115 +
3116 +       err = NULL;
3117 +       if (!subdent->d_inode) {
3118 +               /* not found */
3119 +               d_add(dentry, NULL);
3120 +               goto dput_ret;
3121 +       }
3122 +
3123 +       /* It worked, so now create a shadow supermount inode for the
3124 +          result... */
3125 +       attach_and_prepare(dir->i_sb, dentry, subdent, 0);
3126 +dput_ret:
3127 +       dput(subdent);
3128 +dirput_ret:
3129 +       dput(subfs_dir);
3130 +out:
3131 +       subfs_go_inactive(dir->i_sb);
3132 +       return err;
3133 +}
3134 +
3135 +static int
3136 +supermount_link(struct dentry *old_dentry, struct inode *dir,
3137 +               struct dentry *new_dentry)
3138 +{
3139 +       struct dentry *old_subdent, *subfs_dir, *new_subdent;
3140 +       int rc;
3141 +
3142 +       rc = -EIO;
3143 +       if (subfs_go_online(dir->i_sb))
3144 +               goto out;
3145 +
3146 +       subfs_dir = get_subfs_dentry_by_inode(dir);
3147 +       rc = -EIO;
3148 +       if (IS_ERR(subfs_dir))
3149 +               goto out;
3150 +
3151 +       rc = -ENOENT;
3152 +       if (!subfs_dir->d_inode)
3153 +               goto dirput_ret;
3154 +
3155 +       old_subdent = get_subdent(subfs_dir, old_dentry);
3156 +       rc = PTR_ERR(old_subdent);
3157 +       if (IS_ERR(old_subdent))
3158 +               goto dirput_ret;
3159 +
3160 +       rc = 0;
3161 +       if (old_subdent->d_inode && !old_dentry->d_inode)
3162 +                       attach_and_prepare(dir->i_sb, old_dentry, 
3163 +                                          old_subdent, 0);
3164 +
3165 +       rc = subfs_get_write_access(dir->i_sb);
3166 +       if (rc)
3167 +               goto dput_ret;
3168 +       new_subdent = lookup_one_len(new_dentry->d_name.name, subfs_dir,
3169 +                                new_dentry->d_name.len);
3170 +
3171 +       if (IS_ERR(new_subdent)) {
3172 +               rc = PTR_ERR(new_subdent);
3173 +               goto out_write;
3174 +       }
3175 +
3176 +       rc = vfs_link(old_subdent, subfs_dir->d_inode, new_subdent);
3177 +       /* Now we have subinode, attached to subdent. */
3178 +
3179 +       mark_subfs_dirty(dir->i_sb);
3180 +       subfs_put_write_access(dir->i_sb);
3181 +
3182 +       if (rc)
3183 +               goto dput_ret;
3184 +
3185 +       if (!old_subdent->d_inode) {
3186 +               d_instantiate(old_dentry, NULL);
3187 +               goto dput_ret;
3188 +       }
3189 +
3190 +       /* It worked, so now create a shadow supermount inode for the
3191 +          result... */
3192 +       attach_and_prepare(dir->i_sb, new_dentry, new_subdent, 1);
3193 +dput_ret:
3194 +       dput(old_subdent);
3195 +dirput_ret:
3196 +       dput(subfs_dir);
3197 +out:
3198 +       subfs_go_inactive(dir->i_sb);
3199 +       return rc;
3200 +out_write:
3201 +       subfs_put_write_access(dir->i_sb);
3202 +       goto dput_ret;
3203 +}
3204 +
3205 +static int
3206 +supermount_unlink(struct inode *dir, struct dentry *dentry)
3207 +{
3208 +       struct dentry *subfs_dir, *subdent;
3209 +       int rc;
3210 +
3211 +       rc = -EIO;
3212 +       if (subfs_go_online(dir->i_sb))
3213 +               goto out;
3214 +
3215 +       subfs_dir = get_subfs_dentry_by_inode(dir);
3216 +       rc = -ENOENT;
3217 +       if (IS_ERR(subfs_dir))
3218 +               goto out;
3219 +
3220 +       if (!subfs_dir->d_inode)
3221 +               goto dirput_ret;
3222 +
3223 +       subdent = get_subfs_dentry(dentry);
3224 +       rc = -ENOENT;
3225 +       if (IS_ERR(subdent))
3226 +               goto dirput_ret;
3227 +
3228 +       rc = subfs_get_write_access(dir->i_sb);
3229 +       if (rc)
3230 +               goto dput_ret;
3231 +
3232 +       rc = vfs_unlink(subfs_dir->d_inode, subdent);
3233 +
3234 +       update_nlink(dir, subfs_dir->d_inode);
3235 +       update_nlink(dentry->d_inode, subdent->d_inode);
3236 +       update_ctime(dir, subfs_dir->d_inode);
3237 +       update_mtime(dir, subfs_dir->d_inode);
3238 +       update_ctime(dentry->d_inode, subdent->d_inode);
3239 +
3240 +       /* If subdent->d_count == 1 (which means that this function is the
3241 +        * only holder of dentry then d_delete called a little earlier will
3242 +        * dentry_iput subdent, so if its inode has no other links inode_delete
3243 +        * will be called at this point, otherwise inode_delete will be
3244 +        * called when other link(s) to this inode is deleted. So we
3245 +        * can safely put_write_access now.
3246 +        */
3247 +       /* Then, if subdent->d_count != 1 then last iput will be called on last 
3248 +        * dput (if inode has no other links) so we will have to check for 
3249 +        * ->i_nlink == 0 in supermount_release
3250 +        */
3251 +
3252 +       mark_subfs_dirty(dir->i_sb);
3253 +       subfs_put_write_access(dir->i_sb);
3254 +
3255 +dput_ret:
3256 +       dput(subdent);
3257 +dirput_ret:
3258 +       dput(subfs_dir);
3259 +out:
3260 +       subfs_go_inactive(dir->i_sb);
3261 +       return rc;
3262 +}
3263 +
3264 +static int
3265 +supermount_symlink(struct inode *dir, struct dentry *dentry,
3266 +                  const char *symname)
3267 +{
3268 +       struct dentry *subdent, *subfs_dir;
3269 +       int rc;
3270 +
3271 +       rc = -EIO;
3272 +       if (subfs_go_online(dir->i_sb))
3273 +               goto out;
3274 +
3275 +       subfs_dir = get_subfs_dentry_by_inode(dir);
3276 +       rc = PTR_ERR(subfs_dir);
3277 +       if (IS_ERR(subfs_dir))
3278 +               goto out;
3279 +
3280 +       rc = -ENOENT;
3281 +       if (!subfs_dir->d_inode)
3282 +               goto dirput_ret;
3283 +
3284 +       subdent = get_subdent(subfs_dir, dentry);
3285 +       rc = PTR_ERR(subdent);
3286 +       if (IS_ERR(subdent))
3287 +               goto dirput_ret;
3288 +
3289 +       rc = 0;
3290 +       if (subdent->d_inode && !dentry->d_inode)
3291 +               goto attach;
3292 +
3293 +       rc = subfs_get_write_access(dir->i_sb);
3294 +       if (rc)
3295 +               goto dput_ret;
3296 +
3297 +       rc = vfs_symlink(subfs_dir->d_inode, subdent, symname);
3298 +       /* Now we have subinode, attached to subdent. */
3299 +
3300 +       mark_subfs_dirty(dir->i_sb);
3301 +       subfs_put_write_access(dir->i_sb);
3302 +
3303 +       if (rc)
3304 +               goto dput_ret;
3305 +
3306 +       if (!subdent->d_inode) {
3307 +               d_instantiate(dentry, NULL);
3308 +               goto dput_ret;
3309 +       }
3310 +
3311 +       /* It worked, so now create a shadow supermount inode for the
3312 +          result... */
3313 +attach:
3314 +       attach_and_prepare(dir->i_sb, dentry, subdent, 1);
3315 +dput_ret:
3316 +       dput(subdent);
3317 +dirput_ret:
3318 +       dput(subfs_dir);
3319 +out:
3320 +       subfs_go_inactive(dir->i_sb);
3321 +       return rc;
3322 +}
3323 +
3324 +static int
3325 +supermount_mkdir(struct inode *dir, struct dentry *dentry, int mode)
3326 +{
3327 +       struct dentry *subdent, *subfs_dir;
3328 +       int rc;
3329 +
3330 +       rc = -EIO;
3331 +       if (subfs_go_online(dir->i_sb))
3332 +               goto out;
3333 +
3334 +       subfs_dir = get_subfs_dentry_by_inode(dir);
3335 +       rc = -ENOENT;
3336 +       if (IS_ERR(subfs_dir))
3337 +               goto out;
3338 +
3339 +       if (!subfs_dir->d_inode)
3340 +               goto dirput_ret;
3341 +
3342 +       subdent = get_subdent(subfs_dir, dentry);
3343 +       rc = PTR_ERR(subdent);
3344 +       if (IS_ERR(subdent))
3345 +               goto dirput_ret;
3346 +
3347 +       rc = 0;
3348 +       if (subdent->d_inode && !dentry->d_inode)
3349 +               goto attach;
3350 +
3351 +       rc = subfs_get_write_access(dir->i_sb);
3352 +       if (rc)
3353 +               goto dput_ret;
3354 +
3355 +       rc = vfs_mkdir(subfs_dir->d_inode, subdent, mode);
3356 +
3357 +       update_nlink(dir, subfs_dir->d_inode);
3358 +
3359 +       mark_subfs_dirty(dir->i_sb);
3360 +       subfs_put_write_access(dir->i_sb);
3361 +
3362 +       if (rc)
3363 +               goto dput_ret;
3364 +
3365 +       if (!subdent->d_inode) {
3366 +               d_instantiate(dentry, NULL);
3367 +               goto dput_ret;
3368 +       }
3369 +
3370 +       /* It worked, so now create a shadow supermount inode for the
3371 +          result... */
3372 +attach:
3373 +       attach_and_prepare(dir->i_sb, dentry, subdent, 1);
3374 +dput_ret:
3375 +       dput(subdent);
3376 +dirput_ret:
3377 +       dput(subfs_dir);        /* We don't need it anymore */
3378 +out:
3379 +       subfs_go_inactive(dir->i_sb);
3380 +       return rc;
3381 +}
3382 +
3383 +static int
3384 +supermount_rmdir(struct inode *dir, struct dentry *dentry)
3385 +{
3386 +       struct dentry *subdent, *subfs_dir;
3387 +       int rc = -EIO;
3388 +
3389 +       if (subfs_go_online(dir->i_sb))
3390 +               goto out;
3391 +
3392 +       rc = -ENOENT;
3393 +       subfs_dir = get_subfs_dentry_by_inode(dir);
3394 +       if (IS_ERR(subfs_dir))
3395 +               goto out;
3396 +
3397 +       if (!subfs_dir->d_inode)
3398 +               goto dput_subdir;
3399 +
3400 +       subdent = get_subfs_dentry(dentry);
3401 +       if (IS_ERR(subdent))
3402 +               goto dput_subdir;
3403 +
3404 +       rc = subfs_get_write_access(dir->i_sb);
3405 +       if (rc)
3406 +               goto dput_subdent;
3407 +
3408 +       rc = vfs_rmdir(subfs_dir->d_inode, subdent);
3409 +       if (rc)
3410 +               goto put_write_access;
3411 +
3412 +       update_nlink(dir, subfs_dir->d_inode);
3413 +       update_nlink(dentry->d_inode, subdent->d_inode);
3414 +       update_ctime(dir, subfs_dir->d_inode);
3415 +       update_mtime(dir, subfs_dir->d_inode);
3416 +       update_ctime(dentry->d_inode, subdent->d_inode);
3417 +
3418 +       mark_subfs_dirty(dir->i_sb);
3419 +put_write_access:
3420 +       subfs_put_write_access(dir->i_sb);
3421 +dput_subdent:
3422 +       dput(subdent);
3423 +dput_subdir:
3424 +       dput(subfs_dir);
3425 +out:
3426 +       subfs_go_inactive(dir->i_sb);
3427 +       return rc;
3428 +}
3429 +
3430 +static int
3431 +supermount_mknod(struct inode *dir, struct dentry *dentry, int
3432 +                mode, int dev)
3433 +{
3434 +       struct dentry *subdent, *subfs_dir;
3435 +       int rc = -EIO;
3436 +
3437 +       if (subfs_go_online(dir->i_sb))
3438 +               goto out;
3439 +
3440 +       rc = -ENOENT;
3441 +       subfs_dir = get_subfs_dentry_by_inode(dir);
3442 +       if (IS_ERR(subfs_dir))
3443 +               goto out;
3444 +
3445 +       if (!subfs_dir->d_inode)
3446 +               goto dirput_ret;
3447 +
3448 +       subdent = get_subdent(subfs_dir, dentry);
3449 +       rc = PTR_ERR(subdent);
3450 +       if (IS_ERR(subdent))
3451 +               goto dirput_ret;
3452 +
3453 +       rc = 0;
3454 +       if (subdent->d_inode && !dentry->d_inode)
3455 +               goto attach;
3456 +
3457 +       rc = subfs_get_write_access(dir->i_sb);
3458 +       if (rc)
3459 +               goto dput_ret;
3460 +
3461 +       rc = vfs_mknod(subfs_dir->d_inode, subdent, mode, dev);
3462 +       /* Now we have subinode, attached to subdent. */
3463 +
3464 +       mark_subfs_dirty(dir->i_sb);
3465 +       subfs_put_write_access(dir->i_sb);
3466 +
3467 +       if (rc)
3468 +               goto dput_ret;
3469 +
3470 +       if (!subdent->d_inode) {
3471 +               d_instantiate(dentry, NULL);
3472 +               goto dput_ret;
3473 +       }
3474 +
3475 +       /* It worked, so now create a shadow supermount inode for the
3476 +          result... */
3477 +attach:
3478 +       attach_and_prepare(dir->i_sb, dentry, subdent, 1);
3479 +dput_ret:
3480 +       dput(subdent);
3481 +dirput_ret:
3482 +       dput(subfs_dir);
3483 +out:
3484 +       subfs_go_inactive(dir->i_sb);
3485 +       return rc;
3486 +}
3487 +
3488 +static int
3489 +supermount_rename(struct inode *olddir, struct dentry *olddentry,
3490 +                 struct inode *newdir, struct dentry *newdentry)
3491 +{
3492 +       struct dentry *oldsubdent, *newsubdent, *oldsubfs_dir, *newsubfs_dir;
3493 +       int rc = -EIO;
3494 +
3495 +       if (subfs_go_online(olddir->i_sb))
3496 +               goto out;
3497 +
3498 +       rc = -ENOENT;
3499 +       oldsubdent = get_subfs_dentry(olddentry);
3500 +       if (IS_ERR(oldsubdent))
3501 +               goto out;
3502 +
3503 +       oldsubfs_dir = get_subfs_dentry_by_inode(olddir);
3504 +       if (IS_ERR(oldsubfs_dir))
3505 +               goto olddput_ret;
3506 +
3507 +       if (!oldsubfs_dir->d_inode)
3508 +               goto olddirput_ret;
3509 +
3510 +       newsubfs_dir = get_subfs_dentry_by_inode(newdir);
3511 +       if (IS_ERR(newsubfs_dir))
3512 +               goto olddirput_ret;
3513 +
3514 +       newsubdent = get_subfs_dentry(newdentry);
3515 +       if (IS_ERR(newsubdent)) {
3516 +               rc = PTR_ERR(newsubdent);
3517 +               goto newdirput_ret;
3518 +       }
3519 +
3520 +       rc = subfs_get_write_access(olddir->i_sb);
3521 +       if (rc)
3522 +               goto newdput_ret;
3523 +
3524 +       rc = vfs_rename(oldsubfs_dir->d_inode, oldsubdent,
3525 +                       newsubfs_dir->d_inode, newsubdent);
3526 +       update_nlink(olddir, oldsubfs_dir->d_inode);
3527 +       update_nlink(newdir, newsubfs_dir->d_inode);
3528 +       update_nlink(olddentry->d_inode, oldsubdent->d_inode);
3529 +       update_ctime(olddir, oldsubfs_dir->d_inode);
3530 +       update_mtime(olddir, oldsubfs_dir->d_inode);
3531 +       update_ctime(olddentry->d_inode, oldsubdent->d_inode);
3532 +
3533 +       subfs_put_write_access(olddir->i_sb);
3534 +newdput_ret:
3535 +       dput(newsubdent);
3536 +newdirput_ret:
3537 +       dput(newsubfs_dir);
3538 +olddirput_ret:
3539 +       dput(oldsubfs_dir);
3540 +olddput_ret:
3541 +       dput(oldsubdent);
3542 +out:
3543 +       subfs_go_inactive(olddir->i_sb);
3544 +       return rc;
3545 +}
3546 +
3547 +static int 
3548 +supermount_readlink(struct dentry *dentry, char *buffer , int buflen)
3549 +{
3550 +       struct dentry *subdent;
3551 +       int rc = -EIO;
3552 +
3553 +       if (subfs_go_online(dentry->d_sb))
3554 +               goto out;
3555 +
3556 +       subdent = get_subfs_dentry(dentry);
3557 +       if (IS_ERR(subdent))
3558 +               goto out;
3559 +
3560 +       rc = -ENOENT;
3561 +       if (!subdent->d_inode)
3562 +               goto dput_ret;
3563 +
3564 +       rc = vfs_readlink_real(subdent, buffer, buflen);
3565 +dput_ret:
3566 +       dput(subdent);
3567 +out:
3568 +       subfs_go_inactive(dentry->d_sb);
3569 +       return rc;
3570 +}
3571 +
3572 +static int
3573 +supermount_follow_link(struct dentry *dentry, struct nameidata *nd)
3574 +{
3575 +       struct dentry *subdent = get_subfs_dentry(dentry);
3576 +       int rc = PTR_ERR(subdent);
3577 +
3578 +       if (IS_ERR(subdent))
3579 +               goto out;
3580 +
3581 +       rc = -ENOENT;
3582 +       if (!subdent->d_inode)
3583 +               goto fail;
3584 +
3585 +       if (subdent->d_inode && subdent->d_inode->i_op 
3586 +           && subdent->d_inode->i_op->follow_link)
3587 +               rc = subdent->d_inode->i_op->follow_link(subdent, nd);
3588 +       else {
3589 +               rc = -ENOENT;
3590 +               goto fail;
3591 +       }
3592 +
3593 +       dput(subdent);
3594 +       return rc;
3595 +fail:
3596 +       dput(subdent);  
3597 +out:
3598 +       return vfs_follow_link(nd, ERR_PTR(rc));
3599 +}
3600 +
3601 +static int
3602 +supermount_permission(struct inode *inode, int mask)
3603 +{
3604 +       struct inode *subi;
3605 +       struct dentry *subdent;
3606 +       int rc = -EIO;
3607 +       int need_write_access;
3608 +
3609 +       if (subfs_go_online(inode->i_sb))
3610 +               goto out;
3611 +
3612 +       subdent = get_subfs_dentry_by_inode(inode);
3613 +       if (IS_ERR(subdent)) {
3614 +               rc = PTR_ERR(subdent);
3615 +               goto out;
3616 +       }
3617 +       subi = subdent->d_inode;
3618 +       if (!subi)
3619 +               goto dput_ret;
3620 +       need_write_access = (mask & MAY_WRITE) && IS_RDONLY(subi);
3621 +       if (need_write_access) {
3622 +               rc = subfs_get_write_access(inode->i_sb);
3623 +               if (rc)
3624 +                       goto dput_ret;
3625 +       }
3626 +       rc = permission(subi, mask);
3627 +       if (need_write_access)
3628 +               subfs_put_write_access(inode->i_sb);
3629 +dput_ret:
3630 +       dput(subdent);
3631 +out:
3632 +       subfs_go_inactive(inode->i_sb);
3633 +       return rc;
3634 +}
3635 +
3636 +static int
3637 +supermount_setattr(struct dentry *dentry, struct iattr *attr)
3638 +{
3639 +       struct inode *subi, *inode = dentry->d_inode;
3640 +       struct dentry *subdent;
3641 +       int rc = -ENOENT;
3642 +
3643 +       if (!inode)
3644 +               return -EINVAL;
3645 +
3646 +       rc = -EIO;
3647 +       if (subfs_go_online(dentry->d_sb))
3648 +               goto out;
3649 +
3650 +       subdent = get_subfs_dentry(dentry);
3651 +       if (IS_ERR(subdent)) {
3652 +               rc = PTR_ERR(subdent);
3653 +               goto out;
3654 +       }
3655 +       subi = subdent->d_inode;
3656 +       if (!subi)
3657 +               goto dput_ret;
3658 +
3659 +       rc = subfs_get_write_access(inode->i_sb);
3660 +       if (rc)
3661 +               goto dput_ret;
3662 +
3663 +       rc = notify_change(subdent, attr);
3664 +
3665 +       if (!rc) {
3666 +               /* 
3667 +                * If it worked, then we need to mark the modification
3668 +                * to the subfs, and we also need to propogate the
3669 +                * change up to the shadowing inode.  
3670 +                */
3671 +               mark_subfs_dirty(inode->i_sb);
3672 +               attr->ia_mode = subi->i_mode;
3673 +               attr->ia_uid = subi->i_uid;
3674 +               attr->ia_gid = subi->i_gid;
3675 +               attr->ia_size = subi->i_size;
3676 +               attr->ia_atime = subi->i_atime;
3677 +               attr->ia_mtime = subi->i_mtime;
3678 +               attr->ia_ctime = subi->i_ctime;
3679 +               attr->ia_valid =
3680 +                   ATTR_UID | ATTR_GID | ATTR_MODE | ATTR_SIZE |
3681 +                   ATTR_ATIME | ATTR_MTIME | ATTR_CTIME;
3682 +               inode_setattr(inode, attr);
3683 +       }
3684 +
3685 +       subfs_put_write_access(inode->i_sb);
3686 +dput_ret:
3687 +       dput(subdent);
3688 +out:
3689 +       subfs_go_inactive(inode->i_sb);
3690 +       return rc;
3691 +}
3692 +
3693 +static int
3694 +supermount_getattr(struct vfsmount *mnt, struct dentry *dentry,
3695 +                  struct kstat *stat)
3696 +{
3697 +       struct inode *subi, *inode = dentry->d_inode;
3698 +       struct dentry *subdent;
3699 +       int rc;
3700 +
3701 +       if (!inode)
3702 +               return -EINVAL;
3703 +
3704 +       rc = -EIO;
3705 +       if (subfs_go_online(dentry->d_sb))
3706 +               goto out;
3707 +
3708 +       rc = -ENOENT;
3709 +       subdent = get_subfs_dentry(dentry);
3710 +       if (IS_ERR(subdent)) {
3711 +               rc = PTR_ERR(subdent);
3712 +               goto out;
3713 +       }
3714 +       subi = subdent->d_inode;
3715 +       if (!subi)
3716 +               goto dput_ret;
3717 +
3718 +       getattr_full(mnt, dentry, stat);
3719 +       stat->ino = subi->i_ino;
3720 +       rc = 0;
3721 +dput_ret:
3722 +       dput(subdent);
3723 +out:
3724 +       subfs_go_inactive(inode->i_sb);
3725 +       return rc;
3726 +}
3727 +
3728 +static int
3729 +supermount_root_getattr(struct vfsmount *mnt, struct dentry *dentry,
3730 +                       struct kstat *stat)
3731 +{
3732 +       struct supermount_sb_info *sbi;
3733 +       struct inode *inode = dentry->d_inode;
3734 +       int retval;
3735 +
3736 +       if (!inode)
3737 +               return -EINVAL;
3738 +
3739 +       sbi = supermount_sbi(dentry->d_sb);
3740 +       if (subfs_is_mounted(sbi))
3741 +               retval = supermount_getattr(mnt, dentry, stat);
3742 +       else
3743 +               retval = -EIO;
3744 +
3745 +       if (retval == -EIO)
3746 +               /* there are problems for mounting */
3747 +               return getattr_full(mnt, dentry, stat);
3748 +
3749 +       return retval;
3750 +}
3751 +
3752 +/*
3753 + * directories can handle most operations...  supermount/namei.c just
3754 + * passes them through to the underlying subfs, except for lookup().
3755 + */
3756 +
3757 +/* truncate: is not necesary, handled with setattr
3758 + * revalidate: only needed by nfs
3759 + * FixMe: implement accl functions
3760 + */
3761 +struct inode_operations supermount_root_iops = {
3762 +       .create         = supermount_create,
3763 +       .lookup         = supermount_lookup,
3764 +       .link           = supermount_link,
3765 +       .unlink         = supermount_unlink,
3766 +       .symlink        = supermount_symlink,
3767 +       .mkdir          = supermount_mkdir,
3768 +       .rmdir          = supermount_rmdir,
3769 +       .mknod          = supermount_mknod,
3770 +       .rename         = supermount_rename,
3771 +       .permission     = supermount_permission,
3772 +       .setattr        = supermount_setattr,
3773 +       .getattr        = supermount_root_getattr,
3774 +};
3775 +
3776 +struct inode_operations supermount_dir_iops = {
3777 +       .create         = supermount_create,
3778 +       .lookup         = supermount_lookup,
3779 +       .link           = supermount_link,
3780 +       .unlink         = supermount_unlink,
3781 +       .symlink        = supermount_symlink,
3782 +       .mkdir          = supermount_mkdir,
3783 +       .rmdir          = supermount_rmdir,
3784 +       .mknod          = supermount_mknod,
3785 +       .rename         = supermount_rename,
3786 +       .permission     = supermount_permission,
3787 +       .setattr        = supermount_setattr,
3788 +       .getattr        = supermount_getattr,
3789 +};
3790 +
3791 +struct inode_operations supermount_symlink_iops = {
3792 +       .readlink       = supermount_readlink,
3793 +       .follow_link    = supermount_follow_link,
3794 +       .setattr        = supermount_setattr,
3795 +       .getattr        = supermount_getattr,
3796 +};
3797 +
3798 +struct inode_operations supermount_file_iops = {
3799 +       .setattr        = supermount_setattr,
3800 +       .getattr        = supermount_getattr,
3801 +};
3802 diff -Naurp linux-2.4.20-ck4/fs/supermount/Makefile linux-2.4.20-ck5/fs/supermount/Makefile
3803 --- linux-2.4.20-ck4/fs/supermount/Makefile     1970-01-01 10:00:00.000000000 +1000
3804 +++ linux-2.4.20-ck5/fs/supermount/Makefile     2003-04-08 10:52:51.000000000 +1000
3805 @@ -0,0 +1,13 @@
3806 +#
3807 +# Makefile for the linux supermounting routines.
3808 +#
3809 +
3810 +O_TARGET := supermount.o
3811 +
3812 +obj-y    := super.o init.o mediactl.o translation.o super_operations.o \
3813 +           file_operations.o inode_operations.o \
3814 +           dentry_operations.o
3815 +
3816 +obj-m    := $(O_TARGET)
3817 +
3818 +include $(TOPDIR)/Rules.make
3819 diff -Naurp linux-2.4.20-ck4/fs/supermount/mediactl.c linux-2.4.20-ck5/fs/supermount/mediactl.c
3820 --- linux-2.4.20-ck4/fs/supermount/mediactl.c   1970-01-01 10:00:00.000000000 +1000
3821 +++ linux-2.4.20-ck5/fs/supermount/mediactl.c   2003-04-08 10:52:51.000000000 +1000
3822 @@ -0,0 +1,40 @@
3823 +/*
3824 + *  linux/fs/supermount/mediactl.c
3825 + *
3826 + *  Original version:
3827 + *      Copyright (C) 1995, 1997
3828 + *      Stephen Tweedie (sct@dcs.ed.ac.uk)
3829 + *
3830 + *  Rewriten for kernel 2.2, 2.4. (C) 1999, 2000 Alexis Mikhailov
3831 + *                                    (alexis@abc.cap.ru)
3832 + *
3833 + */
3834 +
3835 +#include <linux/errno.h>
3836 +#include <linux/fs.h>
3837 +#include <linux/major.h>
3838 +#include <linux/cdrom.h>
3839 +
3840 +#include "supermount_i.h"
3841 +
3842 +/* 
3843 + * Try to lock the drive door.  This is not guaranteed to work on all
3844 + * hardware, but we try any tricks we know of anyway.  
3845 + */
3846 +void
3847 +supermount_handle_door(struct super_block *sb, int operation)
3848 +{
3849 +       kdev_t dev;
3850 +       int major;
3851 +       const struct block_device_operations *fops;
3852 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
3853 +       struct super_block *subsb = supermount_subfs_sb(sbi);
3854 +
3855 +       dev = subsb->s_dev;
3856 +       major = MAJOR(dev);
3857 +       if (major >= MAX_BLKDEV || !(fops = get_blkfops(major)))
3858 +               return;
3859 +       if (!fops->mediactl)
3860 +               return;
3861 +       fops->mediactl(dev, operation, 0);
3862 +}
3863 diff -Naurp linux-2.4.20-ck4/fs/supermount/super.c linux-2.4.20-ck5/fs/supermount/super.c
3864 --- linux-2.4.20-ck4/fs/supermount/super.c      1970-01-01 10:00:00.000000000 +1000
3865 +++ linux-2.4.20-ck5/fs/supermount/super.c      2003-04-08 10:52:51.000000000 +1000
3866 @@ -0,0 +1,452 @@
3867 +/*
3868 + *  linux/fs/supermount/super.c
3869 + *
3870 + *  Original version:
3871 + *      Copyright (C) 1995, 1997
3872 + *      Stephen Tweedie (sct@dcs.ed.ac.uk)
3873 + *
3874 + *      from
3875 + *
3876 + *      linux/fs/minix/inode.c
3877 + *      Copyright (C) 1991, 1992  Linus Torvalds
3878 + *
3879 + *      and
3880 + *
3881 + *      linux/fs/ext2/super.c
3882 + *      Copyright (C) 1992, 1993, 1994, 1995  Remy Card
3883 + *
3884 + *  Rewriten for kernel 2.2, 2.4. (C) 1999, 2000 Alexis Mikhailov
3885 + *                                    (alexis@abc.cap.ru)
3886 + *
3887 + */
3888 +
3889 +#include <linux/errno.h>
3890 +#include <linux/fs.h>
3891 +#include <linux/list.h>
3892 +#include <linux/locks.h>
3893 +
3894 +#include "supermount_i.h"
3895 +
3896 +struct inode *
3897 +supermount_create_inode(struct super_block *s)
3898 +{
3899 +       struct inode *inode = new_inode(s);
3900 +       struct supermount_sb_info *sbi = supermount_sbi(s);
3901 +
3902 +       if (!inode)
3903 +               return NULL;
3904 +
3905 +       inode->i_mode = sbi->s_default_mode;
3906 +       if (s->s_root) {
3907 +               inode->i_uid = s->s_root->d_inode->i_uid;
3908 +               inode->i_gid = s->s_root->d_inode->i_gid;
3909 +       } else {
3910 +               inode->i_uid = 0;
3911 +               inode->i_gid = 0;
3912 +       }
3913 +       inode->i_blksize = inode->i_sb->s_blocksize;
3914 +       inode->i_rdev = 0;
3915 +       inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
3916 +       supermount_i(inode)->i_sb_version = sbi->s_version;
3917 +       list_add(&(supermount_i(inode)->i_fs), &sbi->s_inodes);
3918 +
3919 +       return inode;
3920 +}
3921 +
3922 +static void
3923 +supermount_clean_inodes(struct super_block *sb)
3924 +{
3925 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
3926 +       struct list_head *ptr;
3927 +       struct supermount_inode_info *info;
3928 +
3929 +       list_for_each(ptr, &sbi->s_inodes) {
3930 +               info = list_entry(ptr, struct supermount_inode_info, i_fs);
3931 +               if (!info)
3932 +                       BUG();
3933 +               if (!info->i_dentry)
3934 +                       continue;
3935 +               dput(info->i_dentry);
3936 +               info->i_dentry = NULL;
3937 +       }
3938 +}
3939 +
3940 +/*
3941 + * Cut off busy dentries unless mounted over. They go away when
3942 + * their owners die
3943 + * We run under mutex or sb lock so nobody can change directory structure
3944 + * d_drop holds dcache lock for us
3945 + * FIXME: it probably should unmount submounts
3946 + */
3947 +static void
3948 +supermount_drop_dentries(struct super_block *sb)
3949 +{
3950 +       struct dentry *d;
3951 +       struct list_head *ptr;
3952 +
3953 +       if (!sb->s_root)
3954 +               return;
3955 +
3956 +       list_for_each(ptr, &sb->s_root->d_subdirs) {
3957 +               d = list_entry(ptr, struct dentry, d_child);
3958 +
3959 +               if (!have_submounts(d))
3960 +                       d_drop(d);
3961 +        }
3962 +}
3963 +
3964 +void
3965 +subfs_umount(struct super_block *sb)
3966 +{
3967 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
3968 +       struct vfsmount *mnt = sbi->s_undermount;
3969 +       struct inode *root_inode;
3970 +
3971 +       if (sb->s_root) {
3972 +               root_inode = sb->s_root->d_inode;
3973 +               if (!supermount_i(root_inode)->i_dentry)
3974 +                       BUG();
3975 +               dput(supermount_i(root_inode)->i_dentry);
3976 +               supermount_i(root_inode)->i_dentry = NULL;
3977 +       }
3978 +       shrink_dcache_sb(sb);
3979 +       supermount_clean_inodes(sb);
3980 +       supermount_drop_dentries(sb);
3981 +       BUG_ON(!mnt);
3982 +       mntput(mnt);
3983 +       sbi->s_state = SUPERMOUNT_UNMOUNTED;
3984 +       sbi->s_undermount = NULL;
3985 +       sbi->s_version++;
3986 +       sb->s_flags = sbi->s_mflags;
3987 +}
3988 +
3989 +static int
3990 +subfs_remount(struct super_block *sb, int flags)
3991 +{
3992 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
3993 +       struct super_block *subsb = supermount_subfs_sb(sbi);
3994 +       int real_flags = (sb->s_flags | flags) & MS_RMT_MASK;
3995 +       int retval;
3996 +
3997 +       retval = do_remount_sb(subsb, real_flags, NULL);
3998 +       if (flags & MS_RDONLY)
3999 +               fsync_dev(subsb->s_dev);
4000 +       return retval;
4001 +}
4002 +
4003 +static inline int
4004 +subfs_remount_ro(struct super_block *sb)
4005 +{
4006 +       int retval = subfs_remount(sb, MS_RDONLY);
4007 +
4008 +       if (retval)
4009 +               return retval;
4010 +       unmark_subfs_rw(sb);
4011 +       return 0;
4012 +}
4013 +
4014 +static inline int
4015 +subfs_remount_rw(struct super_block *sb)
4016 +{
4017 +       int retval = subfs_remount(sb, 0);
4018 +
4019 +       if (retval)
4020 +               return retval;
4021 +       mark_subfs_rw(sb);
4022 +       return 0;
4023 +}
4024 +
4025 +static int
4026 +subfs_real_mount(struct super_block *sb, char *type)
4027 +{
4028 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4029 +       struct vfsmount *mnt;
4030 +       int retval;
4031 +
4032 +       if (sbi->s_data_copy)
4033 +               strcpy(sbi->s_data, sbi->s_data_copy);
4034 +
4035 +       mnt = do_kern_mount(type,
4036 +                           sb->s_flags | MS_MGC_VAL | MS_SUPERMOUNTED,
4037 +                           sbi->s_devname, sbi->s_data);
4038 +
4039 +       if (IS_ERR(mnt)) {
4040 +               retval = PTR_ERR(mnt);
4041 +       } else {
4042 +               retval = 0;
4043 +               mnt->mnt_sb->s_media_changed = 0;
4044 +               sbi->s_undermount = mnt;
4045 +       }
4046 +       return retval;
4047 +}
4048 +
4049 +static int
4050 +subfs_real_mount2(struct super_block *sb, char *type)
4051 +{
4052 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4053 +       struct inode *root_inode;
4054 +       int retval = 0;
4055 +
4056 +       sb->s_flags = sbi->s_mflags;
4057 +
4058 +       retval = subfs_real_mount(sb, type);
4059 +
4060 +       if (retval == -EROFS) {
4061 +               sb->s_flags |= MS_RDONLY;
4062 +               retval = subfs_real_mount(sb, type);
4063 +               if (!retval)
4064 +                       goto assign_root_inode;
4065 +       }
4066 +       if (retval)
4067 +               goto out;
4068 +
4069 +       if (!(sb->s_flags & MS_RDONLY)) {
4070 +               retval = subfs_remount_ro(sb);
4071 +               if (retval)
4072 +                       goto out;
4073 +       }
4074 +assign_root_inode:
4075 +       root_inode = sb->s_root->d_inode;
4076 +       if (supermount_i(root_inode)->i_dentry)
4077 +               BUG();
4078 +       supermount_i(root_inode)->i_dentry = dget(sbi->s_undermount->mnt_root);
4079 +out:
4080 +       return retval;
4081 +}
4082 +
4083 +static char *types_in_order[] = {
4084 +       "udf",
4085 +       "iso9660",
4086 +       "vfat",
4087 +       "msdos",
4088 +       "ext2",
4089 +       NULL
4090 +};
4091 +
4092 +/*
4093 + * -ENXIO
4094 + *
4095 + */
4096 +
4097 +static int
4098 +subfs_mount(struct super_block *sb)
4099 +{
4100 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4101 +       int retval = -ENODEV;
4102 +       char **type = types_in_order;
4103 +
4104 +       if (sbi->s_type && strcmp(sbi->s_type, "auto"))
4105 +               return subfs_real_mount2(sb, sbi->s_type);
4106 +
4107 +       while (*type && retval
4108 +              && retval != -ENXIO
4109 +              && retval != -ENOMEDIUM
4110 +              && retval != -ENOENT) {
4111 +               retval = subfs_real_mount2(sb, *type);
4112 +               type++;
4113 +       }
4114 +
4115 +       return retval;
4116 +}
4117 +
4118 +/* We used not to check the medium if we was already mounted, this
4119 + * provoked problems in floppies & things that don't have a working
4120 + * locking mechanism, now we _always_ check if the medium has changed.
4121 + */
4122 +
4123 +/* Return 0 (OK) if medium is valid. */
4124 +int
4125 +subfs_go_online(struct super_block *sb)
4126 +{
4127 +       int retval = 0;
4128 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4129 +
4130 +       down(&sbi->sem);
4131 +
4132 +       if (subfs_is_mounted(sbi)) {
4133 +               struct super_block *subsb = supermount_subfs_sb(sbi);
4134 +               kdev_t dev = subsb->s_dev;
4135 +
4136 +               /*
4137 +                * check for disk change or disk not present
4138 +                *
4139 +                * FIXME there is a race here; check must be protected
4140 +                * with mutex; currently it is possible that media changed
4141 +                * flag is stolen
4142 +                */
4143 +
4144 +               if (!(subsb->s_media_changed || query_disk_change(dev)))
4145 +                       goto mounted;
4146 +
4147 +               /* We have a disk change!  Unmount the subfs */
4148 +               subfs_umount(sb);
4149 +               /* The call to disk_changed may clear the media-
4150 +                  changed flag on the device, so we need to force a
4151 +                  media invalidation.  We don't want to do this
4152 +                  before unmounting the subfs, naturally! */
4153 +               invalidate_media(dev);
4154 +       }
4155 +       /* OK, we're unmounted now --- can we remount?  Please? */
4156 +       if (sbi->s_undermount)
4157 +               BUG();
4158 +
4159 +       retval = subfs_mount(sb);
4160 +       if (retval) {
4161 +               retval = 1;
4162 +               goto out;
4163 +       }
4164 +       sbi->s_version++;
4165 +       supermount_i(sb->s_root->d_inode)->i_sb_version = sbi->s_version;
4166 +       unmark_subfs_rw(sb);
4167 +       sbi->s_state = SUPERMOUNT_SUSPENDED;
4168 +mounted:
4169 +       switch (sbi->s_state) {
4170 +       case SUPERMOUNT_UNMOUNTED:
4171 +               BUG();
4172 +       case SUPERMOUNT_SUSPENDED:
4173 +               supermount_lock_door(sb);
4174 +               sbi->s_state = SUPERMOUNT_ONLINE;
4175 +               break;
4176 +       case SUPERMOUNT_ONLINE:
4177 +               /* No need to do anything */ ;
4178 +       }
4179 +out:
4180 +       atomic_inc(&sbi->s_opencount);
4181 +       up(&sbi->sem);
4182 +       return retval;
4183 +}
4184 +
4185 +/* 
4186 + * Check the state of the supermount filesystem after it has been
4187 + * released by some inode.  If it is no longer active, do the necessary
4188 + * cleanup: fsync the disk, remount it readonly if appropriate, and
4189 + * unlock the drive door if possible.
4190 + */
4191 +
4192 +void
4193 +subfs_go_inactive(struct super_block *sb)
4194 +{
4195 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4196 +
4197 +       down(&sbi->sem);
4198 +
4199 +       /* there was a problem mounting */
4200 +       if (!subfs_is_mounted(sbi))
4201 +               goto out;
4202 +
4203 +       if ((atomic_read(&sbi->s_opencount) > 1))
4204 +               goto out;
4205 +
4206 +       /*
4207 +        * Do an initial fsync_dev.  We do this before locking the 
4208 +        * superblock to minimise the duration of the lock. 
4209 +        */
4210 +       if (subfs_is_dirty(sbi)) {
4211 +               fsync_dev(sb->s_dev);
4212 +               mark_subfs_clean(sb);
4213 +       }
4214 +
4215 +       /*
4216 +        * First thing is, has the filesystem been made
4217 +        * read-write since it became active?  If so, now is the
4218 +        * time to retire it back to read-only state.
4219 +        */
4220 +
4221 +       if (subfs_is_rw(sbi)) {
4222 +               int retval = subfs_remount_ro(sb);
4223 +               BUG_ON(retval);
4224 +       }
4225 +       supermount_unlock_door(sb);
4226 +       sbi->s_state = SUPERMOUNT_SUSPENDED;
4227 +out:
4228 +       atomic_dec(&sbi->s_opencount);
4229 +       up(&sbi->sem);
4230 +}
4231 +
4232 +/*
4233 + * Try to put the filesystem into writable mode for the duration of
4234 + * an open(O_RDWR) or an inode operation requiring write access.  
4235 + */
4236 +
4237 +int
4238 +subfs_get_write_access(struct super_block *sb)
4239 +{
4240 +       int retval;
4241 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4242 +
4243 +       down(&sbi->sem);
4244 +       if (!subfs_is_online(sbi))
4245 +               BUG();
4246 +
4247 +       retval = 0;
4248 +       if (atomic_read(&sbi->s_writecount) == 0) {
4249 +               /*
4250 +                * We may already have write access to the filesystem
4251 +                */
4252 +               if (!subfs_is_rw(sbi)) {
4253 +                       if (sb->s_flags & MS_RDONLY)
4254 +                               retval = -EROFS;
4255 +                       else
4256 +                               retval = subfs_remount_rw(sb);
4257 +               }
4258 +       }
4259 +
4260 +       if (!retval)
4261 +               atomic_inc(&sbi->s_writecount);
4262 +       up(&sbi->sem);
4263 +
4264 +       return retval;
4265 +}
4266 +
4267 +/*
4268 + * Once we're done, release write access.
4269 + */
4270 +void
4271 +subfs_put_write_access(struct super_block *sb)
4272 +{
4273 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4274 +
4275 +       down(&sbi->sem);
4276 +       if (!subfs_is_rw(sbi))
4277 +               BUG();
4278 +
4279 +       BUG_ON(atomic_read(&sbi->s_writecount) == 0);
4280 +       atomic_dec(&sbi->s_writecount);
4281 +       up(&sbi->sem);
4282 +}
4283 +
4284 +/* Supermount open/close inode.  These functions maintain the
4285 +   superblock reference counts of active inodes; the subfs is
4286 +   suspended when that count reaches zero.
4287 +
4288 +   Files are opened on any significant reference, and are not closed
4289 +   until they become fully dereferenced (during the last iput).
4290 +   Directories, on the other hand, are always closed unless they are
4291 +   active and opened; a directory referenced as CWD is not open.
4292 +*/
4293 +
4294 +void
4295 +subfs_get_read_access(struct super_block *sb)
4296 +{
4297 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4298 +
4299 +       down(&sbi->sem);
4300 +       BUG_ON(!subfs_is_online(sbi));
4301 +       atomic_inc(&sbi->s_opencount);
4302 +       up(&sbi->sem);
4303 +}
4304 +
4305 +/* we can't check here for subfs_is_online, because in the case of one
4306 + * error, system will call ->release() on inodes, where subfs is not
4307 + * online.
4308 + */
4309 +
4310 +void
4311 +subfs_put_read_access(struct super_block *sb)
4312 +{
4313 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4314 +
4315 +       down(&sbi->sem);
4316 +       atomic_dec(&sbi->s_opencount);
4317 +       up(&sbi->sem);
4318 +}
4319 diff -Naurp linux-2.4.20-ck4/fs/supermount/supermount_i.h linux-2.4.20-ck5/fs/supermount/supermount_i.h
4320 --- linux-2.4.20-ck4/fs/supermount/supermount_i.h       1970-01-01 10:00:00.000000000 +1000
4321 +++ linux-2.4.20-ck5/fs/supermount/supermount_i.h       2003-04-08 10:52:51.000000000 +1000
4322 @@ -0,0 +1,215 @@
4323 +#ifndef _SUPERMOUNT_I_H
4324 +#define _SUPERMOUNT_I_H
4325 +
4326 +#define SUPERMOUNT_DEBUG
4327 +
4328 +/*
4329 + * The supermount superblock magic number
4330 + */
4331 +
4332 +#define SUPERMOUNT_SUPER_MAGIC 0x9fa1
4333 +
4334 +static inline int
4335 +is_inode_supermounted(struct inode *inode)
4336 +{
4337 +       return (inode->i_sb &&
4338 +               (inode->i_sb->s_magic == SUPERMOUNT_SUPER_MAGIC));
4339 +}
4340 +
4341 +static inline int
4342 +is_dentry_supermounted(struct dentry *dentry)
4343 +{
4344 +       return (dentry->d_inode && is_inode_supermounted(dentry->d_inode));
4345 +}
4346 +
4347 +#define SUPERMOUNT_VERSION             "0.7"
4348 +
4349 +/*
4350 + * The difference between SUSPENDED and ONLINE is that in SUSPENDED
4351 + * the door is unlocked, and in ONLINE it is locked.
4352 + */
4353 +
4354 +typedef enum {
4355 +       SUPERMOUNT_UNMOUNTED,   /* No media mounted */
4356 +       SUPERMOUNT_SUSPENDED,   /* Mounted but suspended because 
4357 +                                  no files open */
4358 +       SUPERMOUNT_ONLINE,      /* Mounted and active */
4359 +} sm_state_t;
4360 +
4361 +/*
4362 + * supermount super-block data in memory
4363 + */
4364 +struct supermount_sb_info {
4365 +       sm_state_t s_state;
4366 +       int s_version;          /* Used to indicate obsolete inodes */
4367 +       mode_t s_default_mode;  /* Default mode for supermount root */
4368 +
4369 +       char *s_type;           /* Type of fs to be sub-mounted */
4370 +       char *s_devname;        /* Where to mount the subfs from */
4371 +       /* unused */
4372 +       int s_mflags;           /* Flags to pass when mounting subfs */
4373 +       char *s_data;           /* Data to pass when mounting subfs */
4374 +       char *s_data_copy;      /* copy of previous data.  FS
4375 +                                  destroy that data, and we
4376 +                                  need to mount several
4377 +                                  times.  We could allocate
4378 +                                  the memory in
4379 +                                  supermount_mount, but then
4380 +                                  we have more possible
4381 +                                  errors */
4382 +       struct vfsmount *s_undermount;  /* Mount point for subfs */
4383 +       atomic_t s_opencount;   /* Refcount of opened inodes
4384 +                                  (an inode in use as cwd
4385 +                                  does not count as open) */
4386 +       atomic_t s_writecount;  /* Refcount of write accesses
4387 +                                  on the filesystem */
4388 +       /* Flags */
4389 +       int s_dirty:1;          /* Do we need to fsync() the subfs? */
4390 +       int s_rw:1;             /* Is the subfs mounted read/write? */
4391 +       struct list_head s_inodes;
4392 +       struct semaphore sem;
4393 +};
4394 +
4395 +static inline struct supermount_inode_info *
4396 +supermount_i(struct inode *inode)
4397 +{
4398 +       return (&inode->u.supermount_i);
4399 +}
4400 +
4401 +static inline struct supermount_sb_info *
4402 +supermount_sbi(struct super_block *sb)
4403 +{
4404 +       if (!sb)
4405 +               BUG();
4406 +       return (struct supermount_sb_info *) (sb->u.generic_sbp);
4407 +}
4408 +
4409 +static inline struct super_block *
4410 +supermount_subfs_sb(struct supermount_sb_info *sbi)
4411 +{
4412 +       return sbi->s_undermount->mnt_sb;
4413 +}
4414 +
4415 +/*
4416 + * Function prototypes
4417 + */
4418 +
4419 +static inline struct file *
4420 +get_subfile(struct file *file)
4421 +{
4422 +       struct file *subfile = (struct file *) file->private_data;
4423 +       if (!subfile)
4424 +               BUG();
4425 +       return subfile;
4426 +}
4427 +
4428 +static inline void
4429 +put_subfile(struct file *file, struct file *subfile)
4430 +{
4431 +       file->private_data = (void *) subfile;
4432 +}
4433 +
4434 +/* How to test if an inode is obsolete: */
4435 +static inline int
4436 +is_inode_obsolete(struct inode *inode)
4437 +{
4438 +       struct supermount_sb_info *sbi = supermount_sbi(inode->i_sb);
4439 +
4440 +       return (supermount_i(inode)->i_sb_version != sbi->s_version);
4441 +}
4442 +
4443 +/* Manage the subfs dirty flag */
4444 +static inline void
4445 +mark_subfs_dirty(struct super_block *sb)
4446 +{
4447 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4448 +
4449 +       sbi->s_dirty = 1;
4450 +}
4451 +static inline void
4452 +mark_subfs_clean(struct super_block *sb)
4453 +{
4454 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4455 +
4456 +       sbi->s_dirty = 0;
4457 +}
4458 +static inline int
4459 +subfs_is_dirty(struct supermount_sb_info *sbi)
4460 +{
4461 +       return (sbi->s_dirty);
4462 +}
4463 +
4464 +/* Manage the subfs rw flag */
4465 +static inline void
4466 +mark_subfs_rw(struct super_block *sb)
4467 +{
4468 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4469 +
4470 +       sbi->s_rw = 1;
4471 +}
4472 +static inline void
4473 +unmark_subfs_rw(struct super_block *sb)
4474 +{
4475 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4476 +
4477 +       sbi->s_rw = 0;
4478 +}
4479 +static inline int
4480 +subfs_is_rw(struct supermount_sb_info *sbi)
4481 +{
4482 +       return (sbi->s_rw);
4483 +}
4484 +
4485 +static inline int
4486 +subfs_is_online(struct supermount_sb_info *sbi)
4487 +{
4488 +       return (sbi->s_state == SUPERMOUNT_ONLINE);
4489 +}
4490 +
4491 +static inline int
4492 +subfs_is_mounted(struct supermount_sb_info *sbi)
4493 +{
4494 +       return (sbi->s_state != SUPERMOUNT_UNMOUNTED);
4495 +}
4496 +
4497 +/* super.c */
4498 +extern struct inode *supermount_create_inode(struct super_block *s);
4499 +extern void subfs_umount(struct super_block *sb);
4500 +extern int subfs_go_online(struct super_block *);
4501 +extern void subfs_go_inactive(struct super_block *);
4502 +extern int subfs_get_write_access(struct super_block *);
4503 +extern void subfs_put_write_access(struct super_block *);
4504 +extern void subfs_get_read_access(struct super_block *);
4505 +extern void subfs_put_read_access(struct super_block *);
4506 +/* translate.c */
4507 +extern struct dentry *get_subfs_dentry(struct dentry *dentry);
4508 +extern struct dentry *get_subfs_dentry_by_inode(struct inode *inode);
4509 +/* mediactl.c */
4510 +extern void supermount_handle_door(struct super_block *, int);
4511 +static inline void
4512 +supermount_lock_door(struct super_block *sb)
4513 +{
4514 +       supermount_handle_door(sb, MEDIA_LOCK);
4515 +}
4516 +static inline void
4517 +supermount_unlock_door(struct super_block *sb)
4518 +{
4519 +       supermount_handle_door(sb, MEDIA_UNLOCK);
4520 +}
4521 +
4522 +/* inode_operations.c */
4523 +extern struct inode_operations supermount_root_iops;
4524 +extern struct inode_operations supermount_dir_iops;
4525 +extern struct inode_operations supermount_file_iops;
4526 +extern struct inode_operations supermount_symlink_iops;
4527 +/* super_operations.c */
4528 +extern struct super_block *supermount_read_super(struct super_block *,
4529 +                                                void *, int);
4530 +/* file_operations.c */
4531 +extern struct file_operations supermount_dir_operations;
4532 +extern struct file_operations supermount_file_operations;
4533 +/* dentry_operations.c */
4534 +extern struct dentry_operations supermount_file_dops;
4535 +extern struct dentry_operations supermount_dir_dops;
4536 +
4537 +#endif                         /* _SUPERMOUNT_I_H */
4538 diff -Naurp linux-2.4.20-ck4/fs/supermount/super_operations.c linux-2.4.20-ck5/fs/supermount/super_operations.c
4539 --- linux-2.4.20-ck4/fs/supermount/super_operations.c   1970-01-01 10:00:00.000000000 +1000
4540 +++ linux-2.4.20-ck5/fs/supermount/super_operations.c   2003-04-08 10:52:51.000000000 +1000
4541 @@ -0,0 +1,301 @@
4542 +/*
4543 + *  linux/fs/supermount/super_operations.c
4544 + *
4545 + *  Original version:
4546 + *      Copyright (C) 1995, 1997
4547 + *      Stephen Tweedie (sct@dcs.ed.ac.uk)
4548 + *
4549 + *      from
4550 + *
4551 + *      linux/fs/minix/inode.c
4552 + *      Copyright (C) 1991, 1992  Linus Torvalds
4553 + *
4554 + *      and
4555 + *
4556 + *      linux/fs/ext2/super.c
4557 + *      Copyright (C) 1992, 1993, 1994, 1995  Remy Card
4558 + *
4559 + *  Rewriten for kernel 2.2, 2.4. (C) 1999, 2000 Alexis Mikhailov
4560 + *                                    (alexis@abc.cap.ru)
4561 + *
4562 + */
4563 +
4564 +#include <linux/errno.h>
4565 +#include <linux/fs.h>
4566 +#include <linux/list.h>
4567 +#include <linux/slab.h>
4568 +
4569 +#include "supermount_i.h"
4570 +
4571 +static struct super_operations supermount_sops;
4572 +
4573 +static void
4574 +supermount_write_inode(struct inode *inode, int sync)
4575 +{
4576 +       struct supermount_sb_info *sbi = supermount_sbi(inode->i_sb);
4577 +       struct super_block *subsb;
4578 +       struct dentry *dent;
4579 +       struct inode *subi;
4580 +       int rc = -EIO;
4581 +
4582 +       if (subfs_go_online(inode->i_sb))
4583 +               goto out;
4584 +
4585 +       rc = 0;
4586 +       dent = get_subfs_dentry_by_inode(inode);
4587 +       if (IS_ERR(dent))
4588 +               goto out;
4589 +       subi = dent->d_inode;
4590 +       if (!subi)
4591 +               goto dput_ret;
4592 +       subsb = supermount_subfs_sb(sbi);
4593 +       if (subi && subsb && subsb->s_op && subsb->s_op->write_inode) {
4594 +               subi->i_mode = inode->i_mode;
4595 +               subi->i_uid = inode->i_uid;
4596 +               subi->i_gid = inode->i_gid;
4597 +               subi->i_size = inode->i_size;
4598 +               subi->i_atime = inode->i_atime;
4599 +               subi->i_mtime = inode->i_mtime;
4600 +               subi->i_ctime = inode->i_ctime;
4601 +               rc = subfs_get_write_access(inode->i_sb);
4602 +               if (rc)
4603 +                       goto dput_ret;;
4604 +               subi->i_state |= I_LOCK;
4605 +               subsb->s_op->write_inode(subi, sync);
4606 +               subi->i_state &= ~I_LOCK;
4607 +               mark_subfs_dirty(inode->i_sb);
4608 +               subfs_put_write_access(inode->i_sb);
4609 +       }
4610 +dput_ret:
4611 +       dput(dent);
4612 +out:
4613 +       subfs_go_inactive(inode->i_sb);
4614 +}
4615 +
4616 +static void
4617 +supermount_clear_inode(struct inode *inode)
4618 +{
4619 +       dput(supermount_i(inode)->i_dentry);
4620 +       list_del(&supermount_i(inode)->i_fs);
4621 +}
4622 +
4623 +static struct supermount_sb_info *
4624 +create_sbi(struct super_block *sb)
4625 +{
4626 +       struct supermount_sb_info *sbi = kmalloc(sizeof (*sbi), GFP_KERNEL);
4627 +
4628 +       if (!sbi)
4629 +               return NULL;
4630 +
4631 +       memset(sbi, 0, sizeof (*sbi));
4632 +
4633 +       sbi->s_state = SUPERMOUNT_UNMOUNTED;
4634 +       sbi->s_default_mode = 0777 | S_IFDIR;
4635 +       atomic_set(&sbi->s_opencount, 0);
4636 +       atomic_set(&sbi->s_writecount, 0);
4637 +       sbi->s_mflags = sb->s_flags & MS_RMT_MASK;
4638 +       INIT_LIST_HEAD(&sbi->s_inodes);
4639 +       sema_init(&sbi->sem, 1);
4640 +       return sbi;
4641 +}
4642 +
4643 +static void
4644 +free_sbi(struct supermount_sb_info *sbi)
4645 +{
4646 +       if (sbi->s_type)
4647 +               kfree(sbi->s_type);
4648 +       if (sbi->s_devname)
4649 +               kfree(sbi->s_devname);
4650 +       if (sbi->s_data)
4651 +               kfree(sbi->s_data);
4652 +       if (sbi->s_data_copy)
4653 +               kfree(sbi->s_data_copy);
4654 +       kfree(sbi);
4655 +       
4656 +}
4657 +
4658 +/* Release the superblock and any resources it has reserved 
4659 + * it is called with the sb locked
4660 + */
4661 +
4662 +static void
4663 +supermount_put_super(struct super_block *sb)
4664 +{
4665 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4666 +
4667 +       if (subfs_is_mounted(sbi))
4668 +               subfs_umount(sb);
4669 +
4670 +       sb->u.generic_sbp = 0;
4671 +       free_sbi(sbi);
4672 +       sb->s_dev = 0;
4673 +}
4674 +
4675 +static int
4676 +copy_option(char **option, const char *val)
4677 +{
4678 +       char *tmp;
4679 +       if (!val || !*val)
4680 +               return -EINVAL;
4681 +       tmp = kmalloc(1 + strlen(val), GFP_KERNEL);
4682 +       if (!tmp)
4683 +               return -ENOMEM;
4684 +       strcpy(tmp, val);
4685 +       *option = tmp;
4686 +       return 0;
4687 +}
4688 +
4689 +static int
4690 +parse_options(char *options, struct supermount_sb_info *sbi)
4691 +{
4692 +       char *this_char;
4693 +       char *value;
4694 +       int rc;
4695 +
4696 +       if (!options)
4697 +               return 0;
4698 +       while ((this_char = options)) {
4699 +               if (!strncmp(this_char, "--", 2))
4700 +                       this_char += 2;
4701 +               if (!*this_char)
4702 +                       break;
4703 +               if (*this_char == ',') {
4704 +                       /* An empty option, or the option "--",
4705 +                          introduces options to be passed through to
4706 +                          the subfs */
4707 +                       return copy_option(&sbi->s_data, ++this_char);
4708 +               }
4709 +               if ((options = strchr(this_char, ',')))
4710 +                       *options++ = 0;
4711 +
4712 +               if ((value = strchr(this_char, '=')))
4713 +                       *value++ = 0;
4714 +
4715 +               if (!strcmp(this_char, "fs")) {
4716 +                       rc = copy_option(&sbi->s_type, value);
4717 +                       if (rc)
4718 +                               return rc;
4719 +               } else if (!strcmp(this_char, "dev")) {
4720 +                       rc = copy_option(&sbi->s_devname, value);
4721 +                       if (rc)
4722 +                               return rc;
4723 +               } else {
4724 +                       printk(KERN_DEBUG "Unrecognized mount option %s",
4725 +                                        this_char);
4726 +                       return -EINVAL;
4727 +               }
4728 +       }
4729 +       return 0;
4730 +}
4731 +
4732 +static struct inode *
4733 +supermount_root_inode(struct super_block *s)
4734 +{
4735 +       struct inode *inode = supermount_create_inode(s);
4736 +
4737 +       if (!inode)
4738 +               return NULL;
4739 +
4740 +       inode->i_version = 0;
4741 +       inode->i_op = &supermount_root_iops;
4742 +       inode->i_fop = &supermount_dir_operations;
4743 +
4744 +       return inode;
4745 +}
4746 +
4747 +/* read_super: the main mount() entry point into the VFS layer. */
4748 +struct super_block *
4749 +supermount_read_super(struct super_block *s, void *data, int silent)
4750 +{
4751 +       struct inode *root_inode;
4752 +       struct dentry *root;
4753 +       struct supermount_sb_info *sbi = create_sbi(s);
4754 +
4755 +       if (!sbi)
4756 +               goto fail_no_memory;
4757 +
4758 +       if (parse_options((char *) data, sbi))
4759 +               goto fail_free_sbi;
4760 +
4761 +       if (!sbi->s_devname) {
4762 +               printk(KERN_ERR "%s: no dev=<filesystem> option", __FUNCTION__);
4763 +               goto fail_free_sbi;
4764 +       }
4765 +       if (sbi->s_data) {
4766 +               sbi->s_data_copy = kmalloc(1 + strlen(sbi->s_data), GFP_KERNEL);
4767 +               if (!sbi->s_data_copy) {
4768 +                       printk(KERN_ERR "%s: not enough memory", __FUNCTION__);
4769 +                       goto fail_free_sbi;
4770 +               }
4771 +               strcpy(sbi->s_data_copy, sbi->s_data);
4772 +       } else
4773 +               sbi->s_data_copy = NULL;
4774 +
4775 +       s->s_blocksize = 1024;
4776 +       s->s_blocksize_bits = 10;
4777 +       s->s_magic = SUPERMOUNT_SUPER_MAGIC;
4778 +       s->s_op = &supermount_sops;
4779 +       s->u.generic_sbp = sbi;
4780 +
4781 +       root_inode = supermount_root_inode(s);
4782 +       if (!root_inode)
4783 +               goto fail_free_sbi;
4784 +
4785 +       root = d_alloc_root(root_inode);
4786 +       if (!root)
4787 +               goto fail_free_root_inode;
4788 +
4789 +       s->s_root = root;
4790 +       s->s_root->d_op = &supermount_dir_dops;
4791 +       dget(root);
4792 +
4793 +       return s;
4794 +
4795 +fail_free_root_inode:
4796 +       iput(root_inode);
4797 +fail_free_sbi:
4798 +       s->s_dev = 0;
4799 +       free_sbi(sbi);
4800 +fail_no_memory:
4801 +       return NULL;
4802 +}
4803 +
4804 +/*
4805 + * called with lock_super held
4806 + */
4807 +
4808 +static void
4809 +supermount_write_super(struct super_block *sb)
4810 +{
4811 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4812 +
4813 +       if (subfs_is_online(sbi) && subfs_is_rw(sbi)) {
4814 +               struct super_block *subsb = supermount_subfs_sb(sbi);
4815 +               if (subsb && subsb->s_op && subsb->s_op->write_super)
4816 +                       subsb->s_op->write_super(subsb);
4817 +               mark_subfs_clean(sb);
4818 +       }
4819 +}
4820 +
4821 +static int
4822 +supermount_statfs(struct super_block *sb, struct statfs *buf)
4823 +{
4824 +       int rc = 0;
4825 +       struct supermount_sb_info *sbi = supermount_sbi(sb);
4826 +
4827 +       if (subfs_is_online(sbi)) {
4828 +               struct super_block *subsb = supermount_subfs_sb(sbi);
4829 +               if (subsb->s_op && subsb->s_op->statfs)
4830 +                       rc = subsb->s_op->statfs(subsb, buf);
4831 +       }
4832 +       buf->f_type = SUPERMOUNT_SUPER_MAGIC;
4833 +       return rc;
4834 +}
4835 +
4836 +static struct super_operations supermount_sops = {
4837 +       .write_inode    = supermount_write_inode,
4838 +       .clear_inode    = supermount_clear_inode,
4839 +       .put_super      = supermount_put_super,
4840 +       .write_super    = supermount_write_super,
4841 +       .statfs         = supermount_statfs,
4842 +};
4843 diff -Naurp linux-2.4.20-ck4/fs/supermount/translation.c linux-2.4.20-ck5/fs/supermount/translation.c
4844 --- linux-2.4.20-ck4/fs/supermount/translation.c        1970-01-01 10:00:00.000000000 +1000
4845 +++ linux-2.4.20-ck5/fs/supermount/translation.c        2003-04-08 10:52:51.000000000 +1000
4846 @@ -0,0 +1,155 @@
4847 +/*
4848 + *  linux/fs/supermount/translate.c
4849 + *
4850 + *  Original version:
4851 + *      Copyright (C) 1995, 1997
4852 + *      Stephen Tweedie (sct@dcs.ed.ac.uk)
4853 + *
4854 + *      from
4855 + *
4856 + *      linux/fs/minix/dir.c
4857 + *      Copyright (C) 1991, 1992  Linus Torvalds
4858 + *
4859 + *      and
4860 + *
4861 + *      linux/fs/ext2/dir.c
4862 + *      Copyright (C) 1992, 1993, 1994, 1995  Remy Card
4863 + *
4864 + *  Rewriten for kernel 2.2 & 2.4. (C) 1999, 2000 Alexis Mikhailov
4865 + *                                    (alexis@abc.cap.ru)
4866 + *  Rewriten for kernel 2.4. (C) 2001 MandrakeSoft Inc.
4867 + *                                    Juan Quintela (quintela@mandrakesoft.com)
4868 + *
4869 + */
4870 +
4871 +#include <linux/errno.h>
4872 +#include <linux/fs.h>
4873 +#include <linux/slab.h>
4874 +#include <linux/string.h>
4875 +
4876 +#include "supermount_i.h"
4877 +
4878 +static int
4879 +unwalk_dentry(struct dentry *dentry, char *name)
4880 +{
4881 +       char *tmp;
4882 +       char *path;
4883 +       int number = 0;
4884 +
4885 +       path = name + PATH_MAX;
4886 +       *path = 0;
4887 +
4888 +       spin_lock(&dcache_lock);
4889 +       for (;;) {
4890 +               if (dentry->d_parent == dentry)
4891 +                       break;
4892 +               path -= dentry->d_name.len + 1;
4893 +               if (path < name)
4894 +                       goto err_out;
4895 +               memcpy(path + 1, dentry->d_name.name, dentry->d_name.len);
4896 +               *path = 0;
4897 +               number++;
4898 +               dentry = dentry->d_parent;
4899 +       }
4900 +       spin_unlock(&dcache_lock);
4901 +       if (number)
4902 +               /* we need to removing leading '\0' */
4903 +               path++;
4904 +
4905 +       tmp = name;
4906 +       while (path <= name + PATH_MAX)
4907 +               *tmp++ = *path++;
4908 +
4909 +       return number;
4910 +
4911 +err_out:
4912 +       spin_unlock(&dcache_lock);
4913 +       return -EINVAL;
4914 +}
4915 +
4916 +static struct dentry *
4917 +walk_path(struct dentry *root, char *path, int number)
4918 +{
4919 +       struct dentry *base = root;
4920 +
4921 +       while (number-- && !IS_ERR(base)) {
4922 +               struct dentry *subdent;
4923 +               int len = strlen(path);
4924 +               subdent = lookup_one_len(path, base, len);
4925 +               path += len + 1;
4926 +               dput(base);
4927 +               base = subdent;
4928 +       }
4929 +       return base;
4930 +}
4931 +
4932 +static struct dentry *
4933 +__get_subfs_dentry(struct dentry *dentry)
4934 +{
4935 +       struct supermount_sb_info *sbi;
4936 +       struct dentry *subdent = ERR_PTR(-EINVAL);
4937 +       struct dentry *root;
4938 +       int number;
4939 +       char *name;
4940 +       struct vfsmount *mnt;
4941 +
4942 +       name = __getname();
4943 +       if (!name)
4944 +               return ERR_PTR(-ENOMEM);
4945 +
4946 +       sbi = supermount_sbi(dentry->d_sb);
4947 +       number = unwalk_dentry(dentry, name);
4948 +       if (number < 0) {
4949 +               subdent = ERR_PTR(number);
4950 +               goto out;
4951 +       }
4952 +       mnt = mntget(sbi->s_undermount);
4953 +       if (!mnt)
4954 +               goto out;
4955 +
4956 +       root = dget(mnt->mnt_sb->s_root);
4957 +       subdent = walk_path(root, name, number);
4958 +       mntput(mnt);
4959 +out:
4960 +       putname(name);
4961 +       return subdent;
4962 +}
4963 +
4964 +struct dentry *
4965 +get_subfs_dentry_by_inode(struct inode *inode)
4966 +{
4967 +       struct dentry *dentry;
4968 +       struct supermount_sb_info *sbi;
4969 +
4970 +       BUG_ON(!inode);
4971 +       BUG_ON(!is_inode_supermounted(inode));
4972 +
4973 +       if (is_inode_obsolete(inode))
4974 +               return ERR_PTR(-ESTALE);
4975 +
4976 +       sbi = supermount_sbi(inode->i_sb);
4977 +       if (!subfs_is_mounted(sbi))
4978 +               return ERR_PTR(-EINVAL);
4979 +
4980 +       dentry = dget(supermount_i(inode)->i_dentry);
4981 +       if (!dentry)
4982 +               BUG();
4983 +
4984 +       return dentry;
4985 +}
4986 +
4987 +struct dentry *
4988 +get_subfs_dentry(struct dentry *dentry)
4989 +{
4990 +       struct dentry *subdent;
4991 +
4992 +       BUG_ON(!dentry);
4993 +       BUG_ON(dentry->d_inode && !is_dentry_supermounted(dentry));
4994 +
4995 +       if (dentry->d_inode && !is_inode_obsolete(dentry->d_inode))
4996 +               subdent = get_subfs_dentry_by_inode(dentry->d_inode);
4997 +       else
4998 +               subdent = __get_subfs_dentry(dentry);
4999 +
5000 +       return subdent;
5001 +}
5002 diff -Naurp linux-2.4.20-ck4/fs/udf/super.c linux-2.4.20-ck5/fs/udf/super.c
5003 --- linux-2.4.20-ck4/fs/udf/super.c     2002-08-03 13:14:59.000000000 +1000
5004 +++ linux-2.4.20-ck5/fs/udf/super.c     2003-04-08 10:52:51.000000000 +1000
5005 @@ -268,6 +268,11 @@ udf_parse_options(char *options, struct 
5006                         uopt->nls_map = load_nls(val);
5007                         uopt->flags |= (1 << UDF_FLAG_NLS_MAP);
5008                 }
5009 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
5010 +               /* Silently ignore NLS option */
5011 +               else if (!strcmp (opt, "codepage"))
5012 +                       /* Don't do anything ;-) */ ;
5013 +#endif
5014  #endif
5015                 else if (!strcmp(opt, "utf8") && !val)
5016                         uopt->flags |= (1 << UDF_FLAG_UTF8);
5017 diff -Naurp linux-2.4.20-ck4/include/linux/cdrom.h linux-2.4.20-ck5/include/linux/cdrom.h
5018 --- linux-2.4.20-ck4/include/linux/cdrom.h      2001-11-23 06:47:04.000000000 +1100
5019 +++ linux-2.4.20-ck5/include/linux/cdrom.h      2003-04-08 10:52:51.000000000 +1000
5020 @@ -781,6 +781,7 @@ extern int cdrom_open(struct inode *, st
5021  extern int cdrom_release(struct inode *, struct file *);
5022  extern int cdrom_ioctl(struct inode *, struct file *, unsigned, unsigned long);
5023  extern int cdrom_media_changed(kdev_t);
5024 +extern int cdrom_mediactl (kdev_t dev, int op, int optarg);
5025  
5026  extern int register_cdrom(struct cdrom_device_info *cdi);
5027  extern int unregister_cdrom(struct cdrom_device_info *cdi);
5028 diff -Naurp linux-2.4.20-ck4/include/linux/fs.h linux-2.4.20-ck5/include/linux/fs.h
5029 --- linux/include/linux/fs.h.orig       Mon Apr 14 09:03:15 2003
5030 +++ linux/include/linux/fs.h    Sat Apr 19 11:11:59 2003
5031 @@ -112,6 +112,7 @@
5032  #define MS_REC         16384
5033  #define MS_VERBOSE     32768
5034  #define MS_POSIXACL    65536   /* VFS does not apply the umask */
5035 +#define MS_SUPERMOUNTED (1<<17)
5036  #define MS_ACTIVE      (1<<30)
5037  #define MS_NOUSER      (1<<31)
5038  
5039 @@ -296,6 +297,7 @@
5040  
5041  
5042  #include <linux/pipe_fs_i.h>
5043 +#include <linux/supermount_fs_i.h>
5044  #include <linux/minix_fs_i.h>
5045  #include <linux/ext2_fs_i.h>
5046  #include <linux/ext3_fs_i.h>
5047 @@ -519,6 +521,7 @@
5048                 struct usbdev_inode_info        usbdev_i;
5049                 struct jffs2_inode_info         jffs2_i;
5050                 struct squashfs_inode_info      squashfs_i;
5051 +               struct supermount_inode_info    supermount_i;
5052                 void                            *generic_ip;
5053         } u;
5054  };
5055 @@ -811,6 +814,9 @@
5056          * non-directories) are allowed, but not unconnected diretories.
5057          */
5058         struct semaphore s_nfsd_free_path_sem;
5059 +#if defined(CONFIG_SUPERMOUNT) || defined(CONFIG_SUPERMOUNT_MODULE)
5060 +       int s_media_changed;
5061 +#endif
5062  };
5063  
5064  /*
5065 @@ -825,6 +831,23 @@
5066  extern int vfs_unlink(struct inode *, struct dentry *);
5067  extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
5068  
5069 +struct kstat {
5070 +       ino_t           ino;
5071 +       atomic_t        count;
5072 +       dev_t           dev;
5073 +       umode_t         mode;
5074 +       nlink_t         nlink;
5075 +       uid_t           uid;
5076 +       gid_t           gid;
5077 +       dev_t           rdev;
5078 +       loff_t          size;
5079 +       time_t          atime;
5080 +       time_t          mtime;
5081 +       time_t          ctime;
5082 +       unsigned long   blksize;
5083 +       unsigned long   blocks;
5084 +};
5085 +
5086  /*
5087   * File types
5088   */
5089 @@ -853,6 +876,16 @@
5090         int (*check_media_change) (kdev_t);
5091         int (*revalidate) (kdev_t);
5092         struct module *owner;
5093 +       int (*mediactl) (kdev_t dev, int op, int optarg);
5094 +};
5095 +
5096 +/*
5097 + * These are the "op" operation codes for mediactl() media control
5098 + * calls for device special files 
5099 + */
5100 +enum {
5101 +       MEDIA_LOCK = 1234,      /* Lock the drive door */
5102 +       MEDIA_UNLOCK            /* Unlock the drive door */
5103  };
5104  
5105  /*
5106 @@ -898,7 +931,7 @@
5107         int (*permission) (struct inode *, int);
5108         int (*revalidate) (struct dentry *);
5109         int (*setattr) (struct dentry *, struct iattr *);
5110 -       int (*getattr) (struct dentry *, struct iattr *);
5111 +       int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
5112         int (*setxattr) (struct dentry *, const char *, const void *, size_t, int);
5113         ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
5114         ssize_t (*listxattr) (struct dentry *, char *, size_t);
5115 @@ -1030,6 +1063,8 @@
5116  extern struct vfsmount *kern_mount(struct file_system_type *);
5117  extern int may_umount(struct vfsmount *);
5118  extern long do_mount(char *, char *, char *, unsigned long, void *);
5119 +extern struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
5120 +extern int do_remount_sb(struct super_block *sb, int flags, void * data);
5121  
5122  #define kern_umount mntput
5123  
5124 @@ -1254,8 +1289,11 @@
5125  extern void set_buffer_flushtime(struct buffer_head *);
5126  extern void balance_dirty(void);
5127  extern int check_disk_change(kdev_t);
5128 +extern int query_disk_change(kdev_t dev);
5129 +extern void invalidate_media(kdev_t dev);
5130  extern int invalidate_inodes(struct super_block *);
5131  extern int invalidate_device(kdev_t, int);
5132 +extern int destroy_device(kdev_t);
5133  extern void invalidate_inode_pages(struct inode *);
5134  extern void invalidate_inode_pages2(struct address_space *);
5135  extern void invalidate_inode_buffers(struct inode *);
5136 @@ -1516,12 +1554,14 @@
5137  extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t);
5138  extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
5139  extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin);
5140 +extern loff_t vfs_llseek(struct file *file, loff_t loffset, int origin);
5141  extern ssize_t generic_read_dir(struct file *, char *, size_t, loff_t *);
5142  extern int generic_file_open(struct inode * inode, struct file * filp);
5143  
5144  extern struct file_operations generic_ro_fops;
5145  
5146  extern int vfs_readlink(struct dentry *, char *, int, const char *);
5147 +extern int vfs_readlink_real(struct dentry *, char *, int);
5148  extern int vfs_follow_link(struct nameidata *, const char *);
5149  extern int page_readlink(struct dentry *, char *, int);
5150  extern int page_follow_link(struct dentry *, struct nameidata *);
5151 @@ -1535,6 +1575,13 @@
5152  extern int dcache_readdir(struct file *, void *, filldir_t);
5153  extern struct file_operations dcache_dir_ops;
5154  
5155 +int getattr_full(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
5156 +int getattr_minix(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
5157 +
5158 +extern int vfs_stat(char *, struct kstat *);
5159 +extern int vfs_lstat(char *, struct kstat *);
5160 +extern int vfs_fstat(int, struct kstat *);
5161 +
5162  extern struct file_system_type *get_fs_type(const char *name);
5163  extern struct super_block *get_super(kdev_t);
5164  extern void drop_super(struct super_block *sb);
5165 diff -Naurp linux-2.4.20-ck4/include/linux/ide.h linux-2.4.20-ck5/include/linux/ide.h
5166 --- linux-2.4.20-ck4/include/linux/ide.h        2002-11-30 17:02:23.000000000 +1100
5167 +++ linux-2.4.20-ck5/include/linux/ide.h        2003-04-08 10:52:51.000000000 +1000
5168 @@ -726,6 +726,7 @@ typedef struct ide_driver_s {
5169         ide_special_proc                *special;
5170         ide_proc_entry_t                *proc;
5171         ide_reinit_proc                 *reinit;
5172 +       int             (*mediactl)(ide_drive_t *, int, int);
5173         ata_prebuilder_proc             *ata_prebuilder;
5174         atapi_prebuilder_proc           *atapi_prebuilder;
5175  } ide_driver_t;
5176 @@ -1062,6 +1063,7 @@ int idedisk_init (void);
5177  #ifdef CONFIG_BLK_DEV_IDECD
5178  int ide_cdrom_reinit (ide_drive_t *drive);
5179  int ide_cdrom_init (void);
5180 +int ide_cdrom_mediactl (ide_drive_t *, int, int);
5181  #endif /* CONFIG_BLK_DEV_IDECD */
5182  #ifdef CONFIG_BLK_DEV_IDETAPE
5183  int idetape_reinit (ide_drive_t *drive);
5184 diff -Naurp linux-2.4.20-ck4/include/linux/supermount_fs_i.h linux-2.4.20-ck5/include/linux/supermount_fs_i.h
5185 --- linux-2.4.20-ck4/include/linux/supermount_fs_i.h    1970-01-01 10:00:00.000000000 +1000
5186 +++ linux-2.4.20-ck5/include/linux/supermount_fs_i.h    2003-04-08 10:52:51.000000000 +1000
5187 @@ -0,0 +1,10 @@
5188 +#ifndef _LINUX_SUPERMOUNT_FS_I_H
5189 +#define _LINUX_SUPERMOUNT_FS_I_H
5190 +
5191 +struct supermount_inode_info {
5192 +       int             i_sb_version;
5193 +       struct dentry * i_dentry;
5194 +       struct list_head i_fs;
5195 +};
5196 +
5197 +#endif
5198 diff -Naurp linux-2.4.20-ck4/kernel/ksyms.c linux-2.4.20-ck5/kernel/ksyms.c
5199 --- linux-2.4.20-ck4/kernel/ksyms.c     2003-04-08 10:50:37.000000000 +1000
5200 +++ linux-2.4.20-ck5/kernel/ksyms.c     2003-04-08 10:52:51.000000000 +1000
5201 @@ -177,10 +177,13 @@ EXPORT_SYMBOL(filp_close);
5202  EXPORT_SYMBOL(put_filp);
5203  EXPORT_SYMBOL(files_lock);
5204  EXPORT_SYMBOL(check_disk_change);
5205 +EXPORT_SYMBOL(query_disk_change);
5206 +EXPORT_SYMBOL(invalidate_media);
5207  EXPORT_SYMBOL(__invalidate_buffers);
5208  EXPORT_SYMBOL(invalidate_bdev);
5209  EXPORT_SYMBOL(invalidate_inodes);
5210  EXPORT_SYMBOL(invalidate_device);
5211 +EXPORT_SYMBOL(destroy_device);
5212  EXPORT_SYMBOL(invalidate_inode_pages);
5213  EXPORT_SYMBOL(truncate_inode_pages);
5214  EXPORT_SYMBOL(fsync_dev);
5215 @@ -254,9 +257,12 @@ EXPORT_SYMBOL(vfs_rmdir);
5216  EXPORT_SYMBOL(vfs_unlink);
5217  EXPORT_SYMBOL(vfs_rename);
5218  EXPORT_SYMBOL(vfs_statfs);
5219 +EXPORT_SYMBOL(getattr_full);
5220 +EXPORT_SYMBOL(getattr_minix);
5221  EXPORT_SYMBOL(generic_read_dir);
5222  EXPORT_SYMBOL(generic_file_llseek);
5223  EXPORT_SYMBOL(no_llseek);
5224 +EXPORT_SYMBOL(vfs_llseek);
5225  EXPORT_SYMBOL(__pollwait);
5226  EXPORT_SYMBOL(poll_freewait);
5227  EXPORT_SYMBOL(ROOT_DEV);
5228 @@ -267,6 +273,7 @@ EXPORT_SYMBOL(grab_cache_page_nowait);
5229  EXPORT_SYMBOL(read_cache_page);
5230  EXPORT_SYMBOL(set_page_dirty);
5231  EXPORT_SYMBOL(vfs_readlink);
5232 +EXPORT_SYMBOL(vfs_readlink_real);
5233  EXPORT_SYMBOL(vfs_follow_link);
5234  EXPORT_SYMBOL(page_readlink);
5235  EXPORT_SYMBOL(page_follow_link);
5236 @@ -300,6 +307,7 @@ EXPORT_SYMBOL(register_chrdev);
5237  EXPORT_SYMBOL(unregister_chrdev);
5238  EXPORT_SYMBOL(register_blkdev);
5239  EXPORT_SYMBOL(unregister_blkdev);
5240 +EXPORT_SYMBOL(get_blkfops);
5241  EXPORT_SYMBOL(tty_register_driver);
5242  EXPORT_SYMBOL(tty_unregister_driver);
5243  EXPORT_SYMBOL(tty_std_termios);
5244 @@ -341,6 +349,8 @@ EXPORT_SYMBOL(unregister_filesystem);
5245  EXPORT_SYMBOL(kern_mount);
5246  EXPORT_SYMBOL(__mntput);
5247  EXPORT_SYMBOL(may_umount);
5248 +EXPORT_SYMBOL(do_kern_mount);
5249 +EXPORT_SYMBOL(do_remount_sb);
5250  
5251  /* executable format registration */
5252  EXPORT_SYMBOL(register_binfmt);
This page took 0.949215 seconds and 3 git commands to generate.