2 * linux/fs/ext2_obd/sim_obd.c
4 * These are the only exported functions; they provide the simulated object-
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>
24 extern struct obd_device obd_dev[MAX_OBD_DEVICES];
26 /* map connection to client */
27 struct obd_client *gen_client(struct obd_conn *conn)
29 struct obd_device * obddev = conn->oc_dev;
30 struct list_head * lh, * next;
31 struct obd_client * cli;
33 lh = next = &obddev->obd_gen_clients;
34 while ((lh = lh->next) != &obddev->obd_gen_clients) {
35 cli = list_entry(lh, struct obd_client, cli_chain);
37 if (cli->cli_id == conn->oc_id)
46 /* a connection defines a context in which preallocation can be managed. */
47 int gen_connect (struct obd_conn *conn)
49 struct obd_client * cli;
51 OBD_ALLOC(cli, struct obd_client *, sizeof(struct obd_client));
53 printk("obd_connect (minor %d): no memory!\n",
54 conn->oc_dev->obd_minor);
58 INIT_LIST_HEAD(&cli->cli_prealloc_inodes);
59 /* this should probably spinlocked? */
60 cli->cli_id = ++conn->oc_dev->obd_gen_last_id;
61 cli->cli_prealloc_quota = 0;
62 cli->cli_obd = conn->oc_dev;
63 list_add(&(cli->cli_chain), conn->oc_dev->obd_gen_clients.prev);
65 CDEBUG(D_IOCTL, "connect: new ID %u\n", cli->cli_id);
66 conn->oc_id = cli->cli_id;
68 } /* gen_obd_connect */
71 int gen_disconnect(struct obd_conn *conn)
73 struct obd_client * cli;
76 if (!(cli = gen_client(conn))) {
77 CDEBUG(D_IOCTL, "disconnect: attempting to free "
78 "nonexistent client %u\n", conn->oc_id);
83 list_del(&(cli->cli_chain));
84 OBD_FREE(cli, sizeof(struct obd_client));
86 CDEBUG(D_IOCTL, "disconnect: ID %u\n", conn->oc_id);
90 } /* gen_obd_disconnect */
94 * raid1 defines a number of connections to child devices,
95 * used to make calls to these devices.
98 int gen_multi_setup(struct obd_device *obddev, int len, void *data)
102 for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
104 struct obd_conn *ch_conn = &obddev->obd_multi_conn[i];
105 rc = OBP(ch_conn->oc_dev, connect)(ch_conn);
108 /* XXX disconnect others */
117 int gen_multi_attach(struct obd_device *obddev, int len, void *data)
121 struct obd_device *rdev = obddev->obd_multi_dev[0];
123 count = len/sizeof(int);
124 obddev->obd_multi_count = count;
125 for (i=0 ; i<count ; i++) {
126 rdev = &obd_dev[*((int *)data + i)];
128 CDEBUG(D_IOCTL, "OBD RAID1: replicator %d is of type %s\n", i,
129 (rdev + i)->obd_type->typ_name);
137 * remove all connections to this device
138 * close all connections to lower devices
139 * needed for forced unloads of OBD client drivers
141 int gen_multi_cleanup(struct obd_device *obddev)
145 for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
146 struct obd_conn *ch_conn = &obddev->obd_multi_conn[i];
148 rc = OBP(ch_conn->oc_dev, disconnect)(ch_conn);
151 printk("OBD multi cleanup dev: disconnect failure %d\n", ch_conn->oc_dev->obd_minor);
155 } /* gen_multi_cleanup_device */
159 * forced cleanup of the device:
160 * - remove connections from the device
161 * - cleanup the device afterwards
163 int gen_cleanup(struct obd_device * obddev)
165 struct list_head * lh, * tmp;
166 struct obd_client * cli;
170 lh = tmp = &obddev->obd_gen_clients;
171 while ((tmp = tmp->next) != lh) {
172 cli = list_entry(tmp, struct obd_client, cli_chain);
173 CDEBUG(D_IOCTL, "Disconnecting obd_connection %d, at %p\n",
177 } /* sim_cleanup_device */
179 void ___wait_on_page(struct page *page)
181 struct task_struct *tsk = current;
182 DECLARE_WAITQUEUE(wait, tsk);
184 add_wait_queue(&page->wait, &wait);
186 run_task_queue(&tq_disk);
187 set_task_state(tsk, TASK_UNINTERRUPTIBLE);
188 if (!PageLocked(page))
191 } while (PageLocked(page));
192 tsk->state = TASK_RUNNING;
193 remove_wait_queue(&page->wait, &wait);
196 void lck_page(struct page *page)
198 while (TryLockPage(page))
199 ___wait_on_page(page);
202 /* XXX this should return errors correctly, so should migrate!!! */
203 int gen_copy_data(struct obd_conn *conn, obdattr *tgt, obdattr *src)
206 unsigned long index = 0;
210 CDEBUG(D_INODE, "src: ino %ld blocks %ld, size %Ld, dst: ino %ld\n",
211 src->i_ino, src->i_blocks, src->i_size, dst->i_ino);
212 page = alloc_page(GFP_USER);
220 while (index < ((src->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT)) {
223 rc = OBP(conn->oc_dev, brw)(READ, conn, src, page, 0);
225 if ( rc != PAGE_SIZE )
228 rc = OBP(conn->oc_dev,brw)(WRITE, conn, tgt, page, 1);
229 if ( rc != PAGE_SIZE)
232 CDEBUG(D_INODE, "Copied page %d ...\n", index);
236 tgt->i_size = src->i_size;
237 tgt->i_blocks = src->i_blocks;