0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include <linux/err.h>
0029 #include <linux/uaccess.h>
0030 #include <linux/math64.h>
0031 #include "ubi.h"
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 static int set_update_marker(struct ubi_device *ubi, struct ubi_volume *vol)
0042 {
0043 int err;
0044 struct ubi_vtbl_record vtbl_rec;
0045
0046 dbg_gen("set update marker for volume %d", vol->vol_id);
0047
0048 if (vol->upd_marker) {
0049 ubi_assert(ubi->vtbl[vol->vol_id].upd_marker);
0050 dbg_gen("already set");
0051 return 0;
0052 }
0053
0054 vtbl_rec = ubi->vtbl[vol->vol_id];
0055 vtbl_rec.upd_marker = 1;
0056
0057 mutex_lock(&ubi->device_mutex);
0058 err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);
0059 vol->upd_marker = 1;
0060 mutex_unlock(&ubi->device_mutex);
0061 return err;
0062 }
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol,
0075 long long bytes)
0076 {
0077 int err;
0078 struct ubi_vtbl_record vtbl_rec;
0079
0080 dbg_gen("clear update marker for volume %d", vol->vol_id);
0081
0082 vtbl_rec = ubi->vtbl[vol->vol_id];
0083 ubi_assert(vol->upd_marker && vtbl_rec.upd_marker);
0084 vtbl_rec.upd_marker = 0;
0085
0086 if (vol->vol_type == UBI_STATIC_VOLUME) {
0087 vol->corrupted = 0;
0088 vol->used_bytes = bytes;
0089 vol->used_ebs = div_u64_rem(bytes, vol->usable_leb_size,
0090 &vol->last_eb_bytes);
0091 if (vol->last_eb_bytes)
0092 vol->used_ebs += 1;
0093 else
0094 vol->last_eb_bytes = vol->usable_leb_size;
0095 }
0096
0097 mutex_lock(&ubi->device_mutex);
0098 err = ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);
0099 vol->upd_marker = 0;
0100 mutex_unlock(&ubi->device_mutex);
0101 return err;
0102 }
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
0115 long long bytes)
0116 {
0117 int i, err;
0118
0119 dbg_gen("start update of volume %d, %llu bytes", vol->vol_id, bytes);
0120 ubi_assert(!vol->updating && !vol->changing_leb);
0121 vol->updating = 1;
0122
0123 vol->upd_buf = vmalloc(ubi->leb_size);
0124 if (!vol->upd_buf)
0125 return -ENOMEM;
0126
0127 err = set_update_marker(ubi, vol);
0128 if (err)
0129 return err;
0130
0131
0132 for (i = 0; i < vol->reserved_pebs; i++) {
0133 err = ubi_eba_unmap_leb(ubi, vol, i);
0134 if (err)
0135 return err;
0136 }
0137
0138 err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
0139 if (err)
0140 return err;
0141
0142 if (bytes == 0) {
0143 err = clear_update_marker(ubi, vol, 0);
0144 if (err)
0145 return err;
0146
0147 vfree(vol->upd_buf);
0148 vol->updating = 0;
0149 return 0;
0150 }
0151
0152 vol->upd_ebs = div_u64(bytes + vol->usable_leb_size - 1,
0153 vol->usable_leb_size);
0154 vol->upd_bytes = bytes;
0155 vol->upd_received = 0;
0156 return 0;
0157 }
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168 int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
0169 const struct ubi_leb_change_req *req)
0170 {
0171 ubi_assert(!vol->updating && !vol->changing_leb);
0172
0173 dbg_gen("start changing LEB %d:%d, %u bytes",
0174 vol->vol_id, req->lnum, req->bytes);
0175 if (req->bytes == 0)
0176 return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0);
0177
0178 vol->upd_bytes = req->bytes;
0179 vol->upd_received = 0;
0180 vol->changing_leb = 1;
0181 vol->ch_lnum = req->lnum;
0182
0183 vol->upd_buf = vmalloc(ALIGN((int)req->bytes, ubi->min_io_size));
0184 if (!vol->upd_buf)
0185 return -ENOMEM;
0186
0187 return 0;
0188 }
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219 static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
0220 void *buf, int len, int used_ebs)
0221 {
0222 int err;
0223
0224 if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
0225 int l = ALIGN(len, ubi->min_io_size);
0226
0227 memset(buf + len, 0xFF, l - len);
0228 len = ubi_calc_data_len(ubi, buf, l);
0229 if (len == 0) {
0230 dbg_gen("all %d bytes contain 0xFF - skip", len);
0231 return 0;
0232 }
0233
0234 err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len);
0235 } else {
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245 memset(buf + len, 0, vol->usable_leb_size - len);
0246 err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len, used_ebs);
0247 }
0248
0249 return err;
0250 }
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265 int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
0266 const void __user *buf, int count)
0267 {
0268 int lnum, offs, err = 0, len, to_write = count;
0269
0270 dbg_gen("write %d of %lld bytes, %lld already passed",
0271 count, vol->upd_bytes, vol->upd_received);
0272
0273 if (ubi->ro_mode)
0274 return -EROFS;
0275
0276 lnum = div_u64_rem(vol->upd_received, vol->usable_leb_size, &offs);
0277 if (vol->upd_received + count > vol->upd_bytes)
0278 to_write = count = vol->upd_bytes - vol->upd_received;
0279
0280
0281
0282
0283
0284 if (offs != 0) {
0285
0286
0287
0288
0289
0290
0291
0292 len = vol->usable_leb_size - offs;
0293 if (len > count)
0294 len = count;
0295
0296 err = copy_from_user(vol->upd_buf + offs, buf, len);
0297 if (err)
0298 return -EFAULT;
0299
0300 if (offs + len == vol->usable_leb_size ||
0301 vol->upd_received + len == vol->upd_bytes) {
0302 int flush_len = offs + len;
0303
0304
0305
0306
0307
0308 ubi_assert(flush_len <= vol->usable_leb_size);
0309 err = write_leb(ubi, vol, lnum, vol->upd_buf, flush_len,
0310 vol->upd_ebs);
0311 if (err)
0312 return err;
0313 }
0314
0315 vol->upd_received += len;
0316 count -= len;
0317 buf += len;
0318 lnum += 1;
0319 }
0320
0321
0322
0323
0324
0325 while (count) {
0326 if (count > vol->usable_leb_size)
0327 len = vol->usable_leb_size;
0328 else
0329 len = count;
0330
0331 err = copy_from_user(vol->upd_buf, buf, len);
0332 if (err)
0333 return -EFAULT;
0334
0335 if (len == vol->usable_leb_size ||
0336 vol->upd_received + len == vol->upd_bytes) {
0337 err = write_leb(ubi, vol, lnum, vol->upd_buf,
0338 len, vol->upd_ebs);
0339 if (err)
0340 break;
0341 }
0342
0343 vol->upd_received += len;
0344 count -= len;
0345 lnum += 1;
0346 buf += len;
0347 }
0348
0349 ubi_assert(vol->upd_received <= vol->upd_bytes);
0350 if (vol->upd_received == vol->upd_bytes) {
0351 err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
0352 if (err)
0353 return err;
0354
0355 err = clear_update_marker(ubi, vol, vol->upd_bytes);
0356 if (err)
0357 return err;
0358 vol->updating = 0;
0359 err = to_write;
0360 vfree(vol->upd_buf);
0361 }
0362
0363 return err;
0364 }
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380 int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
0381 const void __user *buf, int count)
0382 {
0383 int err;
0384
0385 dbg_gen("write %d of %lld bytes, %lld already passed",
0386 count, vol->upd_bytes, vol->upd_received);
0387
0388 if (ubi->ro_mode)
0389 return -EROFS;
0390
0391 if (vol->upd_received + count > vol->upd_bytes)
0392 count = vol->upd_bytes - vol->upd_received;
0393
0394 err = copy_from_user(vol->upd_buf + vol->upd_received, buf, count);
0395 if (err)
0396 return -EFAULT;
0397
0398 vol->upd_received += count;
0399
0400 if (vol->upd_received == vol->upd_bytes) {
0401 int len = ALIGN((int)vol->upd_bytes, ubi->min_io_size);
0402
0403 memset(vol->upd_buf + vol->upd_bytes, 0xFF,
0404 len - vol->upd_bytes);
0405 len = ubi_calc_data_len(ubi, vol->upd_buf, len);
0406 err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum,
0407 vol->upd_buf, len);
0408 if (err)
0409 return err;
0410 }
0411
0412 ubi_assert(vol->upd_received <= vol->upd_bytes);
0413 if (vol->upd_received == vol->upd_bytes) {
0414 vol->changing_leb = 0;
0415 err = count;
0416 vfree(vol->upd_buf);
0417 }
0418
0419 return err;
0420 }