Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 4 Jun 2012 20:50:13 GMT
From:      dfilter@FreeBSD.ORG (dfilter service)
To:        freebsd-sparc64@FreeBSD.org
Subject:   Re: sparc64/165025: commit references a PR
Message-ID:  <201206042050.q54KoDKD043081@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR sparc64/165025; it has been noted by GNATS.

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: sparc64/165025: commit references a PR
Date: Mon,  4 Jun 2012 20:45:54 +0000 (UTC)

 Author: marius
 Date: Mon Jun  4 20:45:33 2012
 New Revision: 236579
 URL: http://svn.freebsd.org/changeset/base/236579
 
 Log:
   The workaround added in r151650 for handling firmwares that don't allow
   a single device to be opened multiple times concurrently unfortunately
   isn't sufficient with ZFS. This is due to the fact, that ZFS may open
   different partitions of a single device simultaneously. So the best we
   can do in this case is to cache the lastly used device path and close
   and open devices in ofwd_strategy() as needed.
   
   PR:		165025
   Submitted by:	Gavin Mu
   MFC after:	1 week
 
 Modified:
   head/sys/boot/ofw/libofw/ofw_disk.c
 
 Modified: head/sys/boot/ofw/libofw/ofw_disk.c
 ==============================================================================
 --- head/sys/boot/ofw/libofw/ofw_disk.c	Mon Jun  4 20:36:11 2012	(r236578)
 +++ head/sys/boot/ofw/libofw/ofw_disk.c	Mon Jun  4 20:45:33 2012	(r236579)
 @@ -31,7 +31,6 @@ __FBSDID("$FreeBSD$");
   */
  
  #include <sys/param.h>
 -#include <sys/queue.h>
  
  #include <netinet/in.h>
  
 @@ -43,8 +42,8 @@ __FBSDID("$FreeBSD$");
  #include "libofw.h"
  
  static int	ofwd_init(void);
 -static int	ofwd_strategy(void *devdata, int flag, daddr_t dblk, 
 -				size_t size, char *buf, size_t *rsize);
 +static int	ofwd_strategy(void *devdata, int flag, daddr_t dblk,
 +		    size_t size, char *buf, size_t *rsize);
  static int	ofwd_open(struct open_file *f, ...);
  static int	ofwd_close(struct open_file *f);
  static int	ofwd_ioctl(struct open_file *f, u_long cmd, void *data);
 @@ -61,120 +60,109 @@ struct devsw ofwdisk = {
  	ofwd_print
  };
  
 -struct opened_dev {
 -	ihandle_t		handle;
 -	u_int			count;
 -	SLIST_ENTRY(opened_dev)	link;
 -};
 -
 -SLIST_HEAD(, opened_dev) opened_devs = SLIST_HEAD_INITIALIZER(opened_devs);
 +/*
 + * We're not guaranteed to be able to open a device more than once and there
 + * is no OFW standard method to determine whether a device is already opened.
 + * Opening a device multiple times simultaneously happens to work with most
 + * OFW block device drivers but triggers a trap with at least the driver for
 + * the on-board controllers of Sun Fire V100 and Ultra 1.  Upper layers and MI
 + * code expect to be able to open a device more than once however.  Given that
 + * different partitions of the same device might be opened at the same time as
 + * done by ZFS, we can't generally just keep track of the opened devices and
 + * reuse the instance handle when asked to open an already opened device.  So
 + * the best we can do is to cache the lastly used device path and close and
 + * open devices in ofwd_strategy() as needed.
 + */
 +static struct ofw_devdesc *kdp;
  
  static int
  ofwd_init(void)
  {
  
 -	return 0;
 +	return (0);
  }
  
  static int
 -ofwd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf,
 -    size_t *rsize)
 +ofwd_strategy(void *devdata, int flag __unused, daddr_t dblk, size_t size,
 +    char *buf, size_t *rsize)
  {
  	struct ofw_devdesc *dp = (struct ofw_devdesc *)devdata;
  	daddr_t pos;
  	int n;
  
 +	if (dp != kdp) {
 +		if (kdp != NULL) {
 +#if !defined(__powerpc__)
 +			OF_close(kdp->d_handle);
 +#endif
 +			kdp = NULL;
 +		}
 +		if ((dp->d_handle = OF_open(dp->d_path)) == -1)
 +			return (ENOENT);
 +		kdp = dp;
 +	}
 +
  	pos = dblk * 512;
  	do {
  		if (OF_seek(dp->d_handle, pos) < 0)
 -			return EIO;
 +			return (EIO);
  		n = OF_read(dp->d_handle, buf, size);
  		if (n < 0 && n != -2)
 -			return EIO;
 +			return (EIO);
  	} while (n == -2);
  	*rsize = size;
 -	return 0;
 +	return (0);
  }
  
  static int
  ofwd_open(struct open_file *f, ...)
  {
 -	char path[256];
  	struct ofw_devdesc *dp;
 -	struct opened_dev *odp;
  	va_list vl;
  
  	va_start(vl, f);
  	dp = va_arg(vl, struct ofw_devdesc *);
  	va_end(vl);
 -	/*
 -	 * We're not guaranteed to be able to open a device more than once
 -	 * simultaneously and there is no OFW standard method to determine
 -	 * whether a device is already opened. Opening a device more than
 -	 * once happens to work with most OFW block device drivers but
 -	 * triggers a trap with at least the driver for the on-board SCSI
 -	 * controller in Sun Ultra 1. Upper layers and MI code expect to
 -	 * be able to open a device more than once however. As a workaround
 -	 * keep track of the opened devices and reuse the instance handle
 -	 * when asked to open an already opened device.
 -	 */
 -	SLIST_FOREACH(odp, &opened_devs, link) {
 -		if (OF_instance_to_path(odp->handle, path, sizeof(path)) == -1)
 -			continue;
 -		if (strcmp(path, dp->d_path) == 0) {
 -			odp->count++;
 -			dp->d_handle = odp->handle;
 -			return 0;
 +
 +	if (dp != kdp) {
 +		if (kdp != NULL) {
 +			OF_close(kdp->d_handle);
 +			kdp = NULL;
  		}
 +		if ((dp->d_handle = OF_open(dp->d_path)) == -1) {
 +			printf("%s: Could not open %s\n", __func__,
 +			    dp->d_path);
 +			return (ENOENT);
 +		}
 +		kdp = dp;
  	}
 -	odp = malloc(sizeof(struct opened_dev));
 -	if (odp == NULL) {
 -		printf("ofwd_open: malloc failed\n");
 -		return ENOMEM;
 -	}
 -	if ((odp->handle = OF_open(dp->d_path)) == -1) {
 -		printf("ofwd_open: Could not open %s\n", dp->d_path);
 -		free(odp);
 -		return ENOENT;
 -	}
 -	odp->count = 1;
 -	SLIST_INSERT_HEAD(&opened_devs, odp, link);
 -	dp->d_handle = odp->handle;
 -	return 0;
 +	return (0);
  }
  
  static int
  ofwd_close(struct open_file *f)
  {
  	struct ofw_devdesc *dev = f->f_devdata;
 -	struct opened_dev *odp;
  
 -	SLIST_FOREACH(odp, &opened_devs, link) {
 -		if (odp->handle == dev->d_handle) {
 -			odp->count--;
 -			if (odp->count == 0) {
 -				SLIST_REMOVE(&opened_devs, odp, opened_dev,
 -				    link);
 -			#if !defined(__powerpc__)
 -				OF_close(odp->handle);
 -			#endif
 -				free(odp);
 -			}
 -			break;
 -		}
 +	if (dev == kdp) {
 +#if !defined(__powerpc__)
 +		OF_close(dev->d_handle);
 +#endif
 +		kdp = NULL;
  	}
 -	return 0;
 +	return (0);
  }
  
  static int
 -ofwd_ioctl(struct open_file *f, u_long cmd, void *data)
 +ofwd_ioctl(struct open_file *f __unused, u_long cmd __unused,
 +    void *data __unused)
  {
  
  	return (EINVAL);
  }
  
  static void
 -ofwd_print(int verbose)
 +ofwd_print(int verbose __unused)
  {
  
  }
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201206042050.q54KoDKD043081>