patch-2.1.43 linux/fs/super.c
Next file: linux/fs/sysv/dir.c
Previous file: linux/fs/stat.c
Back to the patch index
Back to the overall index
- Lines: 277
- Date:
Thu Jun 12 16:22:09 1997
- Orig file:
v2.1.42/linux/fs/super.c
- Orig date:
Thu May 29 21:53:08 1997
diff -u --recursive --new-file v2.1.42/linux/fs/super.c linux/fs/super.c
@@ -33,6 +33,7 @@
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/fd.h>
+#include <linux/dalloc.h>
#include <linux/init.h>
#include <asm/system.h>
@@ -59,8 +60,8 @@
struct super_block super_blocks[NR_SUPER];
static struct file_system_type *file_systems = (struct file_system_type *) NULL;
-static struct vfsmount *vfsmntlist = (struct vfsmount *) NULL,
- *vfsmnttail = (struct vfsmount *) NULL,
+struct vfsmount *vfsmntlist = (struct vfsmount *) NULL;
+static struct vfsmount *vfsmnttail = (struct vfsmount *) NULL,
*mru_vfsmnt = (struct vfsmount *) NULL;
/*
@@ -376,7 +377,7 @@
tmp = file_systems;
while (tmp && len < PAGE_SIZE - 80) {
len += sprintf(buf+len, "%s\t%s\n",
- tmp->requires_dev ? "" : "nodev",
+ (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
tmp->name);
tmp = tmp->next;
}
@@ -435,7 +436,7 @@
}
}
-static struct super_block * get_super(kdev_t dev)
+struct super_block * get_super(kdev_t dev)
{
struct super_block * s;
@@ -601,6 +602,10 @@
if (!sb->s_covered->i_mount)
printk("VFS: umount(%s): mounted inode has i_mount=NULL\n",
kdevname(dev));
+ while(sb->s_ibasket)
+ free_ibasket(sb);
+ if(sb->s_mounted->i_dentry)
+ d_del(sb->s_mounted->i_dentry, D_NO_CLEAR_INODE);
/*
* Before checking if the filesystem is still busy make sure the kernel
* doesn't hold any quotafiles open on that device. If the umount fails
@@ -636,15 +641,15 @@
{
struct inode * inode;
kdev_t dev;
+ struct inode * dummy_inode = NULL;
int retval = -EPERM;
- struct inode dummy_inode;
lock_kernel();
if (!suser())
goto out;
- retval = namei(name, &inode);
+ retval = namei(NAM_FOLLOW_LINK, name, &inode);
if (retval) {
- retval = lnamei(name, &inode);
+ retval = namei(NAM_FOLLOW_TRAILSLASH, name, &inode);
if (retval)
goto out;
}
@@ -663,9 +668,8 @@
}
dev = inode->i_sb->s_dev;
iput(inode);
- memset(&dummy_inode, 0, sizeof(dummy_inode));
- dummy_inode.i_rdev = dev;
- inode = &dummy_inode;
+ inode = dummy_inode = get_empty_inode();
+ inode->i_rdev = dev;
}
retval = -ENXIO;
if (MAJOR(dev) >= MAX_BLKDEV) {
@@ -680,8 +684,7 @@
put_unnamed_dev(dev);
}
}
- if (inode != &dummy_inode)
- iput(inode);
+ iput(inode);
if (!retval)
fsync_dev(dev);
out:
@@ -697,22 +700,42 @@
* We cannot mount a filesystem if it has active, used, or dirty inodes.
* We also have to flush all inode-data for this device, as the new mount
* might need new info.
+ *
+ * [21-Mar-97] T.Schoebel-Theuer: Now this can be overridden when
+ * supplying a leading "!" before the dir_name, allowing "stacks" of
+ * mounted filesystems. The stacking will only influence any pathname lookups
+ * _after_ the mount, but open filedescriptors or working directories that
+ * are now covered remain valid. For example, when you overmount /home, any
+ * process with old cwd /home/joe will continue to use the old versions,
+ * as long as relative paths are used, but absolute paths like /home/joe/xxx
+ * will go to the new "top of stack" version. In general, crossing a
+ * mountpoint will always go to the top of stack element.
+ * Anyone using this new feature must know what he/she is doing.
*/
int do_mount(kdev_t dev, const char * dev_name, const char * dir_name, const char * type, int flags, void * data)
{
- struct inode * dir_i;
+ struct inode * dir_i = NULL;
struct super_block * sb;
struct vfsmount *vfsmnt;
int error;
+ int override = 0;
+ if(dir_name) {
+ char c;
+
+ get_user(c, dir_name);
+ override = (c == '!');
+ }
if (!(flags & MS_RDONLY) && dev && is_read_only(dev))
return -EACCES;
/*flags |= MS_RDONLY;*/
- error = namei(dir_name, &dir_i);
+ if(override)
+ dir_name++;
+ error = namei(NAM_FOLLOW_LINK, dir_name, &dir_i);
if (error)
return error;
- if (dir_i->i_count != 1 || dir_i->i_mount) {
+ if (!override && (atomic_read(&dir_i->i_count) != 1 || dir_i->i_mount)) {
iput(dir_i);
return -EBUSY;
}
@@ -720,7 +743,7 @@
iput(dir_i);
return -ENOTDIR;
}
- if (!fs_may_mount(dev)) {
+ if (!fs_may_mount(dev) && !override) {
iput(dir_i);
return -EBUSY;
}
@@ -738,6 +761,22 @@
vfsmnt->mnt_sb = sb;
vfsmnt->mnt_flags = flags;
}
+ {
+ struct dentry * old = dir_i->i_dentry;
+ struct dentry * new;
+ vfs_lock();
+ new = d_alloc(old->d_parent, old->d_len, 1);
+ if(new) {
+ struct qstr copy = { old->d_name, old->d_len };
+ d_add(new, sb->s_mounted, ©, D_DUPLICATE);
+ vfs_unlock();
+ } else {
+ printk("VFS: cannot setup dentry for mount\n");
+ iput(dir_i);
+ return -ENOMEM;
+ }
+ vfs_unlock();
+ }
sb->s_covered = dir_i;
dir_i->i_mount = sb->s_mounted;
return 0; /* we don't iput(dir_i) - see umount */
@@ -781,7 +820,7 @@
struct inode *dir_i;
int retval;
- retval = namei(dir, &dir_i);
+ retval = namei(NAM_FOLLOW_LINK, dir, &dir_i);
if (retval)
return retval;
if (dir_i != dir_i->i_sb->s_mounted) {
@@ -872,8 +911,8 @@
goto out;
t = fstype->name;
fops = NULL;
- if (fstype->requires_dev) {
- retval = namei(dev_name, &inode);
+ if ((fstype->fs_flags & FS_REQUIRES_DEV)) {
+ retval = namei(NAM_FOLLOW_LINK, dev_name, &inode);
if (retval)
goto out;
retval = -ENOTBLK;
@@ -943,7 +982,7 @@
struct file_system_type * fs_type;
struct super_block * sb;
struct vfsmount *vfsmnt;
- struct inode * inode, d_inode;
+ struct inode * inode, * d_inode = NULL;
struct file filp;
int retval;
@@ -963,13 +1002,14 @@
sb->s_flags = root_mountflags & ~MS_RDONLY;
if (nfs_root_mount(sb) >= 0) {
inode = sb->s_mounted;
- inode->i_count += 3 ;
+ atomic_add(3, &inode->i_count);
sb->s_covered = inode;
sb->s_rd_only = 0;
sb->s_dirt = 0;
sb->s_type = fs_type;
current->fs->pwd = inode;
current->fs->root = inode;
+ (void)d_alloc_root(inode);
ROOT_DEV = sb->s_dev;
printk (KERN_NOTICE "VFS: Mounted root (nfs filesystem).\n");
vfsmnt = add_vfsmnt(ROOT_DEV, "/dev/root", "/");
@@ -1000,19 +1040,20 @@
#endif
memset(&filp, 0, sizeof(filp));
- memset(&d_inode, 0, sizeof(d_inode));
- d_inode.i_rdev = ROOT_DEV;
- filp.f_inode = &d_inode;
+ d_inode = get_empty_inode();
+ d_inode->i_rdev = ROOT_DEV;
+ filp.f_inode = d_inode;
if ( root_mountflags & MS_RDONLY)
filp.f_mode = 1; /* read only */
else
filp.f_mode = 3; /* read write */
- retval = blkdev_open(&d_inode, &filp);
+ retval = blkdev_open(d_inode, &filp);
if (retval == -EROFS) {
root_mountflags |= MS_RDONLY;
filp.f_mode = 1;
- retval = blkdev_open(&d_inode, &filp);
+ retval = blkdev_open(d_inode, &filp);
}
+ iput(d_inode);
if (retval)
/*
* Allow the user to distinguish between failed open
@@ -1021,16 +1062,19 @@
printk("VFS: Cannot open root device %s\n",
kdevname(ROOT_DEV));
else for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
- if (!fs_type->requires_dev)
+ if (!(fs_type->fs_flags & FS_REQUIRES_DEV))
continue;
sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
if (sb) {
inode = sb->s_mounted;
- inode->i_count += 3 ; /* NOTE! it is logically used 4 times, not 1 */
+
+ /* NOTE! it is logically used 4 times, not 1 */
+ atomic_add(3, &inode->i_count);
sb->s_covered = inode;
sb->s_flags = root_mountflags;
current->fs->pwd = inode;
current->fs->root = inode;
+ (void)d_alloc_root(inode);
printk ("VFS: Mounted root (%s filesystem)%s.\n",
fs_type->name,
(sb->s_flags & MS_RDONLY) ? " readonly" : "");
@@ -1077,11 +1121,13 @@
do_mount_root();
old_fs = get_fs();
set_fs(get_ds());
- error = namei(put_old,&inode);
+ error = namei(NAM_FOLLOW_LINK, put_old, &inode);
if (error) inode = NULL;
set_fs(old_fs);
- if (!error && (inode->i_count != 1 || inode->i_mount)) error = -EBUSY;
- if (!error && !S_ISDIR(inode->i_mode)) error = -ENOTDIR;
+ if (!error && (atomic_read(&inode->i_count) != 1 || inode->i_mount))
+ error = -EBUSY;
+ if (!error && !S_ISDIR(inode->i_mode))
+ error = -ENOTDIR;
iput(old_root); /* current->fs->root */
iput(old_pwd); /* current->fs->pwd */
if (error) {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov