blkback.c revision 182371
1/*
2 * Copyright (c) 2006, Cisco Systems, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Cisco Systems, Inc. nor the names of its contributors
15 *    may be used to endorse or promote products derived from this software
16 *    without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/xen/blkback/blkback.c 182371 2008-08-28 15:23:18Z attilio $");
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/mbuf.h>
37#include <sys/malloc.h>
38#include <sys/kernel.h>
39#include <sys/socket.h>
40#include <sys/queue.h>
41#include <sys/taskqueue.h>
42#include <sys/namei.h>
43#include <sys/proc.h>
44#include <sys/filedesc.h>
45#include <sys/vnode.h>
46#include <sys/fcntl.h>
47#include <sys/disk.h>
48#include <sys/bio.h>
49
50#include <sys/module.h>
51#include <sys/bus.h>
52#include <sys/sysctl.h>
53
54#include <geom/geom.h>
55
56#include <vm/vm_extern.h>
57#include <vm/vm_kern.h>
58
59#include <machine/xen-os.h>
60#include <machine/hypervisor.h>
61#include <machine/hypervisor-ifs.h>
62#include <machine/xen_intr.h>
63#include <machine/evtchn.h>
64#include <machine/xenbus.h>
65#include <machine/gnttab.h>
66#include <machine/xen-public/memory.h>
67#include <dev/xen/xenbus/xenbus_comms.h>
68
69
70#if XEN_BLKBACK_DEBUG
71#define DPRINTF(fmt, args...) \
72    printf("blkback (%s:%d): " fmt, __FUNCTION__, __LINE__, ##args)
73#else
74#define DPRINTF(fmt, args...) ((void)0)
75#endif
76
77#define WPRINTF(fmt, args...) \
78    printf("blkback (%s:%d): " fmt, __FUNCTION__, __LINE__, ##args)
79
80#define BLKBACK_INVALID_HANDLE (~0)
81
82struct ring_ref {
83	vm_offset_t va;
84	grant_handle_t handle;
85	uint64_t bus_addr;
86};
87
88typedef struct blkback_info {
89
90	/* Schedule lists */
91	STAILQ_ENTRY(blkback_info) next_req;
92	int on_req_sched_list;
93
94	struct xenbus_device *xdev;
95	XenbusState frontend_state;
96
97	domid_t domid;
98
99	int state;
100	int ring_connected;
101	struct ring_ref rr;
102	blkif_back_ring_t ring;
103	evtchn_port_t evtchn;
104	int irq;
105	void *irq_cookie;
106
107	int ref_cnt;
108
109	int handle;
110	char *mode;
111	char *type;
112	char *dev_name;
113
114	struct vnode *vn;
115	struct cdev *cdev;
116	struct cdevsw *csw;
117	u_int sector_size;
118	int sector_size_shift;
119	off_t media_size;
120	u_int media_num_sectors;
121	int major;
122	int minor;
123	int read_only;
124
125	struct mtx blk_ring_lock;
126
127	device_t ndev;
128
129	/* Stats */
130	int st_rd_req;
131	int st_wr_req;
132	int st_oo_req;
133	int st_err_req;
134} blkif_t;
135
136/*
137 * These are rather arbitrary. They are fairly large because adjacent requests
138 * pulled from a communication ring are quite likely to end up being part of
139 * the same scatter/gather request at the disc.
140 *
141 * ** TRY INCREASING 'blkif_reqs' IF WRITE SPEEDS SEEM TOO LOW **
142 *
143 * This will increase the chances of being able to write whole tracks.
144 * 64 should be enough to keep us competitive with Linux.
145 */
146static int blkif_reqs = 64;
147TUNABLE_INT("xen.vbd.blkif_reqs", &blkif_reqs);
148
149static int mmap_pages;
150
151/*
152 * Each outstanding request that we've passed to the lower device layers has a
153 * 'pending_req' allocated to it. Each buffer_head that completes decrements
154 * the pendcnt towards zero. When it hits zero, the specified domain has a
155 * response queued for it, with the saved 'id' passed back.
156 */
157typedef struct pending_req {
158	blkif_t       *blkif;
159	uint64_t       id;
160	int            nr_pages;
161	int            pendcnt;
162	unsigned short operation;
163	int            status;
164	STAILQ_ENTRY(pending_req) free_list;
165} pending_req_t;
166
167static pending_req_t *pending_reqs;
168static STAILQ_HEAD(pending_reqs_list, pending_req) pending_free =
169	STAILQ_HEAD_INITIALIZER(pending_free);
170static struct mtx pending_free_lock;
171
172static STAILQ_HEAD(blkback_req_sched_list, blkback_info) req_sched_list =
173	STAILQ_HEAD_INITIALIZER(req_sched_list);
174static struct mtx req_sched_list_lock;
175
176static unsigned long mmap_vstart;
177static unsigned long *pending_vaddrs;
178static grant_handle_t *pending_grant_handles;
179
180static struct task blk_req_task;
181
182/* Protos */
183static void disconnect_ring(blkif_t *blkif);
184static int vbd_add_dev(struct xenbus_device *xdev);
185
186static inline int vaddr_pagenr(pending_req_t *req, int seg)
187{
188	return (req - pending_reqs) * BLKIF_MAX_SEGMENTS_PER_REQUEST + seg;
189}
190
191static inline unsigned long vaddr(pending_req_t *req, int seg)
192{
193	return pending_vaddrs[vaddr_pagenr(req, seg)];
194}
195
196#define pending_handle(_req, _seg) \
197	(pending_grant_handles[vaddr_pagenr(_req, _seg)])
198
199static unsigned long
200alloc_empty_page_range(unsigned long nr_pages)
201{
202	void *pages;
203	int i = 0, j = 0;
204	multicall_entry_t mcl[17];
205	unsigned long mfn_list[16];
206	struct xen_memory_reservation reservation = {
207		.extent_start = mfn_list,
208		.nr_extents   = 0,
209		.address_bits = 0,
210		.extent_order = 0,
211		.domid        = DOMID_SELF
212	};
213
214	pages = malloc(nr_pages*PAGE_SIZE, M_DEVBUF, M_NOWAIT);
215	if (pages == NULL)
216		return 0;
217
218	memset(mcl, 0, sizeof(mcl));
219
220	while (i < nr_pages) {
221		unsigned long va = (unsigned long)pages + (i++ * PAGE_SIZE);
222
223		mcl[j].op = __HYPERVISOR_update_va_mapping;
224		mcl[j].args[0] = va;
225
226		mfn_list[j++] = vtomach(va) >> PAGE_SHIFT;
227
228		xen_phys_machine[(vtophys(va) >> PAGE_SHIFT)] = INVALID_P2M_ENTRY;
229
230		if (j == 16 || i == nr_pages) {
231			mcl[j-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_LOCAL;
232
233			reservation.nr_extents = j;
234
235			mcl[j].op = __HYPERVISOR_memory_op;
236			mcl[j].args[0] = XENMEM_decrease_reservation;
237			mcl[j].args[1] =  (unsigned long)&reservation;
238
239			(void)HYPERVISOR_multicall(mcl, j+1);
240
241			mcl[j-1].args[MULTI_UVMFLAGS_INDEX] = 0;
242			j = 0;
243		}
244	}
245
246	return (unsigned long)pages;
247}
248
249static pending_req_t *
250alloc_req(void)
251{
252	pending_req_t *req;
253	mtx_lock(&pending_free_lock);
254	if ((req = STAILQ_FIRST(&pending_free))) {
255		STAILQ_REMOVE(&pending_free, req, pending_req, free_list);
256		STAILQ_NEXT(req, free_list) = NULL;
257	}
258	mtx_unlock(&pending_free_lock);
259	return req;
260}
261
262static void
263free_req(pending_req_t *req)
264{
265	int was_empty;
266
267	mtx_lock(&pending_free_lock);
268	was_empty = STAILQ_EMPTY(&pending_free);
269	STAILQ_INSERT_TAIL(&pending_free, req, free_list);
270	mtx_unlock(&pending_free_lock);
271	if (was_empty)
272		taskqueue_enqueue(taskqueue_swi, &blk_req_task);
273}
274
275static void
276fast_flush_area(pending_req_t *req)
277{
278	struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
279	unsigned int i, invcount = 0;
280	grant_handle_t handle;
281	int ret;
282
283	for (i = 0; i < req->nr_pages; i++) {
284		handle = pending_handle(req, i);
285		if (handle == BLKBACK_INVALID_HANDLE)
286			continue;
287		unmap[invcount].host_addr    = vaddr(req, i);
288		unmap[invcount].dev_bus_addr = 0;
289		unmap[invcount].handle       = handle;
290		pending_handle(req, i) = BLKBACK_INVALID_HANDLE;
291		invcount++;
292	}
293
294	ret = HYPERVISOR_grant_table_op(
295		GNTTABOP_unmap_grant_ref, unmap, invcount);
296	PANIC_IF(ret);
297}
298
299static void
300blkif_get(blkif_t *blkif)
301{
302	atomic_add_int(&blkif->ref_cnt, 1);
303}
304
305static void
306blkif_put(blkif_t *blkif)
307{
308	if (atomic_fetchadd_int(&blkif->ref_cnt, -1) == 1) {
309		DPRINTF("Removing %x\n", (unsigned int)blkif);
310		disconnect_ring(blkif);
311		if (blkif->mode)
312			free(blkif->mode, M_DEVBUF);
313		if (blkif->type)
314			free(blkif->type, M_DEVBUF);
315		if (blkif->dev_name)
316			free(blkif->dev_name, M_DEVBUF);
317		free(blkif, M_DEVBUF);
318	}
319}
320
321static int
322blkif_create(struct xenbus_device *xdev, long handle, char *mode, char *type, char *params)
323{
324	blkif_t *blkif;
325
326	blkif = (blkif_t *)malloc(sizeof(*blkif), M_DEVBUF, M_NOWAIT | M_ZERO);
327	if (!blkif)
328		return ENOMEM;
329
330	DPRINTF("Created %x\n", (unsigned int)blkif);
331
332	blkif->ref_cnt = 1;
333	blkif->domid = xdev->otherend_id;
334	blkif->handle = handle;
335	blkif->mode = mode;
336	blkif->type = type;
337	blkif->dev_name = params;
338	blkif->xdev = xdev;
339	xdev->data = blkif;
340
341	mtx_init(&blkif->blk_ring_lock, "blk_ring_ock", "blkback ring lock", MTX_DEF);
342
343	if (strcmp(mode, "w"))
344		blkif->read_only = 1;
345
346	return 0;
347}
348
349static void
350add_to_req_schedule_list_tail(blkif_t *blkif)
351{
352	if (!blkif->on_req_sched_list) {
353		mtx_lock(&req_sched_list_lock);
354		if (!blkif->on_req_sched_list && (blkif->state == XenbusStateConnected)) {
355			blkif_get(blkif);
356			STAILQ_INSERT_TAIL(&req_sched_list, blkif, next_req);
357			blkif->on_req_sched_list = 1;
358			taskqueue_enqueue(taskqueue_swi, &blk_req_task);
359		}
360		mtx_unlock(&req_sched_list_lock);
361	}
362}
363
364/* This routine does not call blkif_get(), does not schedule the blk_req_task to run,
365   and assumes that the state is connected */
366static void
367add_to_req_schedule_list_tail2(blkif_t *blkif)
368{
369	mtx_lock(&req_sched_list_lock);
370	if (!blkif->on_req_sched_list) {
371		STAILQ_INSERT_TAIL(&req_sched_list, blkif, next_req);
372		blkif->on_req_sched_list = 1;
373	}
374	mtx_unlock(&req_sched_list_lock);
375}
376
377/* Removes blkif from front of list and does not call blkif_put() (caller must) */
378static blkif_t *
379remove_from_req_schedule_list(void)
380{
381	blkif_t *blkif;
382
383	mtx_lock(&req_sched_list_lock);
384
385	if ((blkif = STAILQ_FIRST(&req_sched_list))) {
386		STAILQ_REMOVE(&req_sched_list, blkif, blkback_info, next_req);
387		STAILQ_NEXT(blkif, next_req) = NULL;
388		blkif->on_req_sched_list = 0;
389	}
390
391	mtx_unlock(&req_sched_list_lock);
392
393	return blkif;
394}
395
396static void
397make_response(blkif_t *blkif, uint64_t id,
398			  unsigned short op, int st)
399{
400	blkif_response_t *resp;
401	blkif_back_ring_t *blk_ring = &blkif->ring;
402	int more_to_do = 0;
403	int notify;
404
405	mtx_lock(&blkif->blk_ring_lock);
406
407
408	/* Place on the response ring for the relevant domain. */
409	resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
410	resp->id        = id;
411	resp->operation = op;
412	resp->status    = st;
413	blk_ring->rsp_prod_pvt++;
414	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_ring, notify);
415
416	if (blk_ring->rsp_prod_pvt == blk_ring->req_cons) {
417		/*
418		 * Tail check for pending requests. Allows frontend to avoid
419		 * notifications if requests are already in flight (lower
420		 * overheads and promotes batching).
421		 */
422		RING_FINAL_CHECK_FOR_REQUESTS(blk_ring, more_to_do);
423
424	} else if (RING_HAS_UNCONSUMED_REQUESTS(blk_ring))
425		more_to_do = 1;
426
427	mtx_unlock(&blkif->blk_ring_lock);
428
429	if (more_to_do)
430		add_to_req_schedule_list_tail(blkif);
431
432	if (notify)
433		notify_remote_via_irq(blkif->irq);
434}
435
436static void
437end_block_io_op(struct bio *bio)
438{
439	pending_req_t *pending_req = bio->bio_caller2;
440
441	if (bio->bio_error) {
442		DPRINTF("BIO returned error %d for operation on device %s\n",
443				bio->bio_error, pending_req->blkif->dev_name);
444		pending_req->status = BLKIF_RSP_ERROR;
445		pending_req->blkif->st_err_req++;
446	}
447
448#if 0
449	printf("done: bio=%x error=%x completed=%llu resid=%lu flags=%x\n",
450		   (unsigned int)bio, bio->bio_error, bio->bio_completed, bio->bio_resid, bio->bio_flags);
451#endif
452
453	if (atomic_fetchadd_int(&pending_req->pendcnt, -1) == 1) {
454		fast_flush_area(pending_req);
455		make_response(pending_req->blkif, pending_req->id,
456			      pending_req->operation, pending_req->status);
457		blkif_put(pending_req->blkif);
458		free_req(pending_req);
459	}
460
461	g_destroy_bio(bio);
462}
463
464static void
465dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req, pending_req_t *pending_req)
466{
467	struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST];
468	struct {
469		unsigned long buf; unsigned int nsec;
470	} seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
471	unsigned int nseg = req->nr_segments, nr_sects = 0;
472	struct bio *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST];
473	int operation, ret, i, nbio = 0;
474
475	/* Check that number of segments is sane. */
476	if (unlikely(nseg == 0) ||
477	    unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
478		DPRINTF("Bad number of segments in request (%d)\n", nseg);
479		goto fail_response;
480	}
481
482	if (req->operation == BLKIF_OP_WRITE) {
483		if (blkif->read_only) {
484			DPRINTF("Attempt to write to read only device %s\n", blkif->dev_name);
485			goto fail_response;
486		}
487		operation = BIO_WRITE;
488	} else
489		operation = BIO_READ;
490
491	pending_req->blkif     = blkif;
492	pending_req->id        = req->id;
493	pending_req->operation = req->operation;
494	pending_req->status    = BLKIF_RSP_OKAY;
495	pending_req->nr_pages  = nseg;
496
497	for (i = 0; i < nseg; i++) {
498		seg[i].nsec = req->seg[i].last_sect -
499			req->seg[i].first_sect + 1;
500
501		if ((req->seg[i].last_sect >= (PAGE_SIZE >> 9)) ||
502		    (seg[i].nsec <= 0))
503			goto fail_response;
504		nr_sects += seg[i].nsec;
505
506		map[i].host_addr = vaddr(pending_req, i);
507		map[i].dom = blkif->domid;
508		map[i].ref = req->seg[i].gref;
509		map[i].flags = GNTMAP_host_map;
510		if (operation == BIO_WRITE)
511			map[i].flags |= GNTMAP_readonly;
512	}
513
514	/* Convert to the disk's sector size */
515	nr_sects = (nr_sects << 9) >> blkif->sector_size_shift;
516
517	ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg);
518	PANIC_IF(ret);
519
520	for (i = 0; i < nseg; i++) {
521		if (unlikely(map[i].status != 0)) {
522			DPRINTF("invalid buffer -- could not remap it\n");
523			goto fail_flush;
524		}
525
526		pending_handle(pending_req, i) = map[i].handle;
527#if 0
528		/* Can't do this in FreeBSD since vtophys() returns the pfn */
529		/* of the remote domain who loaned us the machine page - DPT */
530		xen_phys_machine[(vtophys(vaddr(pending_req, i)) >> PAGE_SHIFT)] =
531			map[i]dev_bus_addr >> PAGE_SHIFT;
532#endif
533		seg[i].buf  = map[i].dev_bus_addr |
534			(req->seg[i].first_sect << 9);
535	}
536
537	if (req->sector_number + nr_sects > blkif->media_num_sectors) {
538		DPRINTF("%s of [%llu,%llu] extends past end of device %s\n",
539			operation == BIO_READ ? "read" : "write",
540			req->sector_number,
541			req->sector_number + nr_sects, blkif->dev_name);
542		goto fail_flush;
543	}
544
545	for (i = 0; i < nseg; i++) {
546		struct bio *bio;
547
548		if ((int)seg[i].nsec & ((blkif->sector_size >> 9) - 1)) {
549			DPRINTF("Misaligned I/O request from domain %d", blkif->domid);
550			goto fail_put_bio;
551		}
552
553		bio = biolist[nbio++] = g_new_bio();
554		if (unlikely(bio == NULL))
555			goto fail_put_bio;
556
557		bio->bio_cmd = operation;
558		bio->bio_offset = req->sector_number << blkif->sector_size_shift;
559		bio->bio_length = seg[i].nsec << 9;
560		bio->bio_bcount = bio->bio_length;
561		bio->bio_data = (caddr_t)(vaddr(pending_req, i) | (seg[i].buf & PAGE_MASK));
562		bio->bio_done = end_block_io_op;
563		bio->bio_caller2 = pending_req;
564		bio->bio_dev = blkif->cdev;
565
566		req->sector_number += (seg[i].nsec << 9) >> blkif->sector_size_shift;
567#if 0
568		printf("new: bio=%x cmd=%d sect=%llu nsect=%u iosize_max=%u @ %08lx\n",
569			(unsigned int)bio, req->operation, req->sector_number, seg[i].nsec,
570			blkif->cdev->si_iosize_max, seg[i].buf);
571#endif
572	}
573
574	pending_req->pendcnt = nbio;
575	blkif_get(blkif);
576
577	for (i = 0; i < nbio; i++)
578		(*blkif->csw->d_strategy)(biolist[i]);
579
580	return;
581
582 fail_put_bio:
583	for (i = 0; i < (nbio-1); i++)
584		g_destroy_bio(biolist[i]);
585 fail_flush:
586	fast_flush_area(pending_req);
587 fail_response:
588	make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
589	free_req(pending_req);
590}
591
592static void
593blk_req_action(void *context, int pending)
594{
595	blkif_t *blkif;
596
597	DPRINTF("\n");
598
599	while (!STAILQ_EMPTY(&req_sched_list)) {
600		blkif_back_ring_t *blk_ring;
601		RING_IDX rc, rp;
602
603		blkif = remove_from_req_schedule_list();
604
605		blk_ring = &blkif->ring;
606		rc = blk_ring->req_cons;
607		rp = blk_ring->sring->req_prod;
608		rmb(); /* Ensure we see queued requests up to 'rp'. */
609
610		while ((rc != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, rc)) {
611			blkif_request_t *req;
612			pending_req_t *pending_req;
613
614			pending_req = alloc_req();
615			if (pending_req == NULL)
616				goto out_of_preqs;
617
618			req = RING_GET_REQUEST(blk_ring, rc);
619			blk_ring->req_cons = ++rc; /* before make_response() */
620
621			switch (req->operation) {
622			case BLKIF_OP_READ:
623				blkif->st_rd_req++;
624				dispatch_rw_block_io(blkif, req, pending_req);
625				break;
626			case BLKIF_OP_WRITE:
627				blkif->st_wr_req++;
628				dispatch_rw_block_io(blkif, req, pending_req);
629				break;
630			default:
631				blkif->st_err_req++;
632				DPRINTF("error: unknown block io operation [%d]\n",
633						req->operation);
634				make_response(blkif, req->id, req->operation,
635							  BLKIF_RSP_ERROR);
636				free_req(pending_req);
637				break;
638			}
639		}
640
641		blkif_put(blkif);
642	}
643
644	return;
645
646 out_of_preqs:
647	/* We ran out of pending req structs */
648	/* Just requeue interface and wait to be rescheduled to run when one is freed */
649	add_to_req_schedule_list_tail2(blkif);
650	blkif->st_oo_req++;
651}
652
653/* Handle interrupt from a frontend */
654static void
655blkback_intr(void *arg)
656{
657	blkif_t *blkif = arg;
658	DPRINTF("%x\n", (unsigned int)blkif);
659	add_to_req_schedule_list_tail(blkif);
660}
661
662/* Map grant ref for ring */
663static int
664map_ring(grant_ref_t ref, domid_t dom, struct ring_ref *ring)
665{
666	struct gnttab_map_grant_ref op;
667
668	ring->va = kmem_alloc_nofault(kernel_map, PAGE_SIZE);
669	if (ring->va == 0)
670		return ENOMEM;
671
672	op.host_addr = ring->va;
673	op.flags = GNTMAP_host_map;
674	op.ref = ref;
675	op.dom = dom;
676	HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
677	if (op.status) {
678		WPRINTF("grant table op err=%d\n", op.status);
679		kmem_free(kernel_map, ring->va, PAGE_SIZE);
680		ring->va = 0;
681		return EACCES;
682	}
683
684	ring->handle = op.handle;
685	ring->bus_addr = op.dev_bus_addr;
686
687	return 0;
688}
689
690/* Unmap grant ref for ring */
691static void
692unmap_ring(struct ring_ref *ring)
693{
694	struct gnttab_unmap_grant_ref op;
695
696	op.host_addr = ring->va;
697	op.dev_bus_addr = ring->bus_addr;
698	op.handle = ring->handle;
699	HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
700	if (op.status)
701		WPRINTF("grant table op err=%d\n", op.status);
702
703	kmem_free(kernel_map, ring->va, PAGE_SIZE);
704	ring->va = 0;
705}
706
707static int
708connect_ring(blkif_t *blkif)
709{
710	struct xenbus_device *xdev = blkif->xdev;
711	blkif_sring_t *ring;
712	unsigned long ring_ref;
713	evtchn_port_t evtchn;
714	evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
715	int err;
716
717	if (blkif->ring_connected)
718		return 0;
719
720	// Grab FE data and map his memory
721	err = xenbus_gather(NULL, xdev->otherend,
722			"ring-ref", "%lu", &ring_ref,
723		    "event-channel", "%u", &evtchn, NULL);
724	if (err) {
725		xenbus_dev_fatal(xdev, err,
726			"reading %s/ring-ref and event-channel",
727			xdev->otherend);
728		return err;
729	}
730
731	err = map_ring(ring_ref, blkif->domid, &blkif->rr);
732	if (err) {
733		xenbus_dev_fatal(xdev, err, "mapping ring");
734		return err;
735	}
736	ring = (blkif_sring_t *)blkif->rr.va;
737	BACK_RING_INIT(&blkif->ring, ring, PAGE_SIZE);
738
739	op.u.bind_interdomain.remote_dom = blkif->domid;
740	op.u.bind_interdomain.remote_port = evtchn;
741	err = HYPERVISOR_event_channel_op(&op);
742	if (err) {
743		unmap_ring(&blkif->rr);
744		xenbus_dev_fatal(xdev, err, "binding event channel");
745		return err;
746	}
747	blkif->evtchn = op.u.bind_interdomain.local_port;
748
749	/* bind evtchn to irq handler */
750	blkif->irq =
751		bind_evtchn_to_irqhandler(blkif->evtchn, "blkback",
752			blkback_intr, blkif, INTR_TYPE_NET|INTR_MPSAFE, &blkif->irq_cookie);
753
754	blkif->ring_connected = 1;
755
756	DPRINTF("%x rings connected! evtchn=%d irq=%d\n",
757			(unsigned int)blkif, blkif->evtchn, blkif->irq);
758
759	return 0;
760}
761
762static void
763disconnect_ring(blkif_t *blkif)
764{
765	DPRINTF("\n");
766
767	if (blkif->ring_connected) {
768		unbind_from_irqhandler(blkif->irq, blkif->irq_cookie);
769		blkif->irq = 0;
770		unmap_ring(&blkif->rr);
771		blkif->ring_connected = 0;
772	}
773}
774
775static void
776connect(blkif_t *blkif)
777{
778	struct xenbus_transaction *xbt;
779	struct xenbus_device *xdev = blkif->xdev;
780	int err;
781
782	if (!blkif->ring_connected ||
783		blkif->vn == NULL ||
784		blkif->state == XenbusStateConnected)
785		return;
786
787	DPRINTF("%s\n", xdev->otherend);
788
789	/* Supply the information about the device the frontend needs */
790again:
791	xbt = xenbus_transaction_start();
792	if (IS_ERR(xbt)) {
793		xenbus_dev_fatal(xdev, PTR_ERR(xbt),
794						 "Error writing configuration for backend "
795						 "(start transaction)");
796		return;
797	}
798
799	err = xenbus_printf(xbt, xdev->nodename, "sectors", "%u",
800				blkif->media_num_sectors);
801	if (err) {
802		xenbus_dev_fatal(xdev, err, "writing %s/sectors",
803				 xdev->nodename);
804		goto abort;
805	}
806
807	err = xenbus_printf(xbt, xdev->nodename, "info", "%u",
808				blkif->read_only ? VDISK_READONLY : 0);
809	if (err) {
810		xenbus_dev_fatal(xdev, err, "writing %s/info",
811				 xdev->nodename);
812		goto abort;
813	}
814	err = xenbus_printf(xbt, xdev->nodename, "sector-size", "%u",
815			    blkif->sector_size);
816	if (err) {
817		xenbus_dev_fatal(xdev, err, "writing %s/sector-size",
818				 xdev->nodename);
819		goto abort;
820	}
821
822	err = xenbus_transaction_end(xbt, 0);
823	if (err == -EAGAIN)
824		goto again;
825	if (err)
826		xenbus_dev_fatal(xdev, err, "ending transaction");
827
828	err = xenbus_switch_state(xdev, NULL, XenbusStateConnected);
829	if (err)
830		xenbus_dev_fatal(xdev, err, "switching to Connected state",
831				 xdev->nodename);
832
833	blkif->state = XenbusStateConnected;
834
835	return;
836
837 abort:
838	xenbus_transaction_end(xbt, 1);
839}
840
841static int
842blkback_probe(struct xenbus_device *xdev, const struct xenbus_device_id *id)
843{
844	int err;
845	char *p, *mode = NULL, *type = NULL, *params = NULL;
846	long handle;
847
848	DPRINTF("node=%s\n", xdev->nodename);
849
850	p = strrchr(xdev->otherend, '/') + 1;
851	handle = strtoul(p, NULL, 0);
852
853	mode = xenbus_read(NULL, xdev->nodename, "mode", NULL);
854	if (IS_ERR(mode)) {
855		xenbus_dev_fatal(xdev, PTR_ERR(mode), "reading mode");
856		err = PTR_ERR(mode);
857		goto error;
858	}
859
860	type = xenbus_read(NULL, xdev->nodename, "type", NULL);
861	if (IS_ERR(type)) {
862		xenbus_dev_fatal(xdev, PTR_ERR(type), "reading type");
863		err = PTR_ERR(type);
864		goto error;
865	}
866
867	params = xenbus_read(NULL, xdev->nodename, "params", NULL);
868	if (IS_ERR(type)) {
869		xenbus_dev_fatal(xdev, PTR_ERR(params), "reading params");
870		err = PTR_ERR(params);
871		goto error;
872	}
873
874	err = blkif_create(xdev, handle, mode, type, params);
875	if (err) {
876		xenbus_dev_fatal(xdev, err, "creating blkif");
877		goto error;
878	}
879
880	err = vbd_add_dev(xdev);
881	if (err) {
882		blkif_put((blkif_t *)xdev->data);
883		xenbus_dev_fatal(xdev, err, "adding vbd device");
884	}
885
886	return err;
887
888 error:
889	if (mode)
890		free(mode, M_DEVBUF);
891	if (type)
892		free(type, M_DEVBUF);
893	if (params)
894		free(params, M_DEVBUF);
895	return err;
896}
897
898static int
899blkback_remove(struct xenbus_device *xdev)
900{
901	blkif_t *blkif = xdev->data;
902	device_t ndev;
903
904	DPRINTF("node=%s\n", xdev->nodename);
905
906	blkif->state = XenbusStateClosing;
907
908	if ((ndev = blkif->ndev)) {
909		blkif->ndev = NULL;
910		mtx_lock(&Giant);
911		device_detach(ndev);
912		mtx_unlock(&Giant);
913	}
914
915	xdev->data = NULL;
916	blkif->xdev = NULL;
917	blkif_put(blkif);
918
919	return 0;
920}
921
922static int
923blkback_resume(struct xenbus_device *xdev)
924{
925	DPRINTF("node=%s\n", xdev->nodename);
926	return 0;
927}
928
929static void
930frontend_changed(struct xenbus_device *xdev,
931				 XenbusState frontend_state)
932{
933	blkif_t *blkif = xdev->data;
934
935	DPRINTF("state=%d\n", frontend_state);
936
937	blkif->frontend_state = frontend_state;
938
939	switch (frontend_state) {
940	case XenbusStateInitialising:
941		break;
942	case XenbusStateInitialised:
943	case XenbusStateConnected:
944		connect_ring(blkif);
945		connect(blkif);
946		break;
947	case XenbusStateClosing:
948		xenbus_switch_state(xdev, NULL, XenbusStateClosing);
949		break;
950	case XenbusStateClosed:
951		xenbus_remove_device(xdev);
952		break;
953	case XenbusStateUnknown:
954	case XenbusStateInitWait:
955		xenbus_dev_fatal(xdev, EINVAL, "saw state %d at frontend",
956						 frontend_state);
957		break;
958	}
959}
960
961/* ** Driver registration ** */
962
963static struct xenbus_device_id blkback_ids[] = {
964	{ "vbd" },
965	{ "" }
966};
967
968static struct xenbus_driver blkback = {
969	.name = "blkback",
970	.ids = blkback_ids,
971	.probe = blkback_probe,
972	.remove = blkback_remove,
973	.resume = blkback_resume,
974	.otherend_changed = frontend_changed,
975};
976
977static void
978blkback_init(void *unused)
979{
980	int i;
981
982	TASK_INIT(&blk_req_task, 0, blk_req_action, NULL);
983	mtx_init(&req_sched_list_lock, "blk_req_sched_lock", "blkback req sched lock", MTX_DEF);
984
985	mtx_init(&pending_free_lock, "blk_pending_req_ock", "blkback pending request lock", MTX_DEF);
986
987	mmap_pages = blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST;
988	pending_reqs = malloc(sizeof(pending_reqs[0]) *
989		blkif_reqs, M_DEVBUF, M_ZERO|M_NOWAIT);
990	pending_grant_handles = malloc(sizeof(pending_grant_handles[0]) *
991		mmap_pages, M_DEVBUF, M_NOWAIT);
992	pending_vaddrs = malloc(sizeof(pending_vaddrs[0]) *
993		mmap_pages, M_DEVBUF, M_NOWAIT);
994	mmap_vstart = alloc_empty_page_range(mmap_pages);
995	if (!pending_reqs || !pending_grant_handles || !pending_vaddrs || !mmap_vstart) {
996		if (pending_reqs)
997			free(pending_reqs, M_DEVBUF);
998		if (pending_grant_handles)
999			free(pending_grant_handles, M_DEVBUF);
1000		if (pending_vaddrs)
1001			free(pending_vaddrs, M_DEVBUF);
1002		WPRINTF("out of memory\n");
1003		return;
1004	}
1005
1006	for (i = 0; i < mmap_pages; i++) {
1007		pending_vaddrs[i] = mmap_vstart + (i << PAGE_SHIFT);
1008		pending_grant_handles[i] = BLKBACK_INVALID_HANDLE;
1009	}
1010
1011	for (i = 0; i < blkif_reqs; i++) {
1012		STAILQ_INSERT_TAIL(&pending_free, &pending_reqs[i], free_list);
1013	}
1014
1015	DPRINTF("registering %s\n", blkback.name);
1016	xenbus_register_backend(&blkback);
1017}
1018
1019SYSINIT(xbbedev, SI_SUB_PSEUDO, SI_ORDER_ANY, blkback_init, NULL)
1020
1021static void
1022close_device(blkif_t *blkif)
1023{
1024	DPRINTF("closing dev=%s\n", blkif->dev_name);
1025	if (blkif->vn) {
1026		int flags = FREAD;
1027
1028		if (!blkif->read_only)
1029			flags |= FWRITE;
1030
1031		if (blkif->csw) {
1032			dev_relthread(blkif->cdev);
1033			blkif->csw = NULL;
1034		}
1035
1036		(void)vn_close(blkif->vn, flags, NOCRED, curthread);
1037		blkif->vn = NULL;
1038	}
1039}
1040
1041static int
1042open_device(blkif_t *blkif)
1043{
1044	struct nameidata nd;
1045	struct vattr vattr;
1046	struct cdev *dev;
1047	struct cdevsw *devsw;
1048	int flags = FREAD, err = 0;
1049
1050	DPRINTF("opening dev=%s\n", blkif->dev_name);
1051
1052	if (!blkif->read_only)
1053		flags |= FWRITE;
1054
1055	if (!curthread->td_proc->p_fd->fd_cdir) {
1056		curthread->td_proc->p_fd->fd_cdir = rootvnode;
1057		VREF(rootvnode);
1058	}
1059	if (!curthread->td_proc->p_fd->fd_rdir) {
1060		curthread->td_proc->p_fd->fd_rdir = rootvnode;
1061		VREF(rootvnode);
1062	}
1063	if (!curthread->td_proc->p_fd->fd_jdir) {
1064		curthread->td_proc->p_fd->fd_jdir = rootvnode;
1065		VREF(rootvnode);
1066	}
1067
1068 again:
1069	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, blkif->dev_name, curthread);
1070	err = vn_open(&nd, &flags, 0, -1);
1071	if (err) {
1072		if (blkif->dev_name[0] != '/') {
1073			char *dev_path = "/dev/";
1074			char *dev_name;
1075
1076			/* Try adding device path at beginning of name */
1077			dev_name = malloc(strlen(blkif->dev_name) + strlen(dev_path) + 1, M_DEVBUF, M_NOWAIT);
1078			if (dev_name) {
1079				sprintf(dev_name, "%s%s", dev_path, blkif->dev_name);
1080				free(blkif->dev_name, M_DEVBUF);
1081				blkif->dev_name = dev_name;
1082				goto again;
1083			}
1084		}
1085		xenbus_dev_fatal(blkif->xdev, err, "error opening device %s", blkif->dev_name);
1086		return err;
1087	}
1088	NDFREE(&nd, NDF_ONLY_PNBUF);
1089
1090	blkif->vn = nd.ni_vp;
1091
1092	/* We only support disks for now */
1093	if (!vn_isdisk(blkif->vn, &err)) {
1094		xenbus_dev_fatal(blkif->xdev, err, "device %s is not a disk", blkif->dev_name);
1095		VOP_UNLOCK(blkif->vn, 0, curthread);
1096		goto error;
1097	}
1098
1099	blkif->cdev = blkif->vn->v_rdev;
1100	blkif->csw = dev_refthread(blkif->cdev);
1101	PANIC_IF(blkif->csw == NULL);
1102
1103	err = VOP_GETATTR(blkif->vn, &vattr, NOCRED);
1104	if (err) {
1105		xenbus_dev_fatal(blkif->xdev, err,
1106			"error getting vnode attributes for device %s", blkif->dev_name);
1107		VOP_UNLOCK(blkif->vn, 0, curthread);
1108		goto error;
1109	}
1110
1111	VOP_UNLOCK(blkif->vn, 0, curthread);
1112
1113	dev = blkif->vn->v_rdev;
1114	devsw = dev->si_devsw;
1115	if (!devsw->d_ioctl) {
1116		err = ENODEV;
1117		xenbus_dev_fatal(blkif->xdev, err,
1118			"no d_ioctl for device %s!", blkif->dev_name);
1119		goto error;
1120	}
1121
1122	err = (*devsw->d_ioctl)(dev, DIOCGSECTORSIZE, (caddr_t)&blkif->sector_size, FREAD, curthread);
1123	if (err) {
1124		xenbus_dev_fatal(blkif->xdev, err,
1125			"error calling ioctl DIOCGSECTORSIZE for device %s", blkif->dev_name);
1126		goto error;
1127	}
1128	blkif->sector_size_shift = fls(blkif->sector_size) - 1;
1129
1130	err = (*devsw->d_ioctl)(dev, DIOCGMEDIASIZE, (caddr_t)&blkif->media_size, FREAD, curthread);
1131	if (err) {
1132		xenbus_dev_fatal(blkif->xdev, err,
1133			"error calling ioctl DIOCGMEDIASIZE for device %s", blkif->dev_name);
1134		goto error;
1135	}
1136	blkif->media_num_sectors = blkif->media_size >> blkif->sector_size_shift;
1137
1138	blkif->major = umajor(vattr.va_rdev);
1139	blkif->minor = uminor(vattr.va_rdev);
1140
1141	DPRINTF("opened dev=%s major=%d minor=%d sector_size=%u media_size=%lld\n",
1142			blkif->dev_name, blkif->major, blkif->minor, blkif->sector_size, blkif->media_size);
1143
1144	return 0;
1145
1146 error:
1147	close_device(blkif);
1148	return err;
1149}
1150
1151static int
1152vbd_add_dev(struct xenbus_device *xdev)
1153{
1154	blkif_t *blkif = xdev->data;
1155	device_t nexus, ndev;
1156	devclass_t dc;
1157	int err = 0;
1158
1159	mtx_lock(&Giant);
1160
1161	/* We will add a vbd device as a child of nexus0 (for now) */
1162	if (!(dc = devclass_find("nexus")) ||
1163		!(nexus = devclass_get_device(dc, 0))) {
1164		WPRINTF("could not find nexus0!\n");
1165		err = ENOENT;
1166		goto done;
1167	}
1168
1169
1170	/* Create a newbus device representing the vbd */
1171	ndev = BUS_ADD_CHILD(nexus, 0, "vbd", blkif->handle);
1172	if (!ndev) {
1173		WPRINTF("could not create newbus device vbd%d!\n", blkif->handle);
1174		err = EFAULT;
1175		goto done;
1176	}
1177
1178	blkif_get(blkif);
1179	device_set_ivars(ndev, blkif);
1180	blkif->ndev = ndev;
1181
1182	device_probe_and_attach(ndev);
1183
1184 done:
1185
1186	mtx_unlock(&Giant);
1187
1188	return err;
1189}
1190
1191enum {
1192	VBD_SYSCTL_DOMID,
1193	VBD_SYSCTL_ST_RD_REQ,
1194	VBD_SYSCTL_ST_WR_REQ,
1195	VBD_SYSCTL_ST_OO_REQ,
1196	VBD_SYSCTL_ST_ERR_REQ,
1197	VBD_SYSCTL_RING,
1198};
1199
1200static char *
1201vbd_sysctl_ring_info(blkif_t *blkif, int cmd)
1202{
1203	char *buf = malloc(256, M_DEVBUF, M_WAITOK);
1204	if (buf) {
1205		if (!blkif->ring_connected)
1206			sprintf(buf, "ring not connected\n");
1207		else {
1208			blkif_back_ring_t *ring = &blkif->ring;
1209			sprintf(buf, "nr_ents=%x req_cons=%x"
1210					" req_prod=%x req_event=%x"
1211					" rsp_prod=%x rsp_event=%x",
1212					ring->nr_ents, ring->req_cons,
1213					ring->sring->req_prod, ring->sring->req_event,
1214					ring->sring->rsp_prod, ring->sring->rsp_event);
1215		}
1216	}
1217	return buf;
1218}
1219
1220static int
1221vbd_sysctl_handler(SYSCTL_HANDLER_ARGS)
1222{
1223	device_t dev = (device_t)arg1;
1224	blkif_t *blkif = (blkif_t *)device_get_ivars(dev);
1225	const char *value;
1226	char *buf = NULL;
1227	int err;
1228
1229	switch (arg2) {
1230	case VBD_SYSCTL_DOMID:
1231		return sysctl_handle_int(oidp, NULL, blkif->domid, req);
1232	case VBD_SYSCTL_ST_RD_REQ:
1233		return sysctl_handle_int(oidp, NULL, blkif->st_rd_req, req);
1234	case VBD_SYSCTL_ST_WR_REQ:
1235		return sysctl_handle_int(oidp, NULL, blkif->st_wr_req, req);
1236	case VBD_SYSCTL_ST_OO_REQ:
1237		return sysctl_handle_int(oidp, NULL, blkif->st_oo_req, req);
1238	case VBD_SYSCTL_ST_ERR_REQ:
1239		return sysctl_handle_int(oidp, NULL, blkif->st_err_req, req);
1240	case VBD_SYSCTL_RING:
1241		value = buf = vbd_sysctl_ring_info(blkif, arg2);
1242		break;
1243	default:
1244		return (EINVAL);
1245	}
1246
1247	err = SYSCTL_OUT(req, value, strlen(value));
1248	if (buf != NULL)
1249		free(buf, M_DEVBUF);
1250
1251	return err;
1252}
1253
1254/* Newbus vbd device driver probe */
1255static int
1256vbd_probe(device_t dev)
1257{
1258	DPRINTF("vbd%d\n", device_get_unit(dev));
1259	return 0;
1260}
1261
1262/* Newbus vbd device driver attach */
1263static int
1264vbd_attach(device_t dev)
1265{
1266	blkif_t *blkif = (blkif_t *)device_get_ivars(dev);
1267
1268	DPRINTF("%s\n", blkif->dev_name);
1269
1270	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1271	    OID_AUTO, "domid", CTLTYPE_INT|CTLFLAG_RD,
1272	    dev, VBD_SYSCTL_DOMID, vbd_sysctl_handler, "I",
1273	    "domid of frontend");
1274	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1275	    OID_AUTO, "rd_reqs", CTLTYPE_INT|CTLFLAG_RD,
1276	    dev, VBD_SYSCTL_ST_RD_REQ, vbd_sysctl_handler, "I",
1277	    "number of read reqs");
1278	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1279	    OID_AUTO, "wr_reqs", CTLTYPE_INT|CTLFLAG_RD,
1280	    dev, VBD_SYSCTL_ST_WR_REQ, vbd_sysctl_handler, "I",
1281	    "number of write reqs");
1282	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1283	    OID_AUTO, "oo_reqs", CTLTYPE_INT|CTLFLAG_RD,
1284	    dev, VBD_SYSCTL_ST_OO_REQ, vbd_sysctl_handler, "I",
1285	    "number of deferred reqs");
1286	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1287	    OID_AUTO, "err_reqs", CTLTYPE_INT|CTLFLAG_RD,
1288	    dev, VBD_SYSCTL_ST_ERR_REQ, vbd_sysctl_handler, "I",
1289	    "number of reqs that returned error");
1290#if XEN_BLKBACK_DEBUG
1291	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1292	    OID_AUTO, "ring", CTLFLAG_RD,
1293	    dev, VBD_SYSCTL_RING, vbd_sysctl_handler, "A",
1294	    "req ring info");
1295#endif
1296
1297	if (!open_device(blkif))
1298		connect(blkif);
1299
1300	return bus_generic_attach(dev);
1301}
1302
1303/* Newbus vbd device driver detach */
1304static int
1305vbd_detach(device_t dev)
1306{
1307	blkif_t *blkif = (blkif_t *)device_get_ivars(dev);
1308
1309	DPRINTF("%s\n", blkif->dev_name);
1310
1311	close_device(blkif);
1312
1313	bus_generic_detach(dev);
1314
1315	blkif_put(blkif);
1316
1317	return 0;
1318}
1319
1320static device_method_t vbd_methods[] = {
1321	/* Device interface */
1322	DEVMETHOD(device_probe,		vbd_probe),
1323	DEVMETHOD(device_attach, 	vbd_attach),
1324	DEVMETHOD(device_detach,	vbd_detach),
1325	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
1326	DEVMETHOD(device_suspend,	bus_generic_suspend),
1327	DEVMETHOD(device_resume,	bus_generic_resume),
1328	{0, 0}
1329};
1330
1331static devclass_t vbd_devclass;
1332
1333static driver_t vbd_driver = {
1334	"vbd",
1335	vbd_methods,
1336	0,
1337};
1338
1339DRIVER_MODULE(vbd, nexus, vbd_driver, vbd_devclass, 0, 0);
1340
1341/*
1342 * Local variables:
1343 * mode: C
1344 * c-set-style: "BSD"
1345 * c-basic-offset: 4
1346 * tab-width: 4
1347 * indent-tabs-mode: t
1348 * End:
1349 */
1350