Subject: Re: Recent dev kernel?



"A month of sundays ago Peter T. Breuer wrote:"
> "Peter T. Breuer wrote:"
> > No - I'm trying to compile his now for comparison. But I don't see him
> > doing anything significantly different from me in the init routine,
>
> Last news before I go home ...
>
> Pavel's driver hangs partially on init too (compiled for smp). It comes

By looking atthe loop driver, I've made a little more progres. The
driver now inserts safely.

As far as I can tell, all I've done is

1) make sure the add_disk is real late in the init seq
2) don't set the disk size (set_capacity)
3) only call for whole disk, no partitions (alloc_disk(1)).

Either 2) or 3) did the trick. Possibly both, since Pavel does (3),
and his river hangs here, but not as badly ..

Anyway, I'll put up the code in a little while. The client now can't
pen the device, but that's now tracable, since the module at least
inserts without oops.

Here's the diff from the 2.4.31 code. Sorry - it's slightly obscured by
me inventing a global called nbd_queue, since I thought it might be
something to do with the default kernel queue for a while. It's just
set equal to the default in the init routine.


--- linux-2.5.31/drivers/block/enbd.c Tue Oct 29 03:04:25 2002
+++ linux-2.5.44/drivers/block/enbd.c Tue Oct 29 22:42:49 2002
@@ -363,6 +363,8 @@
MODULE_PARM (md5_off_threshold, "i");
#endif

+ static struct request_queue * nbd_queue;
+
#define NO_BUFFERED_WRITES 1

/* *
@@ -681,9 +683,6 @@
MOD_INC_USE_COUNT;

if (!(atomic_read (&lo->flags) & NBD_INITIALISED)) { /* PTB 132 */
- rwlock_init (&lo->queue_lock);
- rwlock_init (&lo->altqueue_lock);
- init_MUTEX(&lo->pid_sem);
atomic_set_mask (NBD_INITIALISED, &lo->flags);
if (!(atomic_read (&lo->flags) & NBD_ENABLED)) {
atomic_set_mask (NBD_ENABLED, &lo->flags);
@@ -1205,8 +1204,8 @@

if (reply.magic != NBD_REPLY_MAGIC) {
if (slot->nerrs++ < 3)
- NBD_ALERT ("Not enough reply magic in "
- __FUNCTION__ "\n");
+ NBD_ALERT ("Not enough reply magic in %s\n",
+ __FUNCTION__ );
/* PTB returning -EAGAIN causes the client to pause 0.5s
* and throw its reply away, then return to service. We leave
* any request we have to age and be rolled back. */
@@ -1838,7 +1837,7 @@

int count = 0;
unsigned long flags;
- request_queue_t *q = BLK_DEFAULT_QUEUE(major);
+ request_queue_t *q = nbd_queue;

spin_lock_irqsave (q->queue_lock, flags);

@@ -2157,13 +2156,14 @@

if (req->flags & REQ_SPECIAL) {
// PTB temporary successful end here for SPECIALS
- NBD_INFO("special req %#x type %ld for dev %d:%d %ld
sectors %ld-%ld\n",
+ NBD_INFO("special req %#x type %ld for dev %d:%d %ld
sectors %Lu-%Lu\n",
(unsigned)req,
rq_data_dir(req),
major(req->rq_dev), dev,
req->nr_sectors,
- req->sector,
- req->sector + req->nr_sectors - 1);
+ (unsigned long long)req->sector,
+ (unsigned long long)req->sector
+ + req->nr_sectors - 1);
// PTB we want to attach it to the device and
// acknowledge it later
nbd_enqueue (lo, req, NBD_UNINTERRUPTIBLE);
@@ -2477,7 +2477,8 @@
lo->bytesize = nbd_bytesizes[nbd << NBD_SHIFT] = arg;
lo->size = nbd_sizes[nbd << NBD_SHIFT] = arg >> 10;
lo->sectors = lo->size << 1;
-
+ if (lo->disk)
+ set_capacity(lo->disk, lo->sectors);
atomic_set_mask (NBD_SIZED, &lo->flags);
return 0;
}
@@ -2757,8 +2758,8 @@
static struct timer_list reenable_timer = {
{NULL, NULL},
0,
- 0,
(void (*)(unsigned long)) nbd_reenable,
+ 0,
};

/*
@@ -2936,7 +2937,7 @@
timeout = lo->req_timeo * HZ;
start_time = jiffies;

- while (!(req = blk_get_request(BLK_DEFAULT_QUEUE(major),WRITE,0))) {
+ while (!(req = blk_get_request(nbd_queue,WRITE,0))) {
if (jiffies >= start_time + timeout) {
// PTB it takes too long
NBD_ALERT
@@ -3507,10 +3508,32 @@
open: nbd_open,
release: nbd_release,
ioctl: nbd_ioctl,
- check_media_change: NULL,
- revalidate: NULL,
+ media_changed: NULL,
+ revalidate_disk: NULL,
};

+static int
+nbd_set_disk (struct nbd_device *lo, unsigned npart)
+{
+ struct gendisk * disk = lo->disk;
+ if (!disk)
+ lo->disk = disk = alloc_disk (npart);
+ if (disk) {
+ disk->major = major;
+ disk->first_minor = lo->nbd * npart;
+ disk->fops = &nbd_blkops;
+ disk->private_data = lo;
+ disk->queue = nbd_queue;
+ sprintf (disk->disk_name, "nd%s", lo->devnam);
+ //set_capacity (disk, lo->bytesize >> 9);
+ add_disk (disk);
+ return 0;
+ }
+
+ NBD_ERROR ("Insufficient memory for partition structs\n");
+ return -ENOMEM;
+}
+
/*
* Pavel - And here should be modules and kernel interface
* (Just smiley confuses emacs :-)
@@ -4411,7 +4434,6 @@

if (i < 0 || i >= MAX_NBD)
return;
- memset (lo, 0, sizeof (struct nbd_device));
lo->magic = NBD_DEV_MAGIC;
strncpy (lo->devnam, device_letter (i), 4);
for (j = 0; j < NBD_MAXCONN; j++) { /* PTB */
@@ -4428,8 +4450,7 @@
lo->nbd = i;
lo->req_timeo = NBD_REQ_TIMEO; /* PTB default pulse intvl */
lo->max_sectors = buf_sectors;
- register_disk(NULL, mk_kdev(major,i * NBD_MAXCONN), 1,
- &nbd_blkops, lo->bytesize >> 9);
+
// speed struct inits
lo->wspeed.getdistance = getwdistance;
lo->rspeed.getdistance = getrdistance;
@@ -4442,12 +4463,17 @@
INIT_LIST_HEAD (&lo->altqueue);
init_waitqueue_head (&lo->wq);
init_waitqueue_head (&lo->req_wq);
+ init_MUTEX(&lo->pid_sem);
+ rwlock_init (&lo->queue_lock);
+ rwlock_init (&lo->altqueue_lock);
for (j = 0; j < NBD_MAXCONN; j++) {
nbd_blksizes[i * NBD_MAXCONN + j] = lo->blksize;
nbd_bytesizes[i * NBD_MAXCONN + j] = lo->bytesize;
nbd_sizes[i * NBD_MAXCONN + j] = lo->size;
nbd_max_sectors[i * NBD_MAXCONN + j] = lo->max_sectors;
}
+
+
if (md5sum) {
atomic_set_mask (NBD_MD5SUM, &lo->flags);
}
@@ -4721,6 +4747,17 @@
"amarin@xxxxxxxxxx\n");
NBD_INFO ("Enhanced Network Block Device " NBD_VERSION " by "
"ptb@xxxxxxxxxx\n");
+
+ nbd_queue = BLK_DEFAULT_QUEUE(major);
+
+ for (i = 0; i < MAX_NBD; i++) {
+ struct nbd_device *lo = &nbd_dev[i];
+ struct gendisk *disk = alloc_disk(NBD_MAXCONN);
+ memset (lo, 0, sizeof (*lo));
+ if (disk)
+ lo->disk = disk;
+ }
+
if (register_blkdev (major, "nbd", &nbd_blkops)) {
NBD_ERROR ("Unable to register major number %d for NBD\n",
major);
@@ -4729,13 +4766,11 @@
#ifdef MODULE
NBD_INFO ("registered device at major %d\n", major);
#endif
- blk_size[major] = nbd_sizes; /* size in KB */

// PTB - set up kernel queue struct with default methods
- blk_init_queue (BLK_DEFAULT_QUEUE (major), do_nbd_request, &nbd_lock);
+ blk_init_queue (nbd_queue, do_nbd_request, &nbd_lock);

- (BLK_DEFAULT_QUEUE (major))->max_sectors
- = buf_sectors; /* max per request */
+ nbd_queue->max_sectors = buf_sectors; /* max per request */

// PTB - I think that put:
// - q->plug_device_fn = generic_plug_device (static ll_rw_blk)
@@ -4748,15 +4783,15 @@
// PTB - we have to do some more init magic in 2.4.*. This says that we
// - take all stuff off the kernel queue before processing it, so in
// - particular it's OK for kernel to do merges with the queue head.
- blk_queue_headactive (BLK_DEFAULT_QUEUE (major), 0);
+ blk_queue_headactive (nbd_queue, 0);

// LA - moved the next #if higher;
// - kernel 2.2.* doesn't know about plug_device_fn

// PTB control merge attempts so we don't overflow our buffer
- ll_merge_requests_fn = (BLK_DEFAULT_QUEUE (major))->merge_requests_fn;
- ll_front_merge_fn = (BLK_DEFAULT_QUEUE (major))->front_merge_fn;
- ll_back_merge_fn = (BLK_DEFAULT_QUEUE (major))->back_merge_fn;
+ ll_merge_requests_fn = nbd_queue->merge_requests_fn;
+ ll_front_merge_fn = nbd_queue->front_merge_fn;
+ ll_back_merge_fn = nbd_queue->back_merge_fn;

// JSA - Add this line because under >=2.4.1, merge optimizations are in flux
// PTB - however it's not this which does damage, I believe. Data: plugging
@@ -4769,16 +4804,19 @@
// PTB - The functions below just impose our own stricter size limit before
// - calling the defaults if all seems OK sizewise.

- (BLK_DEFAULT_QUEUE (major))->merge_requests_fn = &nbd_merge_requests_fn;
- (BLK_DEFAULT_QUEUE (major))->front_merge_fn = &nbd_front_merge_fn;
- (BLK_DEFAULT_QUEUE (major))->back_merge_fn = &nbd_back_merge_fn;
-
+ nbd_queue->merge_requests_fn = &nbd_merge_requests_fn;
+ nbd_queue->front_merge_fn = &nbd_front_merge_fn;
+ nbd_queue->back_merge_fn = &nbd_back_merge_fn;

for (i = 0; i < MAX_NBD; i++) {
struct nbd_device *lo = &nbd_dev[i];
nbd_reset(lo, i);
+ nbd_set_disk(lo, 1 /* NBD_MAXCONN*/);
}

+ // PTB we do the disk and partition stuff after we have
+ // contact, when nbd_open is called for the first time?
+
do {
struct proc_dir_entry *res =
create_proc_read_entry ("nbdinfo", 0, NULL,
@@ -4903,6 +4941,10 @@

for (i = 0; i < MAX_NBD; i++) {
struct nbd_device *lo = &nbd_dev[i];
+ if (lo->disk) {
+ del_gendisk(lo->disk);
+ put_disk(lo->disk);
+ }
atomic_clear_mask (NBD_ENABLED, &lo->flags);
if (lo->blockmap) {
kfree (lo->blockmap);
@@ -4912,8 +4954,7 @@
del_timer (&lo->run_queue);
}

- blk_cleanup_queue (BLK_DEFAULT_QUEUE (major));
- blk_size[major] = NULL;
+ blk_cleanup_queue (nbd_queue);

if (unregister_blkdev (major, "nbd") != 0) {
NBD_ALERT ("cleanup_module failed\n");
--- linux-2.5.31/include/linux/enbd.h Thu Oct 24 17:06:13 2002
+++ linux-2.5.44/include/linux/enbd.h Tue Oct 29 13:10:14 2002
@@ -215,7 +215,7 @@
unsigned long disabled; /* PTB add - when was it disabled */
int req_timeo; /* PTB add - inactivity timeout */
struct timer_list run_queue; /* PTB add - run queue */
- struct tq_struct task_queue; /* PTB add - task queue */
+ struct work_struct task_queue; /* PTB add - task queue */
char devnam[4]; /* PTB add - drive letters */
atomic_t maxreqblks; /* PTB add - maximum req size seen
*/
int max_sectors; /* PTB add - max req size allowed!
*/
@@ -234,6 +234,7 @@
rwlock_t altqueue_lock; /* PTB add - diverted reqs lock */
atomic_t seqno_in; /* PTB add - unacked reqs */
struct semaphore pid_sem; /* PTB control setting pid */
+ struct gendisk *disk; /* PTB for partitions */
};

#endif /* MAJOR_NR */
@@ -385,10 +386,11 @@

/* unlock chained buffers */
while ((bio = req->bio) != NULL) {
- blk_finished_io(bio_sectors(bio));
+ unsigned nsect = bio_sectors(bio);
+ blk_finished_io(nsect);
req->bio = bio->bi_next;
bio->bi_next = NULL;
- bio_endio(bio, uptodate);
+ bio_endio(bio, nsect << 9, uptodate ? 0 : -EIO);
}

if (! (req->flags & REQ_SPECIAL)) {




Programming list archiving by: Enterprise Git Hosting