Re: [linuxce-devel] CRAMFS

From: Pavel Machek (pavel@ucw.cz)
Date: Sun Jul 30 2000 - 12:35:07 EST


Hi!

> >It would be nice to provide patch. Mail it to
> >linuxce-devel@linuxce.org [oops, this was on linuxce ;-)], they will
> >be surely interested. [Is there any reason such patch does not go to
> >linus? It fixes real bug in my eyes.]
>
> I sent an earlier version of the resize_protected_buffers
> patch to Linus about two years ago and, if I recall correctly, I got
> no response. I also posted a message to linux-kernel about the
> cramfs bforget issue (and I think I included a patch and I think

I applied this, and it is certianly better (says "no init found"
instead of bad signature), but still not quite good. Is there anything
else I have to do?

Maybe resize_protected_blocks going into drivers/block/rd.c would be
more acceptable for Linus?

--- /usr/src/linux/fs/buffer.c Tue Jul 11 21:56:57 2000
+++ /tmp/buffer.c Mon Jul 24 12:09:51 2000
@@ -132,6 +132,10 @@
 int bdflush_min[N_PARAM] = { 0, 10, 5, 25, 0, 1*HZ, 1*HZ, 1, 1};
 int bdflush_max[N_PARAM] = {100,50000, 20000, 20000,600*HZ, 6000*HZ, 6000*HZ, 2047, 5};
 
+#ifndef min
+# define min(a,b) (((a)<(b))?(a):(b))
+#endif
+
 /*
  * Rewrote the wait-routines to use the "new" wait-queue functionality,
  * and getting rid of the cli-sti pairs. The wait-queue routines still
@@ -625,11 +629,66 @@
                 goto retry;
 }
 
+/* Copy all protected ramdisk blocks into new blocks. */
+static void
+resize_protected_blocks(kdev_t dev, int oldsize, int newsize)
+{
+ int i;
+ struct buffer_head *bh, *bh_new;
+ int remaining;
+ int iterations = 0;
+ const int minsize = min(oldsize, newsize);
+
+ again:
+ iterations++;
+ spin_lock(&lru_list_lock);
+ for (bh = lru_list[BUF_PROTECTED],
+ remaining = nr_buffers_type[BUF_PROTECTED];
+ remaining != 0 && bh != NULL;
+ bh = bh->b_next_free, remaining--) {
+ if (bh->b_dev == dev && bh->b_size == oldsize) {
+ const int oldblk = bh->b_blocknr;
+ const int newblk = (oldblk * oldsize) / newsize;
+ spin_unlock(&lru_list_lock);
+ bh = bread(dev, oldblk, oldsize);
+ if (!bh) {
+ printk ("ramdisk_resize_save: cannot find existing block. Data lost.\n");
+ return; /* If we were to do "goto again",
+ we would risk an infinite loop. */
+ }
+ for(i = 0; i < oldsize/newsize || i==0; i++) {
+ bh_new = getblk(dev,newblk+i,newsize);
+ if (!bh_new) {
+ printk ("ramdisk_resize_save: memory allocation failure. Data lost.\n");
+ continue;
+ }
+ if (!buffer_protected(bh_new)) {
+ mark_buffer_protected(bh_new);
+ if (newsize > oldsize)
+ memset(bh_new->b_data,
+ 0, newsize);
+ }
+ memcpy(bh_new->b_data +
+ ((oldblk*oldsize)%newsize),
+ bh->b_data + (i * newsize),
+ minsize);
+ brelse(bh_new);
+ }
+ test_and_clear_bit(BH_Protected, &bh->b_state);
+ refile_buffer(bh);
+ __bforget(bh);
+ goto again;
+ }
+ }
+ spin_unlock(&lru_list_lock);
+}
+
 void set_blocksize(kdev_t dev, int size)
 {
         extern int *blksize_size[];
         int i, nlist, slept;
         struct buffer_head * bh, * bh_next;
+ int oldsize;
 
         if (!blksize_size[MAJOR(dev)])
                 return;
@@ -638,13 +697,16 @@
         if (size > PAGE_SIZE || size < 512 || (size & (size-1)))
                 panic("Invalid blocksize passed to set_blocksize");
 
- if (blksize_size[MAJOR(dev)][MINOR(dev)] == 0 && size == BLOCK_SIZE) {
+ oldsize = blksize_size[MAJOR(dev)][MINOR(dev)];
+ if (oldsize == 0 && size == BLOCK_SIZE) {
                 blksize_size[MAJOR(dev)][MINOR(dev)] = size;
                 return;
         }
         if (blksize_size[MAJOR(dev)][MINOR(dev)] == size)
                 return;
         sync_buffers(dev, 2);
+ if (MAJOR(dev) == RAMDISK_MAJOR)
+ resize_protected_blocks(dev, oldsize, size);
         blksize_size[MAJOR(dev)][MINOR(dev)] = size;
 
  retry:
@@ -1620,9 +1682,9 @@
                                                 PAGE_CACHE_SIZE, get_block);
                 if (status)
                         goto out_unmap;
- kaddr = (char*)page_address(page);
+ kaddr = (char*)page_address(new_page);
                 memset(kaddr+zerofrom, 0, PAGE_CACHE_SIZE-zerofrom);
- __block_commit_write(inode, new_page, zerofrom, to);
+ __block_commit_write(inode, new_page, zerofrom, PAGE_CACHE_SIZE);
                 kunmap(new_page);
                 UnlockPage(new_page);
                 page_cache_release(new_page);

> I also emailed it to directly to Linus, but I could be wrong about
> these), and, again, got no resonse. In general, I despair of getting
> Linus to integrate anything but the simplest patches. I really wish
> that there were some post-Linus cvs tree that all of the distribution
> makers could track before adding their own changes.

Well, not speaking for SuSE, but it looks like good idea. SuSE
certainly has internal tree, but AFAIK it is maintained as set of
patches in public directory...

-- 
I'm pavel@ucw.cz. "In my country we have almost anarchy and I don't care."
Panos Katsaloulis describing me w.r.t. patents at discuss@linmodems.org

- 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 : Mon Jul 31 2000 - 21:00:31 EST