diff options
Diffstat (limited to 'drivers/block/aoe/aoedev.c')
-rw-r--r-- | drivers/block/aoe/aoedev.c | 69 |
1 files changed, 48 insertions, 21 deletions
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index ded33ba31acc..ed4258a62df5 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c | |||
@@ -12,6 +12,24 @@ | |||
12 | static struct aoedev *devlist; | 12 | static struct aoedev *devlist; |
13 | static spinlock_t devlist_lock; | 13 | static spinlock_t devlist_lock; |
14 | 14 | ||
15 | int | ||
16 | aoedev_isbusy(struct aoedev *d) | ||
17 | { | ||
18 | struct frame *f, *e; | ||
19 | |||
20 | f = d->frames; | ||
21 | e = f + d->nframes; | ||
22 | do { | ||
23 | if (f->tag != FREETAG) { | ||
24 | printk(KERN_DEBUG "aoe: %ld.%ld isbusy\n", | ||
25 | d->aoemajor, d->aoeminor); | ||
26 | return 1; | ||
27 | } | ||
28 | } while (++f < e); | ||
29 | |||
30 | return 0; | ||
31 | } | ||
32 | |||
15 | struct aoedev * | 33 | struct aoedev * |
16 | aoedev_by_aoeaddr(int maj, int min) | 34 | aoedev_by_aoeaddr(int maj, int min) |
17 | { | 35 | { |
@@ -28,6 +46,18 @@ aoedev_by_aoeaddr(int maj, int min) | |||
28 | return d; | 46 | return d; |
29 | } | 47 | } |
30 | 48 | ||
49 | static void | ||
50 | dummy_timer(ulong vp) | ||
51 | { | ||
52 | struct aoedev *d; | ||
53 | |||
54 | d = (struct aoedev *)vp; | ||
55 | if (d->flags & DEVFL_TKILL) | ||
56 | return; | ||
57 | d->timer.expires = jiffies + HZ; | ||
58 | add_timer(&d->timer); | ||
59 | } | ||
60 | |||
31 | /* called with devlist lock held */ | 61 | /* called with devlist lock held */ |
32 | static struct aoedev * | 62 | static struct aoedev * |
33 | aoedev_newdev(ulong nframes) | 63 | aoedev_newdev(ulong nframes) |
@@ -44,6 +74,8 @@ aoedev_newdev(ulong nframes) | |||
44 | return NULL; | 74 | return NULL; |
45 | } | 75 | } |
46 | 76 | ||
77 | INIT_WORK(&d->work, aoecmd_sleepwork, d); | ||
78 | |||
47 | d->nframes = nframes; | 79 | d->nframes = nframes; |
48 | d->frames = f; | 80 | d->frames = f; |
49 | e = f + nframes; | 81 | e = f + nframes; |
@@ -52,6 +84,10 @@ aoedev_newdev(ulong nframes) | |||
52 | 84 | ||
53 | spin_lock_init(&d->lock); | 85 | spin_lock_init(&d->lock); |
54 | init_timer(&d->timer); | 86 | init_timer(&d->timer); |
87 | d->timer.data = (ulong) d; | ||
88 | d->timer.function = dummy_timer; | ||
89 | d->timer.expires = jiffies + HZ; | ||
90 | add_timer(&d->timer); | ||
55 | d->bufpool = NULL; /* defer to aoeblk_gdalloc */ | 91 | d->bufpool = NULL; /* defer to aoeblk_gdalloc */ |
56 | INIT_LIST_HEAD(&d->bufq); | 92 | INIT_LIST_HEAD(&d->bufq); |
57 | d->next = devlist; | 93 | d->next = devlist; |
@@ -67,9 +103,6 @@ aoedev_downdev(struct aoedev *d) | |||
67 | struct buf *buf; | 103 | struct buf *buf; |
68 | struct bio *bio; | 104 | struct bio *bio; |
69 | 105 | ||
70 | d->flags |= DEVFL_TKILL; | ||
71 | del_timer(&d->timer); | ||
72 | |||
73 | f = d->frames; | 106 | f = d->frames; |
74 | e = f + d->nframes; | 107 | e = f + d->nframes; |
75 | for (; f<e; f->tag = FREETAG, f->buf = NULL, f++) { | 108 | for (; f<e; f->tag = FREETAG, f->buf = NULL, f++) { |
@@ -92,16 +125,15 @@ aoedev_downdev(struct aoedev *d) | |||
92 | bio_endio(bio, bio->bi_size, -EIO); | 125 | bio_endio(bio, bio->bi_size, -EIO); |
93 | } | 126 | } |
94 | 127 | ||
95 | if (d->nopen) | ||
96 | d->flags |= DEVFL_CLOSEWAIT; | ||
97 | if (d->gd) | 128 | if (d->gd) |
98 | d->gd->capacity = 0; | 129 | d->gd->capacity = 0; |
99 | 130 | ||
100 | d->flags &= ~DEVFL_UP; | 131 | d->flags &= ~(DEVFL_UP | DEVFL_PAUSE); |
101 | } | 132 | } |
102 | 133 | ||
134 | /* find it or malloc it */ | ||
103 | struct aoedev * | 135 | struct aoedev * |
104 | aoedev_set(ulong sysminor, unsigned char *addr, struct net_device *ifp, ulong bufcnt) | 136 | aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) |
105 | { | 137 | { |
106 | struct aoedev *d; | 138 | struct aoedev *d; |
107 | ulong flags; | 139 | ulong flags; |
@@ -112,25 +144,19 @@ aoedev_set(ulong sysminor, unsigned char *addr, struct net_device *ifp, ulong bu | |||
112 | if (d->sysminor == sysminor) | 144 | if (d->sysminor == sysminor) |
113 | break; | 145 | break; |
114 | 146 | ||
115 | if (d == NULL && (d = aoedev_newdev(bufcnt)) == NULL) { | 147 | if (d == NULL) { |
116 | spin_unlock_irqrestore(&devlist_lock, flags); | 148 | d = aoedev_newdev(bufcnt); |
117 | printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n"); | 149 | if (d == NULL) { |
118 | return NULL; | 150 | spin_unlock_irqrestore(&devlist_lock, flags); |
119 | } /* if newdev, (d->flags & DEVFL_UP) == 0 for below */ | 151 | printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n"); |
120 | 152 | return NULL; | |
121 | spin_unlock_irqrestore(&devlist_lock, flags); | 153 | } |
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; | 154 | d->sysminor = sysminor; |
129 | d->aoemajor = AOEMAJOR(sysminor); | 155 | d->aoemajor = AOEMAJOR(sysminor); |
130 | d->aoeminor = AOEMINOR(sysminor); | 156 | d->aoeminor = AOEMINOR(sysminor); |
131 | } | 157 | } |
132 | 158 | ||
133 | spin_unlock_irqrestore(&d->lock, flags); | 159 | spin_unlock_irqrestore(&devlist_lock, flags); |
134 | return d; | 160 | return d; |
135 | } | 161 | } |
136 | 162 | ||
@@ -161,6 +187,7 @@ aoedev_exit(void) | |||
161 | 187 | ||
162 | spin_lock_irqsave(&d->lock, flags); | 188 | spin_lock_irqsave(&d->lock, flags); |
163 | aoedev_downdev(d); | 189 | aoedev_downdev(d); |
190 | d->flags |= DEVFL_TKILL; | ||
164 | spin_unlock_irqrestore(&d->lock, flags); | 191 | spin_unlock_irqrestore(&d->lock, flags); |
165 | 192 | ||
166 | del_timer_sync(&d->timer); | 193 | del_timer_sync(&d->timer); |