11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2801c135cSArtem B. Bityutskiy /*
3801c135cSArtem B. Bityutskiy * Copyright (c) International Business Machines Corp., 2006
4801c135cSArtem B. Bityutskiy *
5801c135cSArtem B. Bityutskiy * Author: Artem Bityutskiy (Битюцкий Артём)
6801c135cSArtem B. Bityutskiy */
7801c135cSArtem B. Bityutskiy
8801c135cSArtem B. Bityutskiy /* This file mostly implements UBI kernel API functions */
9801c135cSArtem B. Bityutskiy
10801c135cSArtem B. Bityutskiy #include <linux/module.h>
11801c135cSArtem B. Bityutskiy #include <linux/err.h>
125a0e3ad6STejun Heo #include <linux/slab.h>
13b5710284SCorentin Chary #include <linux/namei.h>
14b5710284SCorentin Chary #include <linux/fs.h>
15801c135cSArtem B. Bityutskiy #include <asm/div64.h>
16801c135cSArtem B. Bityutskiy #include "ubi.h"
17801c135cSArtem B. Bityutskiy
18801c135cSArtem B. Bityutskiy /**
190e0ee1ccSDmitry Pervushin * ubi_do_get_device_info - get information about UBI device.
200e0ee1ccSDmitry Pervushin * @ubi: UBI device description object
210e0ee1ccSDmitry Pervushin * @di: the information is stored here
220e0ee1ccSDmitry Pervushin *
230e0ee1ccSDmitry Pervushin * This function is the same as 'ubi_get_device_info()', but it assumes the UBI
240e0ee1ccSDmitry Pervushin * device is locked and cannot disappear.
250e0ee1ccSDmitry Pervushin */
ubi_do_get_device_info(struct ubi_device * ubi,struct ubi_device_info * di)260e0ee1ccSDmitry Pervushin void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di)
270e0ee1ccSDmitry Pervushin {
280e0ee1ccSDmitry Pervushin di->ubi_num = ubi->ubi_num;
290e0ee1ccSDmitry Pervushin di->leb_size = ubi->leb_size;
30f43ec882SArtem Bityutskiy di->leb_start = ubi->leb_start;
310e0ee1ccSDmitry Pervushin di->min_io_size = ubi->min_io_size;
3230b542efSArtem Bityutskiy di->max_write_size = ubi->max_write_size;
330e0ee1ccSDmitry Pervushin di->ro_mode = ubi->ro_mode;
340e0ee1ccSDmitry Pervushin di->cdev = ubi->cdev.dev;
350e0ee1ccSDmitry Pervushin }
360e0ee1ccSDmitry Pervushin EXPORT_SYMBOL_GPL(ubi_do_get_device_info);
370e0ee1ccSDmitry Pervushin
380e0ee1ccSDmitry Pervushin /**
39801c135cSArtem B. Bityutskiy * ubi_get_device_info - get information about UBI device.
40801c135cSArtem B. Bityutskiy * @ubi_num: UBI device number
41801c135cSArtem B. Bityutskiy * @di: the information is stored here
42801c135cSArtem B. Bityutskiy *
43e73f4459SArtem Bityutskiy * This function returns %0 in case of success, %-EINVAL if the UBI device
44e73f4459SArtem Bityutskiy * number is invalid, and %-ENODEV if there is no such UBI device.
45801c135cSArtem B. Bityutskiy */
ubi_get_device_info(int ubi_num,struct ubi_device_info * di)46801c135cSArtem B. Bityutskiy int ubi_get_device_info(int ubi_num, struct ubi_device_info *di)
47801c135cSArtem B. Bityutskiy {
48e73f4459SArtem Bityutskiy struct ubi_device *ubi;
49801c135cSArtem B. Bityutskiy
50e73f4459SArtem Bityutskiy if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
51e73f4459SArtem Bityutskiy return -EINVAL;
52e73f4459SArtem Bityutskiy ubi = ubi_get_device(ubi_num);
53e73f4459SArtem Bityutskiy if (!ubi)
54801c135cSArtem B. Bityutskiy return -ENODEV;
550e0ee1ccSDmitry Pervushin ubi_do_get_device_info(ubi, di);
56e73f4459SArtem Bityutskiy ubi_put_device(ubi);
57801c135cSArtem B. Bityutskiy return 0;
58801c135cSArtem B. Bityutskiy }
59801c135cSArtem B. Bityutskiy EXPORT_SYMBOL_GPL(ubi_get_device_info);
60801c135cSArtem B. Bityutskiy
61801c135cSArtem B. Bityutskiy /**
620e0ee1ccSDmitry Pervushin * ubi_do_get_volume_info - get information about UBI volume.
630e0ee1ccSDmitry Pervushin * @ubi: UBI device description object
640e0ee1ccSDmitry Pervushin * @vol: volume description object
65801c135cSArtem B. Bityutskiy * @vi: the information is stored here
66801c135cSArtem B. Bityutskiy */
ubi_do_get_volume_info(struct ubi_device * ubi,struct ubi_volume * vol,struct ubi_volume_info * vi)670e0ee1ccSDmitry Pervushin void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol,
68801c135cSArtem B. Bityutskiy struct ubi_volume_info *vi)
69801c135cSArtem B. Bityutskiy {
70801c135cSArtem B. Bityutskiy vi->vol_id = vol->vol_id;
71801c135cSArtem B. Bityutskiy vi->ubi_num = ubi->ubi_num;
72801c135cSArtem B. Bityutskiy vi->size = vol->reserved_pebs;
73801c135cSArtem B. Bityutskiy vi->used_bytes = vol->used_bytes;
74801c135cSArtem B. Bityutskiy vi->vol_type = vol->vol_type;
75801c135cSArtem B. Bityutskiy vi->corrupted = vol->corrupted;
76801c135cSArtem B. Bityutskiy vi->upd_marker = vol->upd_marker;
77801c135cSArtem B. Bityutskiy vi->alignment = vol->alignment;
78801c135cSArtem B. Bityutskiy vi->usable_leb_size = vol->usable_leb_size;
79801c135cSArtem B. Bityutskiy vi->name_len = vol->name_len;
80801c135cSArtem B. Bityutskiy vi->name = vol->name;
8149dfc299SArtem Bityutskiy vi->cdev = vol->cdev.dev;
82*05b8773cSDaniel Golle vi->dev = &vol->dev;
83801c135cSArtem B. Bityutskiy }
840e0ee1ccSDmitry Pervushin
850e0ee1ccSDmitry Pervushin /**
860e0ee1ccSDmitry Pervushin * ubi_get_volume_info - get information about UBI volume.
870e0ee1ccSDmitry Pervushin * @desc: volume descriptor
880e0ee1ccSDmitry Pervushin * @vi: the information is stored here
890e0ee1ccSDmitry Pervushin */
ubi_get_volume_info(struct ubi_volume_desc * desc,struct ubi_volume_info * vi)900e0ee1ccSDmitry Pervushin void ubi_get_volume_info(struct ubi_volume_desc *desc,
910e0ee1ccSDmitry Pervushin struct ubi_volume_info *vi)
920e0ee1ccSDmitry Pervushin {
930e0ee1ccSDmitry Pervushin ubi_do_get_volume_info(desc->vol->ubi, desc->vol, vi);
940e0ee1ccSDmitry Pervushin }
95801c135cSArtem B. Bityutskiy EXPORT_SYMBOL_GPL(ubi_get_volume_info);
96801c135cSArtem B. Bityutskiy
97801c135cSArtem B. Bityutskiy /**
98801c135cSArtem B. Bityutskiy * ubi_open_volume - open UBI volume.
99801c135cSArtem B. Bityutskiy * @ubi_num: UBI device number
100801c135cSArtem B. Bityutskiy * @vol_id: volume ID
101801c135cSArtem B. Bityutskiy * @mode: open mode
102801c135cSArtem B. Bityutskiy *
103801c135cSArtem B. Bityutskiy * The @mode parameter specifies if the volume should be opened in read-only
104801c135cSArtem B. Bityutskiy * mode, read-write mode, or exclusive mode. The exclusive mode guarantees that
105801c135cSArtem B. Bityutskiy * nobody else will be able to open this volume. UBI allows to have many volume
106801c135cSArtem B. Bityutskiy * readers and one writer at a time.
107801c135cSArtem B. Bityutskiy *
108801c135cSArtem B. Bityutskiy * If a static volume is being opened for the first time since boot, it will be
109801c135cSArtem B. Bityutskiy * checked by this function, which means it will be fully read and the CRC
110801c135cSArtem B. Bityutskiy * checksum of each logical eraseblock will be checked.
111801c135cSArtem B. Bityutskiy *
112801c135cSArtem B. Bityutskiy * This function returns volume descriptor in case of success and a negative
113801c135cSArtem B. Bityutskiy * error code in case of failure.
114801c135cSArtem B. Bityutskiy */
ubi_open_volume(int ubi_num,int vol_id,int mode)115801c135cSArtem B. Bityutskiy struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
116801c135cSArtem B. Bityutskiy {
117801c135cSArtem B. Bityutskiy int err;
118801c135cSArtem B. Bityutskiy struct ubi_volume_desc *desc;
1190169b49dSJesper Juhl struct ubi_device *ubi;
120801c135cSArtem B. Bityutskiy struct ubi_volume *vol;
121801c135cSArtem B. Bityutskiy
122e1cf7e6dSArtem Bityutskiy dbg_gen("open device %d, volume %d, mode %d", ubi_num, vol_id, mode);
123801c135cSArtem B. Bityutskiy
12435ad5fb7SArtem Bityutskiy if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
12535ad5fb7SArtem Bityutskiy return ERR_PTR(-EINVAL);
1260169b49dSJesper Juhl
127801c135cSArtem B. Bityutskiy if (mode != UBI_READONLY && mode != UBI_READWRITE &&
128fafdd2bfSRichard Weinberger mode != UBI_EXCLUSIVE && mode != UBI_METAONLY)
12935ad5fb7SArtem Bityutskiy return ERR_PTR(-EINVAL);
13035ad5fb7SArtem Bityutskiy
131e73f4459SArtem Bityutskiy /*
132e73f4459SArtem Bityutskiy * First of all, we have to get the UBI device to prevent its removal.
133e73f4459SArtem Bityutskiy */
134e73f4459SArtem Bityutskiy ubi = ubi_get_device(ubi_num);
13535ad5fb7SArtem Bityutskiy if (!ubi)
13635ad5fb7SArtem Bityutskiy return ERR_PTR(-ENODEV);
13735ad5fb7SArtem Bityutskiy
138e73f4459SArtem Bityutskiy if (vol_id < 0 || vol_id >= ubi->vtbl_slots) {
139e73f4459SArtem Bityutskiy err = -EINVAL;
140e73f4459SArtem Bityutskiy goto out_put_ubi;
141e73f4459SArtem Bityutskiy }
142801c135cSArtem B. Bityutskiy
143801c135cSArtem B. Bityutskiy desc = kmalloc(sizeof(struct ubi_volume_desc), GFP_KERNEL);
144e73f4459SArtem Bityutskiy if (!desc) {
145e73f4459SArtem Bityutskiy err = -ENOMEM;
146e73f4459SArtem Bityutskiy goto out_put_ubi;
147e73f4459SArtem Bityutskiy }
14835ad5fb7SArtem Bityutskiy
14935ad5fb7SArtem Bityutskiy err = -ENODEV;
15035ad5fb7SArtem Bityutskiy if (!try_module_get(THIS_MODULE))
15135ad5fb7SArtem Bityutskiy goto out_free;
152801c135cSArtem B. Bityutskiy
153801c135cSArtem B. Bityutskiy spin_lock(&ubi->volumes_lock);
154801c135cSArtem B. Bityutskiy vol = ubi->volumes[vol_id];
15535ad5fb7SArtem Bityutskiy if (!vol)
156801c135cSArtem B. Bityutskiy goto out_unlock;
157801c135cSArtem B. Bityutskiy
158801c135cSArtem B. Bityutskiy err = -EBUSY;
159801c135cSArtem B. Bityutskiy switch (mode) {
160801c135cSArtem B. Bityutskiy case UBI_READONLY:
161801c135cSArtem B. Bityutskiy if (vol->exclusive)
162801c135cSArtem B. Bityutskiy goto out_unlock;
163801c135cSArtem B. Bityutskiy vol->readers += 1;
164801c135cSArtem B. Bityutskiy break;
165801c135cSArtem B. Bityutskiy
166801c135cSArtem B. Bityutskiy case UBI_READWRITE:
167801c135cSArtem B. Bityutskiy if (vol->exclusive || vol->writers > 0)
168801c135cSArtem B. Bityutskiy goto out_unlock;
169801c135cSArtem B. Bityutskiy vol->writers += 1;
170801c135cSArtem B. Bityutskiy break;
171801c135cSArtem B. Bityutskiy
172801c135cSArtem B. Bityutskiy case UBI_EXCLUSIVE:
173fafdd2bfSRichard Weinberger if (vol->exclusive || vol->writers || vol->readers ||
174fafdd2bfSRichard Weinberger vol->metaonly)
175801c135cSArtem B. Bityutskiy goto out_unlock;
176801c135cSArtem B. Bityutskiy vol->exclusive = 1;
177801c135cSArtem B. Bityutskiy break;
178fafdd2bfSRichard Weinberger
179fafdd2bfSRichard Weinberger case UBI_METAONLY:
180fafdd2bfSRichard Weinberger if (vol->metaonly || vol->exclusive)
181fafdd2bfSRichard Weinberger goto out_unlock;
182fafdd2bfSRichard Weinberger vol->metaonly = 1;
183fafdd2bfSRichard Weinberger break;
184801c135cSArtem B. Bityutskiy }
185450f872aSArtem Bityutskiy get_device(&vol->dev);
186d05c77a8SArtem Bityutskiy vol->ref_count += 1;
187801c135cSArtem B. Bityutskiy spin_unlock(&ubi->volumes_lock);
188801c135cSArtem B. Bityutskiy
189801c135cSArtem B. Bityutskiy desc->vol = vol;
190801c135cSArtem B. Bityutskiy desc->mode = mode;
191801c135cSArtem B. Bityutskiy
192783b273aSArtem Bityutskiy mutex_lock(&ubi->ckvol_mutex);
19362652517SQuentin Schulz if (!vol->checked && !vol->skip_check) {
194801c135cSArtem B. Bityutskiy /* This is the first open - check the volume */
195801c135cSArtem B. Bityutskiy err = ubi_check_volume(ubi, vol_id);
196801c135cSArtem B. Bityutskiy if (err < 0) {
197783b273aSArtem Bityutskiy mutex_unlock(&ubi->ckvol_mutex);
198801c135cSArtem B. Bityutskiy ubi_close_volume(desc);
199801c135cSArtem B. Bityutskiy return ERR_PTR(err);
200801c135cSArtem B. Bityutskiy }
201801c135cSArtem B. Bityutskiy if (err == 1) {
20232608703STanya Brokhman ubi_warn(ubi, "volume %d on UBI device %d is corrupted",
203801c135cSArtem B. Bityutskiy vol_id, ubi->ubi_num);
204801c135cSArtem B. Bityutskiy vol->corrupted = 1;
205801c135cSArtem B. Bityutskiy }
206801c135cSArtem B. Bityutskiy vol->checked = 1;
207801c135cSArtem B. Bityutskiy }
208783b273aSArtem Bityutskiy mutex_unlock(&ubi->ckvol_mutex);
20935ad5fb7SArtem Bityutskiy
210801c135cSArtem B. Bityutskiy return desc;
211801c135cSArtem B. Bityutskiy
212801c135cSArtem B. Bityutskiy out_unlock:
213801c135cSArtem B. Bityutskiy spin_unlock(&ubi->volumes_lock);
214801c135cSArtem B. Bityutskiy module_put(THIS_MODULE);
21535ad5fb7SArtem Bityutskiy out_free:
21635ad5fb7SArtem Bityutskiy kfree(desc);
217e73f4459SArtem Bityutskiy out_put_ubi:
21832608703STanya Brokhman ubi_err(ubi, "cannot open device %d, volume %d, error %d",
219e1cf7e6dSArtem Bityutskiy ubi_num, vol_id, err);
220e5420877SPan Bian ubi_put_device(ubi);
221801c135cSArtem B. Bityutskiy return ERR_PTR(err);
222801c135cSArtem B. Bityutskiy }
223801c135cSArtem B. Bityutskiy EXPORT_SYMBOL_GPL(ubi_open_volume);
224801c135cSArtem B. Bityutskiy
225801c135cSArtem B. Bityutskiy /**
226801c135cSArtem B. Bityutskiy * ubi_open_volume_nm - open UBI volume by name.
227801c135cSArtem B. Bityutskiy * @ubi_num: UBI device number
228801c135cSArtem B. Bityutskiy * @name: volume name
229801c135cSArtem B. Bityutskiy * @mode: open mode
230801c135cSArtem B. Bityutskiy *
231801c135cSArtem B. Bityutskiy * This function is similar to 'ubi_open_volume()', but opens a volume by name.
232801c135cSArtem B. Bityutskiy */
ubi_open_volume_nm(int ubi_num,const char * name,int mode)233801c135cSArtem B. Bityutskiy struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name,
234801c135cSArtem B. Bityutskiy int mode)
235801c135cSArtem B. Bityutskiy {
236801c135cSArtem B. Bityutskiy int i, vol_id = -1, len;
237801c135cSArtem B. Bityutskiy struct ubi_device *ubi;
238e73f4459SArtem Bityutskiy struct ubi_volume_desc *ret;
239801c135cSArtem B. Bityutskiy
240e1cf7e6dSArtem Bityutskiy dbg_gen("open device %d, volume %s, mode %d", ubi_num, name, mode);
241801c135cSArtem B. Bityutskiy
242801c135cSArtem B. Bityutskiy if (!name)
243801c135cSArtem B. Bityutskiy return ERR_PTR(-EINVAL);
244801c135cSArtem B. Bityutskiy
245801c135cSArtem B. Bityutskiy len = strnlen(name, UBI_VOL_NAME_MAX + 1);
246801c135cSArtem B. Bityutskiy if (len > UBI_VOL_NAME_MAX)
247801c135cSArtem B. Bityutskiy return ERR_PTR(-EINVAL);
248801c135cSArtem B. Bityutskiy
24935ad5fb7SArtem Bityutskiy if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
25035ad5fb7SArtem Bityutskiy return ERR_PTR(-EINVAL);
251801c135cSArtem B. Bityutskiy
252e73f4459SArtem Bityutskiy ubi = ubi_get_device(ubi_num);
25335ad5fb7SArtem Bityutskiy if (!ubi)
25435ad5fb7SArtem Bityutskiy return ERR_PTR(-ENODEV);
255801c135cSArtem B. Bityutskiy
256801c135cSArtem B. Bityutskiy spin_lock(&ubi->volumes_lock);
257801c135cSArtem B. Bityutskiy /* Walk all volumes of this UBI device */
258801c135cSArtem B. Bityutskiy for (i = 0; i < ubi->vtbl_slots; i++) {
259801c135cSArtem B. Bityutskiy struct ubi_volume *vol = ubi->volumes[i];
260801c135cSArtem B. Bityutskiy
261801c135cSArtem B. Bityutskiy if (vol && len == vol->name_len && !strcmp(name, vol->name)) {
262801c135cSArtem B. Bityutskiy vol_id = i;
263801c135cSArtem B. Bityutskiy break;
264801c135cSArtem B. Bityutskiy }
265801c135cSArtem B. Bityutskiy }
266801c135cSArtem B. Bityutskiy spin_unlock(&ubi->volumes_lock);
267801c135cSArtem B. Bityutskiy
268e73f4459SArtem Bityutskiy if (vol_id >= 0)
269e73f4459SArtem Bityutskiy ret = ubi_open_volume(ubi_num, vol_id, mode);
270e73f4459SArtem Bityutskiy else
271e73f4459SArtem Bityutskiy ret = ERR_PTR(-ENODEV);
272801c135cSArtem B. Bityutskiy
273e73f4459SArtem Bityutskiy /*
274e73f4459SArtem Bityutskiy * We should put the UBI device even in case of success, because
275e73f4459SArtem Bityutskiy * 'ubi_open_volume()' took a reference as well.
276e73f4459SArtem Bityutskiy */
277e73f4459SArtem Bityutskiy ubi_put_device(ubi);
278e73f4459SArtem Bityutskiy return ret;
279801c135cSArtem B. Bityutskiy }
280801c135cSArtem B. Bityutskiy EXPORT_SYMBOL_GPL(ubi_open_volume_nm);
281801c135cSArtem B. Bityutskiy
282801c135cSArtem B. Bityutskiy /**
283b5710284SCorentin Chary * ubi_open_volume_path - open UBI volume by its character device node path.
284b5710284SCorentin Chary * @pathname: volume character device node path
285b5710284SCorentin Chary * @mode: open mode
286b5710284SCorentin Chary *
287b5710284SCorentin Chary * This function is similar to 'ubi_open_volume()', but opens a volume the path
288b5710284SCorentin Chary * to its character device node.
289b5710284SCorentin Chary */
ubi_open_volume_path(const char * pathname,int mode)290b5710284SCorentin Chary struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode)
291b5710284SCorentin Chary {
29261edc3f3SRichard Weinberger int error, ubi_num, vol_id;
293ad022c87SRichard Weinberger struct path path;
29461edc3f3SRichard Weinberger struct kstat stat;
295b5710284SCorentin Chary
296b5710284SCorentin Chary dbg_gen("open volume %s, mode %d", pathname, mode);
297b5710284SCorentin Chary
298b5710284SCorentin Chary if (!pathname || !*pathname)
299b5710284SCorentin Chary return ERR_PTR(-EINVAL);
300b5710284SCorentin Chary
301ad022c87SRichard Weinberger error = kern_path(pathname, LOOKUP_FOLLOW, &path);
302b5710284SCorentin Chary if (error)
303b5710284SCorentin Chary return ERR_PTR(error);
304b5710284SCorentin Chary
305a528d35eSDavid Howells error = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT);
306ad022c87SRichard Weinberger path_put(&path);
30761edc3f3SRichard Weinberger if (error)
30861edc3f3SRichard Weinberger return ERR_PTR(error);
309ad022c87SRichard Weinberger
31061edc3f3SRichard Weinberger if (!S_ISCHR(stat.mode))
311b531b55aSArtem Bityutskiy return ERR_PTR(-EINVAL);
31261edc3f3SRichard Weinberger
31361edc3f3SRichard Weinberger ubi_num = ubi_major2num(MAJOR(stat.rdev));
31461edc3f3SRichard Weinberger vol_id = MINOR(stat.rdev) - 1;
31561edc3f3SRichard Weinberger
316b531b55aSArtem Bityutskiy if (vol_id >= 0 && ubi_num >= 0)
317b531b55aSArtem Bityutskiy return ubi_open_volume(ubi_num, vol_id, mode);
318b531b55aSArtem Bityutskiy return ERR_PTR(-ENODEV);
319b5710284SCorentin Chary }
320b5710284SCorentin Chary EXPORT_SYMBOL_GPL(ubi_open_volume_path);
321b5710284SCorentin Chary
322b5710284SCorentin Chary /**
323801c135cSArtem B. Bityutskiy * ubi_close_volume - close UBI volume.
324801c135cSArtem B. Bityutskiy * @desc: volume descriptor
325801c135cSArtem B. Bityutskiy */
ubi_close_volume(struct ubi_volume_desc * desc)326801c135cSArtem B. Bityutskiy void ubi_close_volume(struct ubi_volume_desc *desc)
327801c135cSArtem B. Bityutskiy {
328801c135cSArtem B. Bityutskiy struct ubi_volume *vol = desc->vol;
329e73f4459SArtem Bityutskiy struct ubi_device *ubi = vol->ubi;
330801c135cSArtem B. Bityutskiy
331e1cf7e6dSArtem Bityutskiy dbg_gen("close device %d, volume %d, mode %d",
332e1cf7e6dSArtem Bityutskiy ubi->ubi_num, vol->vol_id, desc->mode);
333801c135cSArtem B. Bityutskiy
334e73f4459SArtem Bityutskiy spin_lock(&ubi->volumes_lock);
335801c135cSArtem B. Bityutskiy switch (desc->mode) {
336801c135cSArtem B. Bityutskiy case UBI_READONLY:
337801c135cSArtem B. Bityutskiy vol->readers -= 1;
338801c135cSArtem B. Bityutskiy break;
339801c135cSArtem B. Bityutskiy case UBI_READWRITE:
340801c135cSArtem B. Bityutskiy vol->writers -= 1;
341801c135cSArtem B. Bityutskiy break;
342801c135cSArtem B. Bityutskiy case UBI_EXCLUSIVE:
343801c135cSArtem B. Bityutskiy vol->exclusive = 0;
344fafdd2bfSRichard Weinberger break;
345fafdd2bfSRichard Weinberger case UBI_METAONLY:
346fafdd2bfSRichard Weinberger vol->metaonly = 0;
347fafdd2bfSRichard Weinberger break;
348801c135cSArtem B. Bityutskiy }
349d05c77a8SArtem Bityutskiy vol->ref_count -= 1;
350e73f4459SArtem Bityutskiy spin_unlock(&ubi->volumes_lock);
351801c135cSArtem B. Bityutskiy
352d05c77a8SArtem Bityutskiy kfree(desc);
353e73f4459SArtem Bityutskiy put_device(&vol->dev);
354e73f4459SArtem Bityutskiy ubi_put_device(ubi);
355801c135cSArtem B. Bityutskiy module_put(THIS_MODULE);
356801c135cSArtem B. Bityutskiy }
357801c135cSArtem B. Bityutskiy EXPORT_SYMBOL_GPL(ubi_close_volume);
358801c135cSArtem B. Bityutskiy
359801c135cSArtem B. Bityutskiy /**
3609ff08979SRichard Weinberger * leb_read_sanity_check - does sanity checks on read requests.
3619ff08979SRichard Weinberger * @desc: volume descriptor
3629ff08979SRichard Weinberger * @lnum: logical eraseblock number to read from
3639ff08979SRichard Weinberger * @offset: offset within the logical eraseblock to read from
3649ff08979SRichard Weinberger * @len: how many bytes to read
3659ff08979SRichard Weinberger *
3669ff08979SRichard Weinberger * This function is used by ubi_leb_read() and ubi_leb_read_sg()
3679ff08979SRichard Weinberger * to perform sanity checks.
3689ff08979SRichard Weinberger */
leb_read_sanity_check(struct ubi_volume_desc * desc,int lnum,int offset,int len)3699ff08979SRichard Weinberger static int leb_read_sanity_check(struct ubi_volume_desc *desc, int lnum,
3709ff08979SRichard Weinberger int offset, int len)
3719ff08979SRichard Weinberger {
3729ff08979SRichard Weinberger struct ubi_volume *vol = desc->vol;
3739ff08979SRichard Weinberger struct ubi_device *ubi = vol->ubi;
3749ff08979SRichard Weinberger int vol_id = vol->vol_id;
3759ff08979SRichard Weinberger
3769ff08979SRichard Weinberger if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 ||
3779ff08979SRichard Weinberger lnum >= vol->used_ebs || offset < 0 || len < 0 ||
3789ff08979SRichard Weinberger offset + len > vol->usable_leb_size)
3799ff08979SRichard Weinberger return -EINVAL;
3809ff08979SRichard Weinberger
3819ff08979SRichard Weinberger if (vol->vol_type == UBI_STATIC_VOLUME) {
3829ff08979SRichard Weinberger if (vol->used_ebs == 0)
3839ff08979SRichard Weinberger /* Empty static UBI volume */
3849ff08979SRichard Weinberger return 0;
3859ff08979SRichard Weinberger if (lnum == vol->used_ebs - 1 &&
3869ff08979SRichard Weinberger offset + len > vol->last_eb_bytes)
3879ff08979SRichard Weinberger return -EINVAL;
3889ff08979SRichard Weinberger }
3899ff08979SRichard Weinberger
3909ff08979SRichard Weinberger if (vol->upd_marker)
3919ff08979SRichard Weinberger return -EBADF;
3929ff08979SRichard Weinberger
3939ff08979SRichard Weinberger return 0;
3949ff08979SRichard Weinberger }
3959ff08979SRichard Weinberger
3969ff08979SRichard Weinberger /**
397801c135cSArtem B. Bityutskiy * ubi_leb_read - read data.
398801c135cSArtem B. Bityutskiy * @desc: volume descriptor
399801c135cSArtem B. Bityutskiy * @lnum: logical eraseblock number to read from
400801c135cSArtem B. Bityutskiy * @buf: buffer where to store the read data
401801c135cSArtem B. Bityutskiy * @offset: offset within the logical eraseblock to read from
402801c135cSArtem B. Bityutskiy * @len: how many bytes to read
403801c135cSArtem B. Bityutskiy * @check: whether UBI has to check the read data's CRC or not.
404801c135cSArtem B. Bityutskiy *
405801c135cSArtem B. Bityutskiy * This function reads data from offset @offset of logical eraseblock @lnum and
406801c135cSArtem B. Bityutskiy * stores the data at @buf. When reading from static volumes, @check specifies
407801c135cSArtem B. Bityutskiy * whether the data has to be checked or not. If yes, the whole logical
408801c135cSArtem B. Bityutskiy * eraseblock will be read and its CRC checksum will be checked (i.e., the CRC
409801c135cSArtem B. Bityutskiy * checksum is per-eraseblock). So checking may substantially slow down the
410801c135cSArtem B. Bityutskiy * read speed. The @check argument is ignored for dynamic volumes.
411801c135cSArtem B. Bityutskiy *
412801c135cSArtem B. Bityutskiy * In case of success, this function returns zero. In case of failure, this
413801c135cSArtem B. Bityutskiy * function returns a negative error code.
414801c135cSArtem B. Bityutskiy *
415801c135cSArtem B. Bityutskiy * %-EBADMSG error code is returned:
416801c135cSArtem B. Bityutskiy * o for both static and dynamic volumes if MTD driver has detected a data
417801c135cSArtem B. Bityutskiy * integrity problem (unrecoverable ECC checksum mismatch in case of NAND);
418801c135cSArtem B. Bityutskiy * o for static volumes in case of data CRC mismatch.
419801c135cSArtem B. Bityutskiy *
420801c135cSArtem B. Bityutskiy * If the volume is damaged because of an interrupted update this function just
421801c135cSArtem B. Bityutskiy * returns immediately with %-EBADF error code.
422801c135cSArtem B. Bityutskiy */
ubi_leb_read(struct ubi_volume_desc * desc,int lnum,char * buf,int offset,int len,int check)423801c135cSArtem B. Bityutskiy int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
424801c135cSArtem B. Bityutskiy int len, int check)
425801c135cSArtem B. Bityutskiy {
426801c135cSArtem B. Bityutskiy struct ubi_volume *vol = desc->vol;
427801c135cSArtem B. Bityutskiy struct ubi_device *ubi = vol->ubi;
428801c135cSArtem B. Bityutskiy int err, vol_id = vol->vol_id;
429801c135cSArtem B. Bityutskiy
430c8566350SArtem Bityutskiy dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
431801c135cSArtem B. Bityutskiy
4329ff08979SRichard Weinberger err = leb_read_sanity_check(desc, lnum, offset, len);
4339ff08979SRichard Weinberger if (err < 0)
4349ff08979SRichard Weinberger return err;
435801c135cSArtem B. Bityutskiy
436801c135cSArtem B. Bityutskiy if (len == 0)
437801c135cSArtem B. Bityutskiy return 0;
438801c135cSArtem B. Bityutskiy
43989b96b69SArtem Bityutskiy err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check);
440d57f4054SBrian Norris if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) {
44132608703STanya Brokhman ubi_warn(ubi, "mark volume %d as corrupted", vol_id);
442801c135cSArtem B. Bityutskiy vol->corrupted = 1;
443801c135cSArtem B. Bityutskiy }
444801c135cSArtem B. Bityutskiy
445801c135cSArtem B. Bityutskiy return err;
446801c135cSArtem B. Bityutskiy }
447801c135cSArtem B. Bityutskiy EXPORT_SYMBOL_GPL(ubi_leb_read);
448801c135cSArtem B. Bityutskiy
4499ff08979SRichard Weinberger
4509ff08979SRichard Weinberger /**
4519ff08979SRichard Weinberger * ubi_leb_read_sg - read data into a scatter gather list.
4529ff08979SRichard Weinberger * @desc: volume descriptor
4539ff08979SRichard Weinberger * @lnum: logical eraseblock number to read from
454b6baa996SLee Jones * @sgl: UBI scatter gather list to store the read data
4559ff08979SRichard Weinberger * @offset: offset within the logical eraseblock to read from
4569ff08979SRichard Weinberger * @len: how many bytes to read
4579ff08979SRichard Weinberger * @check: whether UBI has to check the read data's CRC or not.
4589ff08979SRichard Weinberger *
4599ff08979SRichard Weinberger * This function works exactly like ubi_leb_read_sg(). But instead of
4609ff08979SRichard Weinberger * storing the read data into a buffer it writes to an UBI scatter gather
4619ff08979SRichard Weinberger * list.
4629ff08979SRichard Weinberger */
ubi_leb_read_sg(struct ubi_volume_desc * desc,int lnum,struct ubi_sgl * sgl,int offset,int len,int check)4639ff08979SRichard Weinberger int ubi_leb_read_sg(struct ubi_volume_desc *desc, int lnum, struct ubi_sgl *sgl,
4649ff08979SRichard Weinberger int offset, int len, int check)
4659ff08979SRichard Weinberger {
4669ff08979SRichard Weinberger struct ubi_volume *vol = desc->vol;
4679ff08979SRichard Weinberger struct ubi_device *ubi = vol->ubi;
4689ff08979SRichard Weinberger int err, vol_id = vol->vol_id;
4699ff08979SRichard Weinberger
4709ff08979SRichard Weinberger dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
4719ff08979SRichard Weinberger
4729ff08979SRichard Weinberger err = leb_read_sanity_check(desc, lnum, offset, len);
4739ff08979SRichard Weinberger if (err < 0)
4749ff08979SRichard Weinberger return err;
4759ff08979SRichard Weinberger
4769ff08979SRichard Weinberger if (len == 0)
4779ff08979SRichard Weinberger return 0;
4789ff08979SRichard Weinberger
4799ff08979SRichard Weinberger err = ubi_eba_read_leb_sg(ubi, vol, sgl, lnum, offset, len, check);
4809ff08979SRichard Weinberger if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) {
4819ff08979SRichard Weinberger ubi_warn(ubi, "mark volume %d as corrupted", vol_id);
4829ff08979SRichard Weinberger vol->corrupted = 1;
4839ff08979SRichard Weinberger }
4849ff08979SRichard Weinberger
4859ff08979SRichard Weinberger return err;
4869ff08979SRichard Weinberger }
4879ff08979SRichard Weinberger EXPORT_SYMBOL_GPL(ubi_leb_read_sg);
4889ff08979SRichard Weinberger
489801c135cSArtem B. Bityutskiy /**
490801c135cSArtem B. Bityutskiy * ubi_leb_write - write data.
491801c135cSArtem B. Bityutskiy * @desc: volume descriptor
492801c135cSArtem B. Bityutskiy * @lnum: logical eraseblock number to write to
493801c135cSArtem B. Bityutskiy * @buf: data to write
494801c135cSArtem B. Bityutskiy * @offset: offset within the logical eraseblock where to write
495801c135cSArtem B. Bityutskiy * @len: how many bytes to write
496801c135cSArtem B. Bityutskiy *
497801c135cSArtem B. Bityutskiy * This function writes @len bytes of data from @buf to offset @offset of
498b36a261eSRichard Weinberger * logical eraseblock @lnum.
499801c135cSArtem B. Bityutskiy *
500801c135cSArtem B. Bityutskiy * This function takes care of physical eraseblock write failures. If write to
501801c135cSArtem B. Bityutskiy * the physical eraseblock write operation fails, the logical eraseblock is
502801c135cSArtem B. Bityutskiy * re-mapped to another physical eraseblock, the data is recovered, and the
503801c135cSArtem B. Bityutskiy * write finishes. UBI has a pool of reserved physical eraseblocks for this.
504801c135cSArtem B. Bityutskiy *
505801c135cSArtem B. Bityutskiy * If all the data were successfully written, zero is returned. If an error
506801c135cSArtem B. Bityutskiy * occurred and UBI has not been able to recover from it, this function returns
507801c135cSArtem B. Bityutskiy * a negative error code. Note, in case of an error, it is possible that
508801c135cSArtem B. Bityutskiy * something was still written to the flash media, but that may be some
509801c135cSArtem B. Bityutskiy * garbage.
510801c135cSArtem B. Bityutskiy *
511801c135cSArtem B. Bityutskiy * If the volume is damaged because of an interrupted update this function just
512801c135cSArtem B. Bityutskiy * returns immediately with %-EBADF code.
513801c135cSArtem B. Bityutskiy */
ubi_leb_write(struct ubi_volume_desc * desc,int lnum,const void * buf,int offset,int len)514801c135cSArtem B. Bityutskiy int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
515b36a261eSRichard Weinberger int offset, int len)
516801c135cSArtem B. Bityutskiy {
517801c135cSArtem B. Bityutskiy struct ubi_volume *vol = desc->vol;
518801c135cSArtem B. Bityutskiy struct ubi_device *ubi = vol->ubi;
519801c135cSArtem B. Bityutskiy int vol_id = vol->vol_id;
520801c135cSArtem B. Bityutskiy
521c8566350SArtem Bityutskiy dbg_gen("write %d bytes to LEB %d:%d:%d", len, vol_id, lnum, offset);
522801c135cSArtem B. Bityutskiy
523801c135cSArtem B. Bityutskiy if (vol_id < 0 || vol_id >= ubi->vtbl_slots)
524801c135cSArtem B. Bityutskiy return -EINVAL;
525801c135cSArtem B. Bityutskiy
526801c135cSArtem B. Bityutskiy if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
527801c135cSArtem B. Bityutskiy return -EROFS;
528801c135cSArtem B. Bityutskiy
5299a5f09acSBoris Brezillon if (!ubi_leb_valid(vol, lnum) || offset < 0 || len < 0 ||
530cadb40ccSKyungmin Park offset + len > vol->usable_leb_size ||
531cadb40ccSKyungmin Park offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1))
532801c135cSArtem B. Bityutskiy return -EINVAL;
533801c135cSArtem B. Bityutskiy
534801c135cSArtem B. Bityutskiy if (vol->upd_marker)
535801c135cSArtem B. Bityutskiy return -EBADF;
536801c135cSArtem B. Bityutskiy
537801c135cSArtem B. Bityutskiy if (len == 0)
538801c135cSArtem B. Bityutskiy return 0;
539801c135cSArtem B. Bityutskiy
540b36a261eSRichard Weinberger return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len);
541801c135cSArtem B. Bityutskiy }
542801c135cSArtem B. Bityutskiy EXPORT_SYMBOL_GPL(ubi_leb_write);
543801c135cSArtem B. Bityutskiy
544801c135cSArtem B. Bityutskiy /*
545801c135cSArtem B. Bityutskiy * ubi_leb_change - change logical eraseblock atomically.
546801c135cSArtem B. Bityutskiy * @desc: volume descriptor
547801c135cSArtem B. Bityutskiy * @lnum: logical eraseblock number to change
548801c135cSArtem B. Bityutskiy * @buf: data to write
549801c135cSArtem B. Bityutskiy * @len: how many bytes to write
550801c135cSArtem B. Bityutskiy *
551801c135cSArtem B. Bityutskiy * This function changes the contents of a logical eraseblock atomically. @buf
552801c135cSArtem B. Bityutskiy * has to contain new logical eraseblock data, and @len - the length of the
5533f502622SShinya Kuribayashi * data, which has to be aligned. The length may be shorter than the logical
554801c135cSArtem B. Bityutskiy * eraseblock size, ant the logical eraseblock may be appended to more times
555801c135cSArtem B. Bityutskiy * later on. This function guarantees that in case of an unclean reboot the old
556801c135cSArtem B. Bityutskiy * contents is preserved. Returns zero in case of success and a negative error
557801c135cSArtem B. Bityutskiy * code in case of failure.
558801c135cSArtem B. Bityutskiy */
ubi_leb_change(struct ubi_volume_desc * desc,int lnum,const void * buf,int len)559801c135cSArtem B. Bityutskiy int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
560b36a261eSRichard Weinberger int len)
561801c135cSArtem B. Bityutskiy {
562801c135cSArtem B. Bityutskiy struct ubi_volume *vol = desc->vol;
563801c135cSArtem B. Bityutskiy struct ubi_device *ubi = vol->ubi;
564801c135cSArtem B. Bityutskiy int vol_id = vol->vol_id;
565801c135cSArtem B. Bityutskiy
566c8566350SArtem Bityutskiy dbg_gen("atomically write %d bytes to LEB %d:%d", len, vol_id, lnum);
567801c135cSArtem B. Bityutskiy
568801c135cSArtem B. Bityutskiy if (vol_id < 0 || vol_id >= ubi->vtbl_slots)
569801c135cSArtem B. Bityutskiy return -EINVAL;
570801c135cSArtem B. Bityutskiy
571801c135cSArtem B. Bityutskiy if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
572801c135cSArtem B. Bityutskiy return -EROFS;
573801c135cSArtem B. Bityutskiy
5749a5f09acSBoris Brezillon if (!ubi_leb_valid(vol, lnum) || len < 0 ||
575cadb40ccSKyungmin Park len > vol->usable_leb_size || len & (ubi->min_io_size - 1))
576801c135cSArtem B. Bityutskiy return -EINVAL;
577801c135cSArtem B. Bityutskiy
578801c135cSArtem B. Bityutskiy if (vol->upd_marker)
579801c135cSArtem B. Bityutskiy return -EBADF;
580801c135cSArtem B. Bityutskiy
581801c135cSArtem B. Bityutskiy if (len == 0)
582801c135cSArtem B. Bityutskiy return 0;
583801c135cSArtem B. Bityutskiy
584b36a261eSRichard Weinberger return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len);
585801c135cSArtem B. Bityutskiy }
586801c135cSArtem B. Bityutskiy EXPORT_SYMBOL_GPL(ubi_leb_change);
587801c135cSArtem B. Bityutskiy
588801c135cSArtem B. Bityutskiy /**
589801c135cSArtem B. Bityutskiy * ubi_leb_erase - erase logical eraseblock.
590801c135cSArtem B. Bityutskiy * @desc: volume descriptor
591801c135cSArtem B. Bityutskiy * @lnum: logical eraseblock number
592801c135cSArtem B. Bityutskiy *
593801c135cSArtem B. Bityutskiy * This function un-maps logical eraseblock @lnum and synchronously erases the
594801c135cSArtem B. Bityutskiy * correspondent physical eraseblock. Returns zero in case of success and a
595801c135cSArtem B. Bityutskiy * negative error code in case of failure.
596801c135cSArtem B. Bityutskiy *
597801c135cSArtem B. Bityutskiy * If the volume is damaged because of an interrupted update this function just
598801c135cSArtem B. Bityutskiy * returns immediately with %-EBADF code.
599801c135cSArtem B. Bityutskiy */
ubi_leb_erase(struct ubi_volume_desc * desc,int lnum)600801c135cSArtem B. Bityutskiy int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum)
601801c135cSArtem B. Bityutskiy {
602801c135cSArtem B. Bityutskiy struct ubi_volume *vol = desc->vol;
603801c135cSArtem B. Bityutskiy struct ubi_device *ubi = vol->ubi;
604ae616e1bSArtem Bityutskiy int err;
605801c135cSArtem B. Bityutskiy
606c8566350SArtem Bityutskiy dbg_gen("erase LEB %d:%d", vol->vol_id, lnum);
607801c135cSArtem B. Bityutskiy
608801c135cSArtem B. Bityutskiy if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
609801c135cSArtem B. Bityutskiy return -EROFS;
610801c135cSArtem B. Bityutskiy
6119a5f09acSBoris Brezillon if (!ubi_leb_valid(vol, lnum))
612801c135cSArtem B. Bityutskiy return -EINVAL;
613801c135cSArtem B. Bityutskiy
614801c135cSArtem B. Bityutskiy if (vol->upd_marker)
615801c135cSArtem B. Bityutskiy return -EBADF;
616801c135cSArtem B. Bityutskiy
61789b96b69SArtem Bityutskiy err = ubi_eba_unmap_leb(ubi, vol, lnum);
618801c135cSArtem B. Bityutskiy if (err)
619801c135cSArtem B. Bityutskiy return err;
620801c135cSArtem B. Bityutskiy
62162f38455SJoel Reardon return ubi_wl_flush(ubi, vol->vol_id, lnum);
622801c135cSArtem B. Bityutskiy }
623801c135cSArtem B. Bityutskiy EXPORT_SYMBOL_GPL(ubi_leb_erase);
624801c135cSArtem B. Bityutskiy
625801c135cSArtem B. Bityutskiy /**
626801c135cSArtem B. Bityutskiy * ubi_leb_unmap - un-map logical eraseblock.
627801c135cSArtem B. Bityutskiy * @desc: volume descriptor
628801c135cSArtem B. Bityutskiy * @lnum: logical eraseblock number
629801c135cSArtem B. Bityutskiy *
630801c135cSArtem B. Bityutskiy * This function un-maps logical eraseblock @lnum and schedules the
631801c135cSArtem B. Bityutskiy * corresponding physical eraseblock for erasure, so that it will eventually be
6323f502622SShinya Kuribayashi * physically erased in background. This operation is much faster than the
633801c135cSArtem B. Bityutskiy * erase operation.
634801c135cSArtem B. Bityutskiy *
635801c135cSArtem B. Bityutskiy * Unlike erase, the un-map operation does not guarantee that the logical
636801c135cSArtem B. Bityutskiy * eraseblock will contain all 0xFF bytes when UBI is initialized again. For
637801c135cSArtem B. Bityutskiy * example, if several logical eraseblocks are un-mapped, and an unclean reboot
638801c135cSArtem B. Bityutskiy * happens after this, the logical eraseblocks will not necessarily be
639801c135cSArtem B. Bityutskiy * un-mapped again when this MTD device is attached. They may actually be
640801c135cSArtem B. Bityutskiy * mapped to the same physical eraseblocks again. So, this function has to be
641801c135cSArtem B. Bityutskiy * used with care.
642801c135cSArtem B. Bityutskiy *
643801c135cSArtem B. Bityutskiy * In other words, when un-mapping a logical eraseblock, UBI does not store
644801c135cSArtem B. Bityutskiy * any information about this on the flash media, it just marks the logical
645801c135cSArtem B. Bityutskiy * eraseblock as "un-mapped" in RAM. If UBI is detached before the physical
646801c135cSArtem B. Bityutskiy * eraseblock is physically erased, it will be mapped again to the same logical
647801c135cSArtem B. Bityutskiy * eraseblock when the MTD device is attached again.
648801c135cSArtem B. Bityutskiy *
649801c135cSArtem B. Bityutskiy * The main and obvious use-case of this function is when the contents of a
650801c135cSArtem B. Bityutskiy * logical eraseblock has to be re-written. Then it is much more efficient to
6513f502622SShinya Kuribayashi * first un-map it, then write new data, rather than first erase it, then write
652801c135cSArtem B. Bityutskiy * new data. Note, once new data has been written to the logical eraseblock,
653801c135cSArtem B. Bityutskiy * UBI guarantees that the old contents has gone forever. In other words, if an
654801c135cSArtem B. Bityutskiy * unclean reboot happens after the logical eraseblock has been un-mapped and
655801c135cSArtem B. Bityutskiy * then written to, it will contain the last written data.
656801c135cSArtem B. Bityutskiy *
657801c135cSArtem B. Bityutskiy * This function returns zero in case of success and a negative error code in
658801c135cSArtem B. Bityutskiy * case of failure. If the volume is damaged because of an interrupted update
659801c135cSArtem B. Bityutskiy * this function just returns immediately with %-EBADF code.
660801c135cSArtem B. Bityutskiy */
ubi_leb_unmap(struct ubi_volume_desc * desc,int lnum)661801c135cSArtem B. Bityutskiy int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum)
662801c135cSArtem B. Bityutskiy {
663801c135cSArtem B. Bityutskiy struct ubi_volume *vol = desc->vol;
664801c135cSArtem B. Bityutskiy struct ubi_device *ubi = vol->ubi;
665801c135cSArtem B. Bityutskiy
666c8566350SArtem Bityutskiy dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum);
667801c135cSArtem B. Bityutskiy
668801c135cSArtem B. Bityutskiy if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
669801c135cSArtem B. Bityutskiy return -EROFS;
670801c135cSArtem B. Bityutskiy
6719a5f09acSBoris Brezillon if (!ubi_leb_valid(vol, lnum))
672801c135cSArtem B. Bityutskiy return -EINVAL;
673801c135cSArtem B. Bityutskiy
674801c135cSArtem B. Bityutskiy if (vol->upd_marker)
675801c135cSArtem B. Bityutskiy return -EBADF;
676801c135cSArtem B. Bityutskiy
67789b96b69SArtem Bityutskiy return ubi_eba_unmap_leb(ubi, vol, lnum);
678801c135cSArtem B. Bityutskiy }
679801c135cSArtem B. Bityutskiy EXPORT_SYMBOL_GPL(ubi_leb_unmap);
680801c135cSArtem B. Bityutskiy
681801c135cSArtem B. Bityutskiy /**
6820e0ee1ccSDmitry Pervushin * ubi_leb_map - map logical eraseblock to a physical eraseblock.
683393852ecSArtem Bityutskiy * @desc: volume descriptor
684393852ecSArtem Bityutskiy * @lnum: logical eraseblock number
685393852ecSArtem Bityutskiy *
686393852ecSArtem Bityutskiy * This function maps an un-mapped logical eraseblock @lnum to a physical
68773ac36eaSColy Li * eraseblock. This means, that after a successful invocation of this
688393852ecSArtem Bityutskiy * function the logical eraseblock @lnum will be empty (contain only %0xFF
689393852ecSArtem Bityutskiy * bytes) and be mapped to a physical eraseblock, even if an unclean reboot
690393852ecSArtem Bityutskiy * happens.
691393852ecSArtem Bityutskiy *
692393852ecSArtem Bityutskiy * This function returns zero in case of success, %-EBADF if the volume is
693393852ecSArtem Bityutskiy * damaged because of an interrupted update, %-EBADMSG if the logical
694393852ecSArtem Bityutskiy * eraseblock is already mapped, and other negative error codes in case of
695393852ecSArtem Bityutskiy * other failures.
696393852ecSArtem Bityutskiy */
ubi_leb_map(struct ubi_volume_desc * desc,int lnum)697b36a261eSRichard Weinberger int ubi_leb_map(struct ubi_volume_desc *desc, int lnum)
698393852ecSArtem Bityutskiy {
699393852ecSArtem Bityutskiy struct ubi_volume *vol = desc->vol;
700393852ecSArtem Bityutskiy struct ubi_device *ubi = vol->ubi;
701393852ecSArtem Bityutskiy
702960b35d0Sz00189512 dbg_gen("map LEB %d:%d", vol->vol_id, lnum);
703393852ecSArtem Bityutskiy
704393852ecSArtem Bityutskiy if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
705393852ecSArtem Bityutskiy return -EROFS;
706393852ecSArtem Bityutskiy
7079a5f09acSBoris Brezillon if (!ubi_leb_valid(vol, lnum))
708393852ecSArtem Bityutskiy return -EINVAL;
709393852ecSArtem Bityutskiy
710393852ecSArtem Bityutskiy if (vol->upd_marker)
711393852ecSArtem Bityutskiy return -EBADF;
712393852ecSArtem Bityutskiy
71375547696SBoris Brezillon if (ubi_eba_is_mapped(vol, lnum))
714393852ecSArtem Bityutskiy return -EBADMSG;
715393852ecSArtem Bityutskiy
716b36a261eSRichard Weinberger return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0);
717393852ecSArtem Bityutskiy }
718393852ecSArtem Bityutskiy EXPORT_SYMBOL_GPL(ubi_leb_map);
719393852ecSArtem Bityutskiy
720393852ecSArtem Bityutskiy /**
721801c135cSArtem B. Bityutskiy * ubi_is_mapped - check if logical eraseblock is mapped.
722801c135cSArtem B. Bityutskiy * @desc: volume descriptor
723801c135cSArtem B. Bityutskiy * @lnum: logical eraseblock number
724801c135cSArtem B. Bityutskiy *
725801c135cSArtem B. Bityutskiy * This function checks if logical eraseblock @lnum is mapped to a physical
726801c135cSArtem B. Bityutskiy * eraseblock. If a logical eraseblock is un-mapped, this does not necessarily
727801c135cSArtem B. Bityutskiy * mean it will still be un-mapped after the UBI device is re-attached. The
728801c135cSArtem B. Bityutskiy * logical eraseblock may become mapped to the physical eraseblock it was last
729801c135cSArtem B. Bityutskiy * mapped to.
730801c135cSArtem B. Bityutskiy *
731801c135cSArtem B. Bityutskiy * This function returns %1 if the LEB is mapped, %0 if not, and a negative
732801c135cSArtem B. Bityutskiy * error code in case of failure. If the volume is damaged because of an
733801c135cSArtem B. Bityutskiy * interrupted update this function just returns immediately with %-EBADF error
734801c135cSArtem B. Bityutskiy * code.
735801c135cSArtem B. Bityutskiy */
ubi_is_mapped(struct ubi_volume_desc * desc,int lnum)736801c135cSArtem B. Bityutskiy int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum)
737801c135cSArtem B. Bityutskiy {
738801c135cSArtem B. Bityutskiy struct ubi_volume *vol = desc->vol;
739801c135cSArtem B. Bityutskiy
740c8566350SArtem Bityutskiy dbg_gen("test LEB %d:%d", vol->vol_id, lnum);
741801c135cSArtem B. Bityutskiy
7429a5f09acSBoris Brezillon if (!ubi_leb_valid(vol, lnum))
743801c135cSArtem B. Bityutskiy return -EINVAL;
744801c135cSArtem B. Bityutskiy
745801c135cSArtem B. Bityutskiy if (vol->upd_marker)
746801c135cSArtem B. Bityutskiy return -EBADF;
747801c135cSArtem B. Bityutskiy
74875547696SBoris Brezillon return ubi_eba_is_mapped(vol, lnum);
749801c135cSArtem B. Bityutskiy }
750801c135cSArtem B. Bityutskiy EXPORT_SYMBOL_GPL(ubi_is_mapped);
751a5bf6190SArtem Bityutskiy
752a5bf6190SArtem Bityutskiy /**
753a5bf6190SArtem Bityutskiy * ubi_sync - synchronize UBI device buffers.
754a5bf6190SArtem Bityutskiy * @ubi_num: UBI device to synchronize
755a5bf6190SArtem Bityutskiy *
756a5bf6190SArtem Bityutskiy * The underlying MTD device may cache data in hardware or in software. This
757a5bf6190SArtem Bityutskiy * function ensures the caches are flushed. Returns zero in case of success and
758a5bf6190SArtem Bityutskiy * a negative error code in case of failure.
759a5bf6190SArtem Bityutskiy */
ubi_sync(int ubi_num)760a5bf6190SArtem Bityutskiy int ubi_sync(int ubi_num)
761a5bf6190SArtem Bityutskiy {
762a5bf6190SArtem Bityutskiy struct ubi_device *ubi;
763a5bf6190SArtem Bityutskiy
764a5bf6190SArtem Bityutskiy ubi = ubi_get_device(ubi_num);
765a5bf6190SArtem Bityutskiy if (!ubi)
766a5bf6190SArtem Bityutskiy return -ENODEV;
767a5bf6190SArtem Bityutskiy
76885f2f2a8SArtem Bityutskiy mtd_sync(ubi->mtd);
769a5bf6190SArtem Bityutskiy ubi_put_device(ubi);
770a5bf6190SArtem Bityutskiy return 0;
771a5bf6190SArtem Bityutskiy }
772a5bf6190SArtem Bityutskiy EXPORT_SYMBOL_GPL(ubi_sync);
7730e0ee1ccSDmitry Pervushin
77462f38455SJoel Reardon /**
77562f38455SJoel Reardon * ubi_flush - flush UBI work queue.
77662f38455SJoel Reardon * @ubi_num: UBI device to flush work queue
77762f38455SJoel Reardon * @vol_id: volume id to flush for
77862f38455SJoel Reardon * @lnum: logical eraseblock number to flush for
77962f38455SJoel Reardon *
78062f38455SJoel Reardon * This function executes all pending works for a particular volume id / logical
78162f38455SJoel Reardon * eraseblock number pair. If either value is set to %UBI_ALL, then it acts as
78262f38455SJoel Reardon * a wildcard for all of the corresponding volume numbers or logical
78362f38455SJoel Reardon * eraseblock numbers. It returns zero in case of success and a negative error
78462f38455SJoel Reardon * code in case of failure.
78562f38455SJoel Reardon */
ubi_flush(int ubi_num,int vol_id,int lnum)78662f38455SJoel Reardon int ubi_flush(int ubi_num, int vol_id, int lnum)
78762f38455SJoel Reardon {
78862f38455SJoel Reardon struct ubi_device *ubi;
78962f38455SJoel Reardon int err = 0;
79062f38455SJoel Reardon
79162f38455SJoel Reardon ubi = ubi_get_device(ubi_num);
79262f38455SJoel Reardon if (!ubi)
79362f38455SJoel Reardon return -ENODEV;
79462f38455SJoel Reardon
79562f38455SJoel Reardon err = ubi_wl_flush(ubi, vol_id, lnum);
79662f38455SJoel Reardon ubi_put_device(ubi);
79762f38455SJoel Reardon return err;
79862f38455SJoel Reardon }
79962f38455SJoel Reardon EXPORT_SYMBOL_GPL(ubi_flush);
80062f38455SJoel Reardon
8010e0ee1ccSDmitry Pervushin BLOCKING_NOTIFIER_HEAD(ubi_notifiers);
8020e0ee1ccSDmitry Pervushin
8030e0ee1ccSDmitry Pervushin /**
8040e0ee1ccSDmitry Pervushin * ubi_register_volume_notifier - register a volume notifier.
8050e0ee1ccSDmitry Pervushin * @nb: the notifier description object
8060e0ee1ccSDmitry Pervushin * @ignore_existing: if non-zero, do not send "added" notification for all
8070e0ee1ccSDmitry Pervushin * already existing volumes
8080e0ee1ccSDmitry Pervushin *
8090e0ee1ccSDmitry Pervushin * This function registers a volume notifier, which means that
8100e0ee1ccSDmitry Pervushin * 'nb->notifier_call()' will be invoked when an UBI volume is created,
8110e0ee1ccSDmitry Pervushin * removed, re-sized, re-named, or updated. The first argument of the function
8120e0ee1ccSDmitry Pervushin * is the notification type. The second argument is pointer to a
8130e0ee1ccSDmitry Pervushin * &struct ubi_notification object which describes the notification event.
8140e0ee1ccSDmitry Pervushin * Using UBI API from the volume notifier is prohibited.
8150e0ee1ccSDmitry Pervushin *
8160e0ee1ccSDmitry Pervushin * This function returns zero in case of success and a negative error code
8170e0ee1ccSDmitry Pervushin * in case of failure.
8180e0ee1ccSDmitry Pervushin */
ubi_register_volume_notifier(struct notifier_block * nb,int ignore_existing)8190e0ee1ccSDmitry Pervushin int ubi_register_volume_notifier(struct notifier_block *nb,
8200e0ee1ccSDmitry Pervushin int ignore_existing)
8210e0ee1ccSDmitry Pervushin {
8220e0ee1ccSDmitry Pervushin int err;
8230e0ee1ccSDmitry Pervushin
8240e0ee1ccSDmitry Pervushin err = blocking_notifier_chain_register(&ubi_notifiers, nb);
8250e0ee1ccSDmitry Pervushin if (err != 0)
8260e0ee1ccSDmitry Pervushin return err;
8270e0ee1ccSDmitry Pervushin if (ignore_existing)
8280e0ee1ccSDmitry Pervushin return 0;
8290e0ee1ccSDmitry Pervushin
8300e0ee1ccSDmitry Pervushin /*
8310e0ee1ccSDmitry Pervushin * We are going to walk all UBI devices and all volumes, and
8320e0ee1ccSDmitry Pervushin * notify the user about existing volumes by the %UBI_VOLUME_ADDED
8330e0ee1ccSDmitry Pervushin * event. We have to lock the @ubi_devices_mutex to make sure UBI
8340e0ee1ccSDmitry Pervushin * devices do not disappear.
8350e0ee1ccSDmitry Pervushin */
8360e0ee1ccSDmitry Pervushin mutex_lock(&ubi_devices_mutex);
8370e0ee1ccSDmitry Pervushin ubi_enumerate_volumes(nb);
8380e0ee1ccSDmitry Pervushin mutex_unlock(&ubi_devices_mutex);
8390e0ee1ccSDmitry Pervushin
8400e0ee1ccSDmitry Pervushin return err;
8410e0ee1ccSDmitry Pervushin }
8420e0ee1ccSDmitry Pervushin EXPORT_SYMBOL_GPL(ubi_register_volume_notifier);
8430e0ee1ccSDmitry Pervushin
8440e0ee1ccSDmitry Pervushin /**
8450e0ee1ccSDmitry Pervushin * ubi_unregister_volume_notifier - unregister the volume notifier.
8460e0ee1ccSDmitry Pervushin * @nb: the notifier description object
8470e0ee1ccSDmitry Pervushin *
8480e0ee1ccSDmitry Pervushin * This function unregisters volume notifier @nm and returns zero in case of
8490e0ee1ccSDmitry Pervushin * success and a negative error code in case of failure.
8500e0ee1ccSDmitry Pervushin */
ubi_unregister_volume_notifier(struct notifier_block * nb)8510e0ee1ccSDmitry Pervushin int ubi_unregister_volume_notifier(struct notifier_block *nb)
8520e0ee1ccSDmitry Pervushin {
8530e0ee1ccSDmitry Pervushin return blocking_notifier_chain_unregister(&ubi_notifiers, nb);
8540e0ee1ccSDmitry Pervushin }
8550e0ee1ccSDmitry Pervushin EXPORT_SYMBOL_GPL(ubi_unregister_volume_notifier);
856