[kernel] r15763 - in dists/sid/linux-2.6/debian: . patches/features/all/xen

Bastian Blank waldi at alioth.debian.org
Mon May 24 15:38:20 UTC 2010


Author: waldi
Date: Mon May 24 15:38:15 2010
New Revision: 15763

Log:
* debian/changelog: Update.
* debian/patches/features/all/xen/pvops.patch: Update patch to f6fe6583b77a.

Modified:
   dists/sid/linux-2.6/debian/changelog
   dists/sid/linux-2.6/debian/patches/features/all/xen/pvops.patch

Modified: dists/sid/linux-2.6/debian/changelog
==============================================================================
--- dists/sid/linux-2.6/debian/changelog	Mon May 24 03:34:28 2010	(r15762)
+++ dists/sid/linux-2.6/debian/changelog	Mon May 24 15:38:15 2010	(r15763)
@@ -17,6 +17,9 @@
     been blacklisted by cpufrequtils. The acpi-cpufreq driver can be used
     instead on some VIA C7 systems. (Closes: #566208)
 
+  [ Bastian Blank ]
+  * Update Xen patch.
+
  -- Ben Hutchings <ben at decadent.org.uk>  Tue, 18 May 2010 02:13:44 +0100
 
 linux-2.6 (2.6.32-13) unstable; urgency=low

Modified: dists/sid/linux-2.6/debian/patches/features/all/xen/pvops.patch
==============================================================================
--- dists/sid/linux-2.6/debian/patches/features/all/xen/pvops.patch	Mon May 24 03:34:28 2010	(r15762)
+++ dists/sid/linux-2.6/debian/patches/features/all/xen/pvops.patch	Mon May 24 15:38:15 2010	(r15763)
@@ -1,4 +1,4 @@
-Patch based on commit ba739f9abd3f659b907a824af1161926b420a2ce of
+Patch based on commit f6fe6583b77a49b569eef1b66c3d761eec2e561b of
 git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git.
 
 diff --git a/Documentation/x86/x86_64/boot-options.txt b/Documentation/x86/x86_64/boot-options.txt
@@ -3380,7 +3380,7 @@
 +#endif
 +}
 diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
-index 3578688..e6a9f9f 100644
+index 3578688..7638cd6 100644
 --- a/arch/x86/xen/enlighten.c
 +++ b/arch/x86/xen/enlighten.c
 @@ -28,12 +28,19 @@
@@ -3675,7 +3675,7 @@
  	}
  
  	xen_raw_console_write("about to get started...\n");
-@@ -1197,3 +1279,142 @@ asmlinkage void __init xen_start_kernel(void)
+@@ -1197,3 +1279,141 @@ asmlinkage void __init xen_start_kernel(void)
  	x86_64_start_reservations((char *)__pa_symbol(&boot_params));
  #endif
  }
@@ -3792,7 +3792,6 @@
 +	}
 +	have_vcpu_info_placement = 0;
 +	x86_init.irqs.intr_init = xen_init_IRQ;
-+	machine_ops = xen_machine_ops;
 +}
 +
 +static int __init parse_unplug(char *arg)
@@ -6236,7 +6235,7 @@
  	  This driver implements the front-end of the Xen virtual
  	  block device driver.  It communicates with a back-end driver
 diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
-index b8578bb..a8d30d7 100644
+index b8578bb..75f730b 100644
 --- a/drivers/block/xen-blkfront.c
 +++ b/drivers/block/xen-blkfront.c
 @@ -42,6 +42,7 @@
@@ -6247,7 +6246,25 @@
  #include <xen/xenbus.h>
  #include <xen/grant_table.h>
  #include <xen/events.h>
-@@ -102,6 +103,10 @@ struct blkfront_info
+@@ -76,6 +77,7 @@ static const struct block_device_operations xlvbd_block_fops;
+  */
+ struct blkfront_info
+ {
++	struct mutex mutex;
+ 	struct xenbus_device *xbdev;
+ 	struct gendisk *gd;
+ 	int vdevice;
+@@ -92,16 +94,14 @@ struct blkfront_info
+ 	unsigned long shadow_free;
+ 	int feature_barrier;
+ 	int is_ready;
+-
+-	/**
+-	 * The number of people holding this device open.  We won't allow a
+-	 * hot-unplug unless this is 0.
+-	 */
+-	int users;
+ };
  
  static DEFINE_SPINLOCK(blkif_io_lock);
  
@@ -6258,7 +6275,7 @@
  #define MAXIMUM_OUTSTANDING_BLOCK_REQS \
  	(BLKIF_MAX_SEGMENTS_PER_REQUEST * BLK_RING_SIZE)
  #define GRANT_INVALID_REF	0
-@@ -136,6 +141,55 @@ static void add_id_to_freelist(struct blkfront_info *info,
+@@ -136,6 +136,55 @@ static void add_id_to_freelist(struct blkfront_info *info,
  	info->shadow_free = id;
  }
  
@@ -6314,7 +6331,7 @@
  static void blkif_restart_queue_callback(void *arg)
  {
  	struct blkfront_info *info = (struct blkfront_info *)arg;
-@@ -416,9 +470,14 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
+@@ -416,9 +465,14 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
  	if ((minor % nr_parts) == 0)
  		nr_minors = nr_parts;
  
@@ -6330,7 +6347,7 @@
  
  	offset = minor / nr_parts;
  
-@@ -449,7 +508,7 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
+@@ -449,7 +503,7 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
  
  	if (xlvbd_init_blk_queue(gd, sector_size)) {
  		del_gendisk(gd);
@@ -6339,7 +6356,7 @@
  	}
  
  	info->rq = gd->queue;
-@@ -469,6 +528,8 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
+@@ -469,10 +523,45 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
  
  	return 0;
  
@@ -6348,7 +6365,44 @@
   out:
  	return err;
  }
-@@ -650,7 +711,7 @@ fail:
+ 
++static void xlvbd_release_gendisk(struct blkfront_info *info)
++{
++	unsigned int minor, nr_minors;
++	unsigned long flags;
++
++	if (info->rq == NULL)
++		return;
++
++	spin_lock_irqsave(&blkif_io_lock, flags);
++
++	/* No more blkif_request(). */
++	blk_stop_queue(info->rq);
++
++	/* No more gnttab callback work. */
++	gnttab_cancel_free_callback(&info->callback);
++	spin_unlock_irqrestore(&blkif_io_lock, flags);
++
++	/* Flush gnttab callback work. Must be done with no locks held. */
++	flush_scheduled_work();
++
++	del_gendisk(info->gd);
++
++	minor = info->gd->first_minor;
++	nr_minors = info->gd->minors;
++	xlbd_release_minors(minor, nr_minors);
++
++	blk_cleanup_queue(info->rq);
++	info->rq = NULL;
++
++	put_disk(info->gd);
++	info->gd = NULL;
++}
++
+ static void kick_pending_request_queues(struct blkfront_info *info)
+ {
+ 	if (!RING_FULL(&info->ring)) {
+@@ -650,7 +739,7 @@ fail:
  
  
  /* Common code used when first setting up, and when resuming. */
@@ -6357,7 +6411,23 @@
  			   struct blkfront_info *info)
  {
  	const char *message = NULL;
-@@ -755,7 +816,7 @@ static int blkfront_probe(struct xenbus_device *dev,
+@@ -710,7 +799,6 @@ again:
+ 	return err;
+ }
+ 
+-
+ /**
+  * Entry point to this code when a new device is created.  Allocate the basic
+  * structures and the ring buffer for communication with the backend, and
+@@ -742,6 +830,7 @@ static int blkfront_probe(struct xenbus_device *dev,
+ 		return -ENOMEM;
+ 	}
+ 
++	mutex_init(&info->mutex);
+ 	info->xbdev = dev;
+ 	info->vdevice = vdevice;
+ 	info->connected = BLKIF_STATE_DISCONNECTED;
+@@ -755,7 +844,7 @@ static int blkfront_probe(struct xenbus_device *dev,
  	info->handle = simple_strtoul(strrchr(dev->nodename, '/')+1, NULL, 0);
  	dev_set_drvdata(&dev->dev, info);
  
@@ -6366,7 +6436,7 @@
  	if (err) {
  		kfree(info);
  		dev_set_drvdata(&dev->dev, NULL);
-@@ -850,7 +911,7 @@ static int blkfront_resume(struct xenbus_device *dev)
+@@ -850,13 +939,50 @@ static int blkfront_resume(struct xenbus_device *dev)
  
  	blkif_free(info, info->connected == BLKIF_STATE_CONNECTED);
  
@@ -6375,7 +6445,50 @@
  	if (info->connected == BLKIF_STATE_SUSPENDED && !err)
  		err = blkif_recover(info);
  
-@@ -869,10 +930,29 @@ static void blkfront_connect(struct blkfront_info *info)
+ 	return err;
+ }
+ 
++static void
++blkfront_closing(struct blkfront_info *info)
++{
++	struct xenbus_device *xbdev = info->xbdev;
++	struct block_device *bdev = NULL;
++
++	mutex_lock(&info->mutex);
++
++	if (xbdev->state == XenbusStateClosing) {
++		mutex_unlock(&info->mutex);
++		return;
++	}
++
++	if (info->gd)
++		bdev = bdget_disk(info->gd, 0);
++
++	mutex_unlock(&info->mutex);
++
++	if (!bdev) {
++		xenbus_frontend_closed(xbdev);
++		return;
++	}
++
++	mutex_lock(&bdev->bd_mutex);
++
++	if (bdev->bd_openers) {
++		xenbus_dev_error(xbdev, -EBUSY,
++				 "Device in use; refusing to close");
++		xenbus_switch_state(xbdev, XenbusStateClosing);
++	} else {
++		xlvbd_release_gendisk(info);
++		xenbus_frontend_closed(xbdev);
++	}
++
++	mutex_unlock(&bdev->bd_mutex);
++	bdput(bdev);
++}
+ 
+ /*
+  * Invoked when the backend is finally 'ready' (and has told produced
+@@ -869,10 +995,29 @@ static void blkfront_connect(struct blkfront_info *info)
  	unsigned int binfo;
  	int err;
  
@@ -6407,37 +6520,47 @@
  	dev_dbg(&info->xbdev->dev, "%s:%s.\n",
  		__func__, info->xbdev->otherend);
  
-@@ -920,12 +1000,11 @@ static void blkfront_connect(struct blkfront_info *info)
-  * the backend.  Once is this done, we can switch to Closed in
-  * acknowledgement.
-  */
+@@ -915,57 +1060,21 @@ static void blkfront_connect(struct blkfront_info *info)
+ }
+ 
+ /**
+- * Handle the change of state of the backend to Closing.  We must delete our
+- * device-layer structures now, to ensure that writes are flushed through to
+- * the backend.  Once is this done, we can switch to Closed in
+- * acknowledgement.
+- */
 -static void blkfront_closing(struct xenbus_device *dev)
-+static void blkfront_closing(struct blkfront_info *info)
- {
+-{
 -	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
-+	unsigned int minor, nr_minors;
- 	unsigned long flags;
- 
+-	unsigned long flags;
+-
 -	dev_dbg(&dev->dev, "blkfront_closing: %s removed\n", dev->nodename);
- 
- 	if (info->rq == NULL)
- 		goto out;
-@@ -945,27 +1024,33 @@ static void blkfront_closing(struct xenbus_device *dev)
- 	blk_cleanup_queue(info->rq);
- 	info->rq = NULL;
- 
-+	minor = info->gd->first_minor;
-+	nr_minors = info->gd->minors;
- 	del_gendisk(info->gd);
-+	xlbd_release_minors(minor, nr_minors);
- 
-  out:
+-
+-	if (info->rq == NULL)
+-		goto out;
+-
+-	spin_lock_irqsave(&blkif_io_lock, flags);
+-
+-	/* No more blkif_request(). */
+-	blk_stop_queue(info->rq);
+-
+-	/* No more gnttab callback work. */
+-	gnttab_cancel_free_callback(&info->callback);
+-	spin_unlock_irqrestore(&blkif_io_lock, flags);
+-
+-	/* Flush gnttab callback work. Must be done with no locks held. */
+-	flush_scheduled_work();
+-
+-	blk_cleanup_queue(info->rq);
+-	info->rq = NULL;
+-
+-	del_gendisk(info->gd);
+-
+- out:
 -	xenbus_frontend_closed(dev);
-+	if (info->xbdev)
-+		xenbus_frontend_closed(info->xbdev);
- }
- 
- /**
+-}
+-
+-/**
   * Callback received when the backend's state changes.
   */
 -static void backend_changed(struct xenbus_device *dev,
@@ -6445,7 +6568,7 @@
  			    enum xenbus_state backend_state)
  {
  	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
- 	struct block_device *bd;
+-	struct block_device *bd;
  
 -	dev_dbg(&dev->dev, "blkfront:backend_changed.\n");
 +	dev_dbg(&dev->dev, "blkfront:blkback_changed to state %d.\n", backend_state);
@@ -6459,28 +6582,84 @@
  	case XenbusStateUnknown:
  	case XenbusStateClosed:
  		break;
-@@ -988,7 +1073,7 @@ static void backend_changed(struct xenbus_device *dev,
- 			xenbus_dev_error(dev, -EBUSY,
- 					 "Device in use; refusing to close");
- 		else
+@@ -975,35 +1084,56 @@ static void backend_changed(struct xenbus_device *dev,
+ 		break;
+ 
+ 	case XenbusStateClosing:
+-		if (info->gd == NULL) {
+-			xenbus_frontend_closed(dev);
+-			break;
+-		}
+-		bd = bdget_disk(info->gd, 0);
+-		if (bd == NULL)
+-			xenbus_dev_fatal(dev, -ENODEV, "bdget failed");
+-
+-		mutex_lock(&bd->bd_mutex);
+-		if (info->users > 0)
+-			xenbus_dev_error(dev, -EBUSY,
+-					 "Device in use; refusing to close");
+-		else
 -			blkfront_closing(dev);
-+			blkfront_closing(info);
- 		mutex_unlock(&bd->bd_mutex);
- 		bdput(bd);
+-		mutex_unlock(&bd->bd_mutex);
+-		bdput(bd);
++		blkfront_closing(info);
  		break;
-@@ -1003,7 +1088,10 @@ static int blkfront_remove(struct xenbus_device *dev)
+ 	}
+ }
+ 
+-static int blkfront_remove(struct xenbus_device *dev)
++static int blkfront_remove(struct xenbus_device *xbdev)
+ {
+-	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
++	struct blkfront_info *info = dev_get_drvdata(&xbdev->dev);
++	struct block_device *bdev = NULL;
++	struct gendisk *disk;
+ 
+-	dev_dbg(&dev->dev, "blkfront_remove: %s removed\n", dev->nodename);
++	dev_dbg(&xbdev->dev, "%s removed", xbdev->nodename);
  
  	blkif_free(info, 0);
  
 -	kfree(info);
-+	if(info->users == 0)
++	mutex_lock(&info->mutex);
++
++	disk = info->gd;
++	if (disk)
++		bdev = bdget_disk(disk, 0);
++
++	info->xbdev = NULL;
++	mutex_unlock(&info->mutex);
++
++	if (!bdev) {
 +		kfree(info);
-+	else
-+		info->xbdev = NULL;
++		return 0;
++	}
++
++	/*
++	 * The xbdev was removed before we reached the Closed
++	 * state. See if it's safe to remove the disk. If the bdev
++	 * isn't closed yet, we let release take care of it.
++	 */
++
++	mutex_lock(&bdev->bd_mutex);
++	info = disk->private_data;
++
++	dev_warn(disk_to_dev(disk),
++		 "%s was hot-unplugged, %d stale handles\n",
++		 xbdev->nodename, bdev->bd_openers);
++
++	if (info && !bdev->bd_openers) {
++		xlvbd_release_gendisk(info);
++		disk->private_data = NULL;
++		kfree(info);
++	}
++
++	mutex_unlock(&bdev->bd_mutex);
++	bdput(bdev);
  
  	return 0;
  }
-@@ -1012,12 +1100,15 @@ static int blkfront_is_ready(struct xenbus_device *dev)
+@@ -1012,30 +1142,68 @@ static int blkfront_is_ready(struct xenbus_device *dev)
  {
  	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
  
@@ -6490,31 +6669,80 @@
  
  static int blkif_open(struct block_device *bdev, fmode_t mode)
  {
- 	struct blkfront_info *info = bdev->bd_disk->private_data;
+-	struct blkfront_info *info = bdev->bd_disk->private_data;
+-	info->users++;
+-	return 0;
++	struct gendisk *disk = bdev->bd_disk;
++	struct blkfront_info *info;
++	int err = 0;
 +
-+	if (!info->xbdev)
-+		return -ENODEV;
- 	info->users++;
- 	return 0;
++	info = disk->private_data;
++	if (!info)
++		/* xbdev gone */
++		return -ERESTARTSYS;
++
++	mutex_lock(&info->mutex);
++
++	if (!info->gd)
++		/* xbdev is closed */
++		err = -ERESTARTSYS;
++
++	mutex_unlock(&info->mutex);
++
++	return err;
  }
-@@ -1031,10 +1122,13 @@ static int blkif_release(struct gendisk *disk, fmode_t mode)
- 		   have ignored this request initially, as the device was
- 		   still mounted. */
- 		struct xenbus_device *dev = info->xbdev;
--		enum xenbus_state state = xenbus_read_driver_state(dev->otherend);
  
+ static int blkif_release(struct gendisk *disk, fmode_t mode)
+ {
+ 	struct blkfront_info *info = disk->private_data;
+-	info->users--;
+-	if (info->users == 0) {
+-		/* Check whether we have been instructed to close.  We will
+-		   have ignored this request initially, as the device was
+-		   still mounted. */
+-		struct xenbus_device *dev = info->xbdev;
+-		enum xenbus_state state = xenbus_read_driver_state(dev->otherend);
+-
 -		if (state == XenbusStateClosing && info->is_ready)
 -			blkfront_closing(dev);
-+		if (!dev) {
-+			blkfront_closing(info);
-+			kfree(info);
-+		} else if (xenbus_read_driver_state(dev->otherend)
-+			   == XenbusStateClosing && info->is_ready)
-+			blkfront_closing(info);
++	struct block_device *bdev;
++	struct xenbus_device *xbdev;
++
++	bdev = bdget_disk(disk, 0);
++	bdput(bdev);
++
++	if (bdev->bd_openers)
++		return 0;
++
++	/*
++	 * Check if we have been instructed to close. We will have
++	 * deferred this request, because the bdev was still open.
++	 */
++
++	mutex_lock(&info->mutex);
++	xbdev = info->xbdev;
++
++	if (xbdev && xbdev->state == XenbusStateClosing) {
++		/* pending switch to state closed */
++		dev_info(disk_to_dev(bdev->bd_disk), "releasing disk\n");
++		xlvbd_release_gendisk(info);
++		xenbus_frontend_closed(info->xbdev);
++	}
++
++	mutex_unlock(&info->mutex);
++
++	if (!xbdev) {
++		/* sudden device removal */
++		dev_info(disk_to_dev(bdev->bd_disk), "releasing disk\n");
++		xlvbd_release_gendisk(info);
++		disk->private_data = NULL;
++		kfree(info);
  	}
++
  	return 0;
  }
-@@ -1061,7 +1155,7 @@ static struct xenbus_driver blkfront = {
+ 
+@@ -1061,7 +1229,7 @@ static struct xenbus_driver blkfront = {
  	.probe = blkfront_probe,
  	.remove = blkfront_remove,
  	.resume = blkfront_resume,
@@ -16661,7 +16889,7 @@
 +
 +core_initcall(__gnttab_init);
 diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
-index 5d42d55..004b1dd 100644
+index 5d42d55..3924018 100644
 --- a/drivers/xen/manage.c
 +++ b/drivers/xen/manage.c
 @@ -7,15 +7,19 @@
@@ -16716,7 +16944,7 @@
  
  	BUG_ON(!irqs_disabled());
  
-@@ -72,6 +96,59 @@ static int xen_suspend(void *data)
+@@ -72,6 +96,62 @@ static int xen_suspend(void *data)
  	return 0;
  }
  
@@ -16770,13 +16998,16 @@
 +	stop_machine_destroy();
 +
 +out:
++#ifdef CONFIG_PREEMPT
++	thaw_processes();
++#endif
 +	shutting_down = SHUTDOWN_INVALID;
 +}
 +
  static void do_suspend(void)
  {
  	int err;
-@@ -184,7 +261,10 @@ static void shutdown_handler(struct xenbus_watch *watch,
+@@ -184,7 +264,10 @@ static void shutdown_handler(struct xenbus_watch *watch,
  		ctrl_alt_del();
  #ifdef CONFIG_PM_SLEEP
  	} else if (strcmp(str, "suspend") == 0) {
@@ -16788,7 +17019,7 @@
  #endif
  	} else {
  		printk(KERN_INFO "Ignoring shutdown request: %s\n", str);
-@@ -260,7 +340,19 @@ static int shutdown_event(struct notifier_block *notifier,
+@@ -260,7 +343,19 @@ static int shutdown_event(struct notifier_block *notifier,
  	return NOTIFY_DONE;
  }
  
@@ -16809,7 +17040,7 @@
  {
  	static struct notifier_block xenstore_notifier = {
  		.notifier_call = shutdown_event
-@@ -270,4 +362,4 @@ static int __init setup_shutdown_event(void)
+@@ -270,4 +365,4 @@ static int __init setup_shutdown_event(void)
  	return 0;
  }
  
@@ -17697,10 +17928,10 @@
 +}
 diff --git a/drivers/xen/netback/netback.c b/drivers/xen/netback/netback.c
 new file mode 100644
-index 0000000..0bc6398
+index 0000000..5dc4f98
 --- /dev/null
 +++ b/drivers/xen/netback/netback.c
-@@ -0,0 +1,1613 @@
+@@ -0,0 +1,1609 @@
 +/******************************************************************************
 + * drivers/xen/netback/netback.c
 + *
@@ -19035,14 +19266,10 @@
 +			netif_idx_release(pending_idx);
 +		}
 +
-+		/*
-+		 * Old frontends do not assert data_validated but we
-+		 * can infer it from csum_blank so test both flags.
-+		 */
-+		if (txp->flags & (NETTXF_data_validated|NETTXF_csum_blank))
++		if (txp->flags & NETTXF_csum_blank)
 +			skb->ip_summed = CHECKSUM_PARTIAL;
-+		else
-+			skb->ip_summed = CHECKSUM_NONE;
++		else if (txp->flags & NETTXF_data_validated)
++			skb->ip_summed = CHECKSUM_UNNECESSARY;
 +
 +		netbk_fill_frags(skb);
 +
@@ -26043,7 +26270,7 @@
 +
 +obj-$(CONFIG_XEN_XENBUS_FRONTEND) += xenbus_probe_frontend.o
 diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
-index 92a1ef8..da3ca9e 100644
+index 92a1ef8..89f2e42 100644
 --- a/drivers/xen/xenbus/xenbus_client.c
 +++ b/drivers/xen/xenbus/xenbus_client.c
 @@ -49,6 +49,8 @@ const char *xenbus_strstate(enum xenbus_state state)
@@ -26055,6 +26282,133 @@
  	};
  	return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
  }
+@@ -132,17 +134,12 @@ int xenbus_watch_pathfmt(struct xenbus_device *dev,
+ }
+ EXPORT_SYMBOL_GPL(xenbus_watch_pathfmt);
+ 
++static void xenbus_switch_fatal(struct xenbus_device *, int, int,
++				const char *, ...);
+ 
+-/**
+- * xenbus_switch_state
+- * @dev: xenbus device
+- * @state: new state
+- *
+- * Advertise in the store a change of the given driver to the given new_state.
+- * Return 0 on success, or -errno on error.  On error, the device will switch
+- * to XenbusStateClosing, and the error will be saved in the store.
+- */
+-int xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state state)
++static int
++__xenbus_switch_state(struct xenbus_device *dev,
++		      enum xenbus_state state, int depth)
+ {
+ 	/* We check whether the state is currently set to the given value, and
+ 	   if not, then the state is set.  We don't want to unconditionally
+@@ -151,35 +148,65 @@ int xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state state)
+ 	   to it, as the device will be tearing down, and we don't want to
+ 	   resurrect that directory.
+ 
+-	   Note that, because of this cached value of our state, this function
+-	   will not work inside a Xenstore transaction (something it was
+-	   trying to in the past) because dev->state would not get reset if
+-	   the transaction was aborted.
+-
++	   Note that, because of this cached value of our state, this
++	   function will not take a caller's Xenstore transaction
++	   (something it was trying to in the past) because dev->state
++	   would not get reset if the transaction was aborted.
+ 	 */
+ 
++	struct xenbus_transaction xbt;
+ 	int current_state;
+-	int err;
++	int err, abort;
+ 
+ 	if (state == dev->state)
+ 		return 0;
+ 
+-	err = xenbus_scanf(XBT_NIL, dev->nodename, "state", "%d",
+-			   &current_state);
+-	if (err != 1)
++again:
++	abort = 1;
++
++	err = xenbus_transaction_start(&xbt);
++	if (err) {
++		xenbus_switch_fatal(dev, depth, err, "starting transaction");
+ 		return 0;
++	}
++
++	err = xenbus_scanf(xbt, dev->nodename, "state", "%d", &current_state);
++	if (err != 1)
++		goto abort;
+ 
+-	err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%d", state);
++	err = xenbus_printf(xbt, dev->nodename, "state", "%d", state);
+ 	if (err) {
+-		if (state != XenbusStateClosing) /* Avoid looping */
+-			xenbus_dev_fatal(dev, err, "writing new state");
+-		return err;
++		xenbus_switch_fatal(dev, depth, err, "writing new state");
++		goto abort;
+ 	}
+ 
+-	dev->state = state;
++	abort = 0;
++abort:
++	err = xenbus_transaction_end(xbt, abort);
++	if (err) {
++		if (err == -EAGAIN && !abort)
++			goto again;
++		xenbus_switch_fatal(dev, depth, err, "ending transaction");
++	} else
++		dev->state = state;
+ 
+ 	return 0;
+ }
++
++/**
++ * xenbus_switch_state
++ * @dev: xenbus device
++ * @state: new state
++ *
++ * Advertise in the store a change of the given driver to the given new_state.
++ * Return 0 on success, or -errno on error.  On error, the device will switch
++ * to XenbusStateClosing, and the error will be saved in the store.
++ */
++int xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state state)
++{
++	return __xenbus_switch_state(dev, state, 0);
++}
++
+ EXPORT_SYMBOL_GPL(xenbus_switch_state);
+ 
+ int xenbus_frontend_closed(struct xenbus_device *dev)
+@@ -283,6 +310,23 @@ void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, ...)
+ EXPORT_SYMBOL_GPL(xenbus_dev_fatal);
+ 
+ /**
++ * Equivalent to xenbus_dev_fatal(dev, err, fmt, args), but helps
++ * avoiding recursion within xenbus_switch_state.
++ */
++static void xenbus_switch_fatal(struct xenbus_device *dev, int depth, int err,
++				const char *fmt, ...)
++{
++	va_list ap;
++
++	va_start(ap, fmt);
++	xenbus_va_dev_error(dev, err, fmt, ap);
++	va_end(ap);
++
++	if (!depth)
++		__xenbus_switch_state(dev, XenbusStateClosing, 1);
++}
++
++/**
+  * xenbus_grant_ring
+  * @dev: xenbus device
+  * @ring_mfn: mfn of ring to grant
 diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
 index 649fcdf..57fb749 100644
 --- a/drivers/xen/xenbus/xenbus_probe.c



More information about the Kernel-svn-changes mailing list