NTFS: Use i_size_read() in fs/ntfs/file.c::ntfs_file_open().
[sfrench/cifs-2.6.git] / drivers / block / aoe / aoedev.c
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
12 static struct aoedev *devlist;
13 static spinlock_t devlist_lock;
14
15 struct aoedev *
16 aoedev_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 */
32 static struct aoedev *
33 aoedev_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
63 void
64 aoedev_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
103 struct aoedev *
104 aoedev_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                 || memcmp(d->addr, addr, sizeof d->addr) == 0)
114                         break;
115
116         if (d == NULL && (d = aoedev_newdev(bufcnt)) == NULL) {
117                 spin_unlock_irqrestore(&devlist_lock, flags);
118                 printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n");
119                 return NULL;
120         }
121
122         spin_unlock_irqrestore(&devlist_lock, flags);
123         spin_lock_irqsave(&d->lock, flags);
124
125         d->ifp = ifp;
126
127         if (d->sysminor != sysminor
128         || (d->flags & DEVFL_UP) == 0) {
129                 aoedev_downdev(d); /* flushes outstanding frames */
130                 memcpy(d->addr, addr, sizeof d->addr);
131                 d->sysminor = sysminor;
132                 d->aoemajor = AOEMAJOR(sysminor);
133                 d->aoeminor = AOEMINOR(sysminor);
134         }
135
136         spin_unlock_irqrestore(&d->lock, flags);
137         return d;
138 }
139
140 static void
141 aoedev_freedev(struct aoedev *d)
142 {
143         if (d->gd) {
144                 aoedisk_rm_sysfs(d);
145                 del_gendisk(d->gd);
146                 put_disk(d->gd);
147         }
148         kfree(d->frames);
149         if (d->bufpool)
150                 mempool_destroy(d->bufpool);
151         kfree(d);
152 }
153
154 void
155 aoedev_exit(void)
156 {
157         struct aoedev *d;
158         ulong flags;
159
160         flush_scheduled_work();
161
162         while ((d = devlist)) {
163                 devlist = d->next;
164
165                 spin_lock_irqsave(&d->lock, flags);
166                 aoedev_downdev(d);
167                 spin_unlock_irqrestore(&d->lock, flags);
168
169                 del_timer_sync(&d->timer);
170                 aoedev_freedev(d);
171         }
172 }
173
174 int __init
175 aoedev_init(void)
176 {
177         spin_lock_init(&devlist_lock);
178         return 0;
179 }
180