brintos

brintos / linux-shallow public Read only

0
0
Text · 12.0 KiB · 962f693 Raw
421 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) International Business Machines Corp., 20064 * Copyright (c) Nokia Corporation, 20065 *6 * Author: Artem Bityutskiy (Битюцкий Артём)7 *8 * Jan 2007: Alexander Schmidt, hacked per-volume update.9 */10 11/*12 * This file contains implementation of the volume update and atomic LEB change13 * functionality.14 *15 * The update operation is based on the per-volume update marker which is16 * stored in the volume table. The update marker is set before the update17 * starts, and removed after the update has been finished. So if the update was18 * interrupted by an unclean re-boot or due to some other reasons, the update19 * marker stays on the flash media and UBI finds it when it attaches the MTD20 * device next time. If the update marker is set for a volume, the volume is21 * treated as damaged and most I/O operations are prohibited. Only a new update22 * operation is allowed.23 *24 * Note, in general it is possible to implement the update operation as a25 * transaction with a roll-back capability.26 */27 28#include <linux/err.h>29#include <linux/uaccess.h>30#include <linux/math64.h>31#include "ubi.h"32 33/**34 * set_update_marker - set update marker.35 * @ubi: UBI device description object36 * @vol: volume description object37 *38 * This function sets the update marker flag for volume @vol. Returns zero39 * in case of success and a negative error code in case of failure.40 */41static int set_update_marker(struct ubi_device *ubi, struct ubi_volume *vol)42{43	int err;44	struct ubi_vtbl_record vtbl_rec;45 46	dbg_gen("set update marker for volume %d", vol->vol_id);47 48	if (vol->upd_marker) {49		ubi_assert(ubi->vtbl[vol->vol_id].upd_marker);50		dbg_gen("already set");51		return 0;52	}53 54	vtbl_rec = ubi->vtbl[vol->vol_id];55	vtbl_rec.upd_marker = 1;56 57	mutex_lock(&ubi->device_mutex);58	err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);59	vol->upd_marker = 1;60	mutex_unlock(&ubi->device_mutex);61	return err;62}63 64/**65 * clear_update_marker - clear update marker.66 * @ubi: UBI device description object67 * @vol: volume description object68 * @bytes: new data size in bytes69 *70 * This function clears the update marker for volume @vol, sets new volume71 * data size and clears the "corrupted" flag (static volumes only). Returns72 * zero in case of success and a negative error code in case of failure.73 */74static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol,75			       long long bytes)76{77	int err;78	struct ubi_vtbl_record vtbl_rec;79 80	dbg_gen("clear update marker for volume %d", vol->vol_id);81 82	vtbl_rec = ubi->vtbl[vol->vol_id];83	ubi_assert(vol->upd_marker && vtbl_rec.upd_marker);84	vtbl_rec.upd_marker = 0;85 86	if (vol->vol_type == UBI_STATIC_VOLUME) {87		vol->corrupted = 0;88		vol->used_bytes = bytes;89		vol->used_ebs = div_u64_rem(bytes, vol->usable_leb_size,90					    &vol->last_eb_bytes);91		if (vol->last_eb_bytes)92			vol->used_ebs += 1;93		else94			vol->last_eb_bytes = vol->usable_leb_size;95	}96 97	mutex_lock(&ubi->device_mutex);98	err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);99	vol->upd_marker = 0;100	mutex_unlock(&ubi->device_mutex);101	return err;102}103 104/**105 * ubi_start_update - start volume update.106 * @ubi: UBI device description object107 * @vol: volume description object108 * @bytes: update bytes109 *110 * This function starts volume update operation. If @bytes is zero, the volume111 * is just wiped out. Returns zero in case of success and a negative error code112 * in case of failure.113 */114int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,115		     long long bytes)116{117	int i, err;118 119	dbg_gen("start update of volume %d, %llu bytes", vol->vol_id, bytes);120	ubi_assert(!vol->updating && !vol->changing_leb);121	vol->updating = 1;122 123	vol->upd_buf = vmalloc(ubi->leb_size);124	if (!vol->upd_buf)125		return -ENOMEM;126 127	err = set_update_marker(ubi, vol);128	if (err)129		return err;130 131	/* Before updating - wipe out the volume */132	for (i = 0; i < vol->reserved_pebs; i++) {133		err = ubi_eba_unmap_leb(ubi, vol, i);134		if (err)135			return err;136	}137 138	err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);139	if (err)140		return err;141 142	if (bytes == 0) {143		err = clear_update_marker(ubi, vol, 0);144		if (err)145			return err;146 147		vfree(vol->upd_buf);148		vol->updating = 0;149		return 0;150	}151 152	vol->upd_ebs = div_u64(bytes + vol->usable_leb_size - 1,153			       vol->usable_leb_size);154	vol->upd_bytes = bytes;155	vol->upd_received = 0;156	return 0;157}158 159/**160 * ubi_start_leb_change - start atomic LEB change.161 * @ubi: UBI device description object162 * @vol: volume description object163 * @req: operation request164 *165 * This function starts atomic LEB change operation. Returns zero in case of166 * success and a negative error code in case of failure.167 */168int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,169			 const struct ubi_leb_change_req *req)170{171	ubi_assert(!vol->updating && !vol->changing_leb);172 173	dbg_gen("start changing LEB %d:%d, %u bytes",174		vol->vol_id, req->lnum, req->bytes);175	if (req->bytes == 0)176		return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0);177 178	vol->upd_bytes = req->bytes;179	vol->upd_received = 0;180	vol->changing_leb = 1;181	vol->ch_lnum = req->lnum;182 183	vol->upd_buf = vmalloc(ALIGN((int)req->bytes, ubi->min_io_size));184	if (!vol->upd_buf)185		return -ENOMEM;186 187	return 0;188}189 190/**191 * write_leb - write update data.192 * @ubi: UBI device description object193 * @vol: volume description object194 * @lnum: logical eraseblock number195 * @buf: data to write196 * @len: data size197 * @used_ebs: how many logical eraseblocks will this volume contain (static198 * volumes only)199 *200 * This function writes update data to corresponding logical eraseblock. In201 * case of dynamic volume, this function checks if the data contains 0xFF bytes202 * at the end. If yes, the 0xFF bytes are cut and not written. So if the whole203 * buffer contains only 0xFF bytes, the LEB is left unmapped.204 *205 * The reason why we skip the trailing 0xFF bytes in case of dynamic volume is206 * that we want to make sure that more data may be appended to the logical207 * eraseblock in future. Indeed, writing 0xFF bytes may have side effects and208 * this PEB won't be writable anymore. So if one writes the file-system image209 * to the UBI volume where 0xFFs mean free space - UBI makes sure this free210 * space is writable after the update.211 *212 * We do not do this for static volumes because they are read-only. But this213 * also cannot be done because we have to store per-LEB CRC and the correct214 * data length.215 *216 * This function returns zero in case of success and a negative error code in217 * case of failure.218 */219static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,220		     void *buf, int len, int used_ebs)221{222	int err;223 224	if (vol->vol_type == UBI_DYNAMIC_VOLUME) {225		int l = ALIGN(len, ubi->min_io_size);226 227		memset(buf + len, 0xFF, l - len);228		len = ubi_calc_data_len(ubi, buf, l);229		if (len == 0) {230			dbg_gen("all %d bytes contain 0xFF - skip", len);231			return 0;232		}233 234		err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len);235	} else {236		/*237		 * When writing static volume, and this is the last logical238		 * eraseblock, the length (@len) does not have to be aligned to239		 * the minimal flash I/O unit. The 'ubi_eba_write_leb_st()'240		 * function accepts exact (unaligned) length and stores it in241		 * the VID header. And it takes care of proper alignment by242		 * padding the buffer. Here we just make sure the padding will243		 * contain zeros, not random trash.244		 */245		memset(buf + len, 0, vol->usable_leb_size - len);246		err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len, used_ebs);247	}248 249	return err;250}251 252/**253 * ubi_more_update_data - write more update data.254 * @ubi: UBI device description object255 * @vol: volume description object256 * @buf: write data (user-space memory buffer)257 * @count: how much bytes to write258 *259 * This function writes more data to the volume which is being updated. It may260 * be called arbitrary number of times until all the update data arriveis. This261 * function returns %0 in case of success, number of bytes written during the262 * last call if the whole volume update has been successfully finished, and a263 * negative error code in case of failure.264 */265int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,266			 const void __user *buf, int count)267{268	int lnum, offs, err = 0, len, to_write = count;269 270	dbg_gen("write %d of %lld bytes, %lld already passed",271		count, vol->upd_bytes, vol->upd_received);272 273	if (ubi->ro_mode)274		return -EROFS;275 276	lnum = div_u64_rem(vol->upd_received,  vol->usable_leb_size, &offs);277	if (vol->upd_received + count > vol->upd_bytes)278		to_write = count = vol->upd_bytes - vol->upd_received;279 280	/*281	 * When updating volumes, we accumulate whole logical eraseblock of282	 * data and write it at once.283	 */284	if (offs != 0) {285		/*286		 * This is a write to the middle of the logical eraseblock. We287		 * copy the data to our update buffer and wait for more data or288		 * flush it if the whole eraseblock is written or the update289		 * is finished.290		 */291 292		len = vol->usable_leb_size - offs;293		if (len > count)294			len = count;295 296		err = copy_from_user(vol->upd_buf + offs, buf, len);297		if (err)298			return -EFAULT;299 300		if (offs + len == vol->usable_leb_size ||301		    vol->upd_received + len == vol->upd_bytes) {302			int flush_len = offs + len;303 304			/*305			 * OK, we gathered either the whole eraseblock or this306			 * is the last chunk, it's time to flush the buffer.307			 */308			ubi_assert(flush_len <= vol->usable_leb_size);309			err = write_leb(ubi, vol, lnum, vol->upd_buf, flush_len,310					vol->upd_ebs);311			if (err)312				return err;313		}314 315		vol->upd_received += len;316		count -= len;317		buf += len;318		lnum += 1;319	}320 321	/*322	 * If we've got more to write, let's continue. At this point we know we323	 * are starting from the beginning of an eraseblock.324	 */325	while (count) {326		if (count > vol->usable_leb_size)327			len = vol->usable_leb_size;328		else329			len = count;330 331		err = copy_from_user(vol->upd_buf, buf, len);332		if (err)333			return -EFAULT;334 335		if (len == vol->usable_leb_size ||336		    vol->upd_received + len == vol->upd_bytes) {337			err = write_leb(ubi, vol, lnum, vol->upd_buf,338					len, vol->upd_ebs);339			if (err)340				break;341		}342 343		vol->upd_received += len;344		count -= len;345		lnum += 1;346		buf += len;347	}348 349	ubi_assert(vol->upd_received <= vol->upd_bytes);350	if (vol->upd_received == vol->upd_bytes) {351		err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);352		if (err)353			return err;354		/* The update is finished, clear the update marker */355		err = clear_update_marker(ubi, vol, vol->upd_bytes);356		if (err)357			return err;358		vol->updating = 0;359		err = to_write;360		vfree(vol->upd_buf);361	}362 363	return err;364}365 366/**367 * ubi_more_leb_change_data - accept more data for atomic LEB change.368 * @ubi: UBI device description object369 * @vol: volume description object370 * @buf: write data (user-space memory buffer)371 * @count: how much bytes to write372 *373 * This function accepts more data to the volume which is being under the374 * "atomic LEB change" operation. It may be called arbitrary number of times375 * until all data arrives. This function returns %0 in case of success, number376 * of bytes written during the last call if the whole "atomic LEB change"377 * operation has been successfully finished, and a negative error code in case378 * of failure.379 */380int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,381			     const void __user *buf, int count)382{383	int err;384 385	dbg_gen("write %d of %lld bytes, %lld already passed",386		count, vol->upd_bytes, vol->upd_received);387 388	if (ubi->ro_mode)389		return -EROFS;390 391	if (vol->upd_received + count > vol->upd_bytes)392		count = vol->upd_bytes - vol->upd_received;393 394	err = copy_from_user(vol->upd_buf + vol->upd_received, buf, count);395	if (err)396		return -EFAULT;397 398	vol->upd_received += count;399 400	if (vol->upd_received == vol->upd_bytes) {401		int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size);402 403		memset(vol->upd_buf + vol->upd_bytes, 0xFF,404		       len - vol->upd_bytes);405		len = ubi_calc_data_len(ubi, vol->upd_buf, len);406		err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum,407						vol->upd_buf, len);408		if (err)409			return err;410	}411 412	ubi_assert(vol->upd_received <= vol->upd_bytes);413	if (vol->upd_received == vol->upd_bytes) {414		vol->changing_leb = 0;415		err = count;416		vfree(vol->upd_buf);417	}418 419	return err;420}421