]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-supermount.patch
- added description of djurban's branch
[packages/kernel.git] / kernel-supermount.patch
CommitLineData
f60c7f34 1diff -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
151diff -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
391diff -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;}
547diff -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 }
684diff -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;
965diff -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);
1133diff -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;
1364diff -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
1376diff -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+
1446diff -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 = {
1457diff -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);
1530diff -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 = {
1541diff -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. */
1552diff -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;
1563diff -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
1574diff -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 /*
1585diff -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);
1617diff -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 };
1647diff -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 /*
1693diff -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)
1704diff -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
1803diff -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
1815diff -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;
1832diff -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;
1853diff -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
1879diff -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
1890diff -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;
1902diff -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;
1932diff -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 */
2491diff -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);
2509diff -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+
2514diff -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+};
2572diff -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+};
2865diff -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);
2905diff -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+};
3802diff -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
3819diff -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+}
3863diff -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+}
4319diff -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 */
4538diff -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+};
4843diff -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+}
5002diff -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);
5017diff -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);
5028diff -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);
5165diff -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);
5184diff -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
5198diff -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 4.020355 seconds and 4 git commands to generate.