Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.12-rc6 177 lines 3.4 kB view raw
1/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ 2/* 3 * aoedev.c 4 * AoE device utility functions; maintains device list. 5 */ 6 7#include <linux/hdreg.h> 8#include <linux/blkdev.h> 9#include <linux/netdevice.h> 10#include "aoe.h" 11 12static struct aoedev *devlist; 13static spinlock_t devlist_lock; 14 15struct aoedev * 16aoedev_by_aoeaddr(int maj, int min) 17{ 18 struct aoedev *d; 19 ulong flags; 20 21 spin_lock_irqsave(&devlist_lock, flags); 22 23 for (d=devlist; d; d=d->next) 24 if (d->aoemajor == maj && d->aoeminor == min) 25 break; 26 27 spin_unlock_irqrestore(&devlist_lock, flags); 28 return d; 29} 30 31/* called with devlist lock held */ 32static struct aoedev * 33aoedev_newdev(ulong nframes) 34{ 35 struct aoedev *d; 36 struct frame *f, *e; 37 38 d = kcalloc(1, sizeof *d, GFP_ATOMIC); 39 if (d == NULL) 40 return NULL; 41 f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); 42 if (f == NULL) { 43 kfree(d); 44 return NULL; 45 } 46 47 d->nframes = nframes; 48 d->frames = f; 49 e = f + nframes; 50 for (; f<e; f++) 51 f->tag = FREETAG; 52 53 spin_lock_init(&d->lock); 54 init_timer(&d->timer); 55 d->bufpool = NULL; /* defer to aoeblk_gdalloc */ 56 INIT_LIST_HEAD(&d->bufq); 57 d->next = devlist; 58 devlist = d; 59 60 return d; 61} 62 63void 64aoedev_downdev(struct aoedev *d) 65{ 66 struct frame *f, *e; 67 struct buf *buf; 68 struct bio *bio; 69 70 d->flags |= DEVFL_TKILL; 71 del_timer(&d->timer); 72 73 f = d->frames; 74 e = f + d->nframes; 75 for (; f<e; f->tag = FREETAG, f->buf = NULL, f++) { 76 if (f->tag == FREETAG || f->buf == NULL) 77 continue; 78 buf = f->buf; 79 bio = buf->bio; 80 if (--buf->nframesout == 0) { 81 mempool_free(buf, d->bufpool); 82 bio_endio(bio, bio->bi_size, -EIO); 83 } 84 } 85 d->inprocess = NULL; 86 87 while (!list_empty(&d->bufq)) { 88 buf = container_of(d->bufq.next, struct buf, bufs); 89 list_del(d->bufq.next); 90 bio = buf->bio; 91 mempool_free(buf, d->bufpool); 92 bio_endio(bio, bio->bi_size, -EIO); 93 } 94 95 if (d->nopen) 96 d->flags |= DEVFL_CLOSEWAIT; 97 if (d->gd) 98 d->gd->capacity = 0; 99 100 d->flags &= ~DEVFL_UP; 101} 102 103struct aoedev * 104aoedev_set(ulong sysminor, unsigned char *addr, struct net_device *ifp, ulong bufcnt) 105{ 106 struct aoedev *d; 107 ulong flags; 108 109 spin_lock_irqsave(&devlist_lock, flags); 110 111 for (d=devlist; d; d=d->next) 112 if (d->sysminor == sysminor) 113 break; 114 115 if (d == NULL && (d = aoedev_newdev(bufcnt)) == NULL) { 116 spin_unlock_irqrestore(&devlist_lock, flags); 117 printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n"); 118 return NULL; 119 } /* if newdev, (d->flags & DEVFL_UP) == 0 for below */ 120 121 spin_unlock_irqrestore(&devlist_lock, flags); 122 spin_lock_irqsave(&d->lock, flags); 123 124 d->ifp = ifp; 125 memcpy(d->addr, addr, sizeof d->addr); 126 if ((d->flags & DEVFL_UP) == 0) { 127 aoedev_downdev(d); /* flushes outstanding frames */ 128 d->sysminor = sysminor; 129 d->aoemajor = AOEMAJOR(sysminor); 130 d->aoeminor = AOEMINOR(sysminor); 131 } 132 133 spin_unlock_irqrestore(&d->lock, flags); 134 return d; 135} 136 137static void 138aoedev_freedev(struct aoedev *d) 139{ 140 if (d->gd) { 141 aoedisk_rm_sysfs(d); 142 del_gendisk(d->gd); 143 put_disk(d->gd); 144 } 145 kfree(d->frames); 146 if (d->bufpool) 147 mempool_destroy(d->bufpool); 148 kfree(d); 149} 150 151void 152aoedev_exit(void) 153{ 154 struct aoedev *d; 155 ulong flags; 156 157 flush_scheduled_work(); 158 159 while ((d = devlist)) { 160 devlist = d->next; 161 162 spin_lock_irqsave(&d->lock, flags); 163 aoedev_downdev(d); 164 spin_unlock_irqrestore(&d->lock, flags); 165 166 del_timer_sync(&d->timer); 167 aoedev_freedev(d); 168 } 169} 170 171int __init 172aoedev_init(void) 173{ 174 spin_lock_init(&devlist_lock); 175 return 0; 176} 177