patch-2.1.44 linux/fs/super.c
Next file: linux/include/asm-alpha/ioctls.h
Previous file: linux/fs/stat.c
Back to the patch index
Back to the overall index
- Lines: 282
- Date:
Sun Jul 6 20:13:54 1997
- Orig file:
v2.1.43/linux/fs/super.c
- Orig date:
Mon Jun 16 16:35:59 1997
diff -u --recursive --new-file v2.1.43/linux/fs/super.c linux/fs/super.c
@@ -465,7 +465,7 @@
}
if (!(sb = get_super(dev)))
return;
- if (sb->s_covered) {
+ if (sb->s_root != sb->s_root->d_mounts) {
printk("VFS: Mounted device %s - tssk, tssk\n",
kdevname(dev));
return;
@@ -535,7 +535,6 @@
return NULL;
}
s->s_dev = dev;
- s->s_covered = NULL;
s->s_rd_only = 0;
s->s_dirt = 0;
s->s_type = type;
@@ -570,6 +569,30 @@
kdevname(dev));
}
+static void d_umount(struct dentry *dentry)
+{
+ struct dentry * covers = dentry->d_covers;
+
+ if (covers == dentry) {
+ printk("VFS: unmount - covers == dentry?\n");
+ return;
+ }
+ covers->d_mounts = covers;
+ dentry->d_covers = dentry;
+ dput(covers);
+ dput(dentry);
+}
+
+static void d_mount(struct dentry *covers, struct dentry *dentry)
+{
+ if (covers->d_mounts != covers) {
+ printk("VFS: mount - already mounted\n");
+ return;
+ }
+ covers->d_mounts = dentry;
+ dentry->d_covers = covers;
+}
+
static int do_umount(kdev_t dev,int unmount_root)
{
struct super_block * sb;
@@ -597,28 +620,26 @@
}
return 0;
}
- if (!(sb=get_super(dev)) || !(sb->s_covered))
+ sb=get_super(dev);
+ if (!sb)
return -ENOENT;
- 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
* too bad there are no quotas running anymore. Turn them on again by hand.
*/
quota_off(dev, -1);
- if (!fs_may_umount(dev, sb->s_mounted))
+ if (!fs_may_umount(dev, sb->s_root))
return -EBUSY;
- sb->s_covered->i_mount = NULL;
- iput(sb->s_covered);
- sb->s_covered = NULL;
- iput(sb->s_mounted);
- sb->s_mounted = NULL;
+
+ /* Clear up the dcache tree. This should be cleaner.. */
+ if (sb->s_root) {
+ d_umount(sb->s_root);
+ d_delete(sb->s_root);
+ }
+
+ sb->s_root = NULL;
if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
sb->s_op->write_super(sb);
put_super(dev);
@@ -647,12 +668,7 @@
lock_kernel();
if (!suser())
goto out;
- retval = namei(NAM_FOLLOW_LINK, name, &inode);
- if (retval) {
- retval = namei(NAM_FOLLOW_TRAILSLASH, name, &inode);
- if (retval)
- goto out;
- }
+ retval = namei(name, &inode);
if (S_ISBLK(inode->i_mode)) {
dev = inode->i_rdev;
retval = -EACCES;
@@ -662,7 +678,7 @@
}
} else {
retval = -EINVAL;
- if (!inode->i_sb || inode != inode->i_sb->s_mounted) {
+ if (!inode->i_sb || inode != inode->i_sb->s_root->d_inode) {
iput(inode);
goto out;
}
@@ -715,45 +731,44 @@
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 = NULL;
+ struct dentry * dir_d = 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;*/
- if(override)
- dir_name++;
- error = namei(NAM_FOLLOW_LINK, dir_name, &dir_i);
- if (error)
+
+ dir_d = lookup_dentry(dir_name, NULL, 1);
+ error = PTR_ERR(dir_d);
+ if (IS_ERR(dir_d))
return error;
- if (!override && (atomic_read(&dir_i->i_count) != 1 || dir_i->i_mount)) {
- iput(dir_i);
+
+ if (dir_d->d_flag & D_NEGATIVE) {
+ dput(dir_d);
+ return -ENOENT;
+ }
+
+ if (dir_d->d_covers != dir_d) {
+ dput(dir_d);
return -EBUSY;
}
- if (!S_ISDIR(dir_i->i_mode)) {
- iput(dir_i);
+ if (!S_ISDIR(dir_d->d_inode->i_mode)) {
+ dput(dir_d);
return -ENOTDIR;
}
- if (!fs_may_mount(dev) && !override) {
- iput(dir_i);
+ if (!fs_may_mount(dev)) {
+ dput(dir_d);
return -EBUSY;
}
sb = read_super(dev,type,flags,data,0);
if (!sb) {
- iput(dir_i);
+ dput(dir_d);
return -EINVAL;
}
- if (sb->s_covered) {
- iput(dir_i);
+ if (sb->s_root->d_covers != sb->s_root) {
+ dput(dir_d);
return -EBUSY;
}
vfsmnt = add_vfsmnt(dev, dev_name, dir_name);
@@ -761,25 +776,8 @@
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 */
+ d_mount(dir_d, sb->s_root);
+ return 0; /* we don't dput(dir) - see umount */
}
@@ -820,10 +818,10 @@
struct inode *dir_i;
int retval;
- retval = namei(NAM_FOLLOW_LINK, dir, &dir_i);
+ retval = namei(dir, &dir_i);
if (retval)
return retval;
- if (dir_i != dir_i->i_sb->s_mounted) {
+ if (dir_i != dir_i->i_sb->s_root->d_inode) {
iput(dir_i);
return -EINVAL;
}
@@ -912,7 +910,7 @@
t = fstype->name;
fops = NULL;
if ((fstype->fs_flags & FS_REQUIRES_DEV)) {
- retval = namei(NAM_FOLLOW_LINK, dev_name, &inode);
+ retval = namei(dev_name, &inode);
if (retval)
goto out;
retval = -ENOTBLK;
@@ -982,7 +980,7 @@
struct file_system_type * fs_type;
struct super_block * sb;
struct vfsmount *vfsmnt;
- struct inode * inode, * d_inode = NULL;
+ struct inode * d_inode = NULL;
struct file filp;
int retval;
@@ -1001,15 +999,11 @@
sb->s_dev = get_unnamed_dev();
sb->s_flags = root_mountflags & ~MS_RDONLY;
if (nfs_root_mount(sb) >= 0) {
- inode = sb->s_mounted;
- 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);
+ current->fs->root = dget(sb->s_root);
+ current->fs->pwd = dget(sb->s_root);
ROOT_DEV = sb->s_dev;
printk (KERN_NOTICE "VFS: Mounted root (nfs filesystem).\n");
vfsmnt = add_vfsmnt(ROOT_DEV, "/dev/root", "/");
@@ -1066,15 +1060,9 @@
continue;
sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
if (sb) {
- inode = sb->s_mounted;
-
- /* 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);
+ current->fs->root = dget(sb->s_root);
+ current->fs->pwd = dget(sb->s_root);
printk ("VFS: Mounted root (%s filesystem)%s.\n",
fs_type->name,
(sb->s_flags & MS_RDONLY) ? " readonly" : "");
@@ -1121,7 +1109,7 @@
do_mount_root();
old_fs = get_fs();
set_fs(get_ds());
- error = namei(NAM_FOLLOW_LINK, put_old, &inode);
+ error = namei(put_old, &inode);
if (error) inode = NULL;
set_fs(old_fs);
if (!error && (atomic_read(&inode->i_count) != 1 || inode->i_mount))
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov