[PATCH] cloop: Add suspend feature
Hi,
the please find attached a patch, which implements the "suspend" feature.
It allows clean ejecting of the CD Knoppix is running on.
This enables the user to, for example, burn a CD, then put the Knoppix CD back in and continue using the whole CD.
Ok, enough easy speak lets get to the technical details. It works as follows:
# Make sure that everything you now need is cached by the kernel block layer
# It doesn't hurt it its not the case, as long as losetup, glibc and mount are available.
# Copy them to ram disk / unionfs?
cat /usr/bin/losetup /bin/mount /bin/ash >/dev/null
I think I had a minimal losetup assembly version somewhere for those purposes, but I don't remember ...
# /bin/ash # start a ash?
cloop_suspend /dev/cloop
umount /cdrom
# Put in other CD and do what you want to do
# Put in original CD again
mount /cdrom
# Resume cloop
losetup /dev/cloop /cdrom/KNOPPIX/KNOPPIX
# Now all blocked requests will be satisfied again and it all works again as before the suspend
If you do a:
cloop_suspend
cat /KNOPPIX/file_not_in_cache
the cat will simply sleep until the cloop is resumed.
I know that users already use this very carefully with umount -l, but that is a hacky solution, where data requested gets marked as 'bad blocks' while here it simply works again after resume.
There is just one small problem:
What if the Xserver or any other critical part blocks, because it is no longer in the kernel block cache ...
Well, I guess than you are really locked out unless we start a recovery console on tty1, which has all data copied to ram disk.
There should be always _some_ way out for the user.
Well that is a detail.
Ideas? Comments?
I still think the general functionality is useful.
cu
Fabian
--- compressed_loop.c.old 2007-02-02 03:41:36.000000000 +0100
+++ compressed_loop.c 2007-02-02 05:02:27.000000000 +0100
@@ -347,7 +347,7 @@
cloop = &cloop_dev[cloop_num];
#endif
- if (!cloop->backing_file)
+ if (!cloop->backing_file && !cloop->suspended)
{
DEBUGP("do_clo_request: not connected to a file\n");
goto out;
@@ -464,6 +464,10 @@
(unsigned)sizeof(struct cloop_head));
error=-EBADF; goto error_release;
}
+
+ /* In suspended mode, we have done all checks necessary - FF */
+ if (clo->suspended)
+ return error;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
if(isblkdev)
@@ -679,6 +683,26 @@
return 0;
}
+static int clo_suspend_fd(int cloop_num)
+{
+ struct cloop_device *clo = &cloop_dev[cloop_num];
+ struct file *filp = clo->backing_file;
+
+ if(filp==NULL) return -EINVAL;
+ if (clo->suspended) return -EINVAL;
+
+ /* Suspend all running requests - FF */
+ clo->suspended=1;
+ down(&clo->clo_lock);
+
+ if(filp!=initial_file) fput(filp);
+ else { filp_close(initial_file,0); initial_file=NULL; }
+ clo->backing_file = NULL;
+ clo->backing_inode = NULL;
+ memset(clo->backing_file_name, 0, LO_NAME_SIZE);
+ return 0;
+}
+
static int clo_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -702,6 +726,12 @@
#else
err = clo_set_fd(cloop_num, file, inode->i_bdev, arg);
#endif
+ if (err == 0 && clo->suspended)
+ {
+ /* Okay, we have again a backing file - get reqs again - FF */
+ clo->suspended=0;
+ up(&clo->clo_lock);
+ }
break;
case LOOP_CLR_FD:
err = clo_clr_fd(cloop_num, inode->i_bdev);
@@ -737,6 +767,9 @@
} else
err = -ENXIO;
break;
+ case CLOOP_SUSPEND:
+ err = clo_suspend_fd(cloop_num);
+ break;
default:
err = -EINVAL;
}
--- compressed_loop.h.old 2007-02-02 03:43:54.000000000 +0100
+++ compressed_loop.h 2007-02-02 04:45:26.000000000 +0100
@@ -20,4 +20,6 @@
/* data_index (num_blocks 64bit pointers, network order)... */
/* compressed data (gzip block compressed format)... */
+#define CLOOP_SUSPEND LOOP_GET_STATUS+1
+
#endif /*_COMPRESSED_LOOP_H*/
--- Makefile.old 2007-02-02 05:06:34.000000000 +0100
+++ Makefile 2007-02-02 05:07:13.000000000 +0100
@@ -64,6 +64,9 @@
extract_compressed_fs: extract_compressed_fs.o
$(CC) -o $@ $< -lz
+cloop_suspend: cloop_suspend.o
+ $(CC) -o $@ $<
+
clean:
rm -f $(KERNOBJ) create_compressed_fs extract_compressed_fs zoom *.o *.ko
$(MAKE) -C advancecomp-1.9_create_compressed_fs distclean
--- /dev/null 2004-05-02 02:57:33.000000000 +0200
+++ cloop_suspend.c 2007-02-02 05:12:32.000000000 +0100
@@ -0,0 +1,47 @@
+/*
+ * cloop_suspend - Suspend a cloop device until losetup /dev/cloop <file> is
+ * run again.
+ *
+ * Copyright (c) 2007 by Fabian Franz.
+ *
+ * License: GPL, v2.
+ *
+ */
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+/* We don't use the structure, so that define does not hurt */
+#define dev_t int
+#include <linux/loop.h>
+#include "compressed_loop.h"
+
+int main(int argc, char** argv)
+{
+ if (argc < 2)
+ {
+ fprintf(stderr, "syntax: cloop_suspend <device>\n");
+ return 1;
+ }
+ int fd = open(argv[1], O_RDONLY);
+
+ if (fd < 0)
+ {
+ perror(argv[1]);
+ return 1;
+ }
+
+ if (ioctl(fd, CLOOP_SUSPEND) < 0)
+ {
+ perror("ioctl: CLOOP_SUSPEND");
+ return 1;
+ }
+
+ close(fd);
+
+ return 0;
+}
Reply to: