FreeBSD/sys/cam/scsi/scsi_sa.c
/*
 * Go through a list of parameters, coalescing contiguous parameters with
 * the same parent node into a single call to a set_func.
 */
Go through a list of parameters, coalescing contiguous parameters with
the same parent node into a single call to a set_func.
Go through a list of parameters coalescing contiguous parameters with the same parent node into a single call to a set_func .
static int
saparamsetlist(struct cam_periph *periph, struct mtsetlist *list,
    int need_copy)
{
	int i, contig_ents;
	int error;
	struct mtparamset *params, *first;
	struct sa_param_ent *first_ent;
	error = 0;
	params = NULL;
	if (list->num_params == 0)
		goto bailout;
	if ((list->num_params * sizeof(struct mtparamset)) !=
	     list->param_len) {
		xpt_print(periph->path, "%s: length of params %d != "
		    "sizeof(struct mtparamset) %zd * num_params %d\n",
		    __func__, list->param_len, sizeof(struct mtparamset),
		    list->num_params);
		error = EINVAL;
		goto bailout;
	}
	if (need_copy != 0) {
		cam_periph_unlock(periph);
		params = malloc(list->param_len, M_SCSISA, M_WAITOK | M_ZERO);
		error = copyin(list->params, params, list->param_len);
		cam_periph_lock(periph);
		if (error != 0)
			goto bailout;
	} else {
		params = list->params;
	}
	contig_ents = 0;
	first = NULL;
	first_ent = NULL;
	for (i = 0; i < list->num_params; i++) {
		struct sa_param_ent *ent;
		ent = safindparament(&params[i]);
		if (ent == NULL) {
			snprintf(params[i].error_str,
			    sizeof(params[i].error_str),
			    "%s: cannot find parameter %s", __func__,
			    params[i].value_name);
			params[i].status = MT_PARAM_STATUS_ERROR;
			break;
		}
		if (first != NULL) {
			if (first_ent == ent) {
				contig_ents++;
				continue;
			} else {
				error = first_ent->set_func(periph, first,
				    contig_ents);
				first = NULL;
				first_ent = NULL;
				contig_ents = 0;
				if (error != 0) {
					error = 0;
					break;
				}
			}
		}
		if (ent->param_type == SA_PARAM_TYPE_NODE) {
			first = &params[i];
			first_ent = ent;
			contig_ents = 1;
		} else {
			error = ent->set_func(periph, &params[i], 1);
			if (error != 0) {
				error = 0;
				break;
			}
		}
	}
	if (first != NULL)
		first_ent->set_func(periph, first, contig_ents);
bailout:
	if (need_copy != 0) {
		if (error != EFAULT) {
			cam_periph_unlock(periph);
			copyout(params, list->params, list->param_len);
			cam_periph_lock(periph);
		}
		free(params, M_SCSISA);
	}
	return (error);
}
static int saparamsetlist ( struct cam_periph * periph , struct mtsetlist * list , int need_copy ) { int i , contig_ents ; int error ; struct mtparamset * params , * first ; struct sa_param_ent * first_ent ; error = 0 ; params = NULL ; if ( list -> num_params == 0 ) goto bailout ; if ( ( list -> num_params * sizeof ( struct mtparamset ) ) != list -> param_len ) { xpt_print ( periph -> path , " " " \n " , __func__ , list -> param_len , sizeof ( struct mtparamset ) , list -> num_params ) ; error = EINVAL ; goto bailout ; } if ( need_copy != 0 ) { cam_periph_unlock ( periph ) ; params = malloc ( list -> param_len , M_SCSISA , M_WAITOK | M_ZERO ) ; error = copyin ( list -> params , params , list -> param_len ) ; cam_periph_lock ( periph ) ; if ( error != 0 ) goto bailout ; } else { params = list -> params ; } contig_ents = 0 ; first = NULL ; first_ent = NULL ; for ( i = 0 ; i < list -> num_params ; i ++ ) { struct sa_param_ent * ent ; ent = safindparament ( & params [ i ] ) ; if ( ent == NULL ) { snprintf ( params [ i ] . error_str , sizeof ( params [ i ] . error_str ) , " " , __func__ , params [ i ] . value_name ) ; params [ i ] . status = MT_PARAM_STATUS_ERROR ; break ; } if ( first != NULL ) { if ( first_ent == ent ) { contig_ents ++ ; continue ; } else { error = first_ent -> set_func ( periph , first , contig_ents ) ; first = NULL ; first_ent = NULL ; contig_ents = 0 ; if ( error != 0 ) { error = 0 ; break ; } } } if ( ent -> param_type == SA_PARAM_TYPE_NODE ) { first = & params [ i ] ; first_ent = ent ; contig_ents = 1 ; } else { error = ent -> set_func ( periph , & params [ i ] , 1 ) ; if ( error != 0 ) { error = 0 ; break ; } } } if ( first != NULL ) first_ent -> set_func ( periph , first , contig_ents ) ; bailout : if ( need_copy != 0 ) { if ( error != EFAULT ) { cam_periph_unlock ( periph ) ; copyout ( params , list -> params , list -> param_len ) ; cam_periph_lock ( periph ) ; } free ( params , M_SCSISA ) ; } return ( error ) ; }
Go through a list of parameters, coalescing contiguous parameters with
 the same parent node into a single call to a set_func.
Go through a list of parameters coalescing contiguous parameters with the same parent node into a single call to a set_func .
/* Nothing to do */ /*
	 * Verify that the user has the correct structure size.
	 */ /*
		 * XXX KDM will dropping the lock cause an issue here?
		 */ /*
				 * We're still in a contiguous list of
				 * parameters that can be handled by one
				 * node handler.
				 */