Whamcloud - gitweb
Added .cvsignore files to the repository
[fs/lustre-release.git] / lustre / obdclass / genops.c
1 /*
2  *  linux/fs/ext2_obd/sim_obd.c
3  *
4  * These are the only exported functions; they provide the simulated object-
5  * oriented disk.
6  *
7  */
8
9 #include <asm/uaccess.h>
10 #include <linux/sched.h>
11 #include <linux/stat.h>
12 #include <linux/string.h>
13 #include <linux/locks.h>
14 #include <linux/quotaops.h>
15 #include <linux/list.h>
16 #include <linux/file.h>
17 #include <linux/iobuf.h>
18 #include <asm/bitops.h>
19 #include <asm/byteorder.h>
20 #include <linux/obd_support.h>
21 #include <linux/obd_class.h>
22
23
24 extern struct obd_device obd_dev[MAX_OBD_DEVICES];
25
26 /* map connection to client */
27 struct obd_client *gen_client(int cli_id)
28 {
29         struct obd_device * obddev;
30         struct list_head * lh, * next;
31         struct obd_client * cli;
32         int a;
33
34         for (a = 0; a < MAX_OBD_DEVICES; a++) {
35                 obddev = &obd_dev[a];
36
37                 lh = next = &obddev->obd_gen_clients;
38                 while ((lh = lh->next) != &obddev->obd_gen_clients) {
39                         cli = list_entry(lh, struct obd_client, cli_chain);
40                         
41                         if (cli->cli_id == cli_id)
42                                 return cli;
43                 }
44         }
45
46         return NULL;
47 } /* obd_client */
48
49
50
51 /* a connection defines a context in which preallocation can be managed. */ 
52 int gen_connect (struct obd_device *obddev, 
53                         struct obd_conn_info * conninfo)
54 {
55         struct obd_client * cli;
56
57         OBD_ALLOC(cli, struct obd_client *, sizeof(struct obd_client));
58         if ( !cli ) {
59                 printk("obd_connect (minor %d): no memory!\n", 
60                        obddev->obd_minor);
61                 return -ENOMEM;
62         }
63
64         INIT_LIST_HEAD(&cli->cli_prealloc_inodes);
65         /* this should probably spinlocked? */
66         cli->cli_id = ++obddev->obd_gen_last_id;
67         cli->cli_prealloc_quota = 0;
68         cli->cli_obd = obddev;
69         list_add(&(cli->cli_chain), obddev->obd_gen_clients.prev);
70
71         CDEBUG(D_IOCTL, "connect: new ID %u\n", cli->cli_id);
72         conninfo->conn_id = cli->cli_id;
73         return 0;
74 } /* gen_obd_connect */
75
76
77 int gen_disconnect(unsigned int conn_id)
78 {
79         struct obd_client * cli;
80
81         ENTRY;
82
83         if (!(cli = gen_client(conn_id))) {
84                 CDEBUG(D_IOCTL, "disconnect: attempting to free "
85                        "nonexistent client %u\n", conn_id);
86                 return -EINVAL;
87         }
88
89         list_del(&(cli->cli_chain));
90         OBD_FREE(cli, sizeof(struct obd_client));
91
92         CDEBUG(D_IOCTL, "disconnect: ID %u\n", conn_id);
93
94         EXIT;
95         return 0;
96 } /* gen_obd_disconnect */
97
98
99 /* 
100  *   raid1 defines a number of connections to child devices,
101  *   used to make calls to these devices.
102  *   data holds nothing
103  */ 
104 int gen_multi_setup(struct obd_device *obddev, int len, void *data)
105 {
106         int i;
107         struct obd_device *rdev = obddev->obd_multi_dev[0];
108
109         for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
110                 int rc;
111                 struct obd_device *child = rdev + i;
112                 rc  = OBP(child, connect)(child, &rdev->obd_multi_conns[i]);
113
114                 if ( rc != 0 ) {
115                         /* XXX disconnect others */
116                         return -EINVAL;
117                 }
118         }               
119         return 0;
120 }
121
122 int gen_multi_cleanup(struct obd_device * obddev)
123 {
124         int i;
125         struct obd_device **rdev = obddev->obd_multi_dev;
126
127         for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
128                 int rc;
129                 struct obd_device *child = *(rdev + i);
130                 rc  = OBP(child, cleanup)(child);
131                 *(rdev + i) = NULL;
132
133                 if ( rc != 0 ) {
134                         /* XXX disconnect others */
135                         return -EINVAL;
136                 }
137         }
138         gen_cleanup(obddev);
139         return 0;
140 } /* sim_cleanup_obddev */
141
142
143 int gen_multi_attach(struct obd_device *obddev, int len, void *data)
144 {
145         int i;
146         int count;
147         struct obd_device *rdev = obddev->obd_multi_dev[0];
148
149         count = len/sizeof(int);
150         obddev->obd_multi_count = count;
151         for (i=0 ; i<count ; i++) {
152                 rdev = &obd_dev[*((int *)data + i)];
153                 rdev = rdev + 1;
154                 CDEBUG(D_IOCTL, "OBD RAID1: replicator %d is of type %s\n", i,
155                        (rdev + i)->obd_type->typ_name);
156         }
157         return 0;
158 }
159
160
161
162 /*
163  *    remove all connections to this device
164  *    close all connections to lower devices
165  *    needed for forced unloads of OBD client drivers
166  */
167 int gen_multi_cleanup_device(struct obd_device *obddev)
168 {
169         int i;
170         struct obd_device **rdev;
171
172         rdev =  obddev->obd_multi_dev;
173         for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
174                 int rc;
175                 struct obd_device *child = *(rdev + i);
176                 rc  = OBP(child, disconnect)
177                         (obddev->obd_multi_conns[i].conn_id);
178
179                 if ( rc != 0 ) {
180                         printk("OBD multi cleanup dev: disconnect failure %d\n", child->obd_minor);
181                 }
182                 *(rdev + i) = NULL;
183         }               
184         return 0;
185 } /* gen_multi_cleanup_device */
186
187
188 /*
189  *    forced cleanup of the device:
190  *    - remove connections from the device
191  *    - cleanup the device afterwards
192  */
193 int gen_cleanup(struct obd_device * obddev)
194 {
195         struct list_head * lh, * tmp;
196         struct obd_client * cli;
197
198         ENTRY;
199
200         lh = tmp = &obddev->obd_gen_clients;
201         while ((tmp = tmp->next) != lh) {
202                 cli = list_entry(tmp, struct obd_client, cli_chain);
203                 CDEBUG(D_IOCTL, "Disconnecting obd_connection %d, at %p\n",
204                        cli->cli_id, cli);
205                 OBP(obddev, disconnect)(cli->cli_id);
206         }
207
208         return OBP(obddev, cleanup_device)(obddev);
209 } /* sim_cleanup_device */
210
211 /* 
212  * Wait for a page to get unlocked.
213  *
214  * This must be called with the caller "holding" the page,
215  * ie with increased "page->count" so that the page won't
216  * go away during the wait..
217  */
218 static void my__wait_on_page(struct page *page)
219 {
220         struct task_struct *tsk = current;
221         DECLARE_WAITQUEUE(wait, tsk);
222
223         add_wait_queue(&page->wait, &wait);
224         do {
225                 run_task_queue(&tq_disk);
226                 set_task_state(tsk, TASK_UNINTERRUPTIBLE);
227                 if (!PageLocked(page))
228                         break;
229                 schedule();
230         } while (PageLocked(page));
231         tsk->state = TASK_RUNNING;
232         remove_wait_queue(&page->wait, &wait);
233 }
234
235 /*
236  * Get an exclusive lock on the page..
237  */
238 static void lck_page(struct page *page)
239 {
240         while (TryLockPage(page))
241                 my__wait_on_page(page);
242 }
243
244 /* obdo's must be correctly filled in by caller! */
245 int gen_copy_data(struct obd_device *obddev, int conn_id, 
246                        obdattr *source, obdattr *target)
247 {
248         struct page *page;
249 <<<<<<< genops.c
250         int res;
251         int err;
252         int i;
253 =======
254         unsigned long index = 0;
255         int rc;
256 >>>>>>> 1.5
257
258 <<<<<<< genops.c
259         page = __get_pages(GFP_USER, 0);
260         if (!page) 
261                 return EIO;
262         lck_page(page);
263 =======
264         page = alloc_page(GFP_USER);
265         if ( !page ) 
266                 return -ENOMEM;
267 >>>>>>> 1.5
268
269         err = 0;
270         i = 0;
271         while (1) {
272                 CDEBUG(D_IOCTL, "i %d, size %ld\n", i, source->i_size);
273                 err = 0;
274                 if ( i >= (source->i_size >> PAGE_SHIFT) ) 
275                         break;
276         
277 <<<<<<< genops.c
278                 page->offset = i << PAGE_SHIFT;
279                 err = -EIO;
280                 CDEBUG(D_IOCTL, "i %d, offset %ld, size %ld\n", i, 
281                        page->offset, source->i_size);
282                 res = OBP(obddev, brw)(READ, conn_id, source, page, 0);
283                 CDEBUG(D_IOCTL, "Result reading %d\n", res);
284                 if ( res < 0 ) 
285                         break;
286 =======
287         lck_page(page);
288         
289         while (index < ((src->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT)) {
290                 
291                 page->index = index;
292                 rc = OBP(conn->oc_dev, brw)(READ, conn, src, page, 0);
293 >>>>>>> 1.5
294
295                 res = OBP(obddev, brw)(WRITE, conn_id, target, page, 1);
296                 CDEBUG(D_IOCTL, "Result writing %d\n", res);
297                 if ( res < 0 ) 
298                         break;
299
300 <<<<<<< genops.c
301                 i++;
302 =======
303                 rc = OBP(conn->oc_dev,brw)(WRITE, conn, tgt, page, 1);
304                 if ( rc != PAGE_SIZE)
305                         break;
306                 
307                 index ++;
308 >>>>>>> 1.5
309         }
310         UnlockPage(page);
311         __free_page(page);
312
313         target->i_size = source->i_size;
314         OBP(obddev, setattr)(conn_id, target);
315
316         return err;
317 }