int sbull_init(void) { int result, i; /* * Copy the (static) cfg variables to public prefixed ones to allow * snoozing with a debugger. */ sbull_major = major; sbull_devs = devs; sbull_rahead = rahead; sbull_size = size; sbull_blksize = blksize; sbull_hardsect = hardsect; #ifdef LINUX_20 /* Hardsect can't be changed :( */ if (hardsect != 512) { printk(KERN_ERR "sbull: can't change hardsect size\n"); hardsect = sbull_hardsect = 512; } #endif /* * Register your major, and accept a dynamic number */ result = register_blkdev(sbull_major, "sbull", &sbull_fops); if (result < 0) { printk(KERN_WARNING "sbull: can't get major %d\n",sbull_major); return result; } if (sbull_major == 0) sbull_major = result; /* dynamic */ major = sbull_major; /* Use `major' later on to save typing */ /* * Assign the other needed values: request, rahead, size, blksize, * hardsect. All the minor devices feature the same value. * Note that `sbull' defines all of them to allow testing non-default * values. A real device could well avoid setting values in global * arrays if it uses the default values. */ read_ahead[major] = sbull_rahead; result = -ENOMEM; /* for the possible errors */ sbull_sizes = kmalloc(sbull_devs * sizeof(int), GFP_KERNEL); if (!sbull_sizes) goto fail_malloc; for (i=0; i < sbull_devs; i++) /* all the same size */ sbull_sizes[i] = sbull_size; blk_size[major]=sbull_sizes; sbull_blksizes = kmalloc(sbull_devs * sizeof(int), GFP_KERNEL); if (!sbull_blksizes) goto fail_malloc; for (i=0; i < sbull_devs; i++) /* all the same blocksize */ sbull_blksizes[i] = sbull_blksize; blksize_size[major]=sbull_blksizes; sbull_hardsects = kmalloc(sbull_devs * sizeof(int), GFP_KERNEL); if (!sbull_hardsects) goto fail_malloc; for (i=0; i < sbull_devs; i++) /* all the same hardsect */ sbull_hardsects[i] = sbull_hardsect; hardsect_size[major]=sbull_hardsects; /* FIXME: max_readahead and max_sectors */ /* * allocate the devices -- we can't have them static, as the number * can be specified at load time */ sbull_devices = kmalloc(sbull_devs * sizeof (Sbull_Dev), GFP_KERNEL); if (!sbull_devices) goto fail_malloc; memset(sbull_devices, 0, sbull_devs * sizeof (Sbull_Dev)); for (i=0; i < sbull_devs; i++) { /* data and usage remain zeroed */ sbull_devices[i].size = 1024 * sbull_size; init_timer(&(sbull_devices[i].timer)); sbull_devices[i].timer.data = (unsigned long)(sbull_devices+i); sbull_devices[i].timer.function = sbull_expires; spin_lock_init(&sbull_devices[i].lock); } /* * Get the queue set up, and register our (nonexistent) partitions. */ #ifdef SBULL_MULTIQUEUE for (i = 0; i < sbull_devs; i++) { blk_init_queue(&sbull_devices[i].queue, sbull_request); blk_queue_headactive(&sbull_devices[i].queue, 0); blk_queue_pluggable(&sbull_devices[i].queue, sbull_plug); } blk_dev[major].queue = sbull_find_queue; #else # ifdef LINUX_24 if (noqueue) { blk_init_queue(BLK_DEFAULT_QUEUE(major), sbull_unused_request); blk_queue_make_request(BLK_DEFAULT_QUEUE(major), sbull_make_request); } else # endif /* LINUX_24 */ blk_init_queue(BLK_DEFAULT_QUEUE(major), sbull_request); #endif /* A no-op in 2.4.0, but all drivers seem to do it anyway */ for (i = 0; i < sbull_devs; i++) register_disk(NULL, MKDEV(major, i), 1, &sbull_fops, sbull_size << 1); #ifndef SBULL_DEBUG EXPORT_NO_SYMBOLS; /* otherwise, leave global symbols visible */ #endif printk ("<1>sbull: init complete, %d devs, size %d blks %d hs %d\n", sbull_devs, sbull_size, sbull_blksize, sbull_hardsect); #ifdef SBULL_MULTIQUEUE printk ("<1>sbull: Using multiqueue request\n"); #elif defined(LINUX_24) if (noqueue) printk (KERN_INFO "sbull: using direct make_request\n"); #endif #ifdef DO_RAW_INTERFACE sbullr_init(); #endif return 0; /* succeed */ fail_malloc: read_ahead[major] = 0; if (sbull_sizes) kfree(sbull_sizes); blk_size[major] = NULL; if (sbull_blksizes) kfree(sbull_blksizes); blksize_size[major] = NULL; if (sbull_hardsects) kfree(sbull_hardsects); hardsect_size[major] = NULL; if (sbull_devices) kfree(sbull_devices); unregister_blkdev(major, "sbull"); return result; }
/*! - structure de données pour le ndev - création fichier DEVFS - attribution MINOR number - init des valeurs des tableaux kernel (cf. blkdev.h) */ int smd_add_ndev(servernode_t *sn, char *nom_device, char *path_device, int devnb, u64 nb_sectors) { int no_ndev; ndevice_t *nd; PDEBUG("entering. param: sn=%p (name=%s) nom_device=%s " "path_device=%s devnb = %d nb_sectors=%lld\n", sn, sn->name, nom_device, path_device, devnb, nb_sectors); // et si le nouveau ndev existe déjà sur ce snode.. // on met à jour la nouvelle taille si besoin est if (new_ndev(sn, nom_device) == FALSE) { PDEBUG("ndev '%s' exist => checking if its size has changed\n", nom_device); nd = get_ndev_from_name(sn, nom_device); if (nd == NULL) { PERROR("can't get the nd structure of existing ndev '%s'\n", nom_device); return ERROR; } if (quotient64(nb_sectors*SMD_HARDSECT,1024) != nd->size) { // changement de taille PDEBUG("size changed: old size = %lld KB, new size = %lld KB\n", nd->size, quotient64(nb_sectors*SMD_HARDSECT,1024)); nd->size = quotient64(nb_sectors*SMD_HARDSECT,1024); blk_size[SMD_MAJOR_NUMBER][nd->minor] = nd->size; } return SUCCESS; } no_ndev = unused_elt_indice((void *)sn->ndevs, NBMAX_NDEVS); if (no_ndev == NBMAX_NDEVS) { PERROR("can't create the new image device because max number " "(= %d) reached for the server node '%s'\n", NBMAX_NDEVS, sn->name); return ERROR; } PDEBUG("free elt indice %d of sn->ndevs[] chosen\n", no_ndev); nd = vmalloc(sizeof(struct ndevice)); if (nd == NULL) { PERROR("can't allocate memory for new ndev '%s'\n", nom_device); return ERROR; } nd->sn = sn; nd->minor = unused_elt_indice((void *)minor2ndev,NBMAX_NDEVS); if (nd->minor == NBMAX_NDEVS) { PERROR("can't get a minor number for device '%s:%s' " "because max number (= %d) reached \n", nom_device, nd->name, NBMAX_NDEVS); return ERROR; } nd->localnb = devnb; sscanf(nom_device,"%s", nd->name); sscanf(path_device,"%s", nd->rpath); sprintf(nd->lpath,"/dev/%s/%s", sn->name, nd->name); nd->dev_file = devfs_register(sn->dev_rep, nd->name, DEVFS_FL_DEFAULT, SMD_MAJOR_NUMBER, nd->minor, S_IFBLK | S_IRUSR | S_IWUSR, &smd_fops, NULL); PDEBUG(" nd->dev_file = " "devfs_register(sn->dev_rep, nd->name," "DEVFS_FL_DEFAULT, " "SMD_MAJOR_NUMBER, nd->minor, " "S_IFBLK | S_IRUSR | S_IWUSR," "&smd_fops," "NULL) == %p\n",nd->dev_file); if (nd->dev_file == NULL) { PERROR("can't create dev_file for ndev '%s:%s'\n", sn->name, nd->name); goto error; } PDEBUG("devfs file '%s' created\n", nd->name); nd->nb_io = 0; nd->size = quotient64(nb_sectors*SMD_HARDSECT,1024); // en Ko // smd_size[no_brique] mise à jour plus tard blk_size[SMD_MAJOR_NUMBER][nd->minor] = nd->size; blksize_size[SMD_MAJOR_NUMBER][nd->minor] = SMD_BLKSIZE; hardsect_size[SMD_MAJOR_NUMBER][nd->minor] = SMD_HARDSECT; max_readahead[SMD_MAJOR_NUMBER][nd->minor] = SMD_READAHEAD; max_sectors[SMD_MAJOR_NUMBER][nd->minor] = sn->maxsize_req; // on initialise la queue des requêtes blk_init_queue(&nd->queue, smd_request); blk_queue_headactive(&nd->queue,0); PDEBUG("dev queue iniatilized\n"); minor2ndev[nd->minor] = nd; sn->ndevs[no_ndev] = nd; PDEBUG("networked device '%s' added\n", nd->name); return SUCCESS; error: vfree(nd); return ERROR; }