mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
UBIFS: add new flash file system
This is a new flash file system. See http://www.linux-mtd.infradead.org/doc/ubifs.html Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Signed-off-by: Adrian Hunter <ext-adrian.hunter@nokia.com>
This commit is contained in:
731
fs/ubifs/budget.c
Normal file
731
fs/ubifs/budget.c
Normal file
File diff suppressed because it is too large
Load Diff
677
fs/ubifs/commit.c
Normal file
677
fs/ubifs/commit.c
Normal file
File diff suppressed because it is too large
Load Diff
253
fs/ubifs/compress.c
Normal file
253
fs/ubifs/compress.c
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* This file is part of UBIFS.
|
||||
*
|
||||
* Copyright (C) 2006-2008 Nokia Corporation.
|
||||
* Copyright (C) 2006, 2007 University of Szeged, Hungary
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Authors: Adrian Hunter
|
||||
* Artem Bityutskiy (Битюцкий Артём)
|
||||
* Zoltan Sogor
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file provides a single place to access to compression and
|
||||
* decompression.
|
||||
*/
|
||||
|
||||
#include <linux/crypto.h>
|
||||
#include "ubifs.h"
|
||||
|
||||
/* Fake description object for the "none" compressor */
|
||||
static struct ubifs_compressor none_compr = {
|
||||
.compr_type = UBIFS_COMPR_NONE,
|
||||
.name = "no compression",
|
||||
.capi_name = "",
|
||||
};
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_LZO
|
||||
static DEFINE_MUTEX(lzo_mutex);
|
||||
|
||||
static struct ubifs_compressor lzo_compr = {
|
||||
.compr_type = UBIFS_COMPR_LZO,
|
||||
.comp_mutex = &lzo_mutex,
|
||||
.name = "LZO",
|
||||
.capi_name = "lzo",
|
||||
};
|
||||
#else
|
||||
static struct ubifs_compressor lzo_compr = {
|
||||
.compr_type = UBIFS_COMPR_LZO,
|
||||
.name = "LZO",
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_ZLIB
|
||||
static DEFINE_MUTEX(deflate_mutex);
|
||||
static DEFINE_MUTEX(inflate_mutex);
|
||||
|
||||
static struct ubifs_compressor zlib_compr = {
|
||||
.compr_type = UBIFS_COMPR_ZLIB,
|
||||
.comp_mutex = &deflate_mutex,
|
||||
.decomp_mutex = &inflate_mutex,
|
||||
.name = "zlib",
|
||||
.capi_name = "deflate",
|
||||
};
|
||||
#else
|
||||
static struct ubifs_compressor zlib_compr = {
|
||||
.compr_type = UBIFS_COMPR_ZLIB,
|
||||
.name = "zlib",
|
||||
};
|
||||
#endif
|
||||
|
||||
/* All UBIFS compressors */
|
||||
struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
|
||||
|
||||
/**
|
||||
* ubifs_compress - compress data.
|
||||
* @in_buf: data to compress
|
||||
* @in_len: length of the data to compress
|
||||
* @out_buf: output buffer where compressed data should be stored
|
||||
* @out_len: output buffer length is returned here
|
||||
* @compr_type: type of compression to use on enter, actually used compression
|
||||
* type on exit
|
||||
*
|
||||
* This function compresses input buffer @in_buf of length @in_len and stores
|
||||
* the result in the output buffer @out_buf and the resulting length in
|
||||
* @out_len. If the input buffer does not compress, it is just copied to the
|
||||
* @out_buf. The same happens if @compr_type is %UBIFS_COMPR_NONE or if
|
||||
* compression error occurred.
|
||||
*
|
||||
* Note, if the input buffer was not compressed, it is copied to the output
|
||||
* buffer and %UBIFS_COMPR_NONE is returned in @compr_type.
|
||||
*
|
||||
* This functions returns %0 on success or a negative error code on failure.
|
||||
*/
|
||||
void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len,
|
||||
int *compr_type)
|
||||
{
|
||||
int err;
|
||||
struct ubifs_compressor *compr = ubifs_compressors[*compr_type];
|
||||
|
||||
if (*compr_type == UBIFS_COMPR_NONE)
|
||||
goto no_compr;
|
||||
|
||||
/* If the input data is small, do not even try to compress it */
|
||||
if (in_len < UBIFS_MIN_COMPR_LEN)
|
||||
goto no_compr;
|
||||
|
||||
if (compr->comp_mutex)
|
||||
mutex_lock(compr->comp_mutex);
|
||||
err = crypto_comp_compress(compr->cc, in_buf, in_len, out_buf,
|
||||
out_len);
|
||||
if (compr->comp_mutex)
|
||||
mutex_unlock(compr->comp_mutex);
|
||||
if (unlikely(err)) {
|
||||
ubifs_warn("cannot compress %d bytes, compressor %s, "
|
||||
"error %d, leave data uncompressed",
|
||||
in_len, compr->name, err);
|
||||
goto no_compr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Presently, we just require that compression results in less data,
|
||||
* rather than any defined minimum compression ratio or amount.
|
||||
*/
|
||||
if (ALIGN(*out_len, 8) >= ALIGN(in_len, 8))
|
||||
goto no_compr;
|
||||
|
||||
return;
|
||||
|
||||
no_compr:
|
||||
memcpy(out_buf, in_buf, in_len);
|
||||
*out_len = in_len;
|
||||
*compr_type = UBIFS_COMPR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_decompress - decompress data.
|
||||
* @in_buf: data to decompress
|
||||
* @in_len: length of the data to decompress
|
||||
* @out_buf: output buffer where decompressed data should
|
||||
* @out_len: output length is returned here
|
||||
* @compr_type: type of compression
|
||||
*
|
||||
* This function decompresses data from buffer @in_buf into buffer @out_buf.
|
||||
* The length of the uncompressed data is returned in @out_len. This functions
|
||||
* returns %0 on success or a negative error code on failure.
|
||||
*/
|
||||
int ubifs_decompress(const void *in_buf, int in_len, void *out_buf,
|
||||
int *out_len, int compr_type)
|
||||
{
|
||||
int err;
|
||||
struct ubifs_compressor *compr;
|
||||
|
||||
if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) {
|
||||
ubifs_err("invalid compression type %d", compr_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
compr = ubifs_compressors[compr_type];
|
||||
|
||||
if (unlikely(!compr->capi_name)) {
|
||||
ubifs_err("%s compression is not compiled in", compr->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (compr_type == UBIFS_COMPR_NONE) {
|
||||
memcpy(out_buf, in_buf, in_len);
|
||||
*out_len = in_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (compr->decomp_mutex)
|
||||
mutex_lock(compr->decomp_mutex);
|
||||
err = crypto_comp_decompress(compr->cc, in_buf, in_len, out_buf,
|
||||
out_len);
|
||||
if (compr->decomp_mutex)
|
||||
mutex_unlock(compr->decomp_mutex);
|
||||
if (err)
|
||||
ubifs_err("cannot decompress %d bytes, compressor %s, "
|
||||
"error %d", in_len, compr->name, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* compr_init - initialize a compressor.
|
||||
* @compr: compressor description object
|
||||
*
|
||||
* This function initializes the requested compressor and returns zero in case
|
||||
* of success or a negative error code in case of failure.
|
||||
*/
|
||||
static int __init compr_init(struct ubifs_compressor *compr)
|
||||
{
|
||||
if (compr->capi_name) {
|
||||
compr->cc = crypto_alloc_comp(compr->capi_name, 0, 0);
|
||||
if (IS_ERR(compr->cc)) {
|
||||
ubifs_err("cannot initialize compressor %s, error %ld",
|
||||
compr->name, PTR_ERR(compr->cc));
|
||||
return PTR_ERR(compr->cc);
|
||||
}
|
||||
}
|
||||
|
||||
ubifs_compressors[compr->compr_type] = compr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* compr_exit - de-initialize a compressor.
|
||||
* @compr: compressor description object
|
||||
*/
|
||||
static void compr_exit(struct ubifs_compressor *compr)
|
||||
{
|
||||
if (compr->capi_name)
|
||||
crypto_free_comp(compr->cc);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_compressors_init - initialize UBIFS compressors.
|
||||
*
|
||||
* This function initializes the compressor which were compiled in. Returns
|
||||
* zero in case of success and a negative error code in case of failure.
|
||||
*/
|
||||
int __init ubifs_compressors_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = compr_init(&lzo_compr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = compr_init(&zlib_compr);
|
||||
if (err)
|
||||
goto out_lzo;
|
||||
|
||||
ubifs_compressors[UBIFS_COMPR_NONE] = &none_compr;
|
||||
return 0;
|
||||
|
||||
out_lzo:
|
||||
compr_exit(&lzo_compr);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_compressors_exit - de-initialize UBIFS compressors.
|
||||
*/
|
||||
void __exit ubifs_compressors_exit(void)
|
||||
{
|
||||
compr_exit(&lzo_compr);
|
||||
compr_exit(&zlib_compr);
|
||||
}
|
||||
2289
fs/ubifs/debug.c
Normal file
2289
fs/ubifs/debug.c
Normal file
File diff suppressed because it is too large
Load Diff
403
fs/ubifs/debug.h
Normal file
403
fs/ubifs/debug.h
Normal file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* This file is part of UBIFS.
|
||||
*
|
||||
* Copyright (C) 2006-2008 Nokia Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Authors: Artem Bityutskiy (Битюцкий Артём)
|
||||
* Adrian Hunter
|
||||
*/
|
||||
|
||||
#ifndef __UBIFS_DEBUG_H__
|
||||
#define __UBIFS_DEBUG_H__
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG
|
||||
|
||||
#define UBIFS_DBG(op) op
|
||||
|
||||
#define ubifs_assert(expr) do { \
|
||||
if (unlikely(!(expr))) { \
|
||||
printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \
|
||||
__func__, __LINE__, current->pid); \
|
||||
dbg_dump_stack(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ubifs_assert_cmt_locked(c) do { \
|
||||
if (unlikely(down_write_trylock(&(c)->commit_sem))) { \
|
||||
up_write(&(c)->commit_sem); \
|
||||
printk(KERN_CRIT "commit lock is not locked!\n"); \
|
||||
ubifs_assert(0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define dbg_dump_stack() do { \
|
||||
if (!dbg_failure_mode) \
|
||||
dump_stack(); \
|
||||
} while (0)
|
||||
|
||||
/* Generic debugging messages */
|
||||
#define dbg_msg(fmt, ...) do { \
|
||||
spin_lock(&dbg_lock); \
|
||||
printk(KERN_DEBUG "UBIFS DBG (pid %d): %s: " fmt "\n", current->pid, \
|
||||
__func__, ##__VA_ARGS__); \
|
||||
spin_unlock(&dbg_lock); \
|
||||
} while (0)
|
||||
|
||||
#define dbg_do_msg(typ, fmt, ...) do { \
|
||||
if (ubifs_msg_flags & typ) \
|
||||
dbg_msg(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define dbg_err(fmt, ...) do { \
|
||||
spin_lock(&dbg_lock); \
|
||||
ubifs_err(fmt, ##__VA_ARGS__); \
|
||||
spin_unlock(&dbg_lock); \
|
||||
} while (0)
|
||||
|
||||
const char *dbg_key_str0(const struct ubifs_info *c,
|
||||
const union ubifs_key *key);
|
||||
const char *dbg_key_str1(const struct ubifs_info *c,
|
||||
const union ubifs_key *key);
|
||||
|
||||
/*
|
||||
* DBGKEY macros require dbg_lock to be held, which it is in the dbg message
|
||||
* macros.
|
||||
*/
|
||||
#define DBGKEY(key) dbg_key_str0(c, (key))
|
||||
#define DBGKEY1(key) dbg_key_str1(c, (key))
|
||||
|
||||
/* General messages */
|
||||
#define dbg_gen(fmt, ...) dbg_do_msg(UBIFS_MSG_GEN, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional journal messages */
|
||||
#define dbg_jnl(fmt, ...) dbg_do_msg(UBIFS_MSG_JNL, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional TNC messages */
|
||||
#define dbg_tnc(fmt, ...) dbg_do_msg(UBIFS_MSG_TNC, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional lprops messages */
|
||||
#define dbg_lp(fmt, ...) dbg_do_msg(UBIFS_MSG_LP, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional LEB find messages */
|
||||
#define dbg_find(fmt, ...) dbg_do_msg(UBIFS_MSG_FIND, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional mount messages */
|
||||
#define dbg_mnt(fmt, ...) dbg_do_msg(UBIFS_MSG_MNT, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional I/O messages */
|
||||
#define dbg_io(fmt, ...) dbg_do_msg(UBIFS_MSG_IO, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional commit messages */
|
||||
#define dbg_cmt(fmt, ...) dbg_do_msg(UBIFS_MSG_CMT, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional budgeting messages */
|
||||
#define dbg_budg(fmt, ...) dbg_do_msg(UBIFS_MSG_BUDG, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional log messages */
|
||||
#define dbg_log(fmt, ...) dbg_do_msg(UBIFS_MSG_LOG, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional gc messages */
|
||||
#define dbg_gc(fmt, ...) dbg_do_msg(UBIFS_MSG_GC, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional scan messages */
|
||||
#define dbg_scan(fmt, ...) dbg_do_msg(UBIFS_MSG_SCAN, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Additional recovery messages */
|
||||
#define dbg_rcvry(fmt, ...) dbg_do_msg(UBIFS_MSG_RCVRY, fmt, ##__VA_ARGS__)
|
||||
|
||||
/*
|
||||
* Debugging message type flags (must match msg_type_names in debug.c).
|
||||
*
|
||||
* UBIFS_MSG_GEN: general messages
|
||||
* UBIFS_MSG_JNL: journal messages
|
||||
* UBIFS_MSG_MNT: mount messages
|
||||
* UBIFS_MSG_CMT: commit messages
|
||||
* UBIFS_MSG_FIND: LEB find messages
|
||||
* UBIFS_MSG_BUDG: budgeting messages
|
||||
* UBIFS_MSG_GC: garbage collection messages
|
||||
* UBIFS_MSG_TNC: TNC messages
|
||||
* UBIFS_MSG_LP: lprops messages
|
||||
* UBIFS_MSG_IO: I/O messages
|
||||
* UBIFS_MSG_LOG: log messages
|
||||
* UBIFS_MSG_SCAN: scan messages
|
||||
* UBIFS_MSG_RCVRY: recovery messages
|
||||
*/
|
||||
enum {
|
||||
UBIFS_MSG_GEN = 0x1,
|
||||
UBIFS_MSG_JNL = 0x2,
|
||||
UBIFS_MSG_MNT = 0x4,
|
||||
UBIFS_MSG_CMT = 0x8,
|
||||
UBIFS_MSG_FIND = 0x10,
|
||||
UBIFS_MSG_BUDG = 0x20,
|
||||
UBIFS_MSG_GC = 0x40,
|
||||
UBIFS_MSG_TNC = 0x80,
|
||||
UBIFS_MSG_LP = 0x100,
|
||||
UBIFS_MSG_IO = 0x200,
|
||||
UBIFS_MSG_LOG = 0x400,
|
||||
UBIFS_MSG_SCAN = 0x800,
|
||||
UBIFS_MSG_RCVRY = 0x1000,
|
||||
};
|
||||
|
||||
/* Debugging message type flags for each default debug message level */
|
||||
#define UBIFS_MSG_LVL_0 0
|
||||
#define UBIFS_MSG_LVL_1 0x1
|
||||
#define UBIFS_MSG_LVL_2 0x7f
|
||||
#define UBIFS_MSG_LVL_3 0xffff
|
||||
|
||||
/*
|
||||
* Debugging check flags (must match chk_names in debug.c).
|
||||
*
|
||||
* UBIFS_CHK_GEN: general checks
|
||||
* UBIFS_CHK_TNC: check TNC
|
||||
* UBIFS_CHK_IDX_SZ: check index size
|
||||
* UBIFS_CHK_ORPH: check orphans
|
||||
* UBIFS_CHK_OLD_IDX: check the old index
|
||||
* UBIFS_CHK_LPROPS: check lprops
|
||||
* UBIFS_CHK_FS: check the file-system
|
||||
*/
|
||||
enum {
|
||||
UBIFS_CHK_GEN = 0x1,
|
||||
UBIFS_CHK_TNC = 0x2,
|
||||
UBIFS_CHK_IDX_SZ = 0x4,
|
||||
UBIFS_CHK_ORPH = 0x8,
|
||||
UBIFS_CHK_OLD_IDX = 0x10,
|
||||
UBIFS_CHK_LPROPS = 0x20,
|
||||
UBIFS_CHK_FS = 0x40,
|
||||
};
|
||||
|
||||
/*
|
||||
* Special testing flags (must match tst_names in debug.c).
|
||||
*
|
||||
* UBIFS_TST_FORCE_IN_THE_GAPS: force the use of in-the-gaps method
|
||||
* UBIFS_TST_RCVRY: failure mode for recovery testing
|
||||
*/
|
||||
enum {
|
||||
UBIFS_TST_FORCE_IN_THE_GAPS = 0x2,
|
||||
UBIFS_TST_RCVRY = 0x4,
|
||||
};
|
||||
|
||||
#if CONFIG_UBIFS_FS_DEBUG_MSG_LVL == 1
|
||||
#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_1
|
||||
#elif CONFIG_UBIFS_FS_DEBUG_MSG_LVL == 2
|
||||
#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_2
|
||||
#elif CONFIG_UBIFS_FS_DEBUG_MSG_LVL == 3
|
||||
#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_3
|
||||
#else
|
||||
#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_UBIFS_FS_DEBUG_CHKS
|
||||
#define UBIFS_CHK_FLAGS_DEFAULT 0xffffffff
|
||||
#else
|
||||
#define UBIFS_CHK_FLAGS_DEFAULT 0
|
||||
#endif
|
||||
|
||||
extern spinlock_t dbg_lock;
|
||||
|
||||
extern unsigned int ubifs_msg_flags;
|
||||
extern unsigned int ubifs_chk_flags;
|
||||
extern unsigned int ubifs_tst_flags;
|
||||
|
||||
/* Dump functions */
|
||||
|
||||
const char *dbg_ntype(int type);
|
||||
const char *dbg_cstate(int cmt_state);
|
||||
const char *dbg_get_key_dump(const struct ubifs_info *c,
|
||||
const union ubifs_key *key);
|
||||
void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode);
|
||||
void dbg_dump_node(const struct ubifs_info *c, const void *node);
|
||||
void dbg_dump_budget_req(const struct ubifs_budget_req *req);
|
||||
void dbg_dump_lstats(const struct ubifs_lp_stats *lst);
|
||||
void dbg_dump_budg(struct ubifs_info *c);
|
||||
void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp);
|
||||
void dbg_dump_lprops(struct ubifs_info *c);
|
||||
void dbg_dump_leb(const struct ubifs_info *c, int lnum);
|
||||
void dbg_dump_znode(const struct ubifs_info *c,
|
||||
const struct ubifs_znode *znode);
|
||||
void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat);
|
||||
void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
|
||||
struct ubifs_nnode *parent, int iip);
|
||||
void dbg_dump_tnc(struct ubifs_info *c);
|
||||
void dbg_dump_index(struct ubifs_info *c);
|
||||
|
||||
/* Checking helper functions */
|
||||
|
||||
typedef int (*dbg_leaf_callback)(struct ubifs_info *c,
|
||||
struct ubifs_zbranch *zbr, void *priv);
|
||||
typedef int (*dbg_znode_callback)(struct ubifs_info *c,
|
||||
struct ubifs_znode *znode, void *priv);
|
||||
|
||||
int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
|
||||
dbg_znode_callback znode_cb, void *priv);
|
||||
|
||||
/* Checking functions */
|
||||
|
||||
int dbg_check_lprops(struct ubifs_info *c);
|
||||
|
||||
int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot);
|
||||
int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot);
|
||||
|
||||
int dbg_check_cats(struct ubifs_info *c);
|
||||
|
||||
int dbg_check_ltab(struct ubifs_info *c);
|
||||
|
||||
int dbg_check_synced_i_size(struct inode *inode);
|
||||
|
||||
int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir);
|
||||
|
||||
int dbg_check_tnc(struct ubifs_info *c, int extra);
|
||||
|
||||
int dbg_check_idx_size(struct ubifs_info *c, long long idx_size);
|
||||
|
||||
int dbg_check_filesystem(struct ubifs_info *c);
|
||||
|
||||
void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat,
|
||||
int add_pos);
|
||||
|
||||
int dbg_check_lprops(struct ubifs_info *c);
|
||||
int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
|
||||
int row, int col);
|
||||
|
||||
/* Force the use of in-the-gaps method for testing */
|
||||
|
||||
#define dbg_force_in_the_gaps_enabled \
|
||||
(ubifs_tst_flags & UBIFS_TST_FORCE_IN_THE_GAPS)
|
||||
|
||||
int dbg_force_in_the_gaps(void);
|
||||
|
||||
/* Failure mode for recovery testing */
|
||||
|
||||
#define dbg_failure_mode (ubifs_tst_flags & UBIFS_TST_RCVRY)
|
||||
|
||||
void dbg_failure_mode_registration(struct ubifs_info *c);
|
||||
void dbg_failure_mode_deregistration(struct ubifs_info *c);
|
||||
|
||||
#ifndef UBIFS_DBG_PRESERVE_UBI
|
||||
|
||||
#define ubi_leb_read dbg_leb_read
|
||||
#define ubi_leb_write dbg_leb_write
|
||||
#define ubi_leb_change dbg_leb_change
|
||||
#define ubi_leb_erase dbg_leb_erase
|
||||
#define ubi_leb_unmap dbg_leb_unmap
|
||||
#define ubi_is_mapped dbg_is_mapped
|
||||
#define ubi_leb_map dbg_leb_map
|
||||
|
||||
#endif
|
||||
|
||||
int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
|
||||
int len, int check);
|
||||
int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
|
||||
int offset, int len, int dtype);
|
||||
int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
|
||||
int len, int dtype);
|
||||
int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum);
|
||||
int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum);
|
||||
int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum);
|
||||
int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype);
|
||||
|
||||
static inline int dbg_read(struct ubi_volume_desc *desc, int lnum, char *buf,
|
||||
int offset, int len)
|
||||
{
|
||||
return dbg_leb_read(desc, lnum, buf, offset, len, 0);
|
||||
}
|
||||
|
||||
static inline int dbg_write(struct ubi_volume_desc *desc, int lnum,
|
||||
const void *buf, int offset, int len)
|
||||
{
|
||||
return dbg_leb_write(desc, lnum, buf, offset, len, UBI_UNKNOWN);
|
||||
}
|
||||
|
||||
static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
|
||||
const void *buf, int len)
|
||||
{
|
||||
return dbg_leb_change(desc, lnum, buf, len, UBI_UNKNOWN);
|
||||
}
|
||||
|
||||
#else /* !CONFIG_UBIFS_FS_DEBUG */
|
||||
|
||||
#define UBIFS_DBG(op)
|
||||
#define ubifs_assert(expr) ({})
|
||||
#define ubifs_assert_cmt_locked(c)
|
||||
#define dbg_dump_stack()
|
||||
#define dbg_err(fmt, ...) ({})
|
||||
#define dbg_msg(fmt, ...) ({})
|
||||
#define dbg_key(c, key, fmt, ...) ({})
|
||||
|
||||
#define dbg_gen(fmt, ...) ({})
|
||||
#define dbg_jnl(fmt, ...) ({})
|
||||
#define dbg_tnc(fmt, ...) ({})
|
||||
#define dbg_lp(fmt, ...) ({})
|
||||
#define dbg_find(fmt, ...) ({})
|
||||
#define dbg_mnt(fmt, ...) ({})
|
||||
#define dbg_io(fmt, ...) ({})
|
||||
#define dbg_cmt(fmt, ...) ({})
|
||||
#define dbg_budg(fmt, ...) ({})
|
||||
#define dbg_log(fmt, ...) ({})
|
||||
#define dbg_gc(fmt, ...) ({})
|
||||
#define dbg_scan(fmt, ...) ({})
|
||||
#define dbg_rcvry(fmt, ...) ({})
|
||||
|
||||
#define dbg_ntype(type) ""
|
||||
#define dbg_cstate(cmt_state) ""
|
||||
#define dbg_get_key_dump(c, key) ({})
|
||||
#define dbg_dump_inode(c, inode) ({})
|
||||
#define dbg_dump_node(c, node) ({})
|
||||
#define dbg_dump_budget_req(req) ({})
|
||||
#define dbg_dump_lstats(lst) ({})
|
||||
#define dbg_dump_budg(c) ({})
|
||||
#define dbg_dump_lprop(c, lp) ({})
|
||||
#define dbg_dump_lprops(c) ({})
|
||||
#define dbg_dump_leb(c, lnum) ({})
|
||||
#define dbg_dump_znode(c, znode) ({})
|
||||
#define dbg_dump_heap(c, heap, cat) ({})
|
||||
#define dbg_dump_pnode(c, pnode, parent, iip) ({})
|
||||
#define dbg_dump_tnc(c) ({})
|
||||
#define dbg_dump_index(c) ({})
|
||||
|
||||
#define dbg_walk_index(c, leaf_cb, znode_cb, priv) 0
|
||||
|
||||
#define dbg_old_index_check_init(c, zroot) 0
|
||||
#define dbg_check_old_index(c, zroot) 0
|
||||
|
||||
#define dbg_check_cats(c) 0
|
||||
|
||||
#define dbg_check_ltab(c) 0
|
||||
|
||||
#define dbg_check_synced_i_size(inode) 0
|
||||
|
||||
#define dbg_check_dir_size(c, dir) 0
|
||||
|
||||
#define dbg_check_tnc(c, x) 0
|
||||
|
||||
#define dbg_check_idx_size(c, idx_size) 0
|
||||
|
||||
#define dbg_check_filesystem(c) 0
|
||||
|
||||
#define dbg_check_heap(c, heap, cat, add_pos) ({})
|
||||
|
||||
#define dbg_check_lprops(c) 0
|
||||
#define dbg_check_lpt_nodes(c, cnode, row, col) 0
|
||||
|
||||
#define dbg_force_in_the_gaps_enabled 0
|
||||
#define dbg_force_in_the_gaps() 0
|
||||
|
||||
#define dbg_failure_mode 0
|
||||
#define dbg_failure_mode_registration(c) ({})
|
||||
#define dbg_failure_mode_deregistration(c) ({})
|
||||
|
||||
#endif /* !CONFIG_UBIFS_FS_DEBUG */
|
||||
|
||||
#endif /* !__UBIFS_DEBUG_H__ */
|
||||
1240
fs/ubifs/dir.c
Normal file
1240
fs/ubifs/dir.c
Normal file
File diff suppressed because it is too large
Load Diff
1275
fs/ubifs/file.c
Normal file
1275
fs/ubifs/file.c
Normal file
File diff suppressed because it is too large
Load Diff
975
fs/ubifs/find.c
Normal file
975
fs/ubifs/find.c
Normal file
File diff suppressed because it is too large
Load Diff
773
fs/ubifs/gc.c
Normal file
773
fs/ubifs/gc.c
Normal file
File diff suppressed because it is too large
Load Diff
914
fs/ubifs/io.c
Normal file
914
fs/ubifs/io.c
Normal file
File diff suppressed because it is too large
Load Diff
204
fs/ubifs/ioctl.c
Normal file
204
fs/ubifs/ioctl.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* This file is part of UBIFS.
|
||||
*
|
||||
* Copyright (C) 2006-2008 Nokia Corporation.
|
||||
* Copyright (C) 2006, 2007 University of Szeged, Hungary
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Authors: Zoltan Sogor
|
||||
* Artem Bityutskiy (Битюцкий Артём)
|
||||
* Adrian Hunter
|
||||
*/
|
||||
|
||||
/* This file implements EXT2-compatible extended attribute ioctl() calls */
|
||||
|
||||
#include <linux/compat.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/mount.h>
|
||||
#include "ubifs.h"
|
||||
|
||||
/**
|
||||
* ubifs_set_inode_flags - set VFS inode flags.
|
||||
* @inode: VFS inode to set flags for
|
||||
*
|
||||
* This function propagates flags from UBIFS inode object to VFS inode object.
|
||||
*/
|
||||
void ubifs_set_inode_flags(struct inode *inode)
|
||||
{
|
||||
unsigned int flags = ubifs_inode(inode)->flags;
|
||||
|
||||
inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_DIRSYNC);
|
||||
if (flags & UBIFS_SYNC_FL)
|
||||
inode->i_flags |= S_SYNC;
|
||||
if (flags & UBIFS_APPEND_FL)
|
||||
inode->i_flags |= S_APPEND;
|
||||
if (flags & UBIFS_IMMUTABLE_FL)
|
||||
inode->i_flags |= S_IMMUTABLE;
|
||||
if (flags & UBIFS_DIRSYNC_FL)
|
||||
inode->i_flags |= S_DIRSYNC;
|
||||
}
|
||||
|
||||
/*
|
||||
* ioctl2ubifs - convert ioctl inode flags to UBIFS inode flags.
|
||||
* @ioctl_flags: flags to convert
|
||||
*
|
||||
* This function convert ioctl flags (@FS_COMPR_FL, etc) to UBIFS inode flags
|
||||
* (@UBIFS_COMPR_FL, etc).
|
||||
*/
|
||||
static int ioctl2ubifs(int ioctl_flags)
|
||||
{
|
||||
int ubifs_flags = 0;
|
||||
|
||||
if (ioctl_flags & FS_COMPR_FL)
|
||||
ubifs_flags |= UBIFS_COMPR_FL;
|
||||
if (ioctl_flags & FS_SYNC_FL)
|
||||
ubifs_flags |= UBIFS_SYNC_FL;
|
||||
if (ioctl_flags & FS_APPEND_FL)
|
||||
ubifs_flags |= UBIFS_APPEND_FL;
|
||||
if (ioctl_flags & FS_IMMUTABLE_FL)
|
||||
ubifs_flags |= UBIFS_IMMUTABLE_FL;
|
||||
if (ioctl_flags & FS_DIRSYNC_FL)
|
||||
ubifs_flags |= UBIFS_DIRSYNC_FL;
|
||||
|
||||
return ubifs_flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* ubifs2ioctl - convert UBIFS inode flags to ioctl inode flags.
|
||||
* @ubifs_flags: flags to convert
|
||||
*
|
||||
* This function convert UBIFS (@UBIFS_COMPR_FL, etc) to ioctl flags
|
||||
* (@FS_COMPR_FL, etc).
|
||||
*/
|
||||
static int ubifs2ioctl(int ubifs_flags)
|
||||
{
|
||||
int ioctl_flags = 0;
|
||||
|
||||
if (ubifs_flags & UBIFS_COMPR_FL)
|
||||
ioctl_flags |= FS_COMPR_FL;
|
||||
if (ubifs_flags & UBIFS_SYNC_FL)
|
||||
ioctl_flags |= FS_SYNC_FL;
|
||||
if (ubifs_flags & UBIFS_APPEND_FL)
|
||||
ioctl_flags |= FS_APPEND_FL;
|
||||
if (ubifs_flags & UBIFS_IMMUTABLE_FL)
|
||||
ioctl_flags |= FS_IMMUTABLE_FL;
|
||||
if (ubifs_flags & UBIFS_DIRSYNC_FL)
|
||||
ioctl_flags |= FS_DIRSYNC_FL;
|
||||
|
||||
return ioctl_flags;
|
||||
}
|
||||
|
||||
static int setflags(struct inode *inode, int flags)
|
||||
{
|
||||
int oldflags, err, release;
|
||||
struct ubifs_inode *ui = ubifs_inode(inode);
|
||||
struct ubifs_info *c = inode->i_sb->s_fs_info;
|
||||
struct ubifs_budget_req req = { .dirtied_ino = 1,
|
||||
.dirtied_ino_d = ui->data_len };
|
||||
|
||||
err = ubifs_budget_space(c, &req);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* The IMMUTABLE and APPEND_ONLY flags can only be changed by
|
||||
* the relevant capability.
|
||||
*/
|
||||
mutex_lock(&ui->ui_mutex);
|
||||
oldflags = ubifs2ioctl(ui->flags);
|
||||
if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
|
||||
if (!capable(CAP_LINUX_IMMUTABLE)) {
|
||||
err = -EPERM;
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
ui->flags = ioctl2ubifs(flags);
|
||||
ubifs_set_inode_flags(inode);
|
||||
inode->i_ctime = ubifs_current_time(inode);
|
||||
release = ui->dirty;
|
||||
mark_inode_dirty_sync(inode);
|
||||
mutex_unlock(&ui->ui_mutex);
|
||||
|
||||
if (release)
|
||||
ubifs_release_budget(c, &req);
|
||||
if (IS_SYNC(inode))
|
||||
err = write_inode_now(inode, 1);
|
||||
return err;
|
||||
|
||||
out_unlock:
|
||||
ubifs_err("can't modify inode %lu attributes", inode->i_ino);
|
||||
mutex_unlock(&ui->ui_mutex);
|
||||
ubifs_release_budget(c, &req);
|
||||
return err;
|
||||
}
|
||||
|
||||
long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int flags, err;
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
|
||||
switch (cmd) {
|
||||
case FS_IOC_GETFLAGS:
|
||||
flags = ubifs2ioctl(ubifs_inode(inode)->flags);
|
||||
|
||||
return put_user(flags, (int __user *) arg);
|
||||
|
||||
case FS_IOC_SETFLAGS: {
|
||||
if (IS_RDONLY(inode))
|
||||
return -EROFS;
|
||||
|
||||
if (!is_owner_or_cap(inode))
|
||||
return -EACCES;
|
||||
|
||||
if (get_user(flags, (int __user *) arg))
|
||||
return -EFAULT;
|
||||
|
||||
if (!S_ISDIR(inode->i_mode))
|
||||
flags &= ~FS_DIRSYNC_FL;
|
||||
|
||||
/*
|
||||
* Make sure the file-system is read-write and make sure it
|
||||
* will not become read-only while we are changing the flags.
|
||||
*/
|
||||
err = mnt_want_write(file->f_path.mnt);
|
||||
if (err)
|
||||
return err;
|
||||
err = setflags(inode, flags);
|
||||
mnt_drop_write(file->f_path.mnt);
|
||||
return err;
|
||||
}
|
||||
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
switch (cmd) {
|
||||
case FS_IOC32_GETFLAGS:
|
||||
cmd = FS_IOC_GETFLAGS;
|
||||
break;
|
||||
case FS_IOC32_SETFLAGS:
|
||||
cmd = FS_IOC_SETFLAGS;
|
||||
break;
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
return ubifs_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
|
||||
}
|
||||
#endif
|
||||
1387
fs/ubifs/journal.c
Normal file
1387
fs/ubifs/journal.c
Normal file
File diff suppressed because it is too large
Load Diff
533
fs/ubifs/key.h
Normal file
533
fs/ubifs/key.h
Normal file
File diff suppressed because it is too large
Load Diff
805
fs/ubifs/log.c
Normal file
805
fs/ubifs/log.c
Normal file
File diff suppressed because it is too large
Load Diff
1357
fs/ubifs/lprops.c
Normal file
1357
fs/ubifs/lprops.c
Normal file
File diff suppressed because it is too large
Load Diff
2243
fs/ubifs/lpt.c
Normal file
2243
fs/ubifs/lpt.c
Normal file
File diff suppressed because it is too large
Load Diff
1648
fs/ubifs/lpt_commit.c
Normal file
1648
fs/ubifs/lpt_commit.c
Normal file
File diff suppressed because it is too large
Load Diff
387
fs/ubifs/master.c
Normal file
387
fs/ubifs/master.c
Normal file
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* This file is part of UBIFS.
|
||||
*
|
||||
* Copyright (C) 2006-2008 Nokia Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Authors: Artem Bityutskiy (Битюцкий Артём)
|
||||
* Adrian Hunter
|
||||
*/
|
||||
|
||||
/* This file implements reading and writing the master node */
|
||||
|
||||
#include "ubifs.h"
|
||||
|
||||
/**
|
||||
* scan_for_master - search the valid master node.
|
||||
* @c: UBIFS file-system description object
|
||||
*
|
||||
* This function scans the master node LEBs and search for the latest master
|
||||
* node. Returns zero in case of success and a negative error code in case of
|
||||
* failure.
|
||||
*/
|
||||
static int scan_for_master(struct ubifs_info *c)
|
||||
{
|
||||
struct ubifs_scan_leb *sleb;
|
||||
struct ubifs_scan_node *snod;
|
||||
int lnum, offs = 0, nodes_cnt;
|
||||
|
||||
lnum = UBIFS_MST_LNUM;
|
||||
|
||||
sleb = ubifs_scan(c, lnum, 0, c->sbuf);
|
||||
if (IS_ERR(sleb))
|
||||
return PTR_ERR(sleb);
|
||||
nodes_cnt = sleb->nodes_cnt;
|
||||
if (nodes_cnt > 0) {
|
||||
snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
|
||||
list);
|
||||
if (snod->type != UBIFS_MST_NODE)
|
||||
goto out;
|
||||
memcpy(c->mst_node, snod->node, snod->len);
|
||||
offs = snod->offs;
|
||||
}
|
||||
ubifs_scan_destroy(sleb);
|
||||
|
||||
lnum += 1;
|
||||
|
||||
sleb = ubifs_scan(c, lnum, 0, c->sbuf);
|
||||
if (IS_ERR(sleb))
|
||||
return PTR_ERR(sleb);
|
||||
if (sleb->nodes_cnt != nodes_cnt)
|
||||
goto out;
|
||||
if (!sleb->nodes_cnt)
|
||||
goto out;
|
||||
snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, list);
|
||||
if (snod->type != UBIFS_MST_NODE)
|
||||
goto out;
|
||||
if (snod->offs != offs)
|
||||
goto out;
|
||||
if (memcmp((void *)c->mst_node + UBIFS_CH_SZ,
|
||||
(void *)snod->node + UBIFS_CH_SZ,
|
||||
UBIFS_MST_NODE_SZ - UBIFS_CH_SZ))
|
||||
goto out;
|
||||
c->mst_offs = offs;
|
||||
ubifs_scan_destroy(sleb);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
ubifs_scan_destroy(sleb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* validate_master - validate master node.
|
||||
* @c: UBIFS file-system description object
|
||||
*
|
||||
* This function validates data which was read from master node. Returns zero
|
||||
* if the data is all right and %-EINVAL if not.
|
||||
*/
|
||||
static int validate_master(const struct ubifs_info *c)
|
||||
{
|
||||
long long main_sz;
|
||||
int err;
|
||||
|
||||
if (c->max_sqnum >= SQNUM_WATERMARK) {
|
||||
err = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->cmt_no >= c->max_sqnum) {
|
||||
err = 2;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->highest_inum >= INUM_WATERMARK) {
|
||||
err = 3;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->lhead_lnum < UBIFS_LOG_LNUM ||
|
||||
c->lhead_lnum >= UBIFS_LOG_LNUM + c->log_lebs ||
|
||||
c->lhead_offs < 0 || c->lhead_offs >= c->leb_size ||
|
||||
c->lhead_offs & (c->min_io_size - 1)) {
|
||||
err = 4;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->zroot.lnum >= c->leb_cnt || c->zroot.lnum < c->main_first ||
|
||||
c->zroot.offs >= c->leb_size || c->zroot.offs & 7) {
|
||||
err = 5;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->zroot.len < c->ranges[UBIFS_IDX_NODE].min_len ||
|
||||
c->zroot.len > c->ranges[UBIFS_IDX_NODE].max_len) {
|
||||
err = 6;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->gc_lnum >= c->leb_cnt || c->gc_lnum < c->main_first) {
|
||||
err = 7;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->ihead_lnum >= c->leb_cnt || c->ihead_lnum < c->main_first ||
|
||||
c->ihead_offs % c->min_io_size || c->ihead_offs < 0 ||
|
||||
c->ihead_offs > c->leb_size || c->ihead_offs & 7) {
|
||||
err = 8;
|
||||
goto out;
|
||||
}
|
||||
|
||||
main_sz = (long long)c->main_lebs * c->leb_size;
|
||||
if (c->old_idx_sz & 7 || c->old_idx_sz >= main_sz) {
|
||||
err = 9;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->lpt_lnum < c->lpt_first || c->lpt_lnum > c->lpt_last ||
|
||||
c->lpt_offs < 0 || c->lpt_offs + c->nnode_sz > c->leb_size) {
|
||||
err = 10;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->nhead_lnum < c->lpt_first || c->nhead_lnum > c->lpt_last ||
|
||||
c->nhead_offs < 0 || c->nhead_offs % c->min_io_size ||
|
||||
c->nhead_offs > c->leb_size) {
|
||||
err = 11;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->ltab_lnum < c->lpt_first || c->ltab_lnum > c->lpt_last ||
|
||||
c->ltab_offs < 0 ||
|
||||
c->ltab_offs + c->ltab_sz > c->leb_size) {
|
||||
err = 12;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->big_lpt && (c->lsave_lnum < c->lpt_first ||
|
||||
c->lsave_lnum > c->lpt_last || c->lsave_offs < 0 ||
|
||||
c->lsave_offs + c->lsave_sz > c->leb_size)) {
|
||||
err = 13;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->lscan_lnum < c->main_first || c->lscan_lnum >= c->leb_cnt) {
|
||||
err = 14;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->lst.empty_lebs < 0 || c->lst.empty_lebs > c->main_lebs - 2) {
|
||||
err = 15;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->lst.idx_lebs < 0 || c->lst.idx_lebs > c->main_lebs - 1) {
|
||||
err = 16;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->lst.total_free < 0 || c->lst.total_free > main_sz ||
|
||||
c->lst.total_free & 7) {
|
||||
err = 17;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->lst.total_dirty < 0 || (c->lst.total_dirty & 7)) {
|
||||
err = 18;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->lst.total_used < 0 || (c->lst.total_used & 7)) {
|
||||
err = 19;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->lst.total_free + c->lst.total_dirty +
|
||||
c->lst.total_used > main_sz) {
|
||||
err = 20;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->lst.total_dead + c->lst.total_dark +
|
||||
c->lst.total_used + c->old_idx_sz > main_sz) {
|
||||
err = 21;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->lst.total_dead < 0 ||
|
||||
c->lst.total_dead > c->lst.total_free + c->lst.total_dirty ||
|
||||
c->lst.total_dead & 7) {
|
||||
err = 22;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c->lst.total_dark < 0 ||
|
||||
c->lst.total_dark > c->lst.total_free + c->lst.total_dirty ||
|
||||
c->lst.total_dark & 7) {
|
||||
err = 23;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
ubifs_err("bad master node at offset %d error %d", c->mst_offs, err);
|
||||
dbg_dump_node(c, c->mst_node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_read_master - read master node.
|
||||
* @c: UBIFS file-system description object
|
||||
*
|
||||
* This function finds and reads the master node during file-system mount. If
|
||||
* the flash is empty, it creates default master node as well. Returns zero in
|
||||
* case of success and a negative error code in case of failure.
|
||||
*/
|
||||
int ubifs_read_master(struct ubifs_info *c)
|
||||
{
|
||||
int err, old_leb_cnt;
|
||||
|
||||
c->mst_node = kzalloc(c->mst_node_alsz, GFP_KERNEL);
|
||||
if (!c->mst_node)
|
||||
return -ENOMEM;
|
||||
|
||||
err = scan_for_master(c);
|
||||
if (err) {
|
||||
err = ubifs_recover_master_node(c);
|
||||
if (err)
|
||||
/*
|
||||
* Note, we do not free 'c->mst_node' here because the
|
||||
* unmount routine will take care of this.
|
||||
*/
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Make sure that the recovery flag is clear */
|
||||
c->mst_node->flags &= cpu_to_le32(~UBIFS_MST_RCVRY);
|
||||
|
||||
c->max_sqnum = le64_to_cpu(c->mst_node->ch.sqnum);
|
||||
c->highest_inum = le64_to_cpu(c->mst_node->highest_inum);
|
||||
c->cmt_no = le64_to_cpu(c->mst_node->cmt_no);
|
||||
c->zroot.lnum = le32_to_cpu(c->mst_node->root_lnum);
|
||||
c->zroot.offs = le32_to_cpu(c->mst_node->root_offs);
|
||||
c->zroot.len = le32_to_cpu(c->mst_node->root_len);
|
||||
c->lhead_lnum = le32_to_cpu(c->mst_node->log_lnum);
|
||||
c->gc_lnum = le32_to_cpu(c->mst_node->gc_lnum);
|
||||
c->ihead_lnum = le32_to_cpu(c->mst_node->ihead_lnum);
|
||||
c->ihead_offs = le32_to_cpu(c->mst_node->ihead_offs);
|
||||
c->old_idx_sz = le64_to_cpu(c->mst_node->index_size);
|
||||
c->lpt_lnum = le32_to_cpu(c->mst_node->lpt_lnum);
|
||||
c->lpt_offs = le32_to_cpu(c->mst_node->lpt_offs);
|
||||
c->nhead_lnum = le32_to_cpu(c->mst_node->nhead_lnum);
|
||||
c->nhead_offs = le32_to_cpu(c->mst_node->nhead_offs);
|
||||
c->ltab_lnum = le32_to_cpu(c->mst_node->ltab_lnum);
|
||||
c->ltab_offs = le32_to_cpu(c->mst_node->ltab_offs);
|
||||
c->lsave_lnum = le32_to_cpu(c->mst_node->lsave_lnum);
|
||||
c->lsave_offs = le32_to_cpu(c->mst_node->lsave_offs);
|
||||
c->lscan_lnum = le32_to_cpu(c->mst_node->lscan_lnum);
|
||||
c->lst.empty_lebs = le32_to_cpu(c->mst_node->empty_lebs);
|
||||
c->lst.idx_lebs = le32_to_cpu(c->mst_node->idx_lebs);
|
||||
old_leb_cnt = le32_to_cpu(c->mst_node->leb_cnt);
|
||||
c->lst.total_free = le64_to_cpu(c->mst_node->total_free);
|
||||
c->lst.total_dirty = le64_to_cpu(c->mst_node->total_dirty);
|
||||
c->lst.total_used = le64_to_cpu(c->mst_node->total_used);
|
||||
c->lst.total_dead = le64_to_cpu(c->mst_node->total_dead);
|
||||
c->lst.total_dark = le64_to_cpu(c->mst_node->total_dark);
|
||||
|
||||
c->calc_idx_sz = c->old_idx_sz;
|
||||
|
||||
if (c->mst_node->flags & cpu_to_le32(UBIFS_MST_NO_ORPHS))
|
||||
c->no_orphs = 1;
|
||||
|
||||
if (old_leb_cnt != c->leb_cnt) {
|
||||
/* The file system has been resized */
|
||||
int growth = c->leb_cnt - old_leb_cnt;
|
||||
|
||||
if (c->leb_cnt < old_leb_cnt ||
|
||||
c->leb_cnt < UBIFS_MIN_LEB_CNT) {
|
||||
ubifs_err("bad leb_cnt on master node");
|
||||
dbg_dump_node(c, c->mst_node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dbg_mnt("Auto resizing (master) from %d LEBs to %d LEBs",
|
||||
old_leb_cnt, c->leb_cnt);
|
||||
c->lst.empty_lebs += growth;
|
||||
c->lst.total_free += growth * (long long)c->leb_size;
|
||||
c->lst.total_dark += growth * (long long)c->dark_wm;
|
||||
|
||||
/*
|
||||
* Reflect changes back onto the master node. N.B. the master
|
||||
* node gets written immediately whenever mounting (or
|
||||
* remounting) in read-write mode, so we do not need to write it
|
||||
* here.
|
||||
*/
|
||||
c->mst_node->leb_cnt = cpu_to_le32(c->leb_cnt);
|
||||
c->mst_node->empty_lebs = cpu_to_le32(c->lst.empty_lebs);
|
||||
c->mst_node->total_free = cpu_to_le64(c->lst.total_free);
|
||||
c->mst_node->total_dark = cpu_to_le64(c->lst.total_dark);
|
||||
}
|
||||
|
||||
err = validate_master(c);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = dbg_old_index_check_init(c, &c->zroot);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_write_master - write master node.
|
||||
* @c: UBIFS file-system description object
|
||||
*
|
||||
* This function writes the master node. The caller has to take the
|
||||
* @c->mst_mutex lock before calling this function. Returns zero in case of
|
||||
* success and a negative error code in case of failure. The master node is
|
||||
* written twice to enable recovery.
|
||||
*/
|
||||
int ubifs_write_master(struct ubifs_info *c)
|
||||
{
|
||||
int err, lnum, offs, len;
|
||||
|
||||
if (c->ro_media)
|
||||
return -EINVAL;
|
||||
|
||||
lnum = UBIFS_MST_LNUM;
|
||||
offs = c->mst_offs + c->mst_node_alsz;
|
||||
len = UBIFS_MST_NODE_SZ;
|
||||
|
||||
if (offs + UBIFS_MST_NODE_SZ > c->leb_size) {
|
||||
err = ubifs_leb_unmap(c, lnum);
|
||||
if (err)
|
||||
return err;
|
||||
offs = 0;
|
||||
}
|
||||
|
||||
c->mst_offs = offs;
|
||||
c->mst_node->highest_inum = cpu_to_le64(c->highest_inum);
|
||||
|
||||
err = ubifs_write_node(c, c->mst_node, len, lnum, offs, UBI_SHORTTERM);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
lnum += 1;
|
||||
|
||||
if (offs == 0) {
|
||||
err = ubifs_leb_unmap(c, lnum);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
err = ubifs_write_node(c, c->mst_node, len, lnum, offs, UBI_SHORTTERM);
|
||||
|
||||
return err;
|
||||
}
|
||||
342
fs/ubifs/misc.h
Normal file
342
fs/ubifs/misc.h
Normal file
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
* This file is part of UBIFS.
|
||||
*
|
||||
* Copyright (C) 2006-2008 Nokia Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Authors: Artem Bityutskiy (Битюцкий Артём)
|
||||
* Adrian Hunter
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains miscellaneous helper functions.
|
||||
*/
|
||||
|
||||
#ifndef __UBIFS_MISC_H__
|
||||
#define __UBIFS_MISC_H__
|
||||
|
||||
/**
|
||||
* ubifs_zn_dirty - check if znode is dirty.
|
||||
* @znode: znode to check
|
||||
*
|
||||
* This helper function returns %1 if @znode is dirty and %0 otherwise.
|
||||
*/
|
||||
static inline int ubifs_zn_dirty(const struct ubifs_znode *znode)
|
||||
{
|
||||
return !!test_bit(DIRTY_ZNODE, &znode->flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_wake_up_bgt - wake up background thread.
|
||||
* @c: UBIFS file-system description object
|
||||
*/
|
||||
static inline void ubifs_wake_up_bgt(struct ubifs_info *c)
|
||||
{
|
||||
if (c->bgt && !c->need_bgt) {
|
||||
c->need_bgt = 1;
|
||||
wake_up_process(c->bgt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_tnc_find_child - find next child in znode.
|
||||
* @znode: znode to search at
|
||||
* @start: the zbranch index to start at
|
||||
*
|
||||
* This helper function looks for znode child starting at index @start. Returns
|
||||
* the child or %NULL if no children were found.
|
||||
*/
|
||||
static inline struct ubifs_znode *
|
||||
ubifs_tnc_find_child(struct ubifs_znode *znode, int start)
|
||||
{
|
||||
while (start < znode->child_cnt) {
|
||||
if (znode->zbranch[start].znode)
|
||||
return znode->zbranch[start].znode;
|
||||
start += 1;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_inode - get UBIFS inode information by VFS 'struct inode' object.
|
||||
* @inode: the VFS 'struct inode' pointer
|
||||
*/
|
||||
static inline struct ubifs_inode *ubifs_inode(const struct inode *inode)
|
||||
{
|
||||
return container_of(inode, struct ubifs_inode, vfs_inode);
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_ro_mode - switch UBIFS to read read-only mode.
|
||||
* @c: UBIFS file-system description object
|
||||
* @err: error code which is the reason of switching to R/O mode
|
||||
*/
|
||||
static inline void ubifs_ro_mode(struct ubifs_info *c, int err)
|
||||
{
|
||||
if (!c->ro_media) {
|
||||
c->ro_media = 1;
|
||||
ubifs_warn("switched to read-only mode, error %d", err);
|
||||
dbg_dump_stack();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_compr_present - check if compressor was compiled in.
|
||||
* @compr_type: compressor type to check
|
||||
*
|
||||
* This function returns %1 of compressor of type @compr_type is present, and
|
||||
* %0 if not.
|
||||
*/
|
||||
static inline int ubifs_compr_present(int compr_type)
|
||||
{
|
||||
ubifs_assert(compr_type >= 0 && compr_type < UBIFS_COMPR_TYPES_CNT);
|
||||
return !!ubifs_compressors[compr_type]->capi_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_compr_name - get compressor name string by its type.
|
||||
* @compr_type: compressor type
|
||||
*
|
||||
* This function returns compressor type string.
|
||||
*/
|
||||
static inline const char *ubifs_compr_name(int compr_type)
|
||||
{
|
||||
ubifs_assert(compr_type >= 0 && compr_type < UBIFS_COMPR_TYPES_CNT);
|
||||
return ubifs_compressors[compr_type]->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_wbuf_sync - synchronize write-buffer.
|
||||
* @wbuf: write-buffer to synchronize
|
||||
*
|
||||
* This is the same as as 'ubifs_wbuf_sync_nolock()' but it does not assume
|
||||
* that the write-buffer is already locked.
|
||||
*/
|
||||
static inline int ubifs_wbuf_sync(struct ubifs_wbuf *wbuf)
|
||||
{
|
||||
int err;
|
||||
|
||||
mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
|
||||
err = ubifs_wbuf_sync_nolock(wbuf);
|
||||
mutex_unlock(&wbuf->io_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_leb_unmap - unmap an LEB.
|
||||
* @c: UBIFS file-system description object
|
||||
* @lnum: LEB number to unmap
|
||||
*
|
||||
* This function returns %0 on success and a negative error code on failure.
|
||||
*/
|
||||
static inline int ubifs_leb_unmap(const struct ubifs_info *c, int lnum)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (c->ro_media)
|
||||
return -EROFS;
|
||||
err = ubi_leb_unmap(c->ubi, lnum);
|
||||
if (err) {
|
||||
ubifs_err("unmap LEB %d failed, error %d", lnum, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_leb_write - write to a LEB.
|
||||
* @c: UBIFS file-system description object
|
||||
* @lnum: LEB number to write
|
||||
* @buf: buffer to write from
|
||||
* @offs: offset within LEB to write to
|
||||
* @len: length to write
|
||||
* @dtype: data type
|
||||
*
|
||||
* This function returns %0 on success and a negative error code on failure.
|
||||
*/
|
||||
static inline int ubifs_leb_write(const struct ubifs_info *c, int lnum,
|
||||
const void *buf, int offs, int len, int dtype)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (c->ro_media)
|
||||
return -EROFS;
|
||||
err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
|
||||
if (err) {
|
||||
ubifs_err("writing %d bytes at %d:%d, error %d",
|
||||
len, lnum, offs, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_leb_change - atomic LEB change.
|
||||
* @c: UBIFS file-system description object
|
||||
* @lnum: LEB number to write
|
||||
* @buf: buffer to write from
|
||||
* @len: length to write
|
||||
* @dtype: data type
|
||||
*
|
||||
* This function returns %0 on success and a negative error code on failure.
|
||||
*/
|
||||
static inline int ubifs_leb_change(const struct ubifs_info *c, int lnum,
|
||||
const void *buf, int len, int dtype)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (c->ro_media)
|
||||
return -EROFS;
|
||||
err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
|
||||
if (err) {
|
||||
ubifs_err("changing %d bytes in LEB %d, error %d",
|
||||
len, lnum, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_encode_dev - encode device node IDs.
|
||||
* @dev: UBIFS device node information
|
||||
* @rdev: device IDs to encode
|
||||
*
|
||||
* This is a helper function which encodes major/minor numbers of a device node
|
||||
* into UBIFS device node description. We use standard Linux "new" and "huge"
|
||||
* encodings.
|
||||
*/
|
||||
static inline int ubifs_encode_dev(union ubifs_dev_desc *dev, dev_t rdev)
|
||||
{
|
||||
if (new_valid_dev(rdev)) {
|
||||
dev->new = cpu_to_le32(new_encode_dev(rdev));
|
||||
return sizeof(dev->new);
|
||||
} else {
|
||||
dev->huge = cpu_to_le64(huge_encode_dev(rdev));
|
||||
return sizeof(dev->huge);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_add_dirt - add dirty space to LEB properties.
|
||||
* @c: the UBIFS file-system description object
|
||||
* @lnum: LEB to add dirty space for
|
||||
* @dirty: dirty space to add
|
||||
*
|
||||
* This is a helper function which increased amount of dirty LEB space. Returns
|
||||
* zero in case of success and a negative error code in case of failure.
|
||||
*/
|
||||
static inline int ubifs_add_dirt(struct ubifs_info *c, int lnum, int dirty)
|
||||
{
|
||||
return ubifs_update_one_lp(c, lnum, LPROPS_NC, dirty, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_return_leb - return LEB to lprops.
|
||||
* @c: the UBIFS file-system description object
|
||||
* @lnum: LEB to return
|
||||
*
|
||||
* This helper function cleans the "taken" flag of a logical eraseblock in the
|
||||
* lprops. Returns zero in case of success and a negative error code in case of
|
||||
* failure.
|
||||
*/
|
||||
static inline int ubifs_return_leb(struct ubifs_info *c, int lnum)
|
||||
{
|
||||
return ubifs_change_one_lp(c, lnum, LPROPS_NC, LPROPS_NC, 0,
|
||||
LPROPS_TAKEN, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_idx_node_sz - return index node size.
|
||||
* @c: the UBIFS file-system description object
|
||||
* @child_cnt: number of children of this index node
|
||||
*/
|
||||
static inline int ubifs_idx_node_sz(const struct ubifs_info *c, int child_cnt)
|
||||
{
|
||||
return UBIFS_IDX_NODE_SZ + (UBIFS_BRANCH_SZ + c->key_len) * child_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_idx_branch - return pointer to an index branch.
|
||||
* @c: the UBIFS file-system description object
|
||||
* @idx: index node
|
||||
* @bnum: branch number
|
||||
*/
|
||||
static inline
|
||||
struct ubifs_branch *ubifs_idx_branch(const struct ubifs_info *c,
|
||||
const struct ubifs_idx_node *idx,
|
||||
int bnum)
|
||||
{
|
||||
return (struct ubifs_branch *)((void *)idx->branches +
|
||||
(UBIFS_BRANCH_SZ + c->key_len) * bnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_idx_key - return pointer to an index key.
|
||||
* @c: the UBIFS file-system description object
|
||||
* @idx: index node
|
||||
*/
|
||||
static inline void *ubifs_idx_key(const struct ubifs_info *c,
|
||||
const struct ubifs_idx_node *idx)
|
||||
{
|
||||
return (void *)((struct ubifs_branch *)idx->branches)->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_reported_space - calculate reported free space.
|
||||
* @c: the UBIFS file-system description object
|
||||
* @free: amount of free space
|
||||
*
|
||||
* This function calculates amount of free space which will be reported to
|
||||
* user-space. User-space application tend to expect that if the file-system
|
||||
* (e.g., via the 'statfs()' call) reports that it has N bytes available, they
|
||||
* are able to write a file of size N. UBIFS attaches node headers to each data
|
||||
* node and it has to write indexind nodes as well. This introduces additional
|
||||
* overhead, and UBIFS it has to report sligtly less free space to meet the
|
||||
* above expectetion.
|
||||
*
|
||||
* This function assumes free space is made up of uncompressed data nodes and
|
||||
* full index nodes (one per data node, doubled because we always allow enough
|
||||
* space to write the index twice).
|
||||
*
|
||||
* Note, the calculation is pessimistic, which means that most of the time
|
||||
* UBIFS reports less space than it actually has.
|
||||
*/
|
||||
static inline long long ubifs_reported_space(const struct ubifs_info *c,
|
||||
uint64_t free)
|
||||
{
|
||||
int divisor, factor;
|
||||
|
||||
divisor = UBIFS_MAX_DATA_NODE_SZ + (c->max_idx_node_sz << 1);
|
||||
factor = UBIFS_MAX_DATA_NODE_SZ - UBIFS_DATA_NODE_SZ;
|
||||
do_div(free, divisor);
|
||||
|
||||
return free * factor;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_current_time - round current time to time granularity.
|
||||
* @inode: inode
|
||||
*/
|
||||
static inline struct timespec ubifs_current_time(struct inode *inode)
|
||||
{
|
||||
return (inode->i_sb->s_time_gran < NSEC_PER_SEC) ?
|
||||
current_fs_time(inode->i_sb) : CURRENT_TIME_SEC;
|
||||
}
|
||||
|
||||
#endif /* __UBIFS_MISC_H__ */
|
||||
958
fs/ubifs/orphan.c
Normal file
958
fs/ubifs/orphan.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user