svn commit: r271794 - head/sys/cam/ctl

Alexander Motin mav at FreeBSD.org
Thu Sep 18 17:25:20 UTC 2014


Author: mav
Date: Thu Sep 18 17:25:20 2014
New Revision: 271794
URL: http://svnweb.freebsd.org/changeset/base/271794

Log:
  When updating device media size use cached cdevsw pointer.
  
  Using pointer from the cdev directly is dangerous since we have no reference
  on it, and it may change any time.  That caused panic if device has gone.
  
  While there, report capacity change only if it really changed.
  
  MFC after:	3 days

Modified:
  head/sys/cam/ctl/ctl_backend_block.c

Modified: head/sys/cam/ctl/ctl_backend_block.c
==============================================================================
--- head/sys/cam/ctl/ctl_backend_block.c	Thu Sep 18 17:22:42 2014	(r271793)
+++ head/sys/cam/ctl/ctl_backend_block.c	Thu Sep 18 17:25:20 2014	(r271794)
@@ -2278,7 +2278,9 @@ ctl_be_block_modify_file(struct ctl_be_b
 	if (params->lun_size_bytes != 0) {
 		be_lun->size_bytes = params->lun_size_bytes;
 	} else  {
+		vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
 		error = VOP_GETATTR(be_lun->vn, &vattr, curthread->td_ucred);
+		VOP_UNLOCK(be_lun->vn, 0);
 		if (error != 0) {
 			snprintf(req->error_str, sizeof(req->error_str),
 				 "error calling VOP_GETATTR() for file %s",
@@ -2296,24 +2298,22 @@ static int
 ctl_be_block_modify_dev(struct ctl_be_block_lun *be_lun,
 			struct ctl_lun_req *req)
 {
-	struct cdev *dev;
-	struct cdevsw *devsw;
+	struct ctl_be_block_devdata *dev_data;
 	int error;
 	struct ctl_lun_modify_params *params;
 	uint64_t size_bytes;
 
 	params = &req->reqdata.modify;
 
-	dev = be_lun->vn->v_rdev;
-	devsw = dev->si_devsw;
-	if (!devsw->d_ioctl) {
+	dev_data = &be_lun->backend.dev;
+	if (!dev_data->csw->d_ioctl) {
 		snprintf(req->error_str, sizeof(req->error_str),
 			 "%s: no d_ioctl for device %s!", __func__,
 			 be_lun->dev_path);
 		return (ENODEV);
 	}
 
-	error = devsw->d_ioctl(dev, DIOCGMEDIASIZE,
+	error = dev_data->csw->d_ioctl(dev_data->cdev, DIOCGMEDIASIZE,
 			       (caddr_t)&size_bytes, FREAD,
 			       curthread);
 	if (error) {
@@ -2346,6 +2346,7 @@ ctl_be_block_modify(struct ctl_be_block_
 {
 	struct ctl_lun_modify_params *params;
 	struct ctl_be_block_lun *be_lun;
+	uint64_t oldsize;
 	int error;
 
 	params = &req->reqdata.modify;
@@ -2376,28 +2377,27 @@ ctl_be_block_modify(struct ctl_be_block_
 		}
 	}
 
-	vn_lock(be_lun->vn, LK_SHARED | LK_RETRY);
-
+	oldsize = be_lun->size_bytes;
 	if (be_lun->vn->v_type == VREG)
 		error = ctl_be_block_modify_file(be_lun, req);
 	else
 		error = ctl_be_block_modify_dev(be_lun, req);
-
-	VOP_UNLOCK(be_lun->vn, 0);
-
 	if (error != 0)
 		goto bailout_error;
 
-	be_lun->size_blocks = be_lun->size_bytes >> be_lun->blocksize_shift;
+	if (be_lun->size_bytes != oldsize) {
+		be_lun->size_blocks = be_lun->size_bytes >>
+		    be_lun->blocksize_shift;
 
-	/*
-	 * The maximum LBA is the size - 1.
-	 *
-	 * XXX: Note that this field is being updated without locking,
-	 * 	which might cause problems on 32-bit architectures.
-	 */
-	be_lun->ctl_be_lun.maxlba = be_lun->size_blocks - 1;
-	ctl_lun_capacity_changed(&be_lun->ctl_be_lun);
+		/*
+		 * The maximum LBA is the size - 1.
+		 *
+		 * XXX: Note that this field is being updated without locking,
+		 * 	which might cause problems on 32-bit architectures.
+		 */
+		be_lun->ctl_be_lun.maxlba = be_lun->size_blocks - 1;
+		ctl_lun_capacity_changed(&be_lun->ctl_be_lun);
+	}
 
 	/* Tell the user the exact size we ended up using */
 	params->lun_size_bytes = be_lun->size_bytes;


More information about the svn-src-all mailing list