| 1 | |
| 2 | |
| 3 | * This file is part of UBIFS.
|
| 4 | *
|
| 5 | * Copyright (C) 2006-2008 Nokia Corporation.
|
| 6 | *
|
| 7 | * Authors: Artem Bityutskiy (Битюцкий Артём)
|
| 8 | * Adrian Hunter
|
| 9 |
|
| 10 |
|
| 11 | |
| 12 | * This file implements UBIFS superblock. The superblock is stored at the first
|
| 13 | * LEB of the volume and is never changed by UBIFS. Only user-space tools may
|
| 14 | * change it. The superblock node mostly contains geometry information.
|
| 15 |
|
| 16 |
|
| 17 | #include "ubifs.h"
|
| 18 | #include <linux/slab.h>
|
| 19 | #include <linux/math64.h>
|
| 20 | #include <linux/uuid.h>
|
| 21 |
|
| 22 | |
| 23 | * Default journal size in logical eraseblocks as a percent of total
|
| 24 | * flash size.
|
| 25 |
|
| 26 | #define DEFAULT_JNL_PERCENT 5
|
| 27 |
|
| 28 |
|
| 29 | #define DEFAULT_MAX_JNL (32*1024*1024)
|
| 30 |
|
| 31 |
|
| 32 | #define DEFAULT_FANOUT 8
|
| 33 |
|
| 34 |
|
| 35 | #define DEFAULT_JHEADS_CNT 1
|
| 36 |
|
| 37 |
|
| 38 | #define DEFAULT_IDX_LEB 0
|
| 39 | #define DEFAULT_DATA_LEB 1
|
| 40 | #define DEFAULT_GC_LEB 2
|
| 41 |
|
| 42 |
|
| 43 | #define DEFAULT_LSAVE_CNT 256
|
| 44 |
|
| 45 |
|
| 46 | #define DEFAULT_RP_PERCENT 5
|
| 47 |
|
| 48 |
|
| 49 | #define DEFAULT_MAX_RP_SIZE (5*1024*1024)
|
| 50 |
|
| 51 |
|
| 52 | #define DEFAULT_TIME_GRAN 1000000000
|
| 53 |
|
| 54 | static int get_default_compressor(struct ubifs_info *c)
|
| 55 | {
|
| 56 | if (ubifs_compr_present(c, UBIFS_COMPR_ZSTD))
|
| 57 | return UBIFS_COMPR_ZSTD;
|
| 58 |
|
| 59 | if (ubifs_compr_present(c, UBIFS_COMPR_LZO))
|
| 60 | return UBIFS_COMPR_LZO;
|
| 61 |
|
| 62 | if (ubifs_compr_present(c, UBIFS_COMPR_ZLIB))
|
| 63 | return UBIFS_COMPR_ZLIB;
|
| 64 |
|
| 65 | return UBIFS_COMPR_NONE;
|
| 66 | }
|
| 67 |
|
| 68 | |
| 69 | * create_default_filesystem - format empty UBI volume.
|
| 70 | * @c: UBIFS file-system description object
|
| 71 | *
|
| 72 | * This function creates default empty file-system. Returns zero in case of
|
| 73 | * success and a negative error code in case of failure.
|
| 74 |
|
| 75 | static int create_default_filesystem(struct ubifs_info *c)
|
| 76 | {
|
| 77 | struct ubifs_sb_node *sup;
|
| 78 | struct ubifs_mst_node *mst;
|
| 79 | struct ubifs_idx_node *idx;
|
| 80 | struct ubifs_branch *br;
|
| 81 | struct ubifs_ino_node *ino;
|
| 82 | struct ubifs_cs_node *cs;
|
| 83 | union ubifs_key key;
|
| 84 | int err, tmp, jnl_lebs, log_lebs, max_buds, main_lebs, main_first;
|
| 85 | int lpt_lebs, lpt_first, orph_lebs, big_lpt, ino_waste, sup_flags = 0;
|
| 86 | int min_leb_cnt = UBIFS_MIN_LEB_CNT;
|
| 87 | int idx_node_size;
|
| 88 | long long tmp64, main_bytes;
|
| 89 | __le64 tmp_le64;
|
| 90 | struct timespec64 ts;
|
| 91 | u8 hash[UBIFS_HASH_ARR_SZ];
|
| 92 | u8 hash_lpt[UBIFS_HASH_ARR_SZ];
|
| 93 |
|
| 94 |
|
| 95 | c->key_len = UBIFS_SK_LEN;
|
| 96 |
|
| 97 | |
| 98 | * First of all, we have to calculate default file-system geometry -
|
| 99 | * log size, journal size, etc.
|
| 100 |
|
| 101 | if (c->leb_cnt < 0x7FFFFFFF / DEFAULT_JNL_PERCENT)
|
| 102 |
|
| 103 | jnl_lebs = c->leb_cnt * DEFAULT_JNL_PERCENT / 100;
|
| 104 | else
|
| 105 | jnl_lebs = (c->leb_cnt / 100) * DEFAULT_JNL_PERCENT;
|
| 106 |
|
| 107 | if (jnl_lebs < UBIFS_MIN_JNL_LEBS)
|
| 108 | jnl_lebs = UBIFS_MIN_JNL_LEBS;
|
| 109 | if (jnl_lebs * c->leb_size > DEFAULT_MAX_JNL)
|
| 110 | jnl_lebs = DEFAULT_MAX_JNL / c->leb_size;
|
| 111 |
|
| 112 | |
| 113 | * The log should be large enough to fit reference nodes for all bud
|
| 114 | * LEBs. Because buds do not have to start from the beginning of LEBs
|
| 115 | * (half of the LEB may contain committed data), the log should
|
| 116 | * generally be larger, make it twice as large.
|
| 117 |
|
| 118 | tmp = 2 * (c->ref_node_alsz * jnl_lebs) + c->leb_size - 1;
|
| 119 | log_lebs = tmp / c->leb_size;
|
| 120 |
|
| 121 | log_lebs += 1;
|
| 122 | if (c->leb_cnt - min_leb_cnt > 8) {
|
| 123 |
|
| 124 | log_lebs += 1;
|
| 125 | min_leb_cnt += 1;
|
| 126 | }
|
| 127 |
|
| 128 | max_buds = jnl_lebs - log_lebs;
|
| 129 | if (max_buds < UBIFS_MIN_BUD_LEBS)
|
| 130 | max_buds = UBIFS_MIN_BUD_LEBS;
|
| 131 |
|
| 132 | |
| 133 | * Orphan nodes are stored in a separate area. One node can store a lot
|
| 134 | * of orphan inode numbers, but when new orphan comes we just add a new
|
| 135 | * orphan node. At some point the nodes are consolidated into one
|
| 136 | * orphan node.
|
| 137 |
|
| 138 | orph_lebs = UBIFS_MIN_ORPH_LEBS;
|
| 139 | if (c->leb_cnt - min_leb_cnt > 1)
|
| 140 | |
| 141 | * For debugging purposes it is better to have at least 2
|
| 142 | * orphan LEBs, because the orphan subsystem would need to do
|
| 143 | * consolidations and would be stressed more.
|
| 144 |
|
| 145 | orph_lebs += 1;
|
| 146 |
|
| 147 | main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS - log_lebs;
|
| 148 | main_lebs -= orph_lebs;
|
| 149 |
|
| 150 | lpt_first = UBIFS_LOG_LNUM + log_lebs;
|
| 151 | c->lsave_cnt = DEFAULT_LSAVE_CNT;
|
| 152 | c->max_leb_cnt = c->leb_cnt;
|
| 153 | err = ubifs_create_dflt_lpt(c, &main_lebs, lpt_first, &lpt_lebs,
|
| 154 | &big_lpt, hash_lpt);
|
| 155 | if (err)
|
| 156 | return err;
|
| 157 |
|
| 158 | dbg_gen("LEB Properties Tree created (LEBs %d-%d)", lpt_first,
|
| 159 | lpt_first + lpt_lebs - 1);
|
| 160 |
|
| 161 | main_first = c->leb_cnt - main_lebs;
|
| 162 |
|
| 163 | sup = kzalloc(ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size), GFP_KERNEL);
|
| 164 | mst = kzalloc(c->mst_node_alsz, GFP_KERNEL);
|
| 165 | idx_node_size = ubifs_idx_node_sz(c, 1);
|
| 166 | idx = kzalloc(ALIGN(idx_node_size, c->min_io_size), GFP_KERNEL);
|
| 167 | ino = kzalloc(ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size), GFP_KERNEL);
|
| 168 | cs = kzalloc(ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size), GFP_KERNEL);
|
| 169 |
|
| 170 | if (!sup || !mst || !idx || !ino || !cs) {
|
| 171 | err = -ENOMEM;
|
| 172 | goto out;
|
| 173 | }
|
| 174 |
|
| 175 |
|
| 176 |
|
| 177 | tmp64 = (long long)max_buds * c->leb_size;
|
| 178 | if (big_lpt)
|
| 179 | sup_flags |= UBIFS_FLG_BIGLPT;
|
| 180 | if (ubifs_default_version > 4)
|
| 181 | sup_flags |= UBIFS_FLG_DOUBLE_HASH;
|
| 182 |
|
| 183 | if (ubifs_authenticated(c)) {
|
| 184 | sup_flags |= UBIFS_FLG_AUTHENTICATION;
|
| 185 | sup->hash_algo = cpu_to_le16(c->auth_hash_algo);
|
| 186 | err = ubifs_hmac_wkm(c, sup->hmac_wkm);
|
| 187 | if (err)
|
| 188 | goto out;
|
| 189 | } else {
|
| 190 | sup->hash_algo = cpu_to_le16(0xffff);
|
| 191 | }
|
| 192 |
|
| 193 | sup->ch.node_type = UBIFS_SB_NODE;
|
| 194 | sup->key_hash = UBIFS_KEY_HASH_R5;
|
| 195 | sup->flags = cpu_to_le32(sup_flags);
|
| 196 | sup->min_io_size = cpu_to_le32(c->min_io_size);
|
| 197 | sup->leb_size = cpu_to_le32(c->leb_size);
|
| 198 | sup->leb_cnt = cpu_to_le32(c->leb_cnt);
|
| 199 | sup->max_leb_cnt = cpu_to_le32(c->max_leb_cnt);
|
| 200 | sup->max_bud_bytes = cpu_to_le64(tmp64);
|
| 201 | sup->log_lebs = cpu_to_le32(log_lebs);
|
| 202 | sup->lpt_lebs = cpu_to_le32(lpt_lebs);
|
| 203 | sup->orph_lebs = cpu_to_le32(orph_lebs);
|
| 204 | sup->jhead_cnt = cpu_to_le32(DEFAULT_JHEADS_CNT);
|
| 205 | sup->fanout = cpu_to_le32(DEFAULT_FANOUT);
|
| 206 | sup->lsave_cnt = cpu_to_le32(c->lsave_cnt);
|
| 207 | sup->fmt_version = cpu_to_le32(ubifs_default_version);
|
| 208 | sup->time_gran = cpu_to_le32(DEFAULT_TIME_GRAN);
|
| 209 | if (c->mount_opts.override_compr)
|
| 210 | sup->default_compr = cpu_to_le16(c->mount_opts.compr_type);
|
| 211 | else
|
| 212 | sup->default_compr = cpu_to_le16(get_default_compressor(c));
|
| 213 |
|
| 214 | generate_random_uuid(sup->uuid);
|
| 215 |
|
| 216 | main_bytes = (long long)main_lebs * c->leb_size;
|
| 217 | tmp64 = div_u64(main_bytes * DEFAULT_RP_PERCENT, 100);
|
| 218 | if (tmp64 > DEFAULT_MAX_RP_SIZE)
|
| 219 | tmp64 = DEFAULT_MAX_RP_SIZE;
|
| 220 | sup->rp_size = cpu_to_le64(tmp64);
|
| 221 | sup->ro_compat_version = cpu_to_le32(UBIFS_RO_COMPAT_VERSION);
|
| 222 |
|
| 223 | dbg_gen("default superblock created at LEB 0:0");
|
| 224 |
|
| 225 |
|
| 226 |
|
| 227 | mst->ch.node_type = UBIFS_MST_NODE;
|
| 228 | mst->log_lnum = cpu_to_le32(UBIFS_LOG_LNUM);
|
| 229 | mst->highest_inum = cpu_to_le64(UBIFS_FIRST_INO);
|
| 230 | mst->cmt_no = 0;
|
| 231 | mst->root_lnum = cpu_to_le32(main_first + DEFAULT_IDX_LEB);
|
| 232 | mst->root_offs = 0;
|
| 233 | tmp = ubifs_idx_node_sz(c, 1);
|
| 234 | mst->root_len = cpu_to_le32(tmp);
|
| 235 | mst->gc_lnum = cpu_to_le32(main_first + DEFAULT_GC_LEB);
|
| 236 | mst->ihead_lnum = cpu_to_le32(main_first + DEFAULT_IDX_LEB);
|
| 237 | mst->ihead_offs = cpu_to_le32(ALIGN(tmp, c->min_io_size));
|
| 238 | mst->index_size = cpu_to_le64(ALIGN(tmp, 8));
|
| 239 | mst->lpt_lnum = cpu_to_le32(c->lpt_lnum);
|
| 240 | mst->lpt_offs = cpu_to_le32(c->lpt_offs);
|
| 241 | mst->nhead_lnum = cpu_to_le32(c->nhead_lnum);
|
| 242 | mst->nhead_offs = cpu_to_le32(c->nhead_offs);
|
| 243 | mst->ltab_lnum = cpu_to_le32(c->ltab_lnum);
|
| 244 | mst->ltab_offs = cpu_to_le32(c->ltab_offs);
|
| 245 | mst->lsave_lnum = cpu_to_le32(c->lsave_lnum);
|
| 246 | mst->lsave_offs = cpu_to_le32(c->lsave_offs);
|
| 247 | mst->lscan_lnum = cpu_to_le32(main_first);
|
| 248 | mst->empty_lebs = cpu_to_le32(main_lebs - 2);
|
| 249 | mst->idx_lebs = cpu_to_le32(1);
|
| 250 | mst->leb_cnt = cpu_to_le32(c->leb_cnt);
|
| 251 | ubifs_copy_hash(c, hash_lpt, mst->hash_lpt);
|
| 252 |
|
| 253 |
|
| 254 | tmp64 = main_bytes;
|
| 255 | tmp64 -= ALIGN(ubifs_idx_node_sz(c, 1), c->min_io_size);
|
| 256 | tmp64 -= ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size);
|
| 257 | mst->total_free = cpu_to_le64(tmp64);
|
| 258 |
|
| 259 | tmp64 = ALIGN(ubifs_idx_node_sz(c, 1), c->min_io_size);
|
| 260 | ino_waste = ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size) -
|
| 261 | UBIFS_INO_NODE_SZ;
|
| 262 | tmp64 += ino_waste;
|
| 263 | tmp64 -= ALIGN(ubifs_idx_node_sz(c, 1), 8);
|
| 264 | mst->total_dirty = cpu_to_le64(tmp64);
|
| 265 |
|
| 266 |
|
| 267 | tmp64 = ((long long)(c->main_lebs - 1) * c->dark_wm);
|
| 268 | mst->total_dark = cpu_to_le64(tmp64);
|
| 269 |
|
| 270 | mst->total_used = cpu_to_le64(UBIFS_INO_NODE_SZ);
|
| 271 |
|
| 272 | dbg_gen("default master node created at LEB %d:0", UBIFS_MST_LNUM);
|
| 273 |
|
| 274 |
|
| 275 |
|
| 276 | c->key_fmt = UBIFS_SIMPLE_KEY_FMT;
|
| 277 | c->key_hash = key_r5_hash;
|
| 278 |
|
| 279 | idx->ch.node_type = UBIFS_IDX_NODE;
|
| 280 | idx->child_cnt = cpu_to_le16(1);
|
| 281 | ino_key_init(c, &key, UBIFS_ROOT_INO);
|
| 282 | br = ubifs_idx_branch(c, idx, 0);
|
| 283 | key_write_idx(c, &key, &br->key);
|
| 284 | br->lnum = cpu_to_le32(main_first + DEFAULT_DATA_LEB);
|
| 285 | br->len = cpu_to_le32(UBIFS_INO_NODE_SZ);
|
| 286 |
|
| 287 | dbg_gen("default root indexing node created LEB %d:0",
|
| 288 | main_first + DEFAULT_IDX_LEB);
|
| 289 |
|
| 290 |
|
| 291 |
|
| 292 | ino_key_init_flash(c, &ino->key, UBIFS_ROOT_INO);
|
| 293 | ino->ch.node_type = UBIFS_INO_NODE;
|
| 294 | ino->creat_sqnum = cpu_to_le64(++c->max_sqnum);
|
| 295 | ino->nlink = cpu_to_le32(2);
|
| 296 |
|
| 297 | ktime_get_coarse_real_ts64(&ts);
|
| 298 | tmp_le64 = cpu_to_le64(ts.tv_sec);
|
| 299 | ino->atime_sec = tmp_le64;
|
| 300 | ino->ctime_sec = tmp_le64;
|
| 301 | ino->mtime_sec = tmp_le64;
|
| 302 | ino->atime_nsec = 0;
|
| 303 | ino->ctime_nsec = 0;
|
| 304 | ino->mtime_nsec = 0;
|
| 305 | ino->mode = cpu_to_le32(S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO);
|
| 306 | ino->size = cpu_to_le64(UBIFS_INO_NODE_SZ);
|
| 307 |
|
| 308 |
|
| 309 | ino->flags = cpu_to_le32(UBIFS_COMPR_FL);
|
| 310 |
|
| 311 | dbg_gen("root inode created at LEB %d:0",
|
| 312 | main_first + DEFAULT_DATA_LEB);
|
| 313 |
|
| 314 | |
| 315 | * The first node in the log has to be the commit start node. This is
|
| 316 | * always the case during normal file-system operation. Write a fake
|
| 317 | * commit start node to the log.
|
| 318 |
|
| 319 |
|
| 320 | cs->ch.node_type = UBIFS_CS_NODE;
|
| 321 |
|
| 322 | err = ubifs_write_node_hmac(c, sup, UBIFS_SB_NODE_SZ, 0, 0,
|
| 323 | offsetof(struct ubifs_sb_node, hmac));
|
| 324 | if (err)
|
| 325 | goto out;
|
| 326 |
|
| 327 | err = ubifs_write_node(c, ino, UBIFS_INO_NODE_SZ,
|
| 328 | main_first + DEFAULT_DATA_LEB, 0);
|
| 329 | if (err)
|
| 330 | goto out;
|
| 331 |
|
| 332 | ubifs_node_calc_hash(c, ino, hash);
|
| 333 | ubifs_copy_hash(c, hash, ubifs_branch_hash(c, br));
|
| 334 |
|
| 335 | err = ubifs_write_node(c, idx, idx_node_size, main_first + DEFAULT_IDX_LEB, 0);
|
| 336 | if (err)
|
| 337 | goto out;
|
| 338 |
|
| 339 | ubifs_node_calc_hash(c, idx, hash);
|
| 340 | ubifs_copy_hash(c, hash, mst->hash_root_idx);
|
| 341 |
|
| 342 | err = ubifs_write_node_hmac(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM, 0,
|
| 343 | offsetof(struct ubifs_mst_node, hmac));
|
| 344 | if (err)
|
| 345 | goto out;
|
| 346 |
|
| 347 | err = ubifs_write_node_hmac(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1,
|
| 348 | 0, offsetof(struct ubifs_mst_node, hmac));
|
| 349 | if (err)
|
| 350 | goto out;
|
| 351 |
|
| 352 | err = ubifs_write_node(c, cs, UBIFS_CS_NODE_SZ, UBIFS_LOG_LNUM, 0);
|
| 353 | if (err)
|
| 354 | goto out;
|
| 355 |
|
| 356 | ubifs_msg(c, "default file-system created");
|
| 357 |
|
| 358 | err = 0;
|
| 359 | out:
|
| 360 | kfree(sup);
|
| 361 | kfree(mst);
|
| 362 | kfree(idx);
|
| 363 | kfree(ino);
|
| 364 | kfree(cs);
|
| 365 |
|
| 366 | return err;
|
| 367 | }
|
| 368 |
|
| 369 | |
| 370 | * validate_sb - validate superblock node.
|
| 371 | * @c: UBIFS file-system description object
|
| 372 | * @sup: superblock node
|
| 373 | *
|
| 374 | * This function validates superblock node @sup. Since most of data was read
|
| 375 | * from the superblock and stored in @c, the function validates fields in @c
|
| 376 | * instead. Returns zero in case of success and %-EINVAL in case of validation
|
| 377 | * failure.
|
| 378 |
|
| 379 | static int validate_sb(struct ubifs_info *c, struct ubifs_sb_node *sup)
|
| 380 | {
|
| 381 | long long max_bytes;
|
| 382 | int err = 1, min_leb_cnt;
|
| 383 |
|
| 384 | if (!c->key_hash) {
|
| 385 | err = 2;
|
| 386 | goto failed;
|
| 387 | }
|
| 388 |
|
| 389 | if (sup->key_fmt != UBIFS_SIMPLE_KEY_FMT) {
|
| 390 | err = 3;
|
| 391 | goto failed;
|
| 392 | }
|
| 393 |
|
| 394 | if (le32_to_cpu(sup->min_io_size) != c->min_io_size) {
|
| 395 | ubifs_err(c, "min. I/O unit mismatch: %d in superblock, %d real",
|
| 396 | le32_to_cpu(sup->min_io_size), c->min_io_size);
|
| 397 | goto failed;
|
| 398 | }
|
| 399 |
|
| 400 | if (le32_to_cpu(sup->leb_size) != c->leb_size) {
|
| 401 | ubifs_err(c, "LEB size mismatch: %d in superblock, %d real",
|
| 402 | le32_to_cpu(sup->leb_size), c->leb_size);
|
| 403 | goto failed;
|
| 404 | }
|
| 405 |
|
| 406 | if (c->log_lebs < UBIFS_MIN_LOG_LEBS ||
|
| 407 | c->lpt_lebs < UBIFS_MIN_LPT_LEBS ||
|
| 408 | c->orph_lebs < UBIFS_MIN_ORPH_LEBS ||
|
| 409 | c->main_lebs < UBIFS_MIN_MAIN_LEBS) {
|
| 410 | err = 4;
|
| 411 | goto failed;
|
| 412 | }
|
| 413 |
|
| 414 | |
| 415 | * Calculate minimum allowed amount of main area LEBs. This is very
|
| 416 | * similar to %UBIFS_MIN_LEB_CNT, but we take into account real what we
|
| 417 | * have just read from the superblock.
|
| 418 |
|
| 419 | min_leb_cnt = UBIFS_SB_LEBS + UBIFS_MST_LEBS + c->log_lebs;
|
| 420 | min_leb_cnt += c->lpt_lebs + c->orph_lebs + c->jhead_cnt + 6;
|
| 421 |
|
| 422 | if (c->leb_cnt < min_leb_cnt || c->leb_cnt > c->vi.size) {
|
| 423 | ubifs_err(c, "bad LEB count: %d in superblock, %d on UBI volume, %d minimum required",
|
| 424 | c->leb_cnt, c->vi.size, min_leb_cnt);
|
| 425 | goto failed;
|
| 426 | }
|
| 427 |
|
| 428 | if (c->max_leb_cnt < c->leb_cnt) {
|
| 429 | ubifs_err(c, "max. LEB count %d less than LEB count %d",
|
| 430 | c->max_leb_cnt, c->leb_cnt);
|
| 431 | goto failed;
|
| 432 | }
|
| 433 |
|
| 434 | if (c->main_lebs < UBIFS_MIN_MAIN_LEBS) {
|
| 435 | ubifs_err(c, "too few main LEBs count %d, must be at least %d",
|
| 436 | c->main_lebs, UBIFS_MIN_MAIN_LEBS);
|
| 437 | goto failed;
|
| 438 | }
|
| 439 |
|
| 440 | max_bytes = (long long)c->leb_size * UBIFS_MIN_BUD_LEBS;
|
| 441 | if (c->max_bud_bytes < max_bytes) {
|
| 442 | ubifs_err(c, "too small journal (%lld bytes), must be at least %lld bytes",
|
| 443 | c->max_bud_bytes, max_bytes);
|
| 444 | goto failed;
|
| 445 | }
|
| 446 |
|
| 447 | max_bytes = (long long)c->leb_size * c->main_lebs;
|
| 448 | if (c->max_bud_bytes > max_bytes) {
|
| 449 | ubifs_err(c, "too large journal size (%lld bytes), only %lld bytes available in the main area",
|
| 450 | c->max_bud_bytes, max_bytes);
|
| 451 | goto failed;
|
| 452 | }
|
| 453 |
|
| 454 | if (c->jhead_cnt < NONDATA_JHEADS_CNT + 1 ||
|
| 455 | c->jhead_cnt > NONDATA_JHEADS_CNT + UBIFS_MAX_JHEADS) {
|
| 456 | err = 9;
|
| 457 | goto failed;
|
| 458 | }
|
| 459 |
|
| 460 | if (c->fanout < UBIFS_MIN_FANOUT ||
|
| 461 | ubifs_idx_node_sz(c, c->fanout) > c->leb_size) {
|
| 462 | err = 10;
|
| 463 | goto failed;
|
| 464 | }
|
| 465 |
|
| 466 | if (c->lsave_cnt < 0 || (c->lsave_cnt > DEFAULT_LSAVE_CNT &&
|
| 467 | c->lsave_cnt > c->max_leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS -
|
| 468 | c->log_lebs - c->lpt_lebs - c->orph_lebs)) {
|
| 469 | err = 11;
|
| 470 | goto failed;
|
| 471 | }
|
| 472 |
|
| 473 | if (UBIFS_SB_LEBS + UBIFS_MST_LEBS + c->log_lebs + c->lpt_lebs +
|
| 474 | c->orph_lebs + c->main_lebs != c->leb_cnt) {
|
| 475 | err = 12;
|
| 476 | goto failed;
|
| 477 | }
|
| 478 |
|
| 479 | if (c->default_compr >= UBIFS_COMPR_TYPES_CNT) {
|
| 480 | err = 13;
|
| 481 | goto failed;
|
| 482 | }
|
| 483 |
|
| 484 | if (c->rp_size < 0 || max_bytes < c->rp_size) {
|
| 485 | err = 14;
|
| 486 | goto failed;
|
| 487 | }
|
| 488 |
|
| 489 | if (le32_to_cpu(sup->time_gran) > 1000000000 ||
|
| 490 | le32_to_cpu(sup->time_gran) < 1) {
|
| 491 | err = 15;
|
| 492 | goto failed;
|
| 493 | }
|
| 494 |
|
| 495 | if (!c->double_hash && c->fmt_version >= 5) {
|
| 496 | err = 16;
|
| 497 | goto failed;
|
| 498 | }
|
| 499 |
|
| 500 | if (c->encrypted && c->fmt_version < 5) {
|
| 501 | err = 17;
|
| 502 | goto failed;
|
| 503 | }
|
| 504 |
|
| 505 | return 0;
|
| 506 |
|
| 507 | failed:
|
| 508 | ubifs_err(c, "bad superblock, error %d", err);
|
| 509 | ubifs_dump_node(c, sup, ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size));
|
| 510 | return -EINVAL;
|
| 511 | }
|
| 512 |
|
| 513 | |
| 514 | * ubifs_read_sb_node - read superblock node.
|
| 515 | * @c: UBIFS file-system description object
|
| 516 | *
|
| 517 | * This function returns a pointer to the superblock node or a negative error
|
| 518 | * code. Note, the user of this function is responsible of kfree()'ing the
|
| 519 | * returned superblock buffer.
|
| 520 |
|
| 521 | static struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c)
|
| 522 | {
|
| 523 | struct ubifs_sb_node *sup;
|
| 524 | int err;
|
| 525 |
|
| 526 | sup = kmalloc(ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size), GFP_NOFS);
|
| 527 | if (!sup)
|
| 528 | return ERR_PTR(-ENOMEM);
|
| 529 |
|
| 530 | err = ubifs_read_node(c, sup, UBIFS_SB_NODE, UBIFS_SB_NODE_SZ,
|
| 531 | UBIFS_SB_LNUM, 0);
|
| 532 | if (err) {
|
| 533 | kfree(sup);
|
| 534 | return ERR_PTR(err);
|
| 535 | }
|
| 536 |
|
| 537 | return sup;
|
| 538 | }
|
| 539 |
|
| 540 | static int authenticate_sb_node(struct ubifs_info *c,
|
| 541 | const struct ubifs_sb_node *sup)
|
| 542 | {
|
| 543 | unsigned int sup_flags = le32_to_cpu(sup->flags);
|
| 544 | u8 hmac_wkm[UBIFS_HMAC_ARR_SZ];
|
| 545 | int authenticated = !!(sup_flags & UBIFS_FLG_AUTHENTICATION);
|
| 546 | int hash_algo;
|
| 547 | int err;
|
| 548 |
|
| 549 | if (c->authenticated && !authenticated) {
|
| 550 | ubifs_err(c, "authenticated FS forced, but found FS without authentication");
|
| 551 | return -EINVAL;
|
| 552 | }
|
| 553 |
|
| 554 | if (!c->authenticated && authenticated) {
|
| 555 | ubifs_err(c, "authenticated FS found, but no key given");
|
| 556 | return -EINVAL;
|
| 557 | }
|
| 558 |
|
| 559 | ubifs_msg(c, "Mounting in %sauthenticated mode",
|
| 560 | c->authenticated ? "" : "un");
|
| 561 |
|
| 562 | if (!c->authenticated)
|
| 563 | return 0;
|
| 564 |
|
| 565 | if (!IS_ENABLED(CONFIG_UBIFS_FS_AUTHENTICATION))
|
| 566 | return -EOPNOTSUPP;
|
| 567 |
|
| 568 | hash_algo = le16_to_cpu(sup->hash_algo);
|
| 569 | if (hash_algo >= HASH_ALGO__LAST) {
|
| 570 | ubifs_err(c, "superblock uses unknown hash algo %d",
|
| 571 | hash_algo);
|
| 572 | return -EINVAL;
|
| 573 | }
|
| 574 |
|
| 575 | if (strcmp(hash_algo_name[hash_algo], c->auth_hash_name)) {
|
| 576 | ubifs_err(c, "This filesystem uses %s for hashing,"
|
| 577 | " but %s is specified", hash_algo_name[hash_algo],
|
| 578 | c->auth_hash_name);
|
| 579 | return -EINVAL;
|
| 580 | }
|
| 581 |
|
| 582 | |
| 583 | * The super block node can either be authenticated by a HMAC or
|
| 584 | * by a signature in a ubifs_sig_node directly following the
|
| 585 | * super block node to support offline image creation.
|
| 586 |
|
| 587 | if (ubifs_hmac_zero(c, sup->hmac)) {
|
| 588 | err = ubifs_sb_verify_signature(c, sup);
|
| 589 | } else {
|
| 590 | err = ubifs_hmac_wkm(c, hmac_wkm);
|
| 591 | if (err)
|
| 592 | return err;
|
| 593 | if (ubifs_check_hmac(c, hmac_wkm, sup->hmac_wkm)) {
|
| 594 | ubifs_err(c, "provided key does not fit");
|
| 595 | return -ENOKEY;
|
| 596 | }
|
| 597 | err = ubifs_node_verify_hmac(c, sup, sizeof(*sup),
|
| 598 | offsetof(struct ubifs_sb_node,
|
| 599 | hmac));
|
| 600 | }
|
| 601 |
|
| 602 | if (err)
|
| 603 | ubifs_err(c, "Failed to authenticate superblock: %d", err);
|
| 604 |
|
| 605 | return err;
|
| 606 | }
|
| 607 |
|
| 608 | |
| 609 | * ubifs_write_sb_node - write superblock node.
|
| 610 | * @c: UBIFS file-system description object
|
| 611 | * @sup: superblock node read with 'ubifs_read_sb_node()'
|
| 612 | *
|
| 613 | * This function returns %0 on success and a negative error code on failure.
|
| 614 |
|
| 615 | int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup)
|
| 616 | {
|
| 617 | int len = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size);
|
| 618 | int err;
|
| 619 |
|
| 620 | err = ubifs_prepare_node_hmac(c, sup, UBIFS_SB_NODE_SZ,
|
| 621 | offsetof(struct ubifs_sb_node, hmac), 1);
|
| 622 | if (err)
|
| 623 | return err;
|
| 624 |
|
| 625 | return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len);
|
| 626 | }
|
| 627 |
|
| 628 | |
| 629 | * ubifs_read_superblock - read superblock.
|
| 630 | * @c: UBIFS file-system description object
|
| 631 | *
|
| 632 | * This function finds, reads and checks the superblock. If an empty UBI volume
|
| 633 | * is being mounted, this function creates default superblock. Returns zero in
|
| 634 | * case of success, and a negative error code in case of failure.
|
| 635 |
|
| 636 | int ubifs_read_superblock(struct ubifs_info *c)
|
| 637 | {
|
| 638 | int err, sup_flags;
|
| 639 | struct ubifs_sb_node *sup;
|
| 640 |
|
| 641 | if (c->empty) {
|
| 642 | err = create_default_filesystem(c);
|
| 643 | if (err)
|
| 644 | return err;
|
| 645 | }
|
| 646 |
|
| 647 | sup = ubifs_read_sb_node(c);
|
| 648 | if (IS_ERR(sup))
|
| 649 | return PTR_ERR(sup);
|
| 650 |
|
| 651 | c->sup_node = sup;
|
| 652 |
|
| 653 | c->fmt_version = le32_to_cpu(sup->fmt_version);
|
| 654 | c->ro_compat_version = le32_to_cpu(sup->ro_compat_version);
|
| 655 |
|
| 656 | |
| 657 | * The software supports all previous versions but not future versions,
|
| 658 | * due to the unavailability of time-travelling equipment.
|
| 659 |
|
| 660 | if (c->fmt_version > UBIFS_FORMAT_VERSION) {
|
| 661 | ubifs_assert(c, !c->ro_media || c->ro_mount);
|
| 662 | if (!c->ro_mount ||
|
| 663 | c->ro_compat_version > UBIFS_RO_COMPAT_VERSION) {
|
| 664 | ubifs_err(c, "on-flash format version is w%d/r%d, but software only supports up to version w%d/r%d",
|
| 665 | c->fmt_version, c->ro_compat_version,
|
| 666 | UBIFS_FORMAT_VERSION,
|
| 667 | UBIFS_RO_COMPAT_VERSION);
|
| 668 | if (c->ro_compat_version <= UBIFS_RO_COMPAT_VERSION) {
|
| 669 | ubifs_msg(c, "only R/O mounting is possible");
|
| 670 | err = -EROFS;
|
| 671 | } else
|
| 672 | err = -EINVAL;
|
| 673 | goto out;
|
| 674 | }
|
| 675 |
|
| 676 | |
| 677 | * The FS is mounted R/O, and the media format is
|
| 678 | * R/O-compatible with the UBIFS implementation, so we can
|
| 679 | * mount.
|
| 680 |
|
| 681 | c->rw_incompat = 1;
|
| 682 | }
|
| 683 |
|
| 684 | if (c->fmt_version < 3) {
|
| 685 | ubifs_err(c, "on-flash format version %d is not supported",
|
| 686 | c->fmt_version);
|
| 687 | err = -EINVAL;
|
| 688 | goto out;
|
| 689 | }
|
| 690 |
|
| 691 | switch (sup->key_hash) {
|
| 692 | case UBIFS_KEY_HASH_R5:
|
| 693 | c->key_hash = key_r5_hash;
|
| 694 | c->key_hash_type = UBIFS_KEY_HASH_R5;
|
| 695 | break;
|
| 696 |
|
| 697 | case UBIFS_KEY_HASH_TEST:
|
| 698 | c->key_hash = key_test_hash;
|
| 699 | c->key_hash_type = UBIFS_KEY_HASH_TEST;
|
| 700 | break;
|
| 701 | }
|
| 702 |
|
| 703 | c->key_fmt = sup->key_fmt;
|
| 704 |
|
| 705 | switch (c->key_fmt) {
|
| 706 | case UBIFS_SIMPLE_KEY_FMT:
|
| 707 | c->key_len = UBIFS_SK_LEN;
|
| 708 | break;
|
| 709 | default:
|
| 710 | ubifs_err(c, "unsupported key format");
|
| 711 | err = -EINVAL;
|
| 712 | goto out;
|
| 713 | }
|
| 714 |
|
| 715 | c->leb_cnt = le32_to_cpu(sup->leb_cnt);
|
| 716 | c->max_leb_cnt = le32_to_cpu(sup->max_leb_cnt);
|
| 717 | c->max_bud_bytes = le64_to_cpu(sup->max_bud_bytes);
|
| 718 | c->log_lebs = le32_to_cpu(sup->log_lebs);
|
| 719 | c->lpt_lebs = le32_to_cpu(sup->lpt_lebs);
|
| 720 | c->orph_lebs = le32_to_cpu(sup->orph_lebs);
|
| 721 | c->jhead_cnt = le32_to_cpu(sup->jhead_cnt) + NONDATA_JHEADS_CNT;
|
| 722 | c->fanout = le32_to_cpu(sup->fanout);
|
| 723 | c->lsave_cnt = le32_to_cpu(sup->lsave_cnt);
|
| 724 | c->rp_size = le64_to_cpu(sup->rp_size);
|
| 725 | c->rp_uid = make_kuid(&init_user_ns, le32_to_cpu(sup->rp_uid));
|
| 726 | c->rp_gid = make_kgid(&init_user_ns, le32_to_cpu(sup->rp_gid));
|
| 727 | sup_flags = le32_to_cpu(sup->flags);
|
| 728 | if (!c->mount_opts.override_compr)
|
| 729 | c->default_compr = le16_to_cpu(sup->default_compr);
|
| 730 |
|
| 731 | c->vfs_sb->s_time_gran = le32_to_cpu(sup->time_gran);
|
| 732 | memcpy(&c->uuid, &sup->uuid, 16);
|
| 733 | c->big_lpt = !!(sup_flags & UBIFS_FLG_BIGLPT);
|
| 734 | c->space_fixup = !!(sup_flags & UBIFS_FLG_SPACE_FIXUP);
|
| 735 | c->double_hash = !!(sup_flags & UBIFS_FLG_DOUBLE_HASH);
|
| 736 | c->encrypted = !!(sup_flags & UBIFS_FLG_ENCRYPTION);
|
| 737 |
|
| 738 | err = authenticate_sb_node(c, sup);
|
| 739 | if (err)
|
| 740 | goto out;
|
| 741 |
|
| 742 | if ((sup_flags & ~UBIFS_FLG_MASK) != 0) {
|
| 743 | ubifs_err(c, "Unknown feature flags found: %#x",
|
| 744 | sup_flags & ~UBIFS_FLG_MASK);
|
| 745 | err = -EINVAL;
|
| 746 | goto out;
|
| 747 | }
|
| 748 |
|
| 749 | if (!IS_ENABLED(CONFIG_FS_ENCRYPTION) && c->encrypted) {
|
| 750 | ubifs_err(c, "file system contains encrypted files but UBIFS"
|
| 751 | " was built without crypto support.");
|
| 752 | err = -EINVAL;
|
| 753 | goto out;
|
| 754 | }
|
| 755 |
|
| 756 |
|
| 757 | if (c->leb_cnt < c->vi.size && c->leb_cnt < c->max_leb_cnt) {
|
| 758 | int old_leb_cnt = c->leb_cnt;
|
| 759 |
|
| 760 | c->leb_cnt = min_t(int, c->max_leb_cnt, c->vi.size);
|
| 761 | sup->leb_cnt = cpu_to_le32(c->leb_cnt);
|
| 762 |
|
| 763 | c->superblock_need_write = 1;
|
| 764 |
|
| 765 | dbg_mnt("Auto resizing from %d LEBs to %d LEBs",
|
| 766 | old_leb_cnt, c->leb_cnt);
|
| 767 | }
|
| 768 |
|
| 769 | c->log_bytes = (long long)c->log_lebs * c->leb_size;
|
| 770 | c->log_last = UBIFS_LOG_LNUM + c->log_lebs - 1;
|
| 771 | c->lpt_first = UBIFS_LOG_LNUM + c->log_lebs;
|
| 772 | c->lpt_last = c->lpt_first + c->lpt_lebs - 1;
|
| 773 | c->orph_first = c->lpt_last + 1;
|
| 774 | c->orph_last = c->orph_first + c->orph_lebs - 1;
|
| 775 | c->main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS;
|
| 776 | c->main_lebs -= c->log_lebs + c->lpt_lebs + c->orph_lebs;
|
| 777 | c->main_first = c->leb_cnt - c->main_lebs;
|
| 778 |
|
| 779 | err = validate_sb(c, sup);
|
| 780 | out:
|
| 781 | return err;
|
| 782 | }
|
| 783 |
|
| 784 | |
| 785 | * fixup_leb - fixup/unmap an LEB containing free space.
|
| 786 | * @c: UBIFS file-system description object
|
| 787 | * @lnum: the LEB number to fix up
|
| 788 | * @len: number of used bytes in LEB (starting at offset 0)
|
| 789 | *
|
| 790 | * This function reads the contents of the given LEB number @lnum, then fixes
|
| 791 | * it up, so that empty min. I/O units in the end of LEB are actually erased on
|
| 792 | * flash (rather than being just all-0xff real data). If the LEB is completely
|
| 793 | * empty, it is simply unmapped.
|
| 794 |
|
| 795 | static int fixup_leb(struct ubifs_info *c, int lnum, int len)
|
| 796 | {
|
| 797 | int err;
|
| 798 |
|
| 799 | ubifs_assert(c, len >= 0);
|
| 800 | ubifs_assert(c, len % c->min_io_size == 0);
|
| 801 | ubifs_assert(c, len < c->leb_size);
|
| 802 |
|
| 803 | if (len == 0) {
|
| 804 | dbg_mnt("unmap empty LEB %d", lnum);
|
| 805 | return ubifs_leb_unmap(c, lnum);
|
| 806 | }
|
| 807 |
|
| 808 | dbg_mnt("fixup LEB %d, data len %d", lnum, len);
|
| 809 | err = ubifs_leb_read(c, lnum, c->sbuf, 0, len, 1);
|
| 810 | if (err)
|
| 811 | return err;
|
| 812 |
|
| 813 | return ubifs_leb_change(c, lnum, c->sbuf, len);
|
| 814 | }
|
| 815 |
|
| 816 | |
| 817 | * fixup_free_space - find & remap all LEBs containing free space.
|
| 818 | * @c: UBIFS file-system description object
|
| 819 | *
|
| 820 | * This function walks through all LEBs in the filesystem and fiexes up those
|
| 821 | * containing free/empty space.
|
| 822 |
|
| 823 | static int fixup_free_space(struct ubifs_info *c)
|
| 824 | {
|
| 825 | int lnum, err = 0;
|
| 826 | struct ubifs_lprops *lprops;
|
| 827 |
|
| 828 | ubifs_get_lprops(c);
|
| 829 |
|
| 830 |
|
| 831 | for (lnum = UBIFS_MST_LNUM; lnum < UBIFS_LOG_LNUM; lnum++) {
|
| 832 | err = fixup_leb(c, lnum, c->mst_offs + c->mst_node_alsz);
|
| 833 | if (err)
|
| 834 | goto out;
|
| 835 | }
|
| 836 |
|
| 837 |
|
| 838 | lnum = ubifs_next_log_lnum(c, c->lhead_lnum);
|
| 839 | while (lnum != c->ltail_lnum) {
|
| 840 | err = fixup_leb(c, lnum, 0);
|
| 841 | if (err)
|
| 842 | goto out;
|
| 843 | lnum = ubifs_next_log_lnum(c, lnum);
|
| 844 | }
|
| 845 |
|
| 846 | |
| 847 | * Fixup the log head which contains the only a CS node at the
|
| 848 | * beginning.
|
| 849 |
|
| 850 | err = fixup_leb(c, c->lhead_lnum,
|
| 851 | ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size));
|
| 852 | if (err)
|
| 853 | goto out;
|
| 854 |
|
| 855 |
|
| 856 | for (lnum = c->lpt_first; lnum <= c->lpt_last; lnum++) {
|
| 857 | int free = c->ltab[lnum - c->lpt_first].free;
|
| 858 |
|
| 859 | if (free > 0) {
|
| 860 | err = fixup_leb(c, lnum, c->leb_size - free);
|
| 861 | if (err)
|
| 862 | goto out;
|
| 863 | }
|
| 864 | }
|
| 865 |
|
| 866 |
|
| 867 | for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) {
|
| 868 | err = fixup_leb(c, lnum, 0);
|
| 869 | if (err)
|
| 870 | goto out;
|
| 871 | }
|
| 872 |
|
| 873 |
|
| 874 | for (lnum = c->main_first; lnum < c->leb_cnt; lnum++) {
|
| 875 | lprops = ubifs_lpt_lookup(c, lnum);
|
| 876 | if (IS_ERR(lprops)) {
|
| 877 | err = PTR_ERR(lprops);
|
| 878 | goto out;
|
| 879 | }
|
| 880 |
|
| 881 | if (lprops->free > 0) {
|
| 882 | err = fixup_leb(c, lnum, c->leb_size - lprops->free);
|
| 883 | if (err)
|
| 884 | goto out;
|
| 885 | }
|
| 886 | }
|
| 887 |
|
| 888 | out:
|
| 889 | ubifs_release_lprops(c);
|
| 890 | return err;
|
| 891 | }
|
| 892 |
|
| 893 | |
| 894 | * ubifs_fixup_free_space - find & fix all LEBs with free space.
|
| 895 | * @c: UBIFS file-system description object
|
| 896 | *
|
| 897 | * This function fixes up LEBs containing free space on first mount, if the
|
| 898 | * appropriate flag was set when the FS was created. Each LEB with one or more
|
| 899 | * empty min. I/O unit (i.e. free-space-count > 0) is re-written, to make sure
|
| 900 | * the free space is actually erased. E.g., this is necessary for some NAND
|
| 901 | * chips, since the free space may have been programmed like real "0xff" data
|
| 902 | * (generating a non-0xff ECC), causing future writes to the not-really-erased
|
| 903 | * NAND pages to behave badly. After the space is fixed up, the superblock flag
|
| 904 | * is cleared, so that this is skipped for all future mounts.
|
| 905 |
|
| 906 | int ubifs_fixup_free_space(struct ubifs_info *c)
|
| 907 | {
|
| 908 | int err;
|
| 909 | struct ubifs_sb_node *sup = c->sup_node;
|
| 910 |
|
| 911 | ubifs_assert(c, c->space_fixup);
|
| 912 | ubifs_assert(c, !c->ro_mount);
|
| 913 |
|
| 914 | ubifs_msg(c, "start fixing up free space");
|
| 915 |
|
| 916 | err = fixup_free_space(c);
|
| 917 | if (err)
|
| 918 | return err;
|
| 919 |
|
| 920 |
|
| 921 | c->space_fixup = 0;
|
| 922 | sup->flags &= cpu_to_le32(~UBIFS_FLG_SPACE_FIXUP);
|
| 923 |
|
| 924 | c->superblock_need_write = 1;
|
| 925 |
|
| 926 | ubifs_msg(c, "free space fixup complete");
|
| 927 | return err;
|
| 928 | }
|
| 929 |
|
| 930 | int ubifs_enable_encryption(struct ubifs_info *c)
|
| 931 | {
|
| 932 | int err;
|
| 933 | struct ubifs_sb_node *sup = c->sup_node;
|
| 934 |
|
| 935 | if (!IS_ENABLED(CONFIG_FS_ENCRYPTION))
|
| 936 | return -EOPNOTSUPP;
|
| 937 |
|
| 938 | if (c->encrypted)
|
| 939 | return 0;
|
| 940 |
|
| 941 | if (c->ro_mount || c->ro_media)
|
| 942 | return -EROFS;
|
| 943 |
|
| 944 | if (c->fmt_version < 5) {
|
| 945 | ubifs_err(c, "on-flash format version 5 is needed for encryption");
|
| 946 | return -EINVAL;
|
| 947 | }
|
| 948 |
|
| 949 | sup->flags |= cpu_to_le32(UBIFS_FLG_ENCRYPTION);
|
| 950 |
|
| 951 | err = ubifs_write_sb_node(c, sup);
|
| 952 | if (!err)
|
| 953 | c->encrypted = 1;
|
| 954 |
|
| 955 | return err;
|
| 956 | }
|