⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vmt.c

📁 基于linux-2.6.28的mtd驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
			goto out_err;	}	cdev_del(&vol->cdev);	volume_sysfs_close(vol);	spin_lock(&ubi->volumes_lock);	ubi->rsvd_pebs -= reserved_pebs;	ubi->avail_pebs += reserved_pebs;	i = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs;	if (i > 0) {		i = ubi->avail_pebs >= i ? i : ubi->avail_pebs;		ubi->avail_pebs -= i;		ubi->rsvd_pebs += i;		ubi->beb_rsvd_pebs += i;		if (i > 0)			ubi_msg("reserve more %d PEBs", i);	}	ubi->vol_count -= 1;	spin_unlock(&ubi->volumes_lock);	if (!no_vtbl)		err = paranoid_check_volumes(ubi);	return err;out_err:	ubi_err("cannot remove volume %d, error %d", vol_id, err);	spin_lock(&ubi->volumes_lock);	ubi->volumes[vol_id] = vol;out_unlock:	spin_unlock(&ubi->volumes_lock);	return err;}/** * ubi_resize_volume - re-size volume. * @desc: volume descriptor * @reserved_pebs: new size in physical eraseblocks * * This function re-sizes the volume and returns zero in case of success, and a * negative error code in case of failure. The caller has to have the * @ubi->volumes_mutex locked. */int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs){	int i, err, pebs, *new_mapping;	struct ubi_volume *vol = desc->vol;	struct ubi_device *ubi = vol->ubi;	struct ubi_vtbl_record vtbl_rec;	int vol_id = vol->vol_id;	if (ubi->ro_mode)		return -EROFS;	dbg_gen("re-size volume %d to from %d to %d PEBs",		vol_id, vol->reserved_pebs, reserved_pebs);	if (vol->vol_type == UBI_STATIC_VOLUME &&	    reserved_pebs < vol->used_ebs) {		dbg_err("too small size %d, %d LEBs contain data",			reserved_pebs, vol->used_ebs);		return -EINVAL;	}	/* If the size is the same, we have nothing to do */	if (reserved_pebs == vol->reserved_pebs)		return 0;	new_mapping = kmalloc(reserved_pebs * sizeof(int), GFP_KERNEL);	if (!new_mapping)		return -ENOMEM;	for (i = 0; i < reserved_pebs; i++)		new_mapping[i] = UBI_LEB_UNMAPPED;	spin_lock(&ubi->volumes_lock);	if (vol->ref_count > 1) {		spin_unlock(&ubi->volumes_lock);		err = -EBUSY;		goto out_free;	}	spin_unlock(&ubi->volumes_lock);	/* Reserve physical eraseblocks */	pebs = reserved_pebs - vol->reserved_pebs;	if (pebs > 0) {		spin_lock(&ubi->volumes_lock);		if (pebs > ubi->avail_pebs) {			dbg_err("not enough PEBs: requested %d, available %d",				pebs, ubi->avail_pebs);			spin_unlock(&ubi->volumes_lock);			err = -ENOSPC;			goto out_free;		}		ubi->avail_pebs -= pebs;		ubi->rsvd_pebs += pebs;		for (i = 0; i < vol->reserved_pebs; i++)			new_mapping[i] = vol->eba_tbl[i];		kfree(vol->eba_tbl);		vol->eba_tbl = new_mapping;		spin_unlock(&ubi->volumes_lock);	}	/* Change volume table record */	memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record));	vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs);	err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);	if (err)		goto out_acc;	if (pebs < 0) {		for (i = 0; i < -pebs; i++) {			err = ubi_eba_unmap_leb(ubi, vol, reserved_pebs + i);			if (err)				goto out_acc;		}		spin_lock(&ubi->volumes_lock);		ubi->rsvd_pebs += pebs;		ubi->avail_pebs -= pebs;		pebs = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs;		if (pebs > 0) {			pebs = ubi->avail_pebs >= pebs ? pebs : ubi->avail_pebs;			ubi->avail_pebs -= pebs;			ubi->rsvd_pebs += pebs;			ubi->beb_rsvd_pebs += pebs;			if (pebs > 0)				ubi_msg("reserve more %d PEBs", pebs);		}		for (i = 0; i < reserved_pebs; i++)			new_mapping[i] = vol->eba_tbl[i];		kfree(vol->eba_tbl);		vol->eba_tbl = new_mapping;		spin_unlock(&ubi->volumes_lock);	}	vol->reserved_pebs = reserved_pebs;	if (vol->vol_type == UBI_DYNAMIC_VOLUME) {		vol->used_ebs = reserved_pebs;		vol->last_eb_bytes = vol->usable_leb_size;		vol->used_bytes =			(long long)vol->used_ebs * vol->usable_leb_size;	}	err = paranoid_check_volumes(ubi);	return err;out_acc:	if (pebs > 0) {		spin_lock(&ubi->volumes_lock);		ubi->rsvd_pebs -= pebs;		ubi->avail_pebs += pebs;		spin_unlock(&ubi->volumes_lock);	}out_free:	kfree(new_mapping);	return err;}/** * ubi_rename_volumes - re-name UBI volumes. * @ubi: UBI device description object * @rename_list: list of &struct ubi_rename_entry objects * * This function re-names or removes volumes specified in the re-name list. * Returns zero in case of success and a negative error code in case of * failure. */int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list){	int err;	struct ubi_rename_entry *re;	err = ubi_vtbl_rename_volumes(ubi, rename_list);	if (err)		return err;	list_for_each_entry(re, rename_list, list) {		if (re->remove) {			err = ubi_remove_volume(re->desc, 1);			if (err)				break;		} else {			struct ubi_volume *vol = re->desc->vol;			spin_lock(&ubi->volumes_lock);			vol->name_len = re->new_name_len;			memcpy(vol->name, re->new_name, re->new_name_len + 1);			spin_unlock(&ubi->volumes_lock);		}	}	if (!err)		err = paranoid_check_volumes(ubi);	return err;}/** * ubi_add_volume - add volume. * @ubi: UBI device description object * @vol: volume description object * * This function adds an existing volume and initializes all its data * structures. Returns zero in case of success and a negative error code in * case of failure. */int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol){	int err, vol_id = vol->vol_id;	dev_t dev;	dbg_gen("add volume %d", vol_id);	/* Register character device for the volume */	cdev_init(&vol->cdev, &ubi_vol_cdev_operations);	vol->cdev.owner = THIS_MODULE;	dev = MKDEV(MAJOR(ubi->cdev.dev), vol->vol_id + 1);	err = cdev_add(&vol->cdev, dev, 1);	if (err) {		ubi_err("cannot add character device for volume %d, error %d",			vol_id, err);		return err;	}	err = ubi_create_gluebi(ubi, vol);	if (err)		goto out_cdev;	vol->dev.release = vol_release;	vol->dev.parent = &ubi->dev;	vol->dev.devt = dev;	vol->dev.class = ubi_class;	sprintf(&vol->dev.bus_id[0], "%s_%d", ubi->ubi_name, vol->vol_id);	err = device_register(&vol->dev);	if (err)		goto out_gluebi;	err = volume_sysfs_init(ubi, vol);	if (err) {		cdev_del(&vol->cdev);		err = ubi_destroy_gluebi(vol);		volume_sysfs_close(vol);		return err;	}	err = paranoid_check_volumes(ubi);	return err;out_gluebi:	err = ubi_destroy_gluebi(vol);out_cdev:	cdev_del(&vol->cdev);	return err;}/** * ubi_free_volume - free volume. * @ubi: UBI device description object * @vol: volume description object * * This function frees all resources for volume @vol but does not remove it. * Used only when the UBI device is detached. */void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol){	int err;	dbg_gen("free volume %d", vol->vol_id);	ubi->volumes[vol->vol_id] = NULL;	err = ubi_destroy_gluebi(vol);	cdev_del(&vol->cdev);	volume_sysfs_close(vol);}#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID/** * paranoid_check_volume - check volume information. * @ubi: UBI device description object * @vol_id: volume ID * * Returns zero if volume is all right and a a negative error code if not. */static int paranoid_check_volume(struct ubi_device *ubi, int vol_id){	int idx = vol_id2idx(ubi, vol_id);	int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker;	const struct ubi_volume *vol;	long long n;	const char *name;	spin_lock(&ubi->volumes_lock);	reserved_pebs = be32_to_cpu(ubi->vtbl[vol_id].reserved_pebs);	vol = ubi->volumes[idx];	if (!vol) {		if (reserved_pebs) {			ubi_err("no volume info, but volume exists");			goto fail;		}		spin_unlock(&ubi->volumes_lock);		return 0;	}	if (vol->reserved_pebs < 0 || vol->alignment < 0 || vol->data_pad < 0 ||	    vol->name_len < 0) {		ubi_err("negative values");		goto fail;	}	if (vol->alignment > ubi->leb_size || vol->alignment == 0) {		ubi_err("bad alignment");		goto fail;	}	n = vol->alignment & (ubi->min_io_size - 1);	if (vol->alignment != 1 && n) {		ubi_err("alignment is not multiple of min I/O unit");		goto fail;	}	n = ubi->leb_size % vol->alignment;	if (vol->data_pad != n) {		ubi_err("bad data_pad, has to be %lld", n);		goto fail;	}	if (vol->vol_type != UBI_DYNAMIC_VOLUME &&	    vol->vol_type != UBI_STATIC_VOLUME) {		ubi_err("bad vol_type");		goto fail;	}	if (vol->upd_marker && vol->corrupted) {		dbg_err("update marker and corrupted simultaneously");		goto fail;	}	if (vol->reserved_pebs > ubi->good_peb_count) {		ubi_err("too large reserved_pebs");		goto fail;	}	n = ubi->leb_size - vol->data_pad;	if (vol->usable_leb_size != ubi->leb_size - vol->data_pad) {		ubi_err("bad usable_leb_size, has to be %lld", n);		goto fail;	}	if (vol->name_len > UBI_VOL_NAME_MAX) {		ubi_err("too long volume name, max is %d", UBI_VOL_NAME_MAX);		goto fail;	}	if (!vol->name) {		ubi_err("NULL volume name");		goto fail;	}	n = strnlen(vol->name, vol->name_len + 1);	if (n != vol->name_len) {		ubi_err("bad name_len %lld", n);		goto fail;	}	n = (long long)vol->used_ebs * vol->usable_leb_size;	if (vol->vol_type == UBI_DYNAMIC_VOLUME) {		if (vol->corrupted) {			ubi_err("corrupted dynamic volume");			goto fail;		}		if (vol->used_ebs != vol->reserved_pebs) {			ubi_err("bad used_ebs");			goto fail;		}		if (vol->last_eb_bytes != vol->usable_leb_size) {			ubi_err("bad last_eb_bytes");			goto fail;		}		if (vol->used_bytes != n) {			ubi_err("bad used_bytes");			goto fail;		}	} else {		if (vol->used_ebs < 0 || vol->used_ebs > vol->reserved_pebs) {			ubi_err("bad used_ebs");			goto fail;		}		if (vol->last_eb_bytes < 0 ||		    vol->last_eb_bytes > vol->usable_leb_size) {			ubi_err("bad last_eb_bytes");			goto fail;		}		if (vol->used_bytes < 0 || vol->used_bytes > n ||		    vol->used_bytes < n - vol->usable_leb_size) {			ubi_err("bad used_bytes");			goto fail;		}	}	alignment  = be32_to_cpu(ubi->vtbl[vol_id].alignment);	data_pad   = be32_to_cpu(ubi->vtbl[vol_id].data_pad);	name_len   = be16_to_cpu(ubi->vtbl[vol_id].name_len);	upd_marker = ubi->vtbl[vol_id].upd_marker;	name       = &ubi->vtbl[vol_id].name[0];	if (ubi->vtbl[vol_id].vol_type == UBI_VID_DYNAMIC)		vol_type = UBI_DYNAMIC_VOLUME;	else		vol_type = UBI_STATIC_VOLUME;	if (alignment != vol->alignment || data_pad != vol->data_pad ||	    upd_marker != vol->upd_marker || vol_type != vol->vol_type ||	    name_len != vol->name_len || strncmp(name, vol->name, name_len)) {		ubi_err("volume info is different");		goto fail;	}	spin_unlock(&ubi->volumes_lock);	return 0;fail:	ubi_err("paranoid check failed for volume %d", vol_id);	if (vol)		ubi_dbg_dump_vol_info(vol);	ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);	spin_unlock(&ubi->volumes_lock);	return -EINVAL;}/** * paranoid_check_volumes - check information about all volumes. * @ubi: UBI device description object * * Returns zero if volumes are all right and a a negative error code if not. */static int paranoid_check_volumes(struct ubi_device *ubi){	int i, err = 0;	for (i = 0; i < ubi->vtbl_slots; i++) {		err = paranoid_check_volume(ubi, i);		if (err)			break;	}	return err;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -