All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: CSCAN I/O scheduler for 2.6.10 kernel
From: Vishal Patil @ 2006-04-09 16:55 UTC (permalink / raw)
  To: Antonio Vargas; +Cc: Bill Davidsen, Linux Kernel Mailing List
In-Reply-To: <4745278c0604050646n668bc9fy2b8c18462439ae5d@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2723 bytes --]

I am attaching the CSCAN scheduler patch for 2.6.16.2 kernel.

- Vishal

On 4/5/06, Vishal Patil <vishpat@gmail.com> wrote:
> The two queues are used for sorting purposes ONLY. There is the
> dispatch queue to which the requests are moved from one of the queues
> and the request is processes of the dispatch queue.
>
> Example:
>
> Current request  = 40
> Q1 = 55 58 67 72
> Q2 = 10 23 38
>
> Assuming no other request arrives, these will be pushed on the
> dispatch queue in the following order
> 55 58 67 72 10 23 38
>
> I hope this clears things up.
>
> Also I have found that the patch that I had submitted earlier has few
> bugs in it. I am going to fix those and then submit a patch for 2.6.16
> Thanks.
>
>
> - Vishal
>
>
>
> On 4/5/06, Antonio Vargas <windenntw@gmail.com> wrote:
> > On 4/4/06, Vishal Patil <vishpat@gmail.com> wrote:
> > > In that case it would be a normal elevator algorithm and that has a
> > > possiblity of starving the requests at one end of the disk.
> > >
> > > - Vishal
> > >
> > > On 4/4/06, Bill Davidsen <davidsen@tmr.com> wrote:
> > > > Vishal Patil wrote:
> > > > > Maintain two queues which will be sorted in ascending order using Red
> > > > > Black Trees. When a disk request arrives and if the block number it
> > > > > refers to is greater than the block number of the current request
> > > > > being served add (merge) it to the first sorted queue or else add
> > > > > (merge) it to the second sorted queue. Keep on servicing the requests
> > > > > from the first request queue until it is empty after which switch over
> > > > > to the second queue and now reverse the roles of the two queues.
> > > > > Simple and Sweet. Many thanks for the awesome block I/O layer in the
> > > > > 2.6 kernel.
> > > > >
> > > > Why both queues sorting in ascending order? I would think that one
> > > > should be in descending order, which would reduce the seek distance
> > > > between the last i/o on one queue and the first on the next.
> > > >
> >
> > But, if there are two queues, one which is being processed and other
> > which gets the new requests (and the corresponding queue switch when
> > the current is empty), then there is no way to get starved when they
> > are sorted in opposite order.
> >
> >
> > --
> > Greetz, Antonio Vargas aka winden of network
> >
> > http://wind.codepixel.com/
> > windNOenSPAMntw@gmail.com
> > thesameasabove@amigascne.org
> >
> > Every day, every year
> > you have to work
> > you have to study
> > you have to scene.
> >
>
>
> --
> Every passing minute is another chance to turn it all around.
>


--
Every passing minute is another chance to turn it all around.

[-- Attachment #2: cscan-2.6.16.2-patch --]
[-- Type: application/octet-stream, Size: 11599 bytes --]

diff -urN linux-2.6.16.2/block/cscan.c linux-2.6.16.2-cscan/block/cscan.c
--- linux-2.6.16.2/block/cscan.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.16.2-cscan/block/cscan.c	2006-04-09 10:24:52.000000000 -0400
@@ -0,0 +1,338 @@
+/*
+ * elevator cscan
+ */
+#include <linux/blkdev.h>
+#include <linux/elevator.h>
+#include <linux/bio.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#define RQ_DATA(rq) ((struct cscan_request *) (rq)->elevator_private)
+
+#define RB_NONE         (2)
+#define RB_EMPTY(root)  ((root)->rb_node == NULL)
+#define ON_RB(node)     ((node)->rb_color != RB_NONE)
+#define RB_CLEAR(node)  ((node)->rb_color = RB_NONE)
+#define rb_entry_crq(node)      rb_entry((node), struct cscan_request, rb_node)
+#define DRQ_RB_ROOT(cd, crq)    (&(cd)->sort_list[rq_data_dir((crq)->request)])
+#define rq_rb_key(rq)           (rq)->sector
+
+
+struct cscan_data {
+        struct rb_root sort_list[2];
+        unsigned int count[2];
+        
+        sector_t last_sector;
+        unsigned int first;
+        mempool_t * crq_pool;
+};
+
+struct cscan_request {
+        struct rb_node rb_node;
+        sector_t rb_key;
+        unsigned int queue_id;
+
+        struct request * request;
+};
+
+static kmem_cache_t *crq_pool;
+
+/*
+ *      Searching/Sorting routines
+ */
+static struct cscan_request *
+__rb_insert_request(struct rb_root * root, struct cscan_request * crq) 
+{
+        struct rb_node **p = &root->rb_node;
+        struct rb_node *parent = NULL;
+        struct cscan_request * __crq;
+        
+         while(*p) {
+                parent = *p;
+                __crq = rb_entry(parent,struct cscan_request,rb_node);
+
+                if(crq->rb_key < __crq->rb_key) {
+                        p = &(*p)->rb_left;
+                } else if(crq->rb_key > __crq->rb_key) {
+                        p = &(*p)->rb_right;
+                } else {
+                        return __crq;
+                }
+        }
+        rb_link_node(&crq->rb_node,parent,p);
+        return NULL;
+} 
+
+static inline struct
+cscan_request * rb_insert_request(struct rb_root * root, 
+                                     struct cscan_request * crq)
+{
+        struct cscan_request * ret;
+        if((ret = __rb_insert_request(root,crq)))
+                goto out;
+        rb_insert_color(&crq->rb_node,root);
+out:
+        return ret;
+}
+
+static inline struct
+cscan_request * rb_find_request(struct rb_root * root, long key) 
+{
+        struct rb_node * n = root->rb_node;
+        struct cscan_request * crq;
+
+        while(n) 
+        {
+                crq = rb_entry(n,struct cscan_request,rb_node);
+
+                if (key > crq->rb_key) {
+                        n = n->rb_right;
+                } else if (key < crq->rb_key) {
+                        n = n->rb_left;
+                } else {
+                        return crq;
+                }
+        }
+        return NULL;
+}
+static void 
+cscan_remove_request(struct cscan_data * cd, struct cscan_request * crq) 
+{
+        rb_erase(&crq->rb_node, &cd->sort_list[crq->queue_id]);
+        RB_CLEAR(&crq->rb_node);
+        cd->count[crq->queue_id]--;
+}
+
+static void
+cscan_add_crq_rb(struct cscan_data * cd, struct cscan_request * crq) 
+{
+        crq->rb_key = rq_rb_key(crq->request);
+        rb_insert_request(&cd->sort_list[crq->queue_id],crq);
+        cd->count[crq->queue_id]++;
+}
+
+static void 
+cscan_merged_requests(request_queue_t *q, struct request *rq,
+				 struct request *next)
+{
+	struct cscan_data *cd = q->elevator->elevator_data;
+        struct cscan_request * crq;        
+        crq = RQ_DATA(rq);
+
+        cscan_remove_request(cd,crq);
+}
+
+static int 
+cscan_dispatch(request_queue_t *q, int force)
+{
+	struct cscan_data *cd = q->elevator->elevator_data;
+        struct rb_root * root = NULL;
+
+        if(rb_first(&cd->sort_list[cd->first])) {
+               root = &cd->sort_list[cd->first]; 
+        } else if(rb_first(&cd->sort_list[1 - cd->first])) {
+                root = &cd->sort_list[1 - cd->first]; 
+                cd->first = 1 - cd->first; 
+        }
+
+	if (root) {
+		struct cscan_request *crq;
+                struct request * rq;
+                
+		crq = rb_entry_crq(rb_first(root));
+                rq = crq->request;
+                cscan_remove_request(cd,crq);
+                cd->last_sector = rq->sector + rq->nr_sectors;
+		elv_dispatch_sort(q, rq);
+		return 1;
+	}
+	return 0;
+}
+
+static void 
+cscan_add_request(request_queue_t *q, struct request *rq)
+{
+	struct cscan_data *cd = q->elevator->elevator_data;
+        struct cscan_request * crq;        
+        
+        crq = RQ_DATA(rq);
+        if(rq->sector > cd->last_sector) 
+                crq->queue_id = cd->first;
+        else 
+                crq->queue_id = 1 - cd->first;
+        cscan_add_crq_rb(cd,crq);                                 
+}
+
+static int 
+cscan_queue_empty(request_queue_t *q)
+{
+	struct cscan_data *cd = q->elevator->elevator_data;
+
+        return ((rb_first(&cd->sort_list[cd->first]) == NULL) && 
+                (rb_first(&cd->sort_list[1 - cd->first]) == NULL));
+}
+
+static struct request *
+cscan_former_request(request_queue_t *q, struct request *rq)
+{
+	struct cscan_data *cd = q->elevator->elevator_data;
+        struct cscan_request * crq = RQ_DATA(rq); 
+       
+        if((crq->queue_id == cd->first) && (rb_prev(&crq->rb_node) == NULL))
+                return NULL;
+        
+        if( (crq->queue_id == (1 - cd->first)) && 
+                                (rb_prev(&crq->rb_node) == NULL)){
+                if(rb_last(&cd->sort_list[cd->first])){
+                	crq = rb_entry_crq(rb_last(
+                                &cd->sort_list[cd->first]));
+                        return crq->request;                                
+                } else {
+                        return NULL;
+                }
+        }            
+        
+        return rb_entry_crq(rb_prev(&crq->rb_node))->request;
+}
+
+static struct request *
+cscan_latter_request(request_queue_t *q, struct request *rq)
+{
+	struct cscan_data *cd = q->elevator->elevator_data;
+        struct cscan_request * crq = RQ_DATA(rq); 
+       
+        if((crq->queue_id == (1 - cd->first)) && 
+                                (rb_next(&crq->rb_node) == NULL))
+                return NULL;
+        
+        if( (crq->queue_id == cd->first) && 
+                                (rb_next(&crq->rb_node) == NULL)){
+                if(rb_first(&cd->sort_list[1 - cd->first])){
+                	crq = rb_entry_crq(rb_first(
+                                &cd->sort_list[1 - cd->first]));
+                        return crq->request;                                
+                } else {
+                        return NULL;
+                }
+        }            
+        
+        return rb_entry_crq(rb_next(&crq->rb_node))->request;
+
+}
+
+static void 
+cscan_put_request(request_queue_t *q, struct request * rq) 
+{
+        struct cscan_data * cd = q->elevator->elevator_data;
+        struct cscan_request *crq = RQ_DATA(rq);
+
+        mempool_free(crq,cd->crq_pool);
+        rq->elevator_private = NULL;
+}
+
+static int
+cscan_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
+                     gfp_t gfp_mask)
+{
+        struct cscan_data * cd = q->elevator->elevator_data;
+        struct cscan_request * crq;
+        
+        crq = mempool_alloc(cd->crq_pool,gfp_mask);
+        if(crq) {
+                memset(crq,0,sizeof(*crq));
+                RB_CLEAR(&crq->rb_node);
+                crq->request = rq;
+                rq->elevator_private = crq;
+                return 0;
+        }
+        return 1;
+}
+
+
+static int 
+cscan_init_queue(request_queue_t *q, elevator_t *e)
+{
+	struct cscan_data *cd;
+        int i = 0;
+
+	cd = kmalloc(sizeof(*cd), GFP_KERNEL);
+	if (!cd)
+		return -ENOMEM;
+                
+        cd->first = 0;
+        cd->last_sector = 0;
+        for(i=0;i<2;i++) {
+                cd->sort_list[i] = RB_ROOT;
+                cd->count[i]     = 0;
+        }
+	e->elevator_data = cd;
+
+        cd->crq_pool = mempool_create(BLKDEV_MIN_RQ,mempool_alloc_slab,
+                        mempool_free_slab,crq_pool);
+
+       if(!cd->crq_pool) {
+                kfree(cd);
+                return -ENOMEM;
+       }
+	return 0;
+}
+
+static void 
+cscan_exit_queue(elevator_t *e)
+{
+	struct cscan_data *cd = e->elevator_data;
+
+        BUG_ON(rb_first(&cd->sort_list[cd->first]) != NULL);
+        BUG_ON(rb_first(&cd->sort_list[1 - cd->first]) != NULL);
+
+	kfree(cd);
+}
+
+static struct elevator_type elevator_cscan = {
+	.ops = {
+		.elevator_merge_req_fn		= cscan_merged_requests,
+		.elevator_dispatch_fn		= cscan_dispatch,
+		.elevator_add_req_fn		= cscan_add_request,
+		.elevator_queue_empty_fn	= cscan_queue_empty,
+		.elevator_former_req_fn		= cscan_former_request,
+		.elevator_latter_req_fn		= cscan_latter_request,
+                .elevator_set_req_fn            = cscan_set_request,
+                .elevator_put_req_fn            = cscan_put_request,
+		.elevator_init_fn		= cscan_init_queue,
+		.elevator_exit_fn		= cscan_exit_queue,
+	},
+	.elevator_name = "cscan",
+	.elevator_owner = THIS_MODULE,
+};
+
+static int __init 
+cscan_init(void)
+{
+        int ret;
+
+        crq_pool = kmem_cache_create("cscan_crq", sizeof(struct cscan_request),
+                                     0, 0, NULL, NULL);
+        if (!crq_pool)
+                 return -ENOMEM;
+
+        ret = elv_register(&elevator_cscan);
+        if(ret)
+                kmem_cache_destroy(crq_pool);
+        
+        return ret;
+}
+
+static void __exit 
+cscan_exit(void)
+{
+        kmem_cache_destroy(crq_pool);
+	elv_unregister(&elevator_cscan);
+}
+
+module_init(cscan_init);
+module_exit(cscan_exit);
+
+
+MODULE_AUTHOR("Vishal Patil");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("CSCAN I/O scheduler");
diff -urN linux-2.6.16.2/block/Kconfig.iosched linux-2.6.16.2-cscan/block/Kconfig.iosched
--- linux-2.6.16.2/block/Kconfig.iosched	2006-04-07 12:56:47.000000000 -0400
+++ linux-2.6.16.2-cscan/block/Kconfig.iosched	2006-04-09 10:25:07.000000000 -0400
@@ -11,6 +11,19 @@
 	  that do their own scheduling and require only minimal assistance from
 	  the kernel.
 
+config IOSCHED_CSCAN
+	bool
+	default y
+	---help---
+        CSCAN I/O scheduler. Maintain two queues which will be sorted in
+        ascending order using Red Black Trees. When a disk request arrives and
+        if the block number it refers to is greater than the block number of the
+        current request being served add (merge) it to the first sorted queue or
+        else add (merge) it to the second sorted queue. Keep on servicing the
+        requests from the first request queue until it is empty after which
+        switch over to the second queue and now reverse the roles of the two
+        queues
+
 config IOSCHED_AS
 	tristate "Anticipatory I/O scheduler"
 	default y
diff -urN linux-2.6.16.2/block/Makefile linux-2.6.16.2-cscan/block/Makefile
--- linux-2.6.16.2/block/Makefile	2006-04-07 12:56:47.000000000 -0400
+++ linux-2.6.16.2-cscan/block/Makefile	2006-04-09 10:24:58.000000000 -0400
@@ -5,6 +5,7 @@
 obj-y	:= elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o
 
 obj-$(CONFIG_IOSCHED_NOOP)	+= noop-iosched.o
+obj-$(CONFIG_IOSCHED_CSCAN)	+= cscan.o
 obj-$(CONFIG_IOSCHED_AS)	+= as-iosched.o
 obj-$(CONFIG_IOSCHED_DEADLINE)	+= deadline-iosched.o
 obj-$(CONFIG_IOSCHED_CFQ)	+= cfq-iosched.o


^ permalink raw reply

* Re: Linux 2.6.17-rc1: /sbin/iptables does not find kernel netfilter
From: Nix @ 2006-04-09 16:53 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: vherva, linux-kernel, netfilter, davem
In-Reply-To: <4439385B.6010908@trash.net>

On Sun, 09 Apr 2006, Patrick McHardy murmured woefully:
> Nix wrote:
>>>Thanks for the help, and sorry for the noise. I hope not too many people hit
>>>the same glitch while upgrading...
>> 
>> 
>> I cetainly did. A simple `make oldconfig' ends up zapping pretty much
>> all the old iptables CONFIG_ options, so you end up with not much of
>> iptables or netfilter left.
> 
> But it does show you all the new options. Admittedly, it would
> have been better to automatically select the new options when
> needed, but probably not worth changing it now, it has been
> like this for two releases I think.

Oh, yes, it did, and I thought they were userspace-matching related and
left them off. The real problem is that oldconfig doesn't mention when
options you *had* enabled disappear.

>> I must admit not quite understanding why the xtables stuff is needed:
>> I thought that was needed for userspace connection tracking, which
>> while it sounds cool isn't something I'm using yet.
> 
> Its a unification of the matches and targets that are address family
> independant.

Ah, hence the ipv6-matching stuff turning up in 2.6.16. I see.

-- 
`On a scale of 1-10, X's "brokenness rating" is 1.1, but that's only
 because bringing Windows into the picture rescaled "brokenness" by
 a factor of 10.' --- Peter da Silva

^ permalink raw reply

* Re: [PATCH] git log [diff-tree options]...
From: Linus Torvalds @ 2006-04-09 16:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v7j5zce7x.fsf@assigned-by-dhcp.cox.net>



On Sun, 9 Apr 2006, Junio C Hamano wrote:
>
> And this makes "git log" to take common diff-tree options, so
> that it can be used as "git whatchanged".

I wonder... This all looks fine, but there are actually two different 
"diffs" that can be shown for "git log --diff <pathlimiter>":

 - the whole diff for a commit

 - the path-limited diff

and I think we'd likely want to have some way to select the output. 
Probably with the path-limited diff being the default (that's what 
"git-whatchanged" does), but perhaps with "--full-diff" showing the whole 
commit diff (which is what "gitk" does).

		Linus

^ permalink raw reply

* Re: [Qemu-devel] Absolute USB-HID device musings (was Re: VNC Terminal Server)
From: Brad Campbell @ 2006-04-09 16:49 UTC (permalink / raw)
  To: qemu-devel
In-Reply-To: <44393064.2050300@win4lin.com>

Leonardo E. Reiter wrote:
> Yeah, the min/max value thing would be a pain for sure.  The X server 
> config method seems to be the best bet.
> 
> On another note, I am trying to imagine what would make logical sense 
> for say, a touch screen.  For example, an LCD panel has a native 
> resolution, say 1024x768.  It would then emulate (or transparently 
> expand) other VESA resolutions, such as 640x480, on the fly.  I would 
> think that if it had touchscreen capabilities, the coordinates would 
> always be reported in native mode.  So the guest OS must have to scale 
> them down... especially if the device reports the range early on in the 
> identification process.

Every touchscreen I've ever used (which would be serial and USB Intellitouch and serial MicroTouch) 
used to report fixed absolute positions and the driver scaled them after a simple 2 or 5 point 
calibration routine. So they were indexed to the position on the monitor glass, not what was 
underneath it. We never changed screen resolutions so that was never an issue itself..

On LCD's it worked great and never needed recalibrating as the pixels don't move. On CRT's we needed 
to recalibrate every time some donkey fiddled with the H&V pos/scale knobs.

Interestingly enough the Intellitouch reports z axis as well. It delivers an 8 bit force value.

 From what I've been able to figure thus far, the min/max thing seems to be the device telling the 
OS what it's minimum and maximum values are on each axis. It's then up to the OS to relate that to 
the current screen resolution.

And after finding my old code buried under many TB of other garbage.. I note my memory failed me 
partially. The mouse events were poked directly into the windows message queue with 
MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE and the X and Y values were calculated from the touchscreen 
calibration values, scaled to be 0x0->0xffff and poked in as dwords.

This was all cool as I had the cursor turned off. If the cursor needed to be displayed/moved also 
then it was set with SetCursorPos() which of course uses resolution dependent coordinates. Nice of 
windows to be consistent!

Time to do some 'sperimenting I guess..

-- 
"Human beings, who are almost unique in having the ability
to learn from the experience of others, are also remarkable
for their apparent disinclination to do so." -- Douglas Adams

^ permalink raw reply

* Re: [patch][rfc] quell interactive feeding frenzy
From: Al Boldi @ 2006-04-09 16:44 UTC (permalink / raw)
  To: linux-kernel

bert hubert wrote:
> On Sun, Apr 09, 2006 at 01:39:38PM +0200, Mike Galbraith wrote:
> > Ok, unusable may be overstated.  Nonetheless, that bit of code causes
> > serious problems.  It makes my little PIII/500 test box trying to fill
> > one 100Mbit local network unusable.  That is not overstated.
>
> If you try to make a PIII/500 fill 100mbit of TCP/IP using lots of
> different processes, that IS a corner load.
>
> I'm sure you can fix this (rare) workload but are you very sure you are
> not killing off performance for other situations?

This really has nothing to do w/ workload but rather w/ multi-user processing 
/tasking /threading.  And the mere fact that the 2.6 kernel prefers 
kernel-threads should imply an overall performance increase (think pdflush).

The reason why not many have noticed this scheduler problem(s) is because 
most hackers nowadays work w/ the latest fastest hw available which does not 
allow them to see these problems (think Windows, where most problems are 
resolved by buying the latest hw).

Real Hackers never miss out on making their work run on the smallest common 
denominator (think i386dx :).

Thanks!

--
Al


^ permalink raw reply

* Re: [Qemu-devel] qemu-0.8.0 and vde-1.5.9 question
From: Jim C. Brown @ 2006-04-09 16:45 UTC (permalink / raw)
  To: qemu-devel
In-Reply-To: <Pine.LNX.4.56.0604051521320.29607@pali.cps.cmich.edu>

On Wed, Apr 05, 2006 at 03:25:18PM -0400, Ishwar Rattan wrote:
> The system is Kanotix-2005-4
> Qemu-0.8.0
> Vde-1.5.9
> 
> I setup the bridge and add interface tun0 to the bridge
> (have done it before correctly)
> 
> but
> 
> /usr/bin/vdeqemu -hda disk-image -m256 -localtime -net vde -net nic,macaddr=54:52:00:12:34:62
> 
> reports error:
> qemu: invalid option -- '-tun-fd'
> qemu exited: vdeqemu quits
> 
> I seem to reacall that it worked with qemu-0.7.2 ?
> 

qemu network options have changed.

You need vde 1.5.11 or vde2 with qemu 0.8.0 and later versions (includes cvs).

> Any ideas?
> 
> -ishwar
> 
> 
> 
> _______________________________________________
> Qemu-devel mailing list
> Qemu-devel@nongnu.org
> http://lists.nongnu.org/mailman/listinfo/qemu-devel
> 

-- 
Infinite complexity begets infinite beauty.
Infinite precision begets infinite perfection.

^ permalink raw reply

* Re: [ANNOUNCE] git-svnconvert: YASI (Yet Another SVN importer)
From: Jakub Narebski @ 2006-04-09 16:43 UTC (permalink / raw)
  To: git
In-Reply-To: <20060409163426.GA22103@nospam.com>

Rutger Nijlunsing wrote:

> Since I didn't succeed in importing a (private) SVN repo into git, I
> wrote a new converter to handle more cases like:

Both git-svn[*1*] and git-svnimport failed? Have you tried Tailor tool:
  http://www.darcs.net/DarcsWiki/Tailor

>   - use command line svn instead of some perl library to have less
>     dependancies and to support proxy + repo authentification.
>     Might even work on MacOSX ;)

Instead adding dependence on Ruby, eh?


References
----------
[*1*] contrib/git-svn and http://git-svn.yhbt.net/
-- 
Jakub Narebski
Warsaw, Poland

^ permalink raw reply

* Re: [Qemu-devel] VNC terminal server?
From: Anthony Liguori @ 2006-04-09 16:40 UTC (permalink / raw)
  To: qemu-devel
In-Reply-To: <44393116.3060900@win4lin.com>

Leonardo E. Reiter wrote:
> Hi Anthony,
>
> I noticed that the Windows driver does not work... it does send a 
> bunch of commands to the tablet, mostly resets, but then claims that 
> it can't discover it.  I downloaded the latest driver from wacom.com.

Yes, this is what I said.  The Windows driver uses a bunch more commands 
than the Linux driver that I have not implemented (which is why I 
haven't submitted to this list yet).

> I did not try this with a Linux guest yet.... maybe that should be my 
> next thing, and see what it will take to make it work without the SDL 
> grab altogether (and sync up).  If that can work reliably, then adding 
> the bits to the protocol that Windows expects would be worth the work.
>
> I'm thinking that this device would be a good complementary option to 
> an absolute USB HID device.  Having both in the long run won't hurt, 
> especially if certain OS's prefer serial over USB absolute pointers, 
> and vice versa.

Xorg CVS has initial support for absolute USB devices so I think this is 
the best route for the future.

Regards,

Anthony Liguori

> - Leo Reiter
>
> Anthony Liguori wrote:
>> The driver isn't built into Windows.  It's pretty easy to install 
>> though and the way my patch works, the PS/2 mouse is used until it 
>> detects the tablet has been enabled.
>>
>> The Windows driver uses quite a bit more of the features of the 
>> tablet than the X driver so there's a bit more work to do but nothing 
>> extraordinary.
>>
>> Regards,
>>
>> Anthony Liguori
>

^ permalink raw reply

* Re: Linux 2.6.17-rc1: /sbin/iptables does not find kernel netfilter
From: Patrick McHardy @ 2006-04-09 16:37 UTC (permalink / raw)
  To: Nix; +Cc: vherva, linux-kernel, netfilter, davem
In-Reply-To: <87psjqg2nt.fsf@hades.wkstn.nix>

Nix wrote:
> On 9 Apr 2006, Ville Herva yowled:
> 
>>On Sun, Apr 09, 2006 at 05:44:16PM +0300, you [Ville Herva] wrote:
>>
>>>I just realized 
>>># CONFIG_NETFILTER_XT_MATCH_STATE is not set
>>>should probably be set. I'm building a new kernel now...
>>
>>Ok, that seems to do it.
>>
>>Thanks for the help, and sorry for the noise. I hope not too many people hit
>>the same glitch while upgrading...
> 
> 
> I cetainly did. A simple `make oldconfig' ends up zapping pretty much
> all the old iptables CONFIG_ options, so you end up with not much of
> iptables or netfilter left.

But it does show you all the new options. Admittedly, it would
have been better to automatically select the new options when
needed, but probably not worth changing it now, it has been
like this for two releases I think.

> I must admit not quite understanding why the xtables stuff is needed:
> I thought that was needed for userspace connection tracking, which
> while it sounds cool isn't something I'm using yet.

Its a unification of the matches and targets that are address family
independant.

^ permalink raw reply

* [Qemu-devel] Re: experimental FreeBSD {k,}qemu port update
From: Juergen Lock @ 2006-04-09 16:34 UTC (permalink / raw)
  To: freebsd-emulation, qemu-devel
In-Reply-To: <20060401222151.GA45952@saturn.kn-bremen.de>

On Sun, Apr 02, 2006 at 12:21:52AM +0200, Juergen Lock wrote:
> Here is what I have tested on i386 with kqemu.  [...]

Updated version using yesterday's cvs snapshot and malc's latest
sound patch (still needs the kqemu port update from the linked message
which is archived here:
	http://docs.freebsd.org/cgi/mid.cgi?20060401222151.GA45952
)

 With this you no longer need QEMU_AUDIO_DRV=sdl to get sound working
with linux alsa guests. (thanks malc!)

Removed files:
files/patch-dyngen.h files/patch-hw-ne2000.c
files/patch-hw-usb-uhci.c files/patch-hw-usb.c files/patch-sdl.c
files/patch-slirp-socket.c files/patch-slirp_throttle
files/patch-target-i386-translate.c

New file:
files/patch-malc-17h_aqemu

Index: Makefile
===================================================================
RCS file: /home/ncvs/ports/emulators/qemu/Makefile,v
retrieving revision 1.47
diff -u -r1.47 Makefile
--- Makefile	26 Mar 2006 15:11:36 -0000	1.47
+++ Makefile	9 Apr 2006 15:57:39 -0000
@@ -6,8 +6,7 @@
 #
 
 PORTNAME=	qemu
-PORTVERSION=	0.8.0
-PORTREVISION=	5
+PORTVERSION=	0.8.0s.20060408
 CATEGORIES=	emulators
 MASTER_SITES=	http://www.qemu.org/:release \
 		http://people.fruitsalad.org/nox/qemu/:snapshot \
@@ -15,10 +14,8 @@
 		http://qemu.dad-answers.com/download/qemu/:snapshot \
 		http://people.brandeis.edu/~jcoiner/qemu_idedma/:idedma \
 		http://people.freebsd.org/~maho/qemu/:misc
-DISTFILES=	${DISTNAME}${EXTRACT_SUFX}:release
-.if defined (WITH_HACKS_IDEDMA) || defined (WITH_HACKS)
-DISTFILES+=	qemu_dma_patch.tar.gz:idedma
-.endif
+DISTNAME=	${PORTNAME}-snapshot-2006-04-08_23
+DISTFILES=	${DISTNAME}${EXTRACT_SUFX}:snapshot
 .if defined (WITH_HACKS_CIRRUS) || defined (WITH_HACKS)
 DISTFILES+=	patch3_cirrus:misc
 .endif
@@ -33,10 +30,11 @@
 RUN_DEPENDS+=	${LOCALBASE}/sbin/smbd:${PORTSDIR}/net/samba
 .endif
 .if defined(WITH_KQEMU)
-BUILD_DEPENDS+=	${LOCALBASE}/include/kqemu/kqemu.h:${PORTSDIR}/emulators/kqemu-kmod
+BUILD_DEPENDS+=	kqemu-kmod>=1.3.0pre5:${PORTSDIR}/emulators/kqemu-kmod
 .endif
 
 HAS_CONFIGURE=	yes
+USE_BZIP2=	yes
 USE_GMAKE=	yes
 USE_GETOPT_LONG=	yes
 USE_SDL=	sdl
@@ -64,11 +62,9 @@
 	@${ECHO_MSG} "Notice: you can build qemu with the (alpha!) kqemu accelerator kernel module"
 	@${ECHO_MSG} "by defining WITH_KQEMU."
 .endif
-.if !defined(WITH_HACKS_IDEDMA) && !defined(WITH_HACKS_CIRRUS) && !defined(WITH_HACKS)
+.if !defined(WITH_HACKS_CIRRUS) && !defined(WITH_HACKS)
 	@${ECHO_MSG} "You can build qemu with some hacks (esp. for speedup)"
 	@${ECHO_MSG} "by defining WITH_HACKS, or specifically:"
-	@${ECHO_MSG} "1. WITH_HACKS_IDEDMA: IDE Bus-master DMA Support by John Coiner"
-	@${ECHO_MSG} "http://people.brandeis.edu/~jcoiner/qemu_idedma/qemu_dma_patch.html"
 	@${ECHO_MSG} "2. WITH_HACKS_CIRRUS: higher speed on large display (cirrus_vga)"
 	@${ECHO_MSG} "by Juergen Pfennig"
 	@${ECHO_MSG} "http://lists.gnu.org/archive/html/qemu-devel/2006-01/msg00208.html"
@@ -92,9 +88,6 @@
 	done
 
 post-patch:
-.if defined(WITH_HACKS_IDEDMA) || defined (WITH_HACKS)
-	@cd ${WRKDIR} ; ${TAR} xfz ${DISTDIR}/${DIST_SUBDIR}/qemu_dma_patch.tar.gz ; ${CP} new_qemu_dma_patch/bios.bin ${WRKSRC}/pc-bios; cd ${WRKSRC}; ${PATCH} --quiet -p1 < ../new_qemu_dma_patch/qemu-piix4-udma.patch
-.endif
 .if defined(WITH_HACKS_CIRRUS) || defined (WITH_HACKS)
 	@cd ${WRKSRC} ; ${PATCH} --quiet < ${DISTDIR}/${DIST_SUBDIR}/patch3_cirrus
 .endif
Index: distinfo
===================================================================
RCS file: /home/ncvs/ports/emulators/qemu/distinfo,v
retrieving revision 1.27
diff -u -r1.27 distinfo
--- distinfo	21 Jan 2006 23:10:06 -0000	1.27
+++ distinfo	9 Apr 2006 15:58:11 -0000
@@ -1,9 +1,6 @@
-MD5 (qemu/qemu-0.8.0.tar.gz) = eb175b26583280706fe7e4d8910d320d
-SHA256 (qemu/qemu-0.8.0.tar.gz) = de388539ce86971a2cbe8474fca8b6160898c95772e3e6e08a7794d48db32a61
-SIZE (qemu/qemu-0.8.0.tar.gz) = 1497965
-MD5 (qemu/qemu_dma_patch.tar.gz) = 5e339dc201d411af56bad684d3f89338
-SHA256 (qemu/qemu_dma_patch.tar.gz) = cdf74bf5e079d835e100f116d940686b13ec2b7ed6aee5a6a97a4441ea5f2b8f
-SIZE (qemu/qemu_dma_patch.tar.gz) = 25837
+MD5 (qemu/qemu-snapshot-2006-04-08_23.tar.bz2) = 74fd8046d94d5d800f1df35282dba733
+SHA256 (qemu/qemu-snapshot-2006-04-08_23.tar.bz2) = 5cdcab83fa0fa6188c846f2d9c96d019300f6c7742d2ecf3cceae0a014fd6318
+SIZE (qemu/qemu-snapshot-2006-04-08_23.tar.bz2) = 1288264
 MD5 (qemu/patch3_cirrus) = ebe7ed9fce804c49e024bc93bfdfc810
 SHA256 (qemu/patch3_cirrus) = e862371834b7d895a896fbdb84fd9f70d17b5729a6f6789a48a61504fc941e11
 SIZE (qemu/patch3_cirrus) = 8817
Index: files/patch-bsdusb.patch
===================================================================
RCS file: /home/ncvs/ports/emulators/qemu/files/patch-bsdusb.patch,v
retrieving revision 1.1
diff -u -r1.1 patch-bsdusb.patch
--- files/patch-bsdusb.patch	18 Mar 2006 21:23:42 -0000	1.1
+++ files/patch-bsdusb.patch	27 Mar 2006 23:30:53 -0000
@@ -1,8 +1,9 @@
 Index: qemu/configure
-@@ -122,6 +122,7 @@
+@@ -122,7 +122,8 @@
  *)
  oss="yes"
  linux="yes"
+ user="yes"
 +usb="linux"
  if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
      kqemu="yes"
Index: files/patch-fbsd
===================================================================
RCS file: /home/ncvs/ports/emulators/qemu/files/patch-fbsd,v
retrieving revision 1.4
diff -u -r1.4 patch-fbsd
--- files/patch-fbsd	1 Oct 2005 13:25:09 -0000	1.4
+++ files/patch-fbsd	27 Mar 2006 23:39:21 -0000
@@ -1,5 +1,5 @@
 Index: qemu/Makefile
-@@ -13,7 +13,7 @@
+@@ -13,11 +13,14 @@
  endif
  DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1
  
@@ -8,14 +8,6 @@
  	for d in $(TARGET_DIRS); do \
  	$(MAKE) -C $$d $@ || exit 1 ; \
          done
-@@ -21,10 +21,13 @@
- ifdef CONFIG_WIN32
- 	$(MAKE) -C kqemu -f Makefile.winnt
- else
--	$(MAKE) -C kqemu
-+	( cd kqemu && $(BSD_MAKE) -f Makefile.freebsd )
- endif
- endif
  
 +bsd/libmath.a:
 +	( cd bsd ; $(BSD_MAKE) CC=$(CC) )
@@ -23,7 +15,7 @@
  qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c
  	$(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
  
-@@ -33,6 +36,7 @@
+@@ -26,6 +29,7 @@
  
  clean:
  # avoid old build problems by removing potentially incorrect old files
@@ -31,25 +23,6 @@
  	rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h 
  	rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS *.pod *~ */*~
  	$(MAKE) -C tests clean
-@@ -40,7 +44,7 @@
- 	$(MAKE) -C $$d $@ || exit 1 ; \
-         done
- ifdef CONFIG_KQEMU
--	$(MAKE) -C kqemu clean
-+	cd kqemu && $(BSD_MAKE) -f Makefile.freebsd clean
- endif
- 
- distclean: clean
-@@ -73,9 +77,6 @@
- 	for d in $(TARGET_DIRS); do \
- 	$(MAKE) -C $$d $@ || exit 1 ; \
-         done
--ifdef CONFIG_KQEMU
--	cd kqemu ; ./install.sh
--endif
- 
- # various test targets
- test speed test2: all
 Index: qemu/Makefile.target
 @@ -391,8 +391,8 @@
  VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
Index: files/patch-malc-17h_aqemu
@@ -0,0 +1,243 @@
+Index: qemu/audio/alsaaudio.c
+===================================================================
+RCS file: /home/malc/cvsroot/bellard/qemu/audio/alsaaudio.c,v
+retrieving revision 1.1.1.4
+retrieving revision 1.1.1.1.2.8
+diff -u -r1.1.1.4 -r1.1.1.1.2.8
+--- audio/alsaaudio.c	21 Nov 2005 12:47:06 -0000	1.1.1.4
++++ audio/alsaaudio.c	7 Apr 2006 22:05:21 -0000	1.1.1.1.2.8
+@@ -61,8 +61,8 @@
+     .size_in_usec_in = 1,
+     .size_in_usec_out = 1,
+ #endif
+-    .pcm_name_out = "hw:0,0",
+-    .pcm_name_in = "hw:0,0",
++    .pcm_name_out = "default",
++    .pcm_name_in = "default",
+ #ifdef HIGH_LATENCY
+     .buffer_size_in = 400000,
+     .period_size_in = 400000 / 4,
+Index: qemu/audio/audio.h
+===================================================================
+RCS file: /home/malc/cvsroot/bellard/qemu/audio/audio.h,v
+retrieving revision 1.1.1.3
+retrieving revision 1.1.1.1.2.5
+diff -u -r1.1.1.3 -r1.1.1.1.2.5
+--- audio/audio.h	21 Nov 2005 12:47:06 -0000	1.1.1.3
++++ audio/audio.h	7 Apr 2006 22:05:21 -0000	1.1.1.1.2.5
+@@ -111,7 +111,7 @@
+ }
+ 
+ uint32_t popcount (uint32_t u);
+-inline uint32_t lsbindex (uint32_t u);
++uint32_t lsbindex (uint32_t u);
+ 
+ #ifdef __GNUC__
+ #define audio_MIN(a, b) ( __extension__ ({      \
+Index: qemu/audio/dsound_template.h
+===================================================================
+RCS file: /home/malc/cvsroot/bellard/qemu/audio/dsound_template.h,v
+retrieving revision 1.1.1.2
+retrieving revision 1.1.1.1.2.2
+diff -u -r1.1.1.2 -r1.1.1.1.2.2
+--- audio/dsound_template.h	5 Nov 2005 20:42:14 -0000	1.1.1.2
++++ audio/dsound_template.h	7 Apr 2006 22:05:21 -0000	1.1.1.1.2.2
+@@ -70,7 +70,13 @@
+     int i;
+     LPVOID p1 = NULL, p2 = NULL;
+     DWORD blen1 = 0, blen2 = 0;
++    DWORD flag;
+ 
++#ifdef DSBTYPE_IN
++    flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
++#else
++    flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
++#endif
+     for (i = 0; i < conf.lock_retries; ++i) {
+         hr = glue (IFACE, _Lock) (
+             buf,
+@@ -80,13 +86,7 @@
+             &blen1,
+             &p2,
+             &blen2,
+-            (entire
+-#ifdef DSBTYPE_IN
+-             ? DSCBLOCK_ENTIREBUFFER
+-#else
+-             ? DSBLOCK_ENTIREBUFFER
+-#endif
+-             : 0)
++            flag
+             );
+ 
+         if (FAILED (hr)) {
+Index: qemu/audio/dsoundaudio.c
+===================================================================
+RCS file: /home/malc/cvsroot/bellard/qemu/audio/dsoundaudio.c,v
+retrieving revision 1.1.1.2
+retrieving revision 1.1.1.1.2.2
+diff -u -r1.1.1.2 -r1.1.1.1.2.2
+--- audio/dsoundaudio.c	5 Nov 2005 20:42:14 -0000	1.1.1.2
++++ audio/dsoundaudio.c	7 Apr 2006 22:05:21 -0000	1.1.1.1.2.2
+@@ -987,6 +987,12 @@
+     hr = IDirectSound_Initialize (s->dsound, NULL);
+     if (FAILED (hr)) {
+         dsound_logerr (hr, "Could not initialize DirectSound\n");
++
++        hr = IDirectSound_Release (s->dsound);
++        if (FAILED (hr)) {
++            dsound_logerr (hr, "Could not release DirectSound\n");
++        }
++        s->dsound = NULL;
+         return NULL;
+     }
+ 
+Index: qemu/audio/ossaudio.c
+===================================================================
+RCS file: /home/malc/cvsroot/bellard/qemu/audio/ossaudio.c,v
+retrieving revision 1.1.1.4
+retrieving revision 1.1.1.1.2.5
+diff -u -r1.1.1.4 -r1.1.1.1.2.5
+--- audio/ossaudio.c	21 Nov 2005 12:47:06 -0000	1.1.1.4
++++ audio/ossaudio.c	7 Apr 2006 22:23:42 -0000	1.1.1.1.2.5
+@@ -324,9 +324,18 @@
+             return 0;
+         }
+ 
+-        if (abinfo.bytes < 0 || abinfo.bytes > bufsize) {
+-            ldebug ("warning: Invalid available size, size=%d bufsize=%d\n",
+-                    abinfo.bytes, bufsize);
++        if (abinfo.bytes > bufsize) {
++#ifndef __FreeBSD__
++            dolog ("warning: Invalid available size, size=%d bufsize=%d\n"
++                   "please report your OS/audio hw to malc@pulsesoft.com\n",
++                   abinfo.bytes, bufsize);
++#endif
++            abinfo.bytes = bufsize;
++        }
++
++        if (abinfo.bytes < 0) {
++            dolog ("warning: Invalid available size, size=%d bufsize=%d\n",
++                   abinfo.bytes, bufsize);
+             return 0;
+         }
+ 
+Index: qemu/hw/es1370.c
+===================================================================
+RCS file: /home/malc/cvsroot/bellard/qemu/hw/es1370.c,v
+retrieving revision 1.1.1.4
+retrieving revision 1.1.1.1.2.7
+diff -u -r1.1.1.4 -r1.1.1.1.2.7
+--- hw/es1370.c	21 Nov 2005 12:47:06 -0000	1.1.1.4
++++ hw/es1370.c	7 Apr 2006 22:05:21 -0000	1.1.1.1.2.7
+@@ -479,9 +479,10 @@
+ IO_WRITE_PROTO (es1370_writeb)
+ {
+     ES1370State *s = opaque;
+-    addr = es1370_fixup (s, addr);
+     uint32_t shift, mask;
+ 
++    addr = es1370_fixup (s, addr);
++
+     switch (addr) {
+     case ES1370_REG_CONTROL:
+     case ES1370_REG_CONTROL + 1:
+Index: qemu/hw/sb16.c
+===================================================================
+RCS file: /home/malc/cvsroot/bellard/qemu/hw/sb16.c,v
+retrieving revision 1.1.1.4
+retrieving revision 1.1.1.1.2.6
+diff -u -r1.1.1.4 -r1.1.1.1.2.6
+--- hw/sb16.c	21 Nov 2005 12:47:06 -0000	1.1.1.4
++++ hw/sb16.c	7 Apr 2006 22:23:59 -0000	1.1.1.1.2.6
+@@ -193,6 +193,31 @@
+ #define DMA8_AUTO 1
+ #define DMA8_HIGH 2
+ 
++static void continue_dma8 (SB16State *s)
++{
++    if (s->freq > 0) {
++        audsettings_t as;
++
++        s->audio_free = 0;
++
++        as.freq = s->freq;
++        as.nchannels = 1 << s->fmt_stereo;
++        as.fmt = s->fmt;
++
++        s->voice = AUD_open_out (
++            &s->card,
++            s->voice,
++            "sb16",
++            s,
++            SB_audio_callback,
++            &as,
++            0                   /* little endian */
++            );
++    }
++
++    control (s, 1);
++}
++
+ static void dma_cmd8 (SB16State *s, int mask, int dma_len)
+ {
+     s->fmt = AUD_FMT_U8;
+@@ -201,7 +226,8 @@
+     s->fmt_signed = 0;
+     s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
+     if (-1 == s->time_const) {
+-        s->freq = 11025;
++        if (s->freq <= 0)
++            s->freq = 11025;
+     }
+     else {
+         int tmp = (256 - s->time_const);
+@@ -239,27 +265,7 @@
+             s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
+             s->block_size, s->dma_auto, s->fifo, s->highspeed);
+ 
+-    if (s->freq) {
+-        audsettings_t as;
+-
+-        s->audio_free = 0;
+-
+-        as.freq = s->freq;
+-        as.nchannels = 1 << s->fmt_stereo;
+-        as.fmt = s->fmt;
+-
+-        s->voice = AUD_open_out (
+-            &s->card,
+-            s->voice,
+-            "sb16",
+-            s,
+-            SB_audio_callback,
+-            &as,
+-            0                   /* little endian */
+-            );
+-    }
+-
+-    control (s, 1);
++    continue_dma8 (s);
+     speaker (s, 1);
+ }
+ 
+@@ -437,7 +443,7 @@
+             break;
+ 
+         case 0x1c:              /* Auto-Initialize DMA DAC, 8-bit */
+-            control (s, 1);
++            dma_cmd8 (s, DMA8_AUTO, -1);
+             break;
+ 
+         case 0x20:              /* Direct ADC, Juice/PL */
+@@ -531,7 +537,9 @@
+             break;
+ 
+         case 0xd4:              /* continue DMA operation. 8bit */
+-            control (s, 1);
++            /* KQ6 (or maybe Sierras audblst.drv in general) resets
++               the frequency between halt/continue */
++            continue_dma8 (s);
+             break;
+ 
+         case 0xd5:              /* halt DMA operation. 16bit */

^ permalink raw reply

* Re: Linux 2.6.17-rc1: /sbin/iptables does not find kernel netfilter
From: Patrick McHardy @ 2006-04-09 16:37 UTC (permalink / raw)
  To: Nix; +Cc: netfilter, linux-kernel, vherva, davem
In-Reply-To: <87psjqg2nt.fsf@hades.wkstn.nix>

Nix wrote:
> On 9 Apr 2006, Ville Herva yowled:
> 
>>On Sun, Apr 09, 2006 at 05:44:16PM +0300, you [Ville Herva] wrote:
>>
>>>I just realized 
>>># CONFIG_NETFILTER_XT_MATCH_STATE is not set
>>>should probably be set. I'm building a new kernel now...
>>
>>Ok, that seems to do it.
>>
>>Thanks for the help, and sorry for the noise. I hope not too many people hit
>>the same glitch while upgrading...
> 
> 
> I cetainly did. A simple `make oldconfig' ends up zapping pretty much
> all the old iptables CONFIG_ options, so you end up with not much of
> iptables or netfilter left.

But it does show you all the new options. Admittedly, it would
have been better to automatically select the new options when
needed, but probably not worth changing it now, it has been
like this for two releases I think.

> I must admit not quite understanding why the xtables stuff is needed:
> I thought that was needed for userspace connection tracking, which
> while it sounds cool isn't something I'm using yet.

Its a unification of the matches and targets that are address family
independant.


^ permalink raw reply

* [ANNOUNCE] git-svnconvert: YASI (Yet Another SVN importer)
From: Rutger Nijlunsing @ 2006-04-09 16:34 UTC (permalink / raw)
  To: git

[-- Attachment #1: Type: text/plain, Size: 1038 bytes --]

Hi all,

Since I didn't succeed in importing a (private) SVN repo into git, I
wrote a new converter to handle more cases like:

  - use command line svn instead of some perl library to have less
    dependancies and to support proxy + repo authentification.
    Might even work on MacOSX ;)
  - automatic merge detection by looking at from which revision a
    revision gets its files
  - visualisation of the branch tree with dotty to check what git-convert
    would produce _before_ importing it.
  - /trunk is moved to /branches/old, /branches/new_branch becomes /trunk
    in next revision (ARGH!)
  - To be able to continue after a ^C and be able to continue where
    it stopped.
  - have configurable repo layout to handle things like:
    - files next to branches in /branches
    - /branches/

Regards,
Rutger.

-- 
Rutger Nijlunsing ---------------------------------- eludias ed dse.nl
never attribute to a conspiracy which can be explained by incompetence
----------------------------------------------------------------------

[-- Attachment #2: git-svnconvert.rb --]
[-- Type: text/plain, Size: 29546 bytes --]

#!/usr/bin/env ruby

# Convert a Subversion repository with all its branches
# into git incrementally.
#
# The main difference with git-svnimport is
# that it handles a badly-broken archive which I wanted to 
# convert which git-svnimport did not handle ;)
#
# But, of course, your milage may (will!) vary. svn only defines
# snapshot-trees and interpretation of each leaf in the tree is left
# as an exercise for the reader.
#
# Features:
#  - import _all_ branches
#  - uses svn command line, so:
#    - supports HTTP proxy with authentification
#    - supports repository authentification
#    - supports incorrect (self-signed) SSL certificates ;)
#  - can handle multiple branche changes in one revision
#  - supports extra files in /branches next to real branches
#  - gets merge information by looking at which revisions we're based on
#    (so no need to parse commit messages)
#    This (only) works when the merge of two branches results
#    in files from both branches.
#  - handles missing revisions
#  - no extra packages needed, just ruby and subversion.
#  - outputs GraphViz .dot files for visualisation of branches
#  - fairly interrupt-save. Once in a while it saves it state
#    to be able to continue next time where it left off.
#  - works parallel: one process fetches, while another copies
#    it into git.
# Con:
#  - needs a complete, checked-out SVN repository locally
#    _for_ _each_ _branch_.
#    This takes disk space. However, disk space is cheap ;)
# TODO:
#  - parse XML as XML instead of text. In case the exact XML formatting
#    changes in the future...
#  - add tagging support
#  - handle file properties like execute and ignore
#  - use 'svn switch' to checkout other branches fast
#
# Workings
#  - Get a log of all commits
#  - Create a branches graph from this log
#  - Check out each revision separately and write a commit
#    for each revision.
#
# (c)2006 R. Nijlunsing <git-svnconvert@tux.tmfweb.nl>
# Released under the GNU Public License, version 2.


$VERBOSE = true			# Let Ruby warn more

require 'set'
require 'time'
require 'find'
require 'fileutils'
require 'optparse'
require 'cgi'			# For unescapeHTML()

#################### Configuration

# Root directories of the branches and trunk(s).
#   - one line per directory
#   - '*' matches one filename component and is matched last
#   - names are case sensitive
#   - whitespaces at start and end are ignored
$branch_dirs = %q{
  /branches/*
  /branches/cc_test/*
  /branches/pre-dev/trunk
  /branches/pre-dev/trunk_old
  /branches/tasks/*
  /trunk
}

# List of paths which might get matched by $branch_dirs,
# but which are not the root of branches.
#
# Argh. People put files into the root of branches,
# which ends up as a branch (so for example /branches/README
# ends up as a branch). List here all files in the roots
# to ignore them.
$not_branch_dirs = %q{
  /branches/README
  /branches/pre-dev
  /branches/cc_test
  /branches/tasks
}

#################### End of configuration

def read_svn_authors(authors_filename)
  users = {}
  begin
    IO.foreach(authors_filename) { |line|
      if line =~ %r{^(\S+?)\s*=\s*(.+?)\s*<(.+)>\s*$}
	user, name, email = $1, $2, $3
	users[user] = [name, email]
      end
    }
  rescue Errno::ENOENT, Errno::EACCES
    die("Could not read #{authors_filename}: #{$!}")
  end
  if $verbose
    puts "Read #{users.size} authors from #{authors_filename}"
  end
  return users
end

def write_svn_authors(users, authors_filename)
  begin
    File.open(authors_filename, "wb") { |io|
      users.keys.sort.each { |user|
	io.puts "#{user} = #{users[user][0]} <#{users[user][1]}>"
      }
    }
    if $verbose
      puts "Wrote #{users.size} authors to #{authors_filename}"
    end
  rescue Errno::EACCES
    die("Could not write #{authors_filename}: #{$!}")
  end
end

# Given a string with on each line a root directory, generate a regular
# expression matching one of those root directories.
def root_dirs_to_regexp(rootdirs, is_prefix)
  Regexp.new(
    "^(?:" +			# Match at start without capturing
    rootdirs.
      split("\n").
      find_all { |dir| dir.strip != "" }.	# Delete empty lines
      collect { |dir|
        # make path absolute; use '/' as path separator;
        ("/" + dir.strip).gsub(%r{[\\/]+}, "/")
      }.sort { |dir1, dir2|
        # Sort on size so '/branches/development/trunk' comes before
        # '/branches/*' and will therefore be matched.
        dir2.size <=> dir1.size
      }.collect { |dir|
        Regexp.escape(dir)	# Escape everything
      }.join("|").gsub("\\*", "[^/]+") + # Unescape '*' back
    ")" +
    # If not a prefix, must match at end
    # If prefix, must match at path delimiter (or at end)
    (is_prefix ? "(?=/|$)" : "$")  
  )
end

# Execute shell command; bail out at error
def safe_system(cmd)
  puts cmd if $verbose
  system(cmd)
  if $? != 0
    puts cmd if !$verbose
    puts "!!! Command returned non-zero exit code: #{$?}"
    puts "!!! Working dir: #{Dir.pwd}"
    exit $?
  end
end

def safe_popen(cmd, mode = "w+", &callback)
  puts "|" + cmd if $verbose
  res = IO.popen(cmd, mode, &callback)
  if $? != 0
    puts cmd if !$verbose
    puts "!!! Command returned non-zero exit code: #{$?}"
    puts "!!! Working dir: #{Dir.pwd}"
    exit $?
  end
  return res
end

module Shell
  # Escape string string so that it is parsed to the string itself
  # Compare to Regexp.escape .
  def self.escape(string)
    string !~ %r{[ "\\]}i ? 
      string : '"' + string.gsub(%r{(["\\])}i, '\\\\\1') + '"'
  end
end

def svn_common_args(branch = "")
  repo_url = $repo_url
  repo_url += "/" + branch if branch != ""
  res = "--non-interactive"
  res += " --username #{Shell.escape($username)}" if $username
  res += " --password #{Shell.escape($password)}" if $password
  res += " #{Shell.escape(repo_url)}"
  res
end

def svn_get_current_revision
  $stderr.print "Retrieving current HEAD revision... " if $verbose
  # 'svn info' doesn't always work to get most recent revision.
  # So parse output of 'svn log -r HEAD:HEAD'.
  svn_info = `svn log --xml -r HEAD:HEAD #{svn_common_args}`
  svn_info =~ %r{\srevision=\"(\d+)\"}m
  $stderr.puts "r#{$1}" if $verbose
  $1.to_i
end

# Prefix each line with "!!!" and only warn:
#  - once for each unique warning
#  - at most a fixed number of times per caller
$warning_txt = Set.new		# All dumped warnings texts
$warning_callers = {}		# Per caller: number of warnings
def warning(*txt)
  txt = txt.flatten.collect { |t| t.split("\n") }.flatten
  if !$warning_txt.include?(txt)
    $warning_txt << txt
    backtrace = caller[0]
    $warning_callers[backtrace] ||= 0
    times_warned = ($warning_callers[backtrace] += 1)
    if times_warned <= 5
      first = true
      txt.each { |line|
	$stderr.puts((first ? "!!!" : "   ") + " #{line}")
	first = false
      }
      if times_warned == 5
	$stderr.puts 
          "    (more of this type of warnings will be suppressed)"
      end
    end
  end
end

def die(*txt); warning(*txt); exit 1; end

class BranchColor
  @@available_colors = [
    "green", "yellow", "orange", "cyan", "steelblue3",
    "lightblue", "thistle", "red", '".7 .3 1.0"',
    "navy", "violet", "crimson", "azure", "linen", "peru",
    "tan", "darkgreen", "coral"
  ]
  @@branch_color = {}		# String branch -> String color

  def self.color(branch)
    # For a new branch, take a fixed color or a random one if out-of-colors.
    @@branch_color[branch] ||= (
      @@available_colors.shift ||
      ('"%.1f %.1f %.1f"' % [rand + 0.1, rand + 0.1, rand + 0.1])
    )
  end
end

# Map a filename into a branch name part and element name part.
# Branchname may contain '/''s.
# Element name starts with a '/' or is empty.
#
# SVN does not contain branches, but only contains one large tree with
# objects of (potentially different) versions. By only looking at a
# subtree, a branch is emulated. However, we have to know where those
# subtrees are rooted to be able to convert them to branches.
def path_to_branch(filename)
  if filename =~ $branch_dirs
    # We matched a branch-name.
    branch, elem = $&, filename[$&.size..-1]
    return nil if branch =~ $not_branch_dirs
    return [branch[1..-1], elem] # Remove leading '/' from branch name
  else
    # Outside the branches (e.g. a tag). Skip this.
    return nil
  end
end

# Revision of a branch; part of a revision.
# Forms a directed acyclic graph with other BranchRevisions
class BranchRevision
  attr_accessor :must_add_implicit_dep	# Boolean
  attr_accessor :depends_on	# Set of BranchRevision: parents
  attr_accessor :dependers      # Set of BranchRevision: children
  attr_reader :branch		# String: branchname
  attr_accessor :empty		# Bool: true if no reason to keep this rev
  attr_accessor :deleted	# Bool: true if deleted at end
  attr_accessor :commit_sha1	# String. git's SHA1 commit hash.

  # If true, implicitly adds an dependancy on the previous
  # version of this branch. This the the default.
  # However, when we detect that this branch consists of totally new files
  # (for example, when copying /trunk to /branches/branch_name) we set
  # this to false.
  # @must_add_implicit_dep  # Boolean

  def initialize(revision, branch)
    @revision = revision	# Revision
    @branch = branch
    @must_add_implicit_dep = true
    @depends_on = Set.new
    @dependers = Set.new
    @empty = true
    @deleted = false
    @commit_sha1 = nil
  end

  # Compare on revision number
  def <=>(other); self.nr <=> other.nr; end

  def to_s; "#{@branch}:#{nr}"; end

  def nr; @revision.nr; end	# Fixnum: revision nr

  # Returns true if this BranchRevision is a root revision since:
  #   - it does not depend on another BranchRevision
  #   - it contains changes _within_ the branch (== not empty)
  def root?; @depends_on.empty? && !@empty; end

  def add_depends_on(branch_rev)
    @depends_on << branch_rev
    branch_rev.dependers << self
  end

  def remove_depends_on(branch_rev)
    @depends_on.delete(branch_rev)
    branch_rev.dependers.delete(self)
  end

  def rev; @revision; end

  def other_branch_depends_on
    @depends_on.find_all { |b| b.branch != @branch }
  end

  # Returns all BranchRevisions we depend on in the same branch
  def same_branch_depends_on
    @depends_on.find_all { |b| b.branch == @branch }
  end

  # Returns branch revision on which we depend which is least number
  # of revisions back on the same branch. Since we go back, this is
  # the max. revision of the dependancies.
  def closest_same_branch_depends_on
    same_branch_depends_on.max
  end

  # Returns branch revision which depends on us which is least number
  # of revisions forward on the same branch.
  def closest_same_branch_depender
    @dependers.find_all { |b| b.branch == @branch }.min
  end

  # A dependancy is unneeded when:
  #   - the dependancy belongs to the same branch and the same revs
  #     can be reached by removed this dependancy, or
  #   - the dependancy belongs to another branch on which a rev in
  #     the same branch above us is already depending
  def remove_unneeded_depends_on
    return if @depends_on.size <= 1 # Optimisation

    # TODO: look farther back.

    # Same branch dependancy remover:
    # Follow the dependancy chain along the closest parent
    # till we reach the farthest dep.
    same_branch_deps = same_branch_depends_on()
    closest_same_branch_dep = same_branch_deps.max
    farthest_same_branch_nr = !same_branch_deps.empty? && same_branch_deps.min.nr
    current_dep = closest_same_branch_dep
    same_branch_deps_rec = Set.new
    while current_dep && current_dep.nr >= farthest_same_branch_nr
      same_branch_deps_rec.add(current_dep)
      current_dep = current_dep.closest_same_branch_depends_on
    end
    same_branch_deps.each { |red_rev|
      if red_rev != closest_same_branch_dep &&
	  same_branch_deps_rec.include?(red_rev)
#	puts "r#{nr}: Dep. on same branch r#{red_rev.nr} redundant" if $verbose
	remove_depends_on(red_rev)
      end
    }

    # Via-other-branch redundant dependancy remover:
    other_branch_depends_on.each { |other_dep|
      if !((other_dep.dependers & same_branch_deps_rec).empty?)
#	puts "r#{nr}: Dep. on other branch r#{other_dep.nr} redundant" if $verbose
	remove_depends_on(other_dep)
      end
    }
  end

  # Signal the fact that the last action has been added to this revision.
  # Now the dependancies can be calculated.
  def last_action_added
    if @must_add_implicit_dep
      prev_branch_rev = Revision.find_revision_with_branch(nr - 1, @branch)
      add_depends_on(prev_branch_rev) if prev_branch_rev
    end
    @depends_on.dup.each { |br|
      # We might depend on empty branch revisions. Since empty branch will not
      # be checked out, copy dependancies from those branches.
      if br.empty
	br.depends_on.each { |parent_depends_on|
	  add_depends_on(parent_depends_on)
	}
	remove_depends_on(br)
      end
    }
    remove_unneeded_depends_on
  end

  # Internal dotty label.
  def label; "_#{@branch}_#{nr}".delete("^0-9a-zA-Z_"); end

  def to_dotty
    return "\t/* r#{nr} is empty */\n" if @empty
    res = "\t#{label}[label=\"#{File.basename(@branch)} " +
      "#{nr}\\n#{rev.author}\",color=#{BranchColor.color(@branch)}];"
    @depends_on.each { |d|
      res += " #{d.label} -> #{label}"
      res += "[style=dashed]" if @branch != d.branch # A merge or branch
      res += ";"
    }
    res + "\n"
  end
end

# One revision in SVN. Contains zero or more BranchRevisions.
class Revision
  attr_reader :nr		# Fixnum
  attr_accessor :author		# String
  attr_accessor :msg		# String
  attr_accessor :time		# String
  attr_accessor :branches	# Hash: String rootdir to BranchRevision

  @@all_revs = []		# Array: all revisions, indexed by nr

  def self.get_all_revs; @@all_revs; end

  def self.set_all_revs(new_all_revs); @@all_revs = new_all_revs; end

  # Returns first revision number we're interested in.
  def self.get_next_log_nr
    @@all_revs[-1] ? @@all_revs[-1].nr + 1 : $start_revision
  end

  def self.[](nr); @@all_revs[nr]; end
  # Iterate sorted over each revision
  def self.each; @@all_revs.each { |rev| yield(rev) if rev }; end

  # Search for most recent BranchRevision which changed given branch.
  def self.find_revision_with_branch(start_nr, branch)
    start_nr.downto($start_revision) { |nr|
      rev = @@all_revs[nr]
      return rev.branches[branch] if rev && rev.branches.has_key?(branch)
    }
    warning(
      "Could not find branch #{branch.inspect} from revision #{start_nr} back"
    ) if start_nr >= $start_revision
    return nil
  end

  def initialize(nr)
    @nr = nr
    @branches = {}
    # Store new revision in global revision array
    @@all_revs[nr] = self
  end

  # Add an action to this revision
  #   'copyto_path' is the destination being changed. In all cases,
  #   this can be a file or directory.
  #   action == :R  : Replace. copyfrom_* always filled in.
  #   action == :M  : Modify
  #   action == :D  : Delete
  #   action == :A  : Create as new or copy from other revision
  #                   If from other revision, copyfrom_* are filled in.
  $branch_paths = Set.new
  def add_action(action, copyto_path, copyfrom_path, copyfrom_rev)
    branch, elem = *path_to_branch(copyto_path)
    return if !branch		# Action is outside a branch

    if $verbose && !$branch_paths.include?(branch)
      puts "r#{nr}: New branch: #{branch}"
      $branch_paths.add(branch)
    end

    branch_rev = (@branches[branch] ||= BranchRevision.new(self, branch))

    from_branch = from_elem = nil
    if copyfrom_path
      from_branch, from_elem = *path_to_branch(copyfrom_path)
      if !from_branch
	# Not a branch. Must be a tag.
	warning(
          "Ignoring dependancy r#{@nr} on a non-branch: " + 
          "#{copyfrom_path.inspect}:#{copyfrom_rev}"
        )
      else
	from_branch_rev = 
	  Revision.find_revision_with_branch(copyfrom_rev, from_branch)
	branch_rev.add_depends_on(from_branch_rev) if from_branch_rev
      end
    end

    # We cannot checkout deleted branches, so record the fact that
    # it is deleted at the end of the revision.
    branch_rev.deleted = true if elem == "" && action == :D

    # If something changes the root of the branch (deleted, copied
    # from other branch, ...) we break the implicit dependancy chain.
    # However, _modifying_ the root directory (adding files, removing files)
    # does not remove the dependancy.
    branch_rev.must_add_implicit_dep = false if elem == "" && action != :M

    # Check whether this action results in a revision. For example,
    # deleting the root of the branch or creating the root dir does not
    # change anything _within_ the branch.
    branch_rev.empty = false if elem != "" # Real files. Not empty.
  end

  # Signal the fact that the last action has been added to this revision.
  # Now the dependancies can be calculated.
  def last_action_added
    @branches.each_value { |b| b.last_action_added }
  end

  def to_dotty
    @branches.values.collect { |b| b.to_dotty }.join("")
  end
end

# Parse output of 'svn log --xml --verbose'
def parse_svn_log_xml(svnlog_filename)
  $stderr.puts "Branch analysis on svn log files..." if $verbose
  last_rev_nr = nil
  rev = nil			# Current Revision
  File.open(svnlog_filename, "rb") { |io|
    while line = io.gets
      case line
      when %r{^   revision="(\d+)"}
	rev_nr = $1.to_i
	$stderr.print "r#{rev_nr}" + ("\010" * 10)
	# Only create a new revision when not already loaded from
	# state file.
	if rev_nr > $start_revision && Revision[rev_nr] == nil
	  rev = Revision.new(rev_nr)
	  if last_rev_nr && (rev_nr != last_rev_nr + 1)
	    # Missing revisions are a sign of not getting the log of the
	    # whole archive, but only one of its branches (or subprojects).
	    # Which could be valid if we're after a subproject, but not
	    # if we want to import the whole repository.
	    warning("Missing reversion(s) #{last_rev_nr + 1}-#{rev_nr - 1}")
	  end
	  last_rev_nr = rev_nr
	end
      when %r{^\<path}: copyfrom_path = nil; copyfrom_rev = nil
      when %r{^   copyfrom-path="(.*)"}: copyfrom_path = $1
      when %r{^   copyfrom-rev="(\d+)"}: copyfrom_rev = $1.to_i
      when %r{^   action="([A-Z])"\>(.*)\</path\>}
	rev.add_action($1.to_sym, $2, copyfrom_path, copyfrom_rev) if rev
      when %r{^\</paths\>}
	# End of this revision.
	next if !rev
	rev.last_action_added
	root_branches = rev.branches.values.find_all { |branch| branch.root? }
	root_branches.each { |bi|
	  puts "r#{rev.nr} is root of #{bi.branch}"
	}
	changed_branches = rev.branches.values.find_all { |b| !b.empty }
	if changed_branches.size > 1
	  changed_branches_names = changed_branches.collect { |b| b.branch }
	  warning(
            "More than one branch changed in r#{rev.nr}..?",
            changed_branches_names
          )
	end
      when %r{^\<author\>(.*)\</author\>}
	rev.author = $1 if rev
      when %r{^\<msg\>(.*)}
	msg = $1.rstrip
	while !msg.gsub!("\</msg\>", "")
	  msg += "\n" + io.gets.rstrip
	end
	msg = CGI::unescapeHTML(msg.strip + "\n") # &amp; -> & etc.
	rev.msg = msg if rev
      when %r{^\<date\>(.*)\</date\>}
	rev.time = Time.parse($1) if rev
      end
    end
  }
end

$state_version = "20060409"

# Load state of git-svnconvert. Returns true in case of succes.
def load_state
  begin
    state = File.open($state, "rb") { |io| Marshal.load(io) }
    version = state.shift
    if version != $state_version
      warning(
        "Ignoring previous state: has different version (#{version}) " +
        "than this git-svnconvert version (#{$state_version})"
      )
    else
      $repo_url, all_new_revs = *state
      Revision.set_all_revs(all_new_revs)
      return true
    end
  rescue Errno::ENOENT
  end
  return false
end

def save_state
  start_time = Time.now
  File.open($state + ".new", "wb") { |io|
    io.write(Marshal.dump([$state_version, $repo_url, Revision.get_all_revs]))
  }
  # Rename atomically new state into _the_ state
  File.rename($state + ".new", $state)
  $stderr.puts "Saved new state in %.1fs" % (Time.now - start_time) if $verbose
end

# Export current graph of revisions to a GraphViz dotty file
def export_to_dot(dot_file)
  $stderr.puts "Writing branch graph to \"#{dot_file}\"..."
  File.open(dot_file, "wb") { |io|
    io.puts "strict digraph svn {"
    io.puts "\tnode[shape=box,style=filled];\n\n"
    Revision.each { |rev|
      next if !rev || (rev.nr < $start_revision)
      io.print rev.to_dotty
    }
    io.puts "}"
  }
end

# Runs an svn command, and run git-update-index on each file
# echoed to stdout by svn.
def svn_cmd_with_update_index(svn_cmd)
  safe_popen(svn_cmd, "r") { |svn_io|
    safe_popen("git-update-index --add --remove --stdin", "w") { |git_io|
      git_io.sync = true
      # Have a buffer of one line: svn echoes the file it is
      # working on. When svn echoes the next line, we then know
      # it finished the previous file, and can therefore be added
      # to git now.
      last_file = nil
      while line = svn_io.gets
	$stderr.puts line if $verbose
	if line =~ %r{^[A-Z][A-Z ]{3} (.*)$}
	  git_io.puts last_file if last_file 
	  last_file = $1
	end
      end
      git_io.puts last_file if last_file 
    }
  }
end

# Unknown contents in directory; recreate index
def git_update_index
  # Remove incomplete index
  git_index_file = ENV['GIT_INDEX_FILE']
  [git_index_file, git_index_file + ".lock"].each { |f|
    File.delete(f) if File.exist?(f)
  }
  # Add all files
  to_prune = Set.new([".git", ".svn"]) # Directories not to add
  safe_popen("git-update-index --add --remove --stdin") { |io|
    elems = 0
    Find.find(".") { |elem|
      Find.prune if to_prune.include?(File.basename(elem))
      if elem != "."
	elem = elem[2..-1]  # Remove ./
	io.puts elem
	elems += 1
      end
    }
    puts "Dir contained #{elems} elements" if $verbose
  }
end

######################################## Main

# Default values for options
$verbose = true
$username = nil			# Repository username
$password = nil			# Repository password
$start_revision = 1
dot_filename = nil
svn_authors_file = nil		# Mapping from 
$run_dotty = false

# Parse options
$opts = OptionParser.new
$opts.banner = %q{Convertor for a subversion archive into a git archive.

git-svnconvert [options] URL[@REV] [DIR]
  ..to convert complete SVN archive at URL into directory DIR.
  The URL must point to the root directory of the repo, so not f.e. to /trunk!
  By default, DIR will be the basename of the URL.
  Directory DIR will be created if it does not exist.
  Otherwise, DIR must already be a git repository.
git-svnconvert [options]
  ..to incrementally convert newly added revision and add them
    to the git repo in the current directory.

Examples:

git-svnconvert svn://svn.0pointer.net/fusedav .
  ..checks out svn://svn.0pointer.net/fusedav into current dir.
git-svnconvert svn://svn.0pointer.net/fusedav@10
  ..checks out starting at revision 10 into directory fusedav.
git-svnconvert
  ..updates already imported svn archive in current dir.

}
$opts.on("Options (defaults between []'s):")
$opts.on("--verbose", "-v", "Toggle verbose mode [#{$verbose}]") {
  $verbose = !$verbose
}
$opts.on("--help", "-h", "This usage") { puts $opts; exit 1 }
$opts.on("--revision REV", "-s", "Start revision [#{$start_revision}]") {
  |$start_revision|
}
$opts.on("--dot FILENAME", "-d", "Export branch tree as .dot file.") {
  |dot_filename|
}
$opts.on("--dotty", "-D", "Export branch tree and run dotty on it") {
  $run_dotty = true
}
$opts.on("--authors FILENAME", "-A", "Filename of svnauthors file to add") {
  |svn_authors_file|
}
$opts.on("\nOptions passed to 'svn':");
$opts.on("--username NAME", "-u", "Specify a username for SVN repo") {
  |$username|
}
$opts.on("--password PWD", "-p", "Specify a password for SVN repo") {
  |$password|
}

begin
  $opts.parse!(ARGV)
rescue OptionParser::InvalidOption
  die($!.to_s, $opts.to_s)
end

$repo_url = (ARGV.size > 0) ? ARGV.shift.dup : nil
# Parse @REV part of URL@REV if given...
$start_revision = $1.to_i if $repo_url && $repo_url.gsub!(%r{@(\d+)$}, "")
dest_dir = (ARGV.size > 0) ? ARGV.shift : nil
dest_dir = File.basename($repo_url) if $repo_url && !dest_dir
dest_dir ||= Dir.pwd	# No URL and no destdir given: use current dir
dest_dir = File.expand_path(dest_dir)
git_dir = ENV["GIT_DIR"] || "#{dest_dir}/.git"
svnconvert_dir = "#{git_dir}/svnconvert"
# Name of state file with all parsed log files and connection to git archive.
$state = "#{svnconvert_dir}/state"

if !File.exist?($state) && !$repo_url
  puts $opts.to_s
  puts "\n!!! Need an URL to checkout or a previously git-svnconvert'ed dir"
  exit 1
end

# Maping from SVN author name to full name and email
default_svn_authors_file = "#{git_dir}/svn-authors"
users = File.readable?(default_svn_authors_file) ?
  read_svn_authors(default_svn_authors_file) : {}
# If authors file explicitly given, add
if svn_authors_file
  users_to_add = read_svn_authors(svn_authors_file)
  if users_to_add.size > 0
    users.merge!(users_to_add) 
    write_svn_authors(users, default_svn_authors_file)
  end
end

FileUtils.mkdir_p(svnconvert_dir)	# Create destination if not existing
Dir.chdir(dest_dir)

$branch_dirs = root_dirs_to_regexp($branch_dirs, true)
$not_branch_dirs = root_dirs_to_regexp($not_branch_dirs, false)

# Load complete state, or failing that, same empty state with new repo URL
load_state || save_state
next_revision_nr = Revision.get_next_log_nr
if next_revision_nr < svn_get_current_revision
  svnlog = "#{svnconvert_dir}/svnlog.xml"
  puts "Retrieving revision log from #{next_revision_nr} and upwards..."
  cmd = "svn log #{svn_common_args} -r #{next_revision_nr}:HEAD --xml --verbose >#{svnlog}"
  safe_system(cmd)
  parse_svn_log_xml(svnlog)
  save_state
else
  puts "No new revision to get log of."
end

# The graph eases debugging, so export it always...
default_dot_filename = "#{svnconvert_dir}/branches.dot"
export_to_dot(dot_filename || default_dot_filename)
if $run_dotty
  safe_system("dotty #{Shell.escape(dot_filename || default_dot_filename)}")
end
exit 0 if dot_filename || $run_dotty

# Directory of all branches checked out:
svn_co_dir = "#{svnconvert_dir}/checkedout" 
ENV['GIT_DIR'] = git_dir

head_existed = File.exist?("#{git_dir}/HEAD")
safe_system("git-init-db")
if !head_existed
  $stderr.puts "Creating HEAD pointing to trunk"
  File.open("#{git_dir}/HEAD", "wb") { |io|
    io.puts "ref: refs/heads/trunk"
  }
end
Revision.each { |rev|
  next if rev.nr < $start_revision

  rev_commit_sha1s = []
  branches = rev.branches.values
  branches.each { |br|
    branch_dir = "#{svn_co_dir}/#{br.branch}"
    if br.commit_sha1
      # Skip if already imported
    elsif br.deleted
      # Branch contains only an 'delete this branch' command.
      $stderr.puts "r#{rev.nr}: #{br.branch} deleting #{branch_dir}"
#      FileUtils.rm_rf(branch_dir)
    elsif br.empty
      $stderr.puts "r#{rev.nr}: #{br.branch} is empty; skipping..."
    else
      # Hide the git index inside .svn dir.
      git_index_file = ENV['GIT_INDEX_FILE'] = "#{branch_dir}/.svn/index.git"
      if !File.directory?(branch_dir)
        # Start of new branch. Make (empty) directory to start new branch in
        FileUtils.mkdir_p(branch_dir)
	FileUtils.mkdir_p(File.dirname(ENV['GIT_INDEX_FILE']))
	Dir.chdir(branch_dir)
        puts "Checking out new branch #{br.branch}:#{rev.nr} in #{Dir.pwd}"
        cmd = "svn checkout -r #{rev.nr} #{svn_common_args(br.branch)} ."
        svn_cmd_with_update_index(cmd)
      else
	# Branched already checked out, update to new revision.
	Dir.chdir(branch_dir)
	svn_cmd = "svn update -r #{rev.nr} ."
	if File.exist?(git_index_file + ".lock")
	  $stderr.puts "Git index file already locked. Removing lock and recreating index."
	  safe_system(svn_cmd)
	  git_update_index
	else
	  puts "Updating branch to new revision: #{br.branch}:#{rev.nr}"
	  svn_cmd_with_update_index(svn_cmd)
	end
      end

      # git index is now up-to-date. Write the tree.
      tree_sha1 = `git-write-tree`.chomp

      # Now write this tree into an commit
      author = rev.author
      email = "unknown"
      author, email = users[author] if users[author]
      $stderr.puts "r#{rev.nr}: Author: #{author} <#{email}>" if $verbose
      ENV['GIT_AUTHOR_NAME'] = ENV['GIT_COMMITTER_NAME'] = author
      ENV['GIT_AUTHOR_EMAIL'] = ENV['GIT_COMMITTER_EMAIL'] = email
      ENV['GIT_AUTHOR_DATE'] = ENV['GIT_COMMITTER_DATE'] =
	rev.time.strftime("+0000 %Y-%m-%d %H:%M:%S") 
      parents = br.depends_on.find_all { |p|
	# Filter out all non-converted parents
	raise if !p.commit_sha1 && p.nr >= $start_revision
	p.commit_sha1 != nil
      }.collect { |p| "-p #{p.commit_sha1}" }.join(" ")
      puts "Committing #{tree_sha1}..."
      cmd = "git-commit-tree #{tree_sha1} #{parents}"
      puts cmd if $verbose
      safe_popen(cmd) { |io|
        io.puts rev.msg.strip
        io.close_write
        br.commit_sha1 = io.read.chomp
        rev_commit_sha1s << br.commit_sha1    
      }
      puts "#{br.branch}:#{rev.nr} has id #{br.commit_sha1}" if $verbose

      Dir.chdir(dest_dir)
      # Tag current branch + revision.
#    safe_system("git-tag -f #{br.branch}/r#{rev.nr} #{br.commit_sha1}")
      # Update HEAD of this branch
      safe_system("git-update-ref refs/heads/#{br.branch} #{br.commit_sha1}")
      puts
    end
  }
  if rev_commit_sha1s.size == 1
    # '-f' added to make this script restartable (state might not get saved)
    safe_system("git-tag -f r#{rev.nr} #{rev_commit_sha1s}")
  end
  save_state if !rev_commit_sha1s.empty?
}
puts "Done."

^ permalink raw reply

* Re: [Qemu-devel] SPARC iommu mapping
From: Joerg Platte @ 2006-04-09 16:31 UTC (permalink / raw)
  To: qemu-devel
In-Reply-To: <BAY104-F117C8B7ECF3ED07C6591A9FFC90@phx.gbl>

[-- Attachment #1: Type: text/plain, Size: 703 bytes --]

Am Freitag, 7. April 2006 17:44 schrieb Blue Swirl:
Hi!

> Maybe this patch helps?

The attached patch is an updated version of your patch. With whis patch I was 
able to copy files from one directory to another on a disk image. After 
unmounting the image, e2fsck reported no errors on this image. But 
unfortunately, booting from this image was not possible. INIT reported a 
segmentation violation. Maybe there is something else wrong. But now writing 
works much better than before :-)

regards,
Jörg

PS: Is there any reason, why qemu copies disk data byte by byte? Calling 
iommu_translate only once per page and copying a whole page could speed up 
disk access significantly...

[-- Attachment #2: qemu-write.patch --]
[-- Type: text/x-diff, Size: 5321 bytes --]

--- esp.c.orig	2006-04-09 18:20:38.000000000 +0200
+++ esp.c	2006-04-09 18:04:15.000000000 +0200
@@ -63,6 +63,8 @@
     ESPDMAFunc *dma_cb;
     int64_t offset, len;
     int target;
+    int blocksize;
+    int ti_bufstart;
 };
 
 #define STAT_DO 0x00
@@ -229,12 +231,12 @@
                             target_phys_addr_t phys_addr, 
                             int transfer_size1)
 {
+    int len = transfer_size1/s->blocksize;
     DPRINTF("Write callback (offset %lld len %lld size %d trans_size %d)\n",
             s->offset, s->len, s->ti_size, transfer_size1);
-    bdrv_write(s->bd[s->target], s->offset, s->ti_buf, s->len);
-    s->offset = 0;
-    s->len = 0;
-    s->target = 0;
+
+    bdrv_write(s->bd[s->target], s->offset, s->ti_buf+s->ti_bufstart, len);
+    s->offset+=len;
     return 0;
 }
 
@@ -265,6 +267,7 @@
     s->ti_size = 0;
     s->ti_rptr = 0;
     s->ti_wptr = 0;
+    s->ti_bufstart = 0;
 
     if (target >= 4 || !s->bd[target]) { // No such drive
 	s->rregs[4] = STAT_IN;
@@ -293,6 +296,7 @@
 	s->ti_buf[3] = 2;
 	s->ti_buf[4] = 32;
 	s->ti_dir = 1;
+        s->ti_bufstart = 0;
 	s->ti_size = 36;
 	break;
     case 0x1a:
@@ -314,6 +318,7 @@
 	    s->ti_buf[6] = 2; // sector size 512
 	s->ti_buf[7] = 0;
 	s->ti_dir = 1;
+        s->ti_bufstart = 0;
 	s->ti_size = 8;
 	break;
     case 0x28:
@@ -336,6 +341,7 @@
 	    bdrv_read(s->bd[target], offset, s->ti_buf, len);
 	    // XXX error handling
 	    s->ti_dir = 1;
+	    s->ti_bufstart = 0;
 	    break;
 	}
     case 0x2a:
@@ -346,10 +352,12 @@
 		offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;
 		len = ((buf[8] << 8) | buf[9]) * 4;
 		s->ti_size = len * 2048;
+		s->blocksize=2048;
 	    } else {
 		offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
 		len = (buf[8] << 8) | buf[9];
 		s->ti_size = len * 512;
+		s->blocksize=512;
 	    }
 	    DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len);
             if (s->ti_size > TI_BUFSZ) {
@@ -359,6 +367,7 @@
             s->offset = offset;
             s->len = len;
             s->target = target;
+            s->ti_bufstart = 0;
 	    // XXX error handling
 	    s->ti_dir = 0;
 	    break;
@@ -400,6 +409,7 @@
                 break;
             }
 	    s->ti_dir = 1;
+	    s->ti_bufstart = 0;
             break;
         }
     default:
@@ -415,10 +425,9 @@
 
 static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
 {
-    uint32_t dmaptr, dmalen;
+    uint32_t dmaptr;
 
-    dmalen = s->wregs[0] | (s->wregs[1] << 8);
-    DPRINTF("Transfer status len %d\n", dmalen);
+    DPRINTF("Transfer status len %d\n", len);
     if (s->dma) {
 	dmaptr = iommu_translate(s->espdmaregs[1]);
 	DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
@@ -428,10 +437,10 @@
 	s->rregs[6] = SEQ_CD;
     } else {
 	memcpy(s->ti_buf, buf, len);
-	s->ti_size = dmalen;
+	s->ti_size = len;
 	s->ti_rptr = 0;
 	s->ti_wptr = 0;
-	s->rregs[7] = dmalen;
+	s->rregs[7] = len;
     }
     s->espdmaregs[0] |= DMA_INTR;
     pic_set_irq(s->irq, 1);
@@ -442,34 +451,57 @@
 
 static void handle_ti(ESPState *s)
 {
-    uint32_t dmaptr, dmalen;
+    uint32_t dmaptr, dmalen, minlen;
     unsigned int i;
 
     dmalen = s->wregs[0] | (s->wregs[1] << 8);
-    DPRINTF("Transfer Information len %d\n", dmalen);
+    if (dmalen==0) {
+      dmalen=0x10000;
+    }
+
+    minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
+    DPRINTF("Transfer Information len %d\n", minlen);
     if (s->dma) {
 	dmaptr = iommu_translate(s->espdmaregs[1]);
-	DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
-	for (i = 0; i < s->ti_size; i++) {
+	DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x %d %d\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr, s->ti_size, s->ti_bufstart, s->ti_dir);
+	for (i = 0; i < minlen; i++) {
 	    dmaptr = iommu_translate(s->espdmaregs[1] + i);
 	    if (s->ti_dir)
-		cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);
+		cpu_physical_memory_write(dmaptr, &s->ti_buf[s->ti_bufstart+i], 1);
 	    else
-		cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);
+		cpu_physical_memory_read(dmaptr, &s->ti_buf[s->ti_bufstart+i], 1);
 	}
         if (s->dma_cb) {
-            s->dma_cb(s, s->espdmaregs[1], dmalen);
+            s->dma_cb(s, s->espdmaregs[1], minlen);
+        }
+        if (minlen<s->ti_size) {
+	    s->rregs[4] = STAT_IN | STAT_TC | (s->ti_dir?STAT_DO:STAT_DI);
+	    s->ti_size-=minlen;
+	    s->ti_bufstart+=minlen;
+        } else {
+	    s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
             s->dma_cb = NULL;
+            s->offset = 0;
+            s->len = 0;
+            s->target = 0;
+            s->ti_bufstart = 0;
         }
-	s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
-	s->rregs[5] = INTR_BS;
+        s->rregs[5] = INTR_BS;
 	s->rregs[6] = 0;
+	s->rregs[7] = 0;
 	s->espdmaregs[0] |= DMA_INTR;
     } else {
-	s->ti_size = dmalen;
+	s->ti_size = minlen;
 	s->ti_rptr = 0;
 	s->ti_wptr = 0;
-	s->rregs[7] = dmalen;
+	s->rregs[7] = minlen;
     }	
     pic_set_irq(s->irq, 1);
 }
@@ -485,8 +517,10 @@
     s->ti_rptr = 0;
     s->ti_wptr = 0;
     s->ti_dir = 0;
+    s->ti_bufstart = 0;
     s->dma = 0;
     s->dma_cb = NULL;
+    s->blocksize = 0;
 }
 
 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)

^ permalink raw reply

* Re: Linux 2.6.17-rc1: /sbin/iptables does not find kernel netfilter
From: Andre Tomt @ 2006-04-09 16:23 UTC (permalink / raw)
  To: Nix, linux-kernel; +Cc: vherva, Patrick McHardy, netfilter, davem
In-Reply-To: <87psjqg2nt.fsf@hades.wkstn.nix>

Nix wrote:
> I cetainly did. A simple `make oldconfig' ends up zapping pretty much
> all the old iptables CONFIG_ options, so you end up with not much of
> iptables or netfilter left.
> 
> I must admit not quite understanding why the xtables stuff is needed:
> I thought that was needed for userspace connection tracking, which
> while it sounds cool isn't something I'm using yet.
> 

Beeing bitten by such issues in the past, I always diff the old and the 
new config and look for anything suspicious going down.

-- 
André Tomt

^ permalink raw reply

* Re: [Qemu-devel] Unified device model
From: Jim C. Brown @ 2006-04-09 16:08 UTC (permalink / raw)
  To: qemu-devel
In-Reply-To: <200604091621.45594.paul@codesourcery.com>

On Sun, Apr 09, 2006 at 04:21:42PM +0100, Paul Brook wrote:
> > > I'm not a fan of binary plugins (for the same reasons I'm don't like
> > > binary kernel modules), and don't think there's any real need to them.
> >
> > A binary plugin API and a source plugin API (one that requires each driver
> > device to be recompiled for each of the platforms (Xen, qemu, bochs, etc.)
> > would probably be equally hard to design and maintain.
> 
> You've missed my point. The only reason I can see for wanting binary plugins 
> is so that people can distribute proprietary closed-source device emulation.

I agree that proprietary or closed-source device emulation is a bad thing and
should not be supported.

> 
> A stable source API is a prerequisite for any sort of binary plugins.
> 

In that case, perhaps a stable source API would be best.

Like I said before, the type of API/sharing (source vs binary API, and static
vs shared libraries) is a separate issue from the one we are discussing (should
we have or support a unified plugin API?).

> > > I can't see
> > > any good reasons why open source devices would need to be broken out into
> > > a separate shared library.
> >
> > I think the case was already made for this.
> >
> > Xen's hardware emulation, while based on qemu's, is already ahead in
> > several aspects. A separate library would make it more convenient for these
> > changes to be shared back with qemu. Or with E/OS.
> 
> I don't buy that. We either share the same drivers (in which case keeping the 
> two in sync is trivial) or we don't. All of the systems under consideration 
> are [L]GPL licences. We can easily copy the source, so I don't think being 
> able to copy bits of binary goo gains us anything.

A) Makes it simpler for end users to move devices over (they don't have to know
how to cut-and-paste C code)

B) Bochs is not related to qemu at all code-wise, so the cut-and-paste senario
doesn't work here. If we want to share drivers with Bochs we'd need at least a
source API. (The starter of this thread is a Bochs developer I believe...
but correct me if I'm wrong here. :) The alternative is to rewrite Bochs
drivers for qemu from scratch (possbly using the Bochs code as a guide) but
that is even harder than the qemu-xen case.

C) If they are in a special library (say maintained by a 3rd party group that
consists of developers from all the major projects) then maintainance is greatly
simplified over time.

> 
> I don't think executable size is a valid argument either. Device emulation 
> code generally isn't that big so the overhead of breaking it up into multiple 
> shared libraries would outweigh the benefits of not loading the bits you're 
> not using.

Perhaps you are right about that. The size of having even 4 or 5 copies of
complete PC hardware emulation code isn't so large as to be a problem except
on systems that are either embedded or ancient (in which case you probably have
no business running 4 different PC emulators anyways).

Personally, it just seems inelegant to have such code duplication.

> 
> Paul
> 

-- 
Infinite complexity begets infinite beauty.
Infinite precision begets infinite perfection.

^ permalink raw reply

* Re: [Qemu-devel] VNC terminal server?
From: Leonardo E. Reiter @ 2006-04-09 16:06 UTC (permalink / raw)
  To: qemu-devel
In-Reply-To: <4438788F.90504@us.ibm.com>

Hi Anthony,

I noticed that the Windows driver does not work... it does send a bunch 
of commands to the tablet, mostly resets, but then claims that it can't 
discover it.  I downloaded the latest driver from wacom.com.  I did not 
try this with a Linux guest yet.... maybe that should be my next thing, 
and see what it will take to make it work without the SDL grab 
altogether (and sync up).  If that can work reliably, then adding the 
bits to the protocol that Windows expects would be worth the work.

I'm thinking that this device would be a good complementary option to an 
absolute USB HID device.  Having both in the long run won't hurt, 
especially if certain OS's prefer serial over USB absolute pointers, and 
vice versa.

- Leo Reiter

Anthony Liguori wrote:
> The driver isn't built into Windows.  It's pretty easy to install though 
> and the way my patch works, the PS/2 mouse is used until it detects the 
> tablet has been enabled.
> 
> The Windows driver uses quite a bit more of the features of the tablet 
> than the X driver so there's a bit more work to do but nothing 
> extraordinary.
> 
> Regards,
> 
> Anthony Liguori

-- 
Leonardo E. Reiter
Vice President of Product Development, CTO

Win4Lin, Inc.
Virtual Computing from Desktop to Data Center
Main: +1 512 339 7979
Fax: +1 512 532 6501
http://www.win4lin.com

^ permalink raw reply

* Re: [Qemu-devel] Absolute USB-HID device musings (was Re: VNC Terminal Server)
From: Leonardo E. Reiter @ 2006-04-09 16:03 UTC (permalink / raw)
  To: qemu-devel
In-Reply-To: <44388F43.20207@us.ibm.com>

Yeah, the min/max value thing would be a pain for sure.  The X server 
config method seems to be the best bet.

On another note, I am trying to imagine what would make logical sense 
for say, a touch screen.  For example, an LCD panel has a native 
resolution, say 1024x768.  It would then emulate (or transparently 
expand) other VESA resolutions, such as 640x480, on the fly.  I would 
think that if it had touchscreen capabilities, the coordinates would 
always be reported in native mode.  So the guest OS must have to scale 
them down... especially if the device reports the range early on in the 
identification process.

If this were done in QEMU, we'd have to pick an arbitrary "native" 
resolution - for example, 1600x1200, the max the cirrus device can go. 
We would then have to scale it down automatically based on the set 
resolution, so that the guest OS can scale it up.

I'm just thinking out loud.  The good news is that making changes to the 
open source bits on guests (like Xorg) is trivial... it's, as been said, 
the closed source guests that would be the most problematic.  So 
sticking to the HID protocol to make this happen would be best.

- Leo

Anthony Liguori wrote:
> I was looking through the Xorg evdev driver and it doesn't appear to 
> support absolute coordinate reporting.  evdev is how the USB mouse would 
> show up to userspace.  A little googling confirmed it for me:
> 
> http://lists.freedesktop.org/archives/xorg/2005-September/010140.html
> 
> USB wacom still seems the most promising to me but I fear getting it to 
> work under Windows will be a pain.
> 
> Regards,
> 
> Anthony Liguori
> 
> 
> Leonardo E. Reiter wrote:
> 
>> This is by no means a complete patch (do not apply it as it will break 
>> usb-hid.c), but it adjusts the report descriptor in usb-hid.c to 
>> provide position in 16-bits, and in absolute coordinates:
>>
>> Index: usb-hid.c
>> ===================================================================
>> RCS file: /cvsroot/qemu/qemu/hw/usb-hid.c,v
>> retrieving revision 1.1
>> diff -a -u -r1.1 usb-hid.c
>> --- usb-hid.c   5 Nov 2005 16:57:08 -0000       1.1
>> +++ usb-hid.c   8 Apr 2006 20:56:02 -0000
>> @@ -117,7 +117,7 @@
>>      0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01,
>>      0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01,
>>      0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81,
>> -    0x25, 0x7F, 0x75, 0x08, 0x95, 0x02, 0x81, 0x06,
>> +    0x25, 0x7F, 0x75, 0x16, 0x95, 0x02, 0x81, 0x02,
>>      0xC0, 0xC0,
>>  };
>>
>> According to: 
>> http://72.14.203.104/search?q=cache:wVYUTwc33f8J:www.usb.org/developers/devclass_docs/HID1_11.pdf+usb+hid+specification+absolute+relative&hl=en&gl=us&ct=clnk&cd=1 
>>
>>
>> I'm still trying to figure out how the logical min/max apply if we are 
>> to report absolute (unsigned) positions in 16-bits.  Obviously 8-bits 
>> is not enough for absolute coordinates.  You could theoretically use 
>> only 12-bits per coordinate but that would make life difficult I 
>> think, and probably unnecessarily frugal in a software emulation.
>>
>> It's not clear to me [yet] how the scroll wheel comes into play, and 
>> whether or not it (the dz coordinate) can be kept relative for ease of 
>> implementation.  Also the code would need to be changed to report 
>> coordinates in 16-bits rather than 8, and of course made to report 
>> absolute coordinates (like from sdl.c, etc.)  Still it looks fairly 
>> easy to implement - the USB spec is pretty simple.
>>
>> So to reiterate, my patch does virtually nothing - in fact it will 
>> break usb-hid.c so please don't use it.  I was just illustrating how 
>> to get it to report the device as providing 16-bit absolute 
>> coordinates instead of 8-bit relative ones.  If anyone wants to chime 
>> in with more info, I'd be glad to make this a discussion.  *If* using 
>> the USB HID device only, not any real USB devices, can be done without 
>> slowing down QEMU, then I think this is a great way to get a tablet 
>> emulated without having to deal with drivers on either side.  Plus, in 
>> the long run, it probably means other neat stuff like being able to 
>> get away from ISA bus emulation, and also it's portable to other 
>> targets (for example, OS-X on PPC would talk to the USB HID device the 
>> same way theoretically), so it's likely the most portable and cleanest 
>> option.
>>
>> Regards,
>>
>> Leo Reiter
>>
>> Brad Campbell wrote:
>>
>>> Apparently USB HID supports absolute input devices natively. Given we 
>>> have a HID mouse driver of sorts in qemu I wonder if that is another 
>>> avenue perhaps ?
>>>
>>>
>>
> 
> 
> 
> _______________________________________________
> Qemu-devel mailing list
> Qemu-devel@nongnu.org
> http://lists.nongnu.org/mailman/listinfo/qemu-devel

-- 
Leonardo E. Reiter
Vice President of Product Development, CTO

Win4Lin, Inc.
Virtual Computing from Desktop to Data Center
Main: +1 512 339 7979
Fax: +1 512 532 6501
http://www.win4lin.com

^ permalink raw reply

* Re: Linux 2.6.17-rc1: /sbin/iptables does not find kernel netfilter
From: Nix @ 2006-04-09 16:00 UTC (permalink / raw)
  To: vherva; +Cc: Patrick McHardy, linux-kernel, netfilter, davem
In-Reply-To: <20060409144534.GN29797@vianova.fi>

On 9 Apr 2006, Ville Herva yowled:
> On Sun, Apr 09, 2006 at 05:44:16PM +0300, you [Ville Herva] wrote:
>> I just realized 
>> # CONFIG_NETFILTER_XT_MATCH_STATE is not set
>> should probably be set. I'm building a new kernel now...
> 
> Ok, that seems to do it.
> 
> Thanks for the help, and sorry for the noise. I hope not too many people hit
> the same glitch while upgrading...

I cetainly did. A simple `make oldconfig' ends up zapping pretty much
all the old iptables CONFIG_ options, so you end up with not much of
iptables or netfilter left.

I must admit not quite understanding why the xtables stuff is needed:
I thought that was needed for userspace connection tracking, which
while it sounds cool isn't something I'm using yet.

-- 
`On a scale of 1-10, X's "brokenness rating" is 1.1, but that's only
 because bringing Windows into the picture rescaled "brokenness" by
 a factor of 10.' --- Peter da Silva

^ permalink raw reply

* [2.6 patch] drivers/char/random.c: unexport secure_ipv6_port_ephemeral
From: Adrian Bunk @ 2006-04-09 15:58 UTC (permalink / raw)
  To: Andrew Morton; +Cc: mpm, linux-kernel, netdev

This patch removes the unused EXPORT_SYMBOL(secure_ipv6_port_ephemeral).

Signed-off-by: Adrian Bunk <bunk@stusta.de>

---

This patch was already sent on:
- 5 Apr 2006

--- linux-2.6.17-rc1-mm1-full/drivers/char/random.c.old	2006-04-05 17:00:04.000000000 +0200
+++ linux-2.6.17-rc1-mm1-full/drivers/char/random.c	2006-04-05 17:00:22.000000000 +0200
@@ -1584,7 +1584,6 @@
 
 	return twothirdsMD4Transform(daddr, hash);
 }
-EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
 #endif
 
 #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)


^ permalink raw reply

* [2.6 patch] drivers/net/via-rhine.c: make a function static
From: Adrian Bunk @ 2006-04-09 15:58 UTC (permalink / raw)
  To: Andrew Morton; +Cc: rl, jgarzik, netdev, linux-kernel

This patch makes the needlessly global rhine_set_carrier() static.

Signed-off-by: Adrian Bunk <bunk@stusta.de>

---

This patch was already sent on:
- 4 Apr 2006

--- linux-2.6.17-rc1-mm1-full/drivers/net/via-rhine.c.old	2006-04-04 17:41:16.000000000 +0200
+++ linux-2.6.17-rc1-mm1-full/drivers/net/via-rhine.c	2006-04-04 17:41:29.000000000 +0200
@@ -1091,7 +1091,7 @@
 }
 
 /* Called after status of force_media possibly changed */
-void rhine_set_carrier(struct mii_if_info *mii)
+static void rhine_set_carrier(struct mii_if_info *mii)
 {
 	if (mii->force_media) {
 		/* autoneg is off: Link is always assumed to be up */


^ permalink raw reply

* [2.6 patch] fix section mismatch in pm2fb.o
From: Adrian Bunk @ 2006-04-09 15:58 UTC (permalink / raw)
  To: adaplas; +Cc: linux-fbdev-devel, Darren Jenkins, linux-kernel

From: Darren Jenkins <darrenrjenkins@gmail.com>

There are a couple of Section mismatch problems in drivers/video/pm2fb.o

WARNING: drivers/video/pm2fb.o - Section mismatch: reference
to .init.data: from .text after 'pm2fb_set_par' (at offset 0xd5d)
WARNING: drivers/video/pm2fb.o - Section mismatch: reference
to .init.data: from .text after 'pm2fb_set_par' (at offset 0xd82)

They are caused because pm2fb_set_par() uses lowhsync and lowvsync which
are marked __devinitdata.

This patch simply removes the __devinitdata annotations.

Signed-off-by: Darren Jenkins <darrenrjenkins@gmail.com>
Signed-off-by: Adrian Bunk <bunk@stusta.de>

--- 2.6.16-git20/drivers/video/pm2fb.c.orig	2006-04-03 19:08:51.000000000 +1000
+++ 2.6.16-git20/drivers/video/pm2fb.c	2006-04-03 19:09:34.000000000 +1000
@@ -73,8 +73,8 @@ static char *mode __devinitdata = NULL;
  * these flags allow the user to specify that requests for +ve sync
  * should be silently turned in -ve sync.
  */
-static int lowhsync __devinitdata = 0;
-static int lowvsync __devinitdata = 0;
+static int lowhsync = 0;
+static int lowvsync = 0;
 
 /*
  * The hardware state of the graphics card that isn't part of the

^ permalink raw reply

* [cpufrequtils patch] sanitize rpath and quieten the strip command
From: Mattia Dongili @ 2006-04-09 15:57 UTC (permalink / raw)
  To: cpufreq
In-Reply-To: <20060326101231.GA19126@dominikbrodowski.de>

[-- Attachment #1: Type: text/plain, Size: 797 bytes --]

Hello Dominik,

one more patch addressing two issues (one hunk each):

1 - use ccdv to run strip (yes, a really cosmetic change)

2 - use the proper rpath when linking libcpufreq.so. It is needed
    because otherwise libtool will create a messed libdir in
    libcpufreq.la fooling 3rd parties linking against libcpufreq (and
    using libtool for themselves).
    Since the problem is the usage of $(DESTDIR) this will probably only
    show in prebuilt packages in linux distros.

Eg: building cpufrequtils in /tmp/cpufrequtils-001/ and willing to
install in /tmp/package

# cd /tmp/cpufrequtils-001/ && make DESTDIR=/tmp/package
...
# grep libdir /tmp/cpufrequtils-001/libcpufreq.la
libdir='/tmp/package/usr/lib'

I suppose this is definitely not the wanted behaviour.

Thanks
-- 
mattia
:wq!

[-- Attachment #2: sanitize_rpath+quieten_strip.diff --]
[-- Type: text/plain, Size: 767 bytes --]

--- cpufrequtils-001.clean/Makefile	2006-04-09 17:20:39.029391478 +0200
+++ cpufrequtils-001/Makefile	2006-04-09 09:27:00.433340228 +0200
@@ -185,14 +185,14 @@ libcpufreq.la: $(LIB_OBJS) $(LIB_HEADERS
 		exit -1; \
 	fi;
 	$(QUIET) $(LIBTOOL) $(LIBTOOL_OPT) --mode=link $(CC) $(CFLAGDEF) $(CFLAGS) $(LDFLAGS) -o libcpufreq.la -rpath \
-		$(DESTDIR)${libdir} -version-info $(LIB_VERSION) $(LIB_PARTS)
+		${libdir} -version-info $(LIB_VERSION) $(LIB_PARTS)
 
 libcpufreq: libcpufreq.la
 
 cpufreq-%: $(UTIL_OBJS)
 	$(QUIET) $(CC) $(CFLAGDEF) $(CFLAGS) -g -I. -I./lib/ -c -o utils/$@.o utils/$*.c
 	$(QUIET) $(CC) $(CFLAGDEF) $(CFLAGS) -g -I./lib/ -L. -L./.libs/ -lcpufreq -o $@ utils/$@.o
-	$(STRIPCMD) $@
+	$(QUIET) $(STRIPCMD) $@
 
 utils: cpufreq-info cpufreq-set
 

[-- Attachment #3: Type: text/plain, Size: 147 bytes --]

_______________________________________________
Cpufreq mailing list
Cpufreq@lists.linux.org.uk
http://lists.linux.org.uk/mailman/listinfo/cpufreq

^ permalink raw reply

* Re: reading time value in dom0 and domU kernels
From: Keir Fraser @ 2006-04-09 15:56 UTC (permalink / raw)
  To: sanjay kumar; +Cc: xen-devel
In-Reply-To: <2717599f0604090819g5433b228p486ae4f8dbb343e9@mail.gmail.com>


On 9 Apr 2006, at 16:19, sanjay kumar wrote:

> Hi Folks,
>  I want to calculate latency in transferring a buffer from domU kernel 
> to dom0 kernel and vice versa. for that I need a time 'flavour' (cycle 
> counter time?) which reads the same in dom0 and domU. Could someone 
> please let me know if cycle counter time is the right time to use? if 
> not then which one (system time or wall clock time)? Also could 
> someone please tell me how to read to read this timer value.
>
>  if I use rdtsc() in both dom0 and domU, will it give me the same time 
> value?

It should be close enough as Xen attempts to synchronise the TSCs of 
all CPUs during boot and on most x86 platforms the TSCs will not 
diverge.

If you're measuring in the kernel then something like 'sched_clock()' 
will get you system time in nanoseconds. That would be slightly 
preferable as system time is actively synchronised across all domains. 
With TSC you are winging it a tiny bit (although it's usually an okay 
strategy on x86).

  -- Keir

^ permalink raw reply

* Re: 2.6.17-rc1-mm1: drivers/acpi/numa.c compile error
From: Randy.Dunlap @ 2006-04-09 15:57 UTC (permalink / raw)
  To: Adrian Bunk
  Cc: akpm, len.brown, linux-kernel, linux-acpi, y-goto, tony.luck, ak,
	haveblue
In-Reply-To: <20060409154446.GE8454@stusta.de>

On Sun, 9 Apr 2006 17:44:46 +0200 Adrian Bunk wrote:

> On Fri, Apr 07, 2006 at 01:59:37PM -0700, Andrew Morton wrote:
> > Adrian Bunk <bunk@stusta.de> wrote:
> > >
> > > I'm getting the following compile error with CONFIG_ACPI_NUMA=y:
> > > 
> > > <--  snip  -->
> > > 
> > > ...
> > >   CC      drivers/acpi/numa.o
> > > drivers/acpi/numa.c: In function 'acpi_numa_init':
> > > drivers/acpi/numa.c:231: error: 'NR_NODE_MEMBLKS' undeclared (first use in this function)
> > 
> > I'm not quite sure how we managed that, but I guess
> > unify-pxm_to_node-and-node_to_pxm.patch triggered it?
> 
> Yes, obviously (I got this error on i386):
> 
>  config ACPI_NUMA
>         bool "NUMA support"
>         depends on NUMA
> -       depends on (IA64 || X86_64)
> +       depends on (X86_32 || IA64 || X86_64)
>         default y if IA64_GENERIC || IA64_SGI_SN2

The new/fixed line should just be
	depends on X86 || IA64
since X86_32 and X86_64 both set X86.

---
~Randy

^ permalink raw reply

* Re: How to correct ELCR? - was Re: [PATCH 2.6.16] Shared interrupts sometimes lost
From: Francois Romieu @ 2006-04-09 15:48 UTC (permalink / raw)
  To: Neil Brown; +Cc: Robert Hancock, linux-kernel
In-Reply-To: <17464.55398.270243.839773@cse.unsw.edu.au>

Neil Brown <neilb@suse.de> :
[...]

Can you send an url for the exact rt2500 sources that you are
actually using ?

Just curious :o)

-- 
Ueimor

^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.