ANNOUNCE: rebootless installs via new patch
Hi all, I am almost finished with the boot-floppies support for this.
Basically this all ends up allowing for rebootless installs.
I'de like to see this in the main kernel-source package so each arch wont
have to incorporate it seperately.
Once I have dbootstrap and busybox's init handling this properly, I will
commit the changes.
Thanks,
Ben
--
-----------=======-=-======-=========-----------=====------------=-=------
/ Ben Collins -- ...on that fantastic voyage... -- Debian GNU/Linux \
` bcollins@debian.org -- bcollins@openldap.org -- bmc@visi.net '
`---=========------=======-------------=-=-----=-===-======-------=--=---'
--- kernel-source-2.2.14.old/fs/dcache.c Tue Jan 4 18:59:27 2000
+++ kernel-source-2.2.14/fs/dcache.c Sun Jan 16 12:50:12 2000
@@ -327,7 +327,7 @@
* child dentries were freed. This allows a non-destructive
* test for unmounting a device.
*/
-int is_root_busy(struct dentry *root)
+int __is_root_busy(struct dentry *root,int ignore_mount_points)
{
struct dentry *this_parent = root;
struct list_head *next;
@@ -339,15 +339,20 @@
while (next != &this_parent->d_subdirs) {
struct list_head *tmp = next;
struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
+ int effective_count;
next = tmp->next;
+ /* Mount points may not count */
+ effective_count = dentry->d_count;
+ if (ignore_mount_points && dentry->d_mounts != dentry)
+ effective_count--;
/* Decrement count for unused children */
- count += (dentry->d_count - 1);
+ count += (effective_count - 1);
if (!list_empty(&dentry->d_subdirs)) {
this_parent = dentry;
goto repeat;
}
/* root is busy if any leaf is busy */
- if (dentry->d_count)
+ if (effective_count)
return 1;
}
/*
@@ -359,6 +364,11 @@
goto resume;
}
return (count > 1); /* remaining users? */
+}
+
+int is_root_busy(struct dentry *root)
+{
+ return __is_root_busy(root,0);
}
/*
--- kernel-source-2.2.14.old/fs/super.c Tue Jan 4 18:59:52 2000
+++ kernel-source-2.2.14/fs/super.c Sun Jan 16 12:50:12 2000
@@ -316,11 +316,15 @@
struct proc_nfs_info *nfs_infop;
struct nfs_server *nfss;
int len = 0;
+ char *path,*buffer = (char *) __get_free_page(GFP_KERNEL);
+ if (!buffer) return 0;
while ( tmp && len < PAGE_SIZE - 160)
{
+ path = d_path(tmp->mnt_sb->s_root,buffer,PAGE_SIZE);
len += sprintf( buf + len, "%s %s %s %s",
- tmp->mnt_devname, tmp->mnt_dirname, tmp->mnt_sb->s_type->name,
+ tmp->mnt_devname, path,
+ tmp->mnt_sb->s_type->name,
tmp->mnt_flags & MS_RDONLY ? "ro" : "rw" );
for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
if (tmp->mnt_flags & fs_infop->flag) {
@@ -377,6 +381,7 @@
tmp = tmp->mnt_next;
}
+ free_page((unsigned long) buffer);
return len;
}
@@ -476,6 +481,34 @@
return NULL;
}
+static void detach_mount_points(struct super_block *sb)
+{
+ struct super_block *s;
+
+ for (s = sb_entry(super_blocks.next); s != sb_entry(&super_blocks);
+ s = sb_entry(s->s_list.next)) {
+ struct dentry *root,*covered;
+
+ if (!s->s_dev || s == sb) continue;
+ root = s->s_root;
+ covered = root->d_covers;
+ if (covered->d_sb != sb) continue;
+ if (covered->d_inode->i_count != 1) {
+ printk(KERN_CRIT "detach_mount_points: inode %ld on %s "
+ "count %d (must be 1)\n",covered->d_inode->i_ino,
+ kdevname(sb->s_dev),covered->d_inode->i_count);
+ continue;
+ }
+ covered->d_mounts = covered; /* l'art pour l'art ... */
+ dput(covered);
+ root->d_covers = root;
+ printk(KERN_DEBUG "detached %s (count %d)",kdevname(s->s_dev),
+ root->d_count);
+ printk(" from %s (count %d)\n",kdevname(sb->s_dev),
+ sb->s_root->d_count);
+ }
+}
+
asmlinkage int sys_ustat(dev_t dev, struct ustat * ubuf)
{
struct super_block *s;
@@ -612,8 +645,15 @@
struct dentry * root = sb->s_root;
struct dentry * covered = root->d_covers;
- if (root->d_count != 1)
- return -EBUSY;
+ printk(KERN_DEBUG "d_umount: ref %d\n",root->d_count);
+ if (root->d_count != 1) {
+ if (__is_root_busy(sb->s_root,1)) return -EBUSY;
+ else {
+ detach_mount_points(sb);
+ shrink_dcache_sb(sb);
+ fsync_dev(sb->s_dev);
+ }
+ }
if (root->d_inode->i_state)
return -EBUSY;
@@ -680,7 +720,8 @@
shrink_dcache_sb(sb);
fsync_dev(dev);
- if (dev==ROOT_DEV && !unmount_root) {
+ printk(KERN_DEBUG "do_umount: ref %d\n",sb->s_root->d_count);
+ if (dev==ROOT_DEV && !unmount_root && __is_root_busy(sb->s_root,1)) {
/*
* Special case for "unmounting" root ...
* we just try to remount it readonly.
--- kernel-source-2.2.14.old/include/linux/dcache.h Tue Jan 4 18:59:53 2000
+++ kernel-source-2.2.14/include/linux/dcache.h Sun Jan 16 12:50:12 2000
@@ -150,6 +150,7 @@
/* test whether root is busy without destroying dcache */
extern int is_root_busy(struct dentry *);
+extern int __is_root_busy(struct dentry *,int ignore_mount_points);
/* test whether we have any submounts in a subdir tree */
extern int have_submounts(struct dentry *);
--- kernel-source-2.2.14.old/include/linux/sysctl.h Tue Jan 4 18:59:53 2000
+++ kernel-source-2.2.14/include/linux/sysctl.h Sun Jan 16 20:41:26 2000
@@ -106,6 +106,7 @@
KERN_SYSRQ=38, /* int: Sysreq enable */
KERN_SHMALL=41, /* int: maximum size of shared memory */
KERN_SPARC_STOP_A=44, /* int: Sparc Stop-A enable */
+ KERN_INITCHROOT=45, /* string: allows detecting chroot patch */
};
--- kernel-source-2.2.14.old/kernel/sysctl.c Tue Jan 4 18:59:54 2000
+++ kernel-source-2.2.14/kernel/sysctl.c Sun Jan 16 21:13:46 2000
@@ -87,6 +87,7 @@
static ctl_table debug_table[];
static ctl_table dev_table[];
+static char init_chroot[256];
/* /proc declarations: */
@@ -231,6 +232,8 @@
{KERN_SYSRQ, "sysrq", &sysrq_enabled, sizeof (int),
0644, NULL, &proc_dointvec},
#endif
+ {KERN_INITCHROOT, "init-chroot", &init_chroot, 256,
+ 0644, NULL, &proc_dostring, &sysctl_string},
{0}
};
@@ -294,6 +297,7 @@
void __init sysctl_init(void)
{
+ init_chroot[0] = '\0';
#ifdef CONFIG_PROC_FS
register_proc_table(root_table, &proc_sys_root);
#endif
Reply to: