Got it. Patch below seems to fix the problems with procfs - we used to
lose a reference to vfsmnt of /proc upon every follow_link() on
/proc/<pid>/fd/<n>, where n was an descriptor of pipe or socket. Fixed.
Linus, if you need incremental to previous patch - tell and I'll send it.
Patch below is against -pre7-1.
Cheers,
Al
diff -urN linux-2.3.99-pre7-1/drivers/block/loop.c linux-bird.vfs/drivers/block/loop.c
--- linux-2.3.99-pre7-1/drivers/block/loop.c Fri Mar 24 03:22:11 2000
+++ linux-bird.vfs/drivers/block/loop.c Sat Apr 29 18:41:56 2000
@@ -443,6 +443,7 @@
lo->lo_backing_file->f_flags = file->f_flags;
lo->lo_backing_file->f_owner = file->f_owner;
lo->lo_backing_file->f_dentry = file->f_dentry;
+ lo->lo_backing_file->f_vfsmnt = file->f_vfsmnt;
lo->lo_backing_file->f_op = file->f_op;
lo->lo_backing_file->private_data = file->private_data;
file_moveto(lo->lo_backing_file, file);
diff -urN linux-2.3.99-pre7-1/fs/autofs/autofs_i.h linux-bird.vfs/fs/autofs/autofs_i.h
--- linux-2.3.99-pre7-1/fs/autofs/autofs_i.h Wed Apr 26 21:01:00 2000
+++ linux-bird.vfs/fs/autofs/autofs_i.h Sat Apr 29 17:28:42 2000
@@ -132,7 +132,7 @@
/* Expiration-handling functions */
void autofs_update_usage(struct autofs_dirhash *,struct autofs_dir_ent *);
-struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info *);
+struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info *, struct vfsmount *mnt);
/* Operations structures */
diff -urN linux-2.3.99-pre7-1/fs/autofs/dirhash.c linux-bird.vfs/fs/autofs/dirhash.c
--- linux-2.3.99-pre7-1/fs/autofs/dirhash.c Sat Apr 29 17:11:00 2000
+++ linux-bird.vfs/fs/autofs/dirhash.c Sat Apr 29 17:13:08 2000
@@ -34,7 +34,8 @@
}
struct autofs_dir_ent *autofs_expire(struct super_block *sb,
- struct autofs_sb_info *sbi)
+ struct autofs_sb_info *sbi,
+ struct vfsmount *mnt)
{
struct autofs_dirhash *dh = &sbi->dirhash;
struct autofs_dir_ent *ent;
@@ -79,12 +80,25 @@
DPRINTK(("autofs: not expirable (not a mounted directory): %s\n", ent->name));
continue;
}
+ mntget(mnt);
+ dget(dentry);
+ if (!follow_down(&mnt, &dentry)) {
+ dput(dentry);
+ mntput(mnt);
+ DPRINTK(("autofs: not expirable (not a mounted directory): %s\n", ent->name));
+ continue;
+ }
+ while (d_mountpoint(dentry) && follow_down(&mnt, &dentry))
+ ;
+ dput(dentry);
- if ( may_umount(dentry->d_mounts->d_sb) == 0 ) {
+ if ( may_umount(mnt) == 0 ) {
+ mntput(mnt);
DPRINTK(("autofs: signaling expire on %s\n", ent->name));
return ent; /* Expirable! */
}
DPRINTK(("autofs: didn't expire due to may_umount: %s\n", ent->name));
+ mntput(mnt);
}
return NULL; /* No expirable entries */
}
diff -urN linux-2.3.99-pre7-1/fs/autofs/root.c linux-bird.vfs/fs/autofs/root.c
--- linux-2.3.99-pre7-1/fs/autofs/root.c Wed Apr 26 21:01:00 2000
+++ linux-bird.vfs/fs/autofs/root.c Sat Apr 29 17:13:08 2000
@@ -432,6 +432,7 @@
/* Perform an expiry operation */
static inline int autofs_expire_run(struct super_block *sb,
struct autofs_sb_info *sbi,
+ struct vfsmount *mnt,
struct autofs_packet_expire *pkt_p)
{
struct autofs_dir_ent *ent;
@@ -443,7 +444,7 @@
pkt.hdr.type = autofs_ptype_expire;
if ( !sbi->exp_timeout ||
- !(ent = autofs_expire(sb,sbi)) )
+ !(ent = autofs_expire(sb,sbi,mnt)) )
return -EAGAIN;
pkt.len = ent->len;
@@ -487,7 +488,7 @@
case AUTOFS_IOC_SETTIMEOUT:
return autofs_get_set_timeout(sbi,(unsigned long *)arg);
case AUTOFS_IOC_EXPIRE:
- return autofs_expire_run(inode->i_sb,sbi,
+ return autofs_expire_run(inode->i_sb, sbi, filp->f_vfsmnt,
(struct autofs_packet_expire *)arg);
default:
return -ENOSYS;
diff -urN linux-2.3.99-pre7-1/fs/nfsd/vfs.c linux-bird.vfs/fs/nfsd/vfs.c
--- linux-2.3.99-pre7-1/fs/nfsd/vfs.c Sat Apr 29 17:11:00 2000
+++ linux-bird.vfs/fs/nfsd/vfs.c Sat Apr 29 17:14:56 2000
@@ -141,7 +141,7 @@
} else {
dentry = lookup_one(name, dparent);
err = PTR_ERR(dentry);
- if (err)
+ if (IS_ERR(dentry))
goto out_nfserr;
/*
* check if we have crossed a mount point ...
diff -urN linux-2.3.99-pre7-1/fs/pipe.c linux-bird.vfs/fs/pipe.c
--- linux-2.3.99-pre7-1/fs/pipe.c Wed Apr 26 21:01:02 2000
+++ linux-bird.vfs/fs/pipe.c Sat Apr 29 18:40:10 2000
@@ -528,6 +528,8 @@
error = -ENOMEM;
f1->f_dentry = f2->f_dentry = dget(d_alloc_root(inode));
+ /* MOUNT_REWRITE: set to pipefs internal vfsmnt */
+ f1->f_vfsmnt = f2->f_vfsmnt = NULL;
if (!f1->f_dentry)
goto close_f12_inode_i_j;
diff -urN linux-2.3.99-pre7-1/fs/proc/base.c linux-bird.vfs/fs/proc/base.c
--- linux-2.3.99-pre7-1/fs/proc/base.c Wed Apr 26 21:01:02 2000
+++ linux-bird.vfs/fs/proc/base.c Sat Apr 29 19:21:31 2000
@@ -40,12 +40,18 @@
int proc_pid_cpu(struct task_struct*,char*);
/* MOUNT_REWRITE: make all files have non-NULL ->f_vfsmnt (pipefs, sockfs) */
+/* Until then... */
+#define NULL_VFSMNT /* remove as soon as pipefs and sockfs will be there */
+
static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
{
if (inode->u.proc_i.file) {
- if (inode->u.proc_i.file->f_vfsmnt) {
- *mnt = mntget(inode->u.proc_i.file->f_vfsmnt);
- }
+#ifdef NULL_VFSMNT
+ if (!inode->u.proc_i.file->f_vfsmnt)
+ mntget(*mnt);
+ else
+#endif
+ *mnt = mntget(inode->u.proc_i.file->f_vfsmnt);
*dentry = dget(inode->u.proc_i.file->f_dentry);
return 0;
}
@@ -174,7 +180,6 @@
static int proc_permission(struct inode *inode, int mask)
{
struct dentry *de, *base, *root;
- struct super_block *our_sb, *sb, *below;
struct vfsmount *our_vfsmnt, *vfsmnt, *mnt;
if (standard_permission(inode, mask) != 0)
@@ -187,14 +192,12 @@
de = root;
mnt = vfsmnt;
- our_sb = base->d_inode->i_sb;
- sb = de->d_inode->i_sb;
- while (sb != our_sb) {
- de = sb->s_root->d_covers;
- below = de->d_inode->i_sb;
- if (sb == below)
+
+ while (vfsmnt != our_vfsmnt) {
+ if (vfsmnt == vfsmnt->mnt_parent)
goto out;
- sb = below;
+ de = vfsmnt->mnt_mountpoint;
+ vfsmnt = vfsmnt->mnt_parent;
}
if (!is_subdir(de, base))
@@ -368,6 +371,9 @@
{
struct inode *inode = dentry->d_inode;
int error;
+#ifdef NULL_VFSMNT
+ struct vfsmount *dummy = mntget(nd->mnt);
+#endif
/* We don't need a base pointer in the /proc filesystem */
dput(nd->dentry);
@@ -379,6 +385,9 @@
error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt);
out:
+#ifdef NULL_VFSMNT
+ mntput(dummy);
+#endif
return error;
}
diff -urN linux-2.3.99-pre7-1/fs/super.c linux-bird.vfs/fs/super.c
--- linux-2.3.99-pre7-1/fs/super.c Sat Apr 29 17:11:00 2000
+++ linux-bird.vfs/fs/super.c Sat Apr 29 17:13:08 2000
@@ -872,16 +872,30 @@
* give false negatives. The main reason why it's here is that we need
* a non-destructive way to look for easily umountable filesystems.
*/
- /* MOUNT_REWRITE: it should take vfsmount, not superblock */
-int may_umount(struct super_block *sb)
+int may_umount(struct vfsmount *mnt)
{
+ struct super_block * sb = mnt->mnt_sb;
struct dentry * root;
int count;
+ if (atomic_read(&mnt->mnt_count) > 2)
+ return -EBUSY;
+
+ if (mnt->mnt_instances.next != mnt->mnt_instances.prev)
+ return 0;
+
+ /*
+ * OK, at that point we have only one instance. We should have
+ * one active reference from ->s_root, one active reference
+ * from ->mnt_root (which may be different) and possibly one
+ * active reference from ->mnt_mountpoint (if mnt->mnt_parent == mnt).
+ * Anything above that means that tree is busy.
+ */
+
root = sb->s_root;
count = d_active_refs(root);
- if (root->d_covers == root)
+ if (mnt->mnt_parent == mnt)
count--;
if (count != 2)
return -EBUSY;
diff -urN linux-2.3.99-pre7-1/include/linux/fs.h linux-bird.vfs/include/linux/fs.h
--- linux-2.3.99-pre7-1/include/linux/fs.h Sat Apr 29 17:11:00 2000
+++ linux-bird.vfs/include/linux/fs.h Sat Apr 29 17:22:32 2000
@@ -786,7 +786,7 @@
extern int register_filesystem(struct file_system_type *);
extern int unregister_filesystem(struct file_system_type *);
-extern int may_umount(struct super_block *);
+extern int may_umount(struct vfsmount *);
static inline int vfs_statfs(struct super_block *sb, struct statfs *buf)
{
diff -urN linux-2.3.99-pre7-1/net/socket.c linux-bird.vfs/net/socket.c
--- linux-2.3.99-pre7-1/net/socket.c Wed Apr 26 21:01:08 2000
+++ linux-bird.vfs/net/socket.c Sat Apr 29 18:41:28 2000
@@ -269,6 +269,8 @@
}
file->f_dentry = d_alloc_root(sock->inode);
+ /* MOUNT_REWRITE: set to sockfs internal vfsmnt */
+ file->f_vfsmnt = NULL;
if (!file->f_dentry) {
put_filp(file);
put_unused_fd(fd);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Sun Apr 30 2000 - 21:00:17 EST