befs fixes for 4.9-rc1
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJYAnNOAAoJEGu/nxmHO1GNOzQH/3p+j1yPUR08+qhlZBdF/vCH i9Qb13yUT8yEN9tCZ7bsMhRZYQ70GuPMtLJbhklwGmnDAEZwzGoCrokexCsKoKiv 0RmzLUsbN7GM6LFXOyTj3QwFGxjQnVzk5TKXSR2qUpqvvffFsAFlTpg/JqRNpTjF c85naRDFYmZ3fGi2mT/emoY8MAu90XnjWbAMrg+uipsriBqOcbUD487CubDeR0CK svO3JSvv2W6vjMVzkLSWnpFrhiWmqAcOHFS4NEcCeQaJkDmyRCnmVNXBaB1YGZey 47+r8oLo64oByCt+Z60Dxb5rwDJfDLLDfRQeDOltgR4i2nnSZ5cS21V55Z5alqg= =sDD1 -----END PGP SIGNATURE----- Merge tag 'befs-v4.9-rc1' of git://github.com/luisbg/linux-befs Pull befs fixes from Luis de Bethencourt: "I recently took maintainership of the befs file system [0]. This is the first time I send you a git pull request, so please let me know if all the below is OK. Salah Triki and myself have been cleaning the code and fixing a few small bugs. Sorry I couldn't send this sooner in the merge window, I was waiting to have my GPG key signed by kernel members at ELCE in Berlin a few days ago." [0] https://lkml.org/lkml/2016/7/27/502 * tag 'befs-v4.9-rc1' of git://github.com/luisbg/linux-befs: (39 commits) befs: befs: fix style issues in datastream.c befs: improve documentation in datastream.c befs: fix typos in datastream.c befs: fix typos in btree.c befs: fix style issues in super.c befs: fix comment style befs: add check for ag_shift in superblock befs: dump inode_size superblock information befs: remove unnecessary initialization befs: fix typo in befs_sb_info befs: add flags field to validate superblock state befs: fix typo in befs_find_key befs: remove unused BEFS_BT_PARMATCH fs: befs: remove ret variable fs: befs: remove in vain variable assignment fs: befs: remove unnecessary *befs_sb variable fs: befs: remove useless initialization to zero fs: befs: remove in vain variable assignment fs: befs: Insert NULL inode to dentry fs: befs: Remove useless calls to brelse in befs_find_brun_dblindirect ...
This commit is contained in:
Коммит
df34d04a6f
|
@ -43,7 +43,10 @@ struct befs_sb_info {
|
||||||
u32 ag_shift;
|
u32 ag_shift;
|
||||||
u32 num_ags;
|
u32 num_ags;
|
||||||
|
|
||||||
/* jornal log entry */
|
/* State of the superblock */
|
||||||
|
u32 flags;
|
||||||
|
|
||||||
|
/* Journal log entry */
|
||||||
befs_block_run log_blocks;
|
befs_block_run log_blocks;
|
||||||
befs_off_t log_start;
|
befs_off_t log_start;
|
||||||
befs_off_t log_end;
|
befs_off_t log_end;
|
||||||
|
@ -79,7 +82,7 @@ enum befs_err {
|
||||||
BEFS_BT_END,
|
BEFS_BT_END,
|
||||||
BEFS_BT_EMPTY,
|
BEFS_BT_EMPTY,
|
||||||
BEFS_BT_MATCH,
|
BEFS_BT_MATCH,
|
||||||
BEFS_BT_PARMATCH,
|
BEFS_BT_OVERFLOW,
|
||||||
BEFS_BT_NOT_FOUND
|
BEFS_BT_NOT_FOUND
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -140,18 +143,6 @@ befs_iaddrs_per_block(struct super_block *sb)
|
||||||
return BEFS_SB(sb)->block_size / sizeof (befs_disk_inode_addr);
|
return BEFS_SB(sb)->block_size / sizeof (befs_disk_inode_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
|
||||||
befs_iaddr_is_empty(const befs_inode_addr *iaddr)
|
|
||||||
{
|
|
||||||
return (!iaddr->allocation_group) && (!iaddr->start) && (!iaddr->len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline size_t
|
|
||||||
befs_brun_size(struct super_block *sb, befs_block_run run)
|
|
||||||
{
|
|
||||||
return BEFS_SB(sb)->block_size * run.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "endian.h"
|
#include "endian.h"
|
||||||
|
|
||||||
#endif /* _LINUX_BEFS_H */
|
#endif /* _LINUX_BEFS_H */
|
||||||
|
|
|
@ -85,7 +85,7 @@ struct befs_btree_node {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* local constants */
|
/* local constants */
|
||||||
static const befs_off_t befs_bt_inval = 0xffffffffffffffffULL;
|
static const befs_off_t BEFS_BT_INVAL = 0xffffffffffffffffULL;
|
||||||
|
|
||||||
/* local functions */
|
/* local functions */
|
||||||
static int befs_btree_seekleaf(struct super_block *sb, const befs_data_stream *ds,
|
static int befs_btree_seekleaf(struct super_block *sb, const befs_data_stream *ds,
|
||||||
|
@ -156,8 +156,6 @@ befs_bt_read_super(struct super_block *sb, const befs_data_stream *ds,
|
||||||
sup->max_depth = fs32_to_cpu(sb, od_sup->max_depth);
|
sup->max_depth = fs32_to_cpu(sb, od_sup->max_depth);
|
||||||
sup->data_type = fs32_to_cpu(sb, od_sup->data_type);
|
sup->data_type = fs32_to_cpu(sb, od_sup->data_type);
|
||||||
sup->root_node_ptr = fs64_to_cpu(sb, od_sup->root_node_ptr);
|
sup->root_node_ptr = fs64_to_cpu(sb, od_sup->root_node_ptr);
|
||||||
sup->free_node_ptr = fs64_to_cpu(sb, od_sup->free_node_ptr);
|
|
||||||
sup->max_size = fs64_to_cpu(sb, od_sup->max_size);
|
|
||||||
|
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
if (sup->magic != BEFS_BTREE_MAGIC) {
|
if (sup->magic != BEFS_BTREE_MAGIC) {
|
||||||
|
@ -183,8 +181,8 @@ befs_bt_read_super(struct super_block *sb, const befs_data_stream *ds,
|
||||||
* Calls befs_read_datastream to read in the indicated btree node and
|
* Calls befs_read_datastream to read in the indicated btree node and
|
||||||
* makes sure its header fields are in cpu byteorder, byteswapping if
|
* makes sure its header fields are in cpu byteorder, byteswapping if
|
||||||
* necessary.
|
* necessary.
|
||||||
* Note: node->bh must be NULL when this function called first
|
* Note: node->bh must be NULL when this function is called the first time.
|
||||||
* time. Don't forget brelse(node->bh) after last call.
|
* Don't forget brelse(node->bh) after last call.
|
||||||
*
|
*
|
||||||
* On success, returns BEFS_OK and *@node contains the btree node that
|
* On success, returns BEFS_OK and *@node contains the btree node that
|
||||||
* starts at @node_off, with the node->head fields in cpu byte order.
|
* starts at @node_off, with the node->head fields in cpu byte order.
|
||||||
|
@ -244,7 +242,7 @@ befs_bt_read_node(struct super_block *sb, const befs_data_stream *ds,
|
||||||
* Read the superblock and rootnode of the b+tree.
|
* Read the superblock and rootnode of the b+tree.
|
||||||
* Drill down through the interior nodes using befs_find_key().
|
* Drill down through the interior nodes using befs_find_key().
|
||||||
* Once at the correct leaf node, use befs_find_key() again to get the
|
* Once at the correct leaf node, use befs_find_key() again to get the
|
||||||
* actuall value stored with the key.
|
* actual value stored with the key.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
befs_btree_find(struct super_block *sb, const befs_data_stream *ds,
|
befs_btree_find(struct super_block *sb, const befs_data_stream *ds,
|
||||||
|
@ -283,9 +281,9 @@ befs_btree_find(struct super_block *sb, const befs_data_stream *ds,
|
||||||
|
|
||||||
while (!befs_leafnode(this_node)) {
|
while (!befs_leafnode(this_node)) {
|
||||||
res = befs_find_key(sb, this_node, key, &node_off);
|
res = befs_find_key(sb, this_node, key, &node_off);
|
||||||
if (res == BEFS_BT_NOT_FOUND)
|
/* if no key set, try the overflow node */
|
||||||
|
if (res == BEFS_BT_OVERFLOW)
|
||||||
node_off = this_node->head.overflow;
|
node_off = this_node->head.overflow;
|
||||||
/* if no match, go to overflow node */
|
|
||||||
if (befs_bt_read_node(sb, ds, this_node, node_off) != BEFS_OK) {
|
if (befs_bt_read_node(sb, ds, this_node, node_off) != BEFS_OK) {
|
||||||
befs_error(sb, "befs_btree_find() failed to read "
|
befs_error(sb, "befs_btree_find() failed to read "
|
||||||
"node at %llu", node_off);
|
"node at %llu", node_off);
|
||||||
|
@ -293,15 +291,15 @@ befs_btree_find(struct super_block *sb, const befs_data_stream *ds,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* at the correct leaf node now */
|
/* at a leaf node now, check if it is correct */
|
||||||
|
|
||||||
res = befs_find_key(sb, this_node, key, value);
|
res = befs_find_key(sb, this_node, key, value);
|
||||||
|
|
||||||
brelse(this_node->bh);
|
brelse(this_node->bh);
|
||||||
kfree(this_node);
|
kfree(this_node);
|
||||||
|
|
||||||
if (res != BEFS_BT_MATCH) {
|
if (res != BEFS_BT_MATCH) {
|
||||||
befs_debug(sb, "<--- %s Key %s not found", __func__, key);
|
befs_error(sb, "<--- %s Key %s not found", __func__, key);
|
||||||
|
befs_debug(sb, "<--- %s ERROR", __func__);
|
||||||
*value = 0;
|
*value = 0;
|
||||||
return BEFS_BT_NOT_FOUND;
|
return BEFS_BT_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
@ -324,16 +322,12 @@ befs_btree_find(struct super_block *sb, const befs_data_stream *ds,
|
||||||
* @findkey: Keystring to search for
|
* @findkey: Keystring to search for
|
||||||
* @value: If key is found, the value stored with the key is put here
|
* @value: If key is found, the value stored with the key is put here
|
||||||
*
|
*
|
||||||
* finds exact match if one exists, and returns BEFS_BT_MATCH
|
* Finds exact match if one exists, and returns BEFS_BT_MATCH.
|
||||||
* If no exact match, finds first key in node that is greater
|
* If there is no match and node's value array is too small for key, return
|
||||||
* (alphabetically) than the search key and returns BEFS_BT_PARMATCH
|
* BEFS_BT_OVERFLOW.
|
||||||
* (for partial match, I guess). Can you think of something better to
|
* If no match and node should countain this key, return BEFS_BT_NOT_FOUND.
|
||||||
* call it?
|
|
||||||
*
|
*
|
||||||
* If no key was a match or greater than the search key, return
|
* Uses binary search instead of a linear.
|
||||||
* BEFS_BT_NOT_FOUND.
|
|
||||||
*
|
|
||||||
* Use binary search instead of a linear.
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
befs_find_key(struct super_block *sb, struct befs_btree_node *node,
|
befs_find_key(struct super_block *sb, struct befs_btree_node *node,
|
||||||
|
@ -348,18 +342,16 @@ befs_find_key(struct super_block *sb, struct befs_btree_node *node,
|
||||||
|
|
||||||
befs_debug(sb, "---> %s %s", __func__, findkey);
|
befs_debug(sb, "---> %s %s", __func__, findkey);
|
||||||
|
|
||||||
*value = 0;
|
|
||||||
|
|
||||||
findkey_len = strlen(findkey);
|
findkey_len = strlen(findkey);
|
||||||
|
|
||||||
/* if node can not contain key, just skeep this node */
|
/* if node can not contain key, just skip this node */
|
||||||
last = node->head.all_key_count - 1;
|
last = node->head.all_key_count - 1;
|
||||||
thiskey = befs_bt_get_key(sb, node, last, &keylen);
|
thiskey = befs_bt_get_key(sb, node, last, &keylen);
|
||||||
|
|
||||||
eq = befs_compare_strings(thiskey, keylen, findkey, findkey_len);
|
eq = befs_compare_strings(thiskey, keylen, findkey, findkey_len);
|
||||||
if (eq < 0) {
|
if (eq < 0) {
|
||||||
befs_debug(sb, "<--- %s %s not found", __func__, findkey);
|
befs_debug(sb, "<--- node can't contain %s", findkey);
|
||||||
return BEFS_BT_NOT_FOUND;
|
return BEFS_BT_OVERFLOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
valarray = befs_bt_valarray(node);
|
valarray = befs_bt_valarray(node);
|
||||||
|
@ -387,12 +379,15 @@ befs_find_key(struct super_block *sb, struct befs_btree_node *node,
|
||||||
else
|
else
|
||||||
first = mid + 1;
|
first = mid + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return an existing value so caller can arrive to a leaf node */
|
||||||
if (eq < 0)
|
if (eq < 0)
|
||||||
*value = fs64_to_cpu(sb, valarray[mid + 1]);
|
*value = fs64_to_cpu(sb, valarray[mid + 1]);
|
||||||
else
|
else
|
||||||
*value = fs64_to_cpu(sb, valarray[mid]);
|
*value = fs64_to_cpu(sb, valarray[mid]);
|
||||||
befs_debug(sb, "<--- %s found %s at %d", __func__, thiskey, mid);
|
befs_error(sb, "<--- %s %s not found", __func__, findkey);
|
||||||
return BEFS_BT_PARMATCH;
|
befs_debug(sb, "<--- %s ERROR", __func__);
|
||||||
|
return BEFS_BT_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -405,7 +400,7 @@ befs_find_key(struct super_block *sb, struct befs_btree_node *node,
|
||||||
* @keysize: Length of the returned key
|
* @keysize: Length of the returned key
|
||||||
* @value: Value stored with the returned key
|
* @value: Value stored with the returned key
|
||||||
*
|
*
|
||||||
* Heres how it works: Key_no is the index of the key/value pair to
|
* Here's how it works: Key_no is the index of the key/value pair to
|
||||||
* return in keybuf/value.
|
* return in keybuf/value.
|
||||||
* Bufsize is the size of keybuf (BEFS_NAME_LEN+1 is a good size). Keysize is
|
* Bufsize is the size of keybuf (BEFS_NAME_LEN+1 is a good size). Keysize is
|
||||||
* the number of characters in the key (just a convenience).
|
* the number of characters in the key (just a convenience).
|
||||||
|
@ -422,7 +417,7 @@ befs_btree_read(struct super_block *sb, const befs_data_stream *ds,
|
||||||
{
|
{
|
||||||
struct befs_btree_node *this_node;
|
struct befs_btree_node *this_node;
|
||||||
befs_btree_super bt_super;
|
befs_btree_super bt_super;
|
||||||
befs_off_t node_off = 0;
|
befs_off_t node_off;
|
||||||
int cur_key;
|
int cur_key;
|
||||||
fs64 *valarray;
|
fs64 *valarray;
|
||||||
char *keystart;
|
char *keystart;
|
||||||
|
@ -467,7 +462,7 @@ befs_btree_read(struct super_block *sb, const befs_data_stream *ds,
|
||||||
while (key_sum + this_node->head.all_key_count <= key_no) {
|
while (key_sum + this_node->head.all_key_count <= key_no) {
|
||||||
|
|
||||||
/* no more nodes to look in: key_no is too large */
|
/* no more nodes to look in: key_no is too large */
|
||||||
if (this_node->head.right == befs_bt_inval) {
|
if (this_node->head.right == BEFS_BT_INVAL) {
|
||||||
*keysize = 0;
|
*keysize = 0;
|
||||||
*value = 0;
|
*value = 0;
|
||||||
befs_debug(sb,
|
befs_debug(sb,
|
||||||
|
@ -541,7 +536,6 @@ befs_btree_read(struct super_block *sb, const befs_data_stream *ds,
|
||||||
* @node_off: Pointer to offset of current node within datastream. Modified
|
* @node_off: Pointer to offset of current node within datastream. Modified
|
||||||
* by the function.
|
* by the function.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* Helper function for btree traverse. Moves the current position to the
|
* Helper function for btree traverse. Moves the current position to the
|
||||||
* start of the first leaf node.
|
* start of the first leaf node.
|
||||||
*
|
*
|
||||||
|
@ -608,7 +602,7 @@ static int
|
||||||
befs_leafnode(struct befs_btree_node *node)
|
befs_leafnode(struct befs_btree_node *node)
|
||||||
{
|
{
|
||||||
/* all interior nodes (and only interior nodes) have an overflow node */
|
/* all interior nodes (and only interior nodes) have an overflow node */
|
||||||
if (node->head.overflow == befs_bt_inval)
|
if (node->head.overflow == BEFS_BT_INVAL)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -715,7 +709,7 @@ befs_bt_get_key(struct super_block *sb, struct befs_btree_node *node,
|
||||||
*
|
*
|
||||||
* Returns 0 if @key1 and @key2 are equal.
|
* Returns 0 if @key1 and @key2 are equal.
|
||||||
* Returns >0 if @key1 is greater.
|
* Returns >0 if @key1 is greater.
|
||||||
* Returns <0 if @key2 is greater..
|
* Returns <0 if @key2 is greater.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
befs_compare_strings(const void *key1, int keylen1,
|
befs_compare_strings(const void *key1, int keylen1,
|
||||||
|
|
|
@ -37,7 +37,7 @@ static int befs_find_brun_dblindirect(struct super_block *sb,
|
||||||
/**
|
/**
|
||||||
* befs_read_datastream - get buffer_head containing data, starting from pos.
|
* befs_read_datastream - get buffer_head containing data, starting from pos.
|
||||||
* @sb: Filesystem superblock
|
* @sb: Filesystem superblock
|
||||||
* @ds: datastrem to find data with
|
* @ds: datastream to find data with
|
||||||
* @pos: start of data
|
* @pos: start of data
|
||||||
* @off: offset of data in buffer_head->b_data
|
* @off: offset of data in buffer_head->b_data
|
||||||
*
|
*
|
||||||
|
@ -75,7 +75,13 @@ befs_read_datastream(struct super_block *sb, const befs_data_stream *ds,
|
||||||
return bh;
|
return bh;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
|
* befs_fblock2brun - give back block run for fblock
|
||||||
|
* @sb: the superblock
|
||||||
|
* @data: datastream to read from
|
||||||
|
* @fblock: the blocknumber with the file position to find
|
||||||
|
* @run: The found run is passed back through this pointer
|
||||||
|
*
|
||||||
* Takes a file position and gives back a brun who's starting block
|
* Takes a file position and gives back a brun who's starting block
|
||||||
* is block number fblock of the file.
|
* is block number fblock of the file.
|
||||||
*
|
*
|
||||||
|
@ -115,7 +121,7 @@ befs_fblock2brun(struct super_block *sb, const befs_data_stream *data,
|
||||||
/**
|
/**
|
||||||
* befs_read_lsmylink - read long symlink from datastream.
|
* befs_read_lsmylink - read long symlink from datastream.
|
||||||
* @sb: Filesystem superblock
|
* @sb: Filesystem superblock
|
||||||
* @ds: Datastrem to read from
|
* @ds: Datastream to read from
|
||||||
* @buff: Buffer in which to place long symlink data
|
* @buff: Buffer in which to place long symlink data
|
||||||
* @len: Length of the long symlink in bytes
|
* @len: Length of the long symlink in bytes
|
||||||
*
|
*
|
||||||
|
@ -128,6 +134,7 @@ befs_read_lsymlink(struct super_block *sb, const befs_data_stream *ds,
|
||||||
befs_off_t bytes_read = 0; /* bytes readed */
|
befs_off_t bytes_read = 0; /* bytes readed */
|
||||||
u16 plen;
|
u16 plen;
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
|
|
||||||
befs_debug(sb, "---> %s length: %llu", __func__, len);
|
befs_debug(sb, "---> %s length: %llu", __func__, len);
|
||||||
|
|
||||||
while (bytes_read < len) {
|
while (bytes_read < len) {
|
||||||
|
@ -183,13 +190,13 @@ befs_count_blocks(struct super_block *sb, const befs_data_stream *ds)
|
||||||
metablocks += ds->indirect.len;
|
metablocks += ds->indirect.len;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Double indir block, plus all the indirect blocks it mapps
|
* Double indir block, plus all the indirect blocks it maps.
|
||||||
In the double-indirect range, all block runs of data are
|
* In the double-indirect range, all block runs of data are
|
||||||
BEFS_DBLINDIR_BRUN_LEN blocks long. Therefore, we know
|
* BEFS_DBLINDIR_BRUN_LEN blocks long. Therefore, we know
|
||||||
how many data block runs are in the double-indirect region,
|
* how many data block runs are in the double-indirect region,
|
||||||
and from that we know how many indirect blocks it takes to
|
* and from that we know how many indirect blocks it takes to
|
||||||
map them. We assume that the indirect blocks are also
|
* map them. We assume that the indirect blocks are also
|
||||||
BEFS_DBLINDIR_BRUN_LEN blocks long.
|
* BEFS_DBLINDIR_BRUN_LEN blocks long.
|
||||||
*/
|
*/
|
||||||
if (ds->size > ds->max_indirect_range && ds->max_indirect_range != 0) {
|
if (ds->size > ds->max_indirect_range && ds->max_indirect_range != 0) {
|
||||||
uint dbl_bytes;
|
uint dbl_bytes;
|
||||||
|
@ -212,35 +219,34 @@ befs_count_blocks(struct super_block *sb, const befs_data_stream *ds)
|
||||||
return blocks;
|
return blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Finds the block run that starts at file block number blockno
|
* befs_find_brun_direct - find a direct block run in the datastream
|
||||||
in the file represented by the datastream data, if that
|
* @sb: the superblock
|
||||||
blockno is in the direct region of the datastream.
|
* @data: the datastream
|
||||||
|
* @blockno: the blocknumber to find
|
||||||
sb: the superblock
|
* @run: The found run is passed back through this pointer
|
||||||
data: the datastream
|
*
|
||||||
blockno: the blocknumber to find
|
* Finds the block run that starts at file block number blockno
|
||||||
run: The found run is passed back through this pointer
|
* in the file represented by the datastream data, if that
|
||||||
|
* blockno is in the direct region of the datastream.
|
||||||
Return value is BEFS_OK if the blockrun is found, BEFS_ERR
|
*
|
||||||
otherwise.
|
* Return value is BEFS_OK if the blockrun is found, BEFS_ERR
|
||||||
|
* otherwise.
|
||||||
Algorithm:
|
*
|
||||||
Linear search. Checks each element of array[] to see if it
|
* Algorithm:
|
||||||
contains the blockno-th filesystem block. This is necessary
|
* Linear search. Checks each element of array[] to see if it
|
||||||
because the block runs map variable amounts of data. Simply
|
* contains the blockno-th filesystem block. This is necessary
|
||||||
keeps a count of the number of blocks searched so far (sum),
|
* because the block runs map variable amounts of data. Simply
|
||||||
incrementing this by the length of each block run as we come
|
* keeps a count of the number of blocks searched so far (sum),
|
||||||
across it. Adds sum to *count before returning (this is so
|
* incrementing this by the length of each block run as we come
|
||||||
you can search multiple arrays that are logicaly one array,
|
* across it. Adds sum to *count before returning (this is so
|
||||||
as in the indirect region code).
|
* you can search multiple arrays that are logicaly one array,
|
||||||
|
* as in the indirect region code).
|
||||||
When/if blockno is found, if blockno is inside of a block
|
*
|
||||||
run as stored on disk, we offset the start and length members
|
* When/if blockno is found, if blockno is inside of a block
|
||||||
of the block run, so that blockno is the start and len is
|
* run as stored on disk, we offset the start and length members
|
||||||
still valid (the run ends in the same place).
|
* of the block run, so that blockno is the start and len is
|
||||||
|
* still valid (the run ends in the same place).
|
||||||
2001-11-15 Will Dyson
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
befs_find_brun_direct(struct super_block *sb, const befs_data_stream *data,
|
befs_find_brun_direct(struct super_block *sb, const befs_data_stream *data,
|
||||||
|
@ -249,21 +255,14 @@ befs_find_brun_direct(struct super_block *sb, const befs_data_stream *data,
|
||||||
int i;
|
int i;
|
||||||
const befs_block_run *array = data->direct;
|
const befs_block_run *array = data->direct;
|
||||||
befs_blocknr_t sum;
|
befs_blocknr_t sum;
|
||||||
befs_blocknr_t max_block =
|
|
||||||
data->max_direct_range >> BEFS_SB(sb)->block_shift;
|
|
||||||
|
|
||||||
befs_debug(sb, "---> %s, find %lu", __func__, (unsigned long)blockno);
|
befs_debug(sb, "---> %s, find %lu", __func__, (unsigned long)blockno);
|
||||||
|
|
||||||
if (blockno > max_block) {
|
|
||||||
befs_error(sb, "%s passed block outside of direct region",
|
|
||||||
__func__);
|
|
||||||
return BEFS_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0, sum = 0; i < BEFS_NUM_DIRECT_BLOCKS;
|
for (i = 0, sum = 0; i < BEFS_NUM_DIRECT_BLOCKS;
|
||||||
sum += array[i].len, i++) {
|
sum += array[i].len, i++) {
|
||||||
if (blockno >= sum && blockno < sum + (array[i].len)) {
|
if (blockno >= sum && blockno < sum + (array[i].len)) {
|
||||||
int offset = blockno - sum;
|
int offset = blockno - sum;
|
||||||
|
|
||||||
run->allocation_group = array[i].allocation_group;
|
run->allocation_group = array[i].allocation_group;
|
||||||
run->start = array[i].start + offset;
|
run->start = array[i].start + offset;
|
||||||
run->len = array[i].len - offset;
|
run->len = array[i].len - offset;
|
||||||
|
@ -275,32 +274,33 @@ befs_find_brun_direct(struct super_block *sb, const befs_data_stream *data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
befs_error(sb, "%s failed to find file block %lu", __func__,
|
||||||
|
(unsigned long)blockno);
|
||||||
befs_debug(sb, "---> %s ERROR", __func__);
|
befs_debug(sb, "---> %s ERROR", __func__);
|
||||||
return BEFS_ERR;
|
return BEFS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Finds the block run that starts at file block number blockno
|
* befs_find_brun_indirect - find a block run in the datastream
|
||||||
in the file represented by the datastream data, if that
|
* @sb: the superblock
|
||||||
blockno is in the indirect region of the datastream.
|
* @data: the datastream
|
||||||
|
* @blockno: the blocknumber to find
|
||||||
sb: the superblock
|
* @run: The found run is passed back through this pointer
|
||||||
data: the datastream
|
*
|
||||||
blockno: the blocknumber to find
|
* Finds the block run that starts at file block number blockno
|
||||||
run: The found run is passed back through this pointer
|
* in the file represented by the datastream data, if that
|
||||||
|
* blockno is in the indirect region of the datastream.
|
||||||
Return value is BEFS_OK if the blockrun is found, BEFS_ERR
|
*
|
||||||
otherwise.
|
* Return value is BEFS_OK if the blockrun is found, BEFS_ERR
|
||||||
|
* otherwise.
|
||||||
Algorithm:
|
*
|
||||||
For each block in the indirect run of the datastream, read
|
* Algorithm:
|
||||||
it in and search through it for search_blk.
|
* For each block in the indirect run of the datastream, read
|
||||||
|
* it in and search through it for search_blk.
|
||||||
XXX:
|
*
|
||||||
Really should check to make sure blockno is inside indirect
|
* XXX:
|
||||||
region.
|
* Really should check to make sure blockno is inside indirect
|
||||||
|
* region.
|
||||||
2001-11-15 Will Dyson
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
befs_find_brun_indirect(struct super_block *sb,
|
befs_find_brun_indirect(struct super_block *sb,
|
||||||
|
@ -326,11 +326,12 @@ befs_find_brun_indirect(struct super_block *sb,
|
||||||
|
|
||||||
/* Examine blocks of the indirect run one at a time */
|
/* Examine blocks of the indirect run one at a time */
|
||||||
for (i = 0; i < indirect.len; i++) {
|
for (i = 0; i < indirect.len; i++) {
|
||||||
indirblock = befs_bread(sb, indirblockno + i);
|
indirblock = sb_bread(sb, indirblockno + i);
|
||||||
if (indirblock == NULL) {
|
if (indirblock == NULL) {
|
||||||
befs_debug(sb, "---> %s failed to read "
|
befs_error(sb, "---> %s failed to read "
|
||||||
"disk block %lu from the indirect brun",
|
"disk block %lu from the indirect brun",
|
||||||
__func__, (unsigned long)indirblockno + i);
|
__func__, (unsigned long)indirblockno + i);
|
||||||
|
befs_debug(sb, "<--- %s ERROR", __func__);
|
||||||
return BEFS_ERR;
|
return BEFS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,46 +371,45 @@ befs_find_brun_indirect(struct super_block *sb,
|
||||||
return BEFS_ERR;
|
return BEFS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Finds the block run that starts at file block number blockno
|
* befs_find_brun_dblindirect - find a block run in the datastream
|
||||||
in the file represented by the datastream data, if that
|
* @sb: the superblock
|
||||||
blockno is in the double-indirect region of the datastream.
|
* @data: the datastream
|
||||||
|
* @blockno: the blocknumber to find
|
||||||
sb: the superblock
|
* @run: The found run is passed back through this pointer
|
||||||
data: the datastream
|
*
|
||||||
blockno: the blocknumber to find
|
* Finds the block run that starts at file block number blockno
|
||||||
run: The found run is passed back through this pointer
|
* in the file represented by the datastream data, if that
|
||||||
|
* blockno is in the double-indirect region of the datastream.
|
||||||
Return value is BEFS_OK if the blockrun is found, BEFS_ERR
|
*
|
||||||
otherwise.
|
* Return value is BEFS_OK if the blockrun is found, BEFS_ERR
|
||||||
|
* otherwise.
|
||||||
Algorithm:
|
*
|
||||||
The block runs in the double-indirect region are different.
|
* Algorithm:
|
||||||
They are always allocated 4 fs blocks at a time, so each
|
* The block runs in the double-indirect region are different.
|
||||||
block run maps a constant amount of file data. This means
|
* They are always allocated 4 fs blocks at a time, so each
|
||||||
that we can directly calculate how many block runs into the
|
* block run maps a constant amount of file data. This means
|
||||||
double-indirect region we need to go to get to the one that
|
* that we can directly calculate how many block runs into the
|
||||||
maps a particular filesystem block.
|
* double-indirect region we need to go to get to the one that
|
||||||
|
* maps a particular filesystem block.
|
||||||
We do this in two stages. First we calculate which of the
|
*
|
||||||
inode addresses in the double-indirect block will point us
|
* We do this in two stages. First we calculate which of the
|
||||||
to the indirect block that contains the mapping for the data,
|
* inode addresses in the double-indirect block will point us
|
||||||
then we calculate which of the inode addresses in that
|
* to the indirect block that contains the mapping for the data,
|
||||||
indirect block maps the data block we are after.
|
* then we calculate which of the inode addresses in that
|
||||||
|
* indirect block maps the data block we are after.
|
||||||
Oh, and once we've done that, we actually read in the blocks
|
*
|
||||||
that contain the inode addresses we calculated above. Even
|
* Oh, and once we've done that, we actually read in the blocks
|
||||||
though the double-indirect run may be several blocks long,
|
* that contain the inode addresses we calculated above. Even
|
||||||
we can calculate which of those blocks will contain the index
|
* though the double-indirect run may be several blocks long,
|
||||||
we are after and only read that one. We then follow it to
|
* we can calculate which of those blocks will contain the index
|
||||||
the indirect block and perform a similar process to find
|
* we are after and only read that one. We then follow it to
|
||||||
the actual block run that maps the data block we are interested
|
* the indirect block and perform a similar process to find
|
||||||
in.
|
* the actual block run that maps the data block we are interested
|
||||||
|
* in.
|
||||||
Then we offset the run as in befs_find_brun_array() and we are
|
*
|
||||||
done.
|
* Then we offset the run as in befs_find_brun_array() and we are
|
||||||
|
* done.
|
||||||
2001-11-15 Will Dyson
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
befs_find_brun_dblindirect(struct super_block *sb,
|
befs_find_brun_dblindirect(struct super_block *sb,
|
||||||
|
@ -430,10 +430,9 @@ befs_find_brun_dblindirect(struct super_block *sb,
|
||||||
struct buffer_head *indir_block;
|
struct buffer_head *indir_block;
|
||||||
befs_block_run indir_run;
|
befs_block_run indir_run;
|
||||||
befs_disk_inode_addr *iaddr_array;
|
befs_disk_inode_addr *iaddr_array;
|
||||||
struct befs_sb_info *befs_sb = BEFS_SB(sb);
|
|
||||||
|
|
||||||
befs_blocknr_t indir_start_blk =
|
befs_blocknr_t indir_start_blk =
|
||||||
data->max_indirect_range >> befs_sb->block_shift;
|
data->max_indirect_range >> BEFS_SB(sb)->block_shift;
|
||||||
|
|
||||||
off_t dbl_indir_off = blockno - indir_start_blk;
|
off_t dbl_indir_off = blockno - indir_start_blk;
|
||||||
|
|
||||||
|
@ -471,7 +470,7 @@ befs_find_brun_dblindirect(struct super_block *sb,
|
||||||
}
|
}
|
||||||
|
|
||||||
dbl_indir_block =
|
dbl_indir_block =
|
||||||
befs_bread(sb, iaddr2blockno(sb, &data->double_indirect) +
|
sb_bread(sb, iaddr2blockno(sb, &data->double_indirect) +
|
||||||
dbl_which_block);
|
dbl_which_block);
|
||||||
if (dbl_indir_block == NULL) {
|
if (dbl_indir_block == NULL) {
|
||||||
befs_error(sb, "%s couldn't read the "
|
befs_error(sb, "%s couldn't read the "
|
||||||
|
@ -479,7 +478,6 @@ befs_find_brun_dblindirect(struct super_block *sb,
|
||||||
(unsigned long)
|
(unsigned long)
|
||||||
iaddr2blockno(sb, &data->double_indirect) +
|
iaddr2blockno(sb, &data->double_indirect) +
|
||||||
dbl_which_block);
|
dbl_which_block);
|
||||||
brelse(dbl_indir_block);
|
|
||||||
return BEFS_ERR;
|
return BEFS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,12 +497,11 @@ befs_find_brun_dblindirect(struct super_block *sb,
|
||||||
}
|
}
|
||||||
|
|
||||||
indir_block =
|
indir_block =
|
||||||
befs_bread(sb, iaddr2blockno(sb, &indir_run) + which_block);
|
sb_bread(sb, iaddr2blockno(sb, &indir_run) + which_block);
|
||||||
if (indir_block == NULL) {
|
if (indir_block == NULL) {
|
||||||
befs_error(sb, "%s couldn't read the indirect block "
|
befs_error(sb, "%s couldn't read the indirect block "
|
||||||
"at blockno %lu", __func__, (unsigned long)
|
"at blockno %lu", __func__, (unsigned long)
|
||||||
iaddr2blockno(sb, &indir_run) + which_block);
|
iaddr2blockno(sb, &indir_run) + which_block);
|
||||||
brelse(indir_block);
|
|
||||||
return BEFS_ERR;
|
return BEFS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -169,6 +169,7 @@ befs_dump_super_block(const struct super_block *sb, befs_super_block * sup)
|
||||||
|
|
||||||
befs_debug(sb, " num_blocks %llu", fs64_to_cpu(sb, sup->num_blocks));
|
befs_debug(sb, " num_blocks %llu", fs64_to_cpu(sb, sup->num_blocks));
|
||||||
befs_debug(sb, " used_blocks %llu", fs64_to_cpu(sb, sup->used_blocks));
|
befs_debug(sb, " used_blocks %llu", fs64_to_cpu(sb, sup->used_blocks));
|
||||||
|
befs_debug(sb, " inode_size %u", fs32_to_cpu(sb, sup->inode_size));
|
||||||
|
|
||||||
befs_debug(sb, " magic2 %08x", fs32_to_cpu(sb, sup->magic2));
|
befs_debug(sb, " magic2 %08x", fs32_to_cpu(sb, sup->magic2));
|
||||||
befs_debug(sb, " blocks_per_ag %u",
|
befs_debug(sb, " blocks_per_ag %u",
|
||||||
|
|
26
fs/befs/io.c
26
fs/befs/io.c
|
@ -27,7 +27,7 @@ struct buffer_head *
|
||||||
befs_bread_iaddr(struct super_block *sb, befs_inode_addr iaddr)
|
befs_bread_iaddr(struct super_block *sb, befs_inode_addr iaddr)
|
||||||
{
|
{
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
befs_blocknr_t block = 0;
|
befs_blocknr_t block;
|
||||||
struct befs_sb_info *befs_sb = BEFS_SB(sb);
|
struct befs_sb_info *befs_sb = BEFS_SB(sb);
|
||||||
|
|
||||||
befs_debug(sb, "---> Enter %s "
|
befs_debug(sb, "---> Enter %s "
|
||||||
|
@ -59,27 +59,3 @@ befs_bread_iaddr(struct super_block *sb, befs_inode_addr iaddr)
|
||||||
befs_debug(sb, "<--- %s ERROR", __func__);
|
befs_debug(sb, "<--- %s ERROR", __func__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct buffer_head *
|
|
||||||
befs_bread(struct super_block *sb, befs_blocknr_t block)
|
|
||||||
{
|
|
||||||
struct buffer_head *bh;
|
|
||||||
|
|
||||||
befs_debug(sb, "---> Enter %s %lu", __func__, (unsigned long)block);
|
|
||||||
|
|
||||||
bh = sb_bread(sb, block);
|
|
||||||
|
|
||||||
if (bh == NULL) {
|
|
||||||
befs_error(sb, "Failed to read block %lu",
|
|
||||||
(unsigned long)block);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
befs_debug(sb, "<--- %s", __func__);
|
|
||||||
|
|
||||||
return bh;
|
|
||||||
|
|
||||||
error:
|
|
||||||
befs_debug(sb, "<--- %s ERROR", __func__);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,5 +5,3 @@
|
||||||
struct buffer_head *befs_bread_iaddr(struct super_block *sb,
|
struct buffer_head *befs_bread_iaddr(struct super_block *sb,
|
||||||
befs_inode_addr iaddr);
|
befs_inode_addr iaddr);
|
||||||
|
|
||||||
struct buffer_head *befs_bread(struct super_block *sb, befs_blocknr_t block);
|
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ befs_get_block(struct inode *inode, sector_t block,
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
befs_data_stream *ds = &BEFS_I(inode)->i_data.ds;
|
befs_data_stream *ds = &BEFS_I(inode)->i_data.ds;
|
||||||
befs_block_run run = BAD_IADDR;
|
befs_block_run run = BAD_IADDR;
|
||||||
int res = 0;
|
int res;
|
||||||
ulong disk_off;
|
ulong disk_off;
|
||||||
|
|
||||||
befs_debug(sb, "---> befs_get_block() for inode %lu, block %ld",
|
befs_debug(sb, "---> befs_get_block() for inode %lu, block %ld",
|
||||||
|
@ -179,15 +179,16 @@ befs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
|
||||||
kfree(utfname);
|
kfree(utfname);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ret = befs_btree_find(sb, ds, dentry->d_name.name, &offset);
|
ret = befs_btree_find(sb, ds, name, &offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == BEFS_BT_NOT_FOUND) {
|
if (ret == BEFS_BT_NOT_FOUND) {
|
||||||
befs_debug(sb, "<--- %s %pd not found", __func__, dentry);
|
befs_debug(sb, "<--- %s %pd not found", __func__, dentry);
|
||||||
|
d_add(dentry, NULL);
|
||||||
return ERR_PTR(-ENOENT);
|
return ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
} else if (ret != BEFS_OK || offset == 0) {
|
} else if (ret != BEFS_OK || offset == 0) {
|
||||||
befs_warning(sb, "<--- %s Error", __func__);
|
befs_error(sb, "<--- %s Error", __func__);
|
||||||
return ERR_PTR(-ENODATA);
|
return ERR_PTR(-ENODATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,13 +212,12 @@ befs_readdir(struct file *file, struct dir_context *ctx)
|
||||||
befs_off_t value;
|
befs_off_t value;
|
||||||
int result;
|
int result;
|
||||||
size_t keysize;
|
size_t keysize;
|
||||||
unsigned char d_type;
|
|
||||||
char keybuf[BEFS_NAME_LEN + 1];
|
char keybuf[BEFS_NAME_LEN + 1];
|
||||||
|
|
||||||
befs_debug(sb, "---> %s name %pD, inode %ld, ctx->pos %lld",
|
befs_debug(sb, "---> %s name %pD, inode %ld, ctx->pos %lld",
|
||||||
__func__, file, inode->i_ino, ctx->pos);
|
__func__, file, inode->i_ino, ctx->pos);
|
||||||
|
|
||||||
more:
|
while (1) {
|
||||||
result = befs_btree_read(sb, ds, ctx->pos, BEFS_NAME_LEN + 1,
|
result = befs_btree_read(sb, ds, ctx->pos, BEFS_NAME_LEN + 1,
|
||||||
keybuf, &keysize, &value);
|
keybuf, &keysize, &value);
|
||||||
|
|
||||||
|
@ -236,31 +236,31 @@ more:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
d_type = DT_UNKNOWN;
|
|
||||||
|
|
||||||
/* Convert to NLS */
|
/* Convert to NLS */
|
||||||
if (BEFS_SB(sb)->nls) {
|
if (BEFS_SB(sb)->nls) {
|
||||||
char *nlsname;
|
char *nlsname;
|
||||||
int nlsnamelen;
|
int nlsnamelen;
|
||||||
|
|
||||||
result =
|
result =
|
||||||
befs_utf2nls(sb, keybuf, keysize, &nlsname, &nlsnamelen);
|
befs_utf2nls(sb, keybuf, keysize, &nlsname,
|
||||||
|
&nlsnamelen);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
befs_debug(sb, "<--- %s ERROR", __func__);
|
befs_debug(sb, "<--- %s ERROR", __func__);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (!dir_emit(ctx, nlsname, nlsnamelen,
|
if (!dir_emit(ctx, nlsname, nlsnamelen,
|
||||||
(ino_t) value, d_type)) {
|
(ino_t) value, DT_UNKNOWN)) {
|
||||||
kfree(nlsname);
|
kfree(nlsname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
kfree(nlsname);
|
kfree(nlsname);
|
||||||
} else {
|
} else {
|
||||||
if (!dir_emit(ctx, keybuf, keysize,
|
if (!dir_emit(ctx, keybuf, keysize,
|
||||||
(ino_t) value, d_type))
|
(ino_t) value, DT_UNKNOWN))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ctx->pos++;
|
ctx->pos++;
|
||||||
goto more;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct inode *
|
static struct inode *
|
||||||
|
@ -299,7 +299,6 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
|
||||||
struct befs_sb_info *befs_sb = BEFS_SB(sb);
|
struct befs_sb_info *befs_sb = BEFS_SB(sb);
|
||||||
struct befs_inode_info *befs_ino;
|
struct befs_inode_info *befs_ino;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
long ret = -EIO;
|
|
||||||
|
|
||||||
befs_debug(sb, "---> %s inode = %lu", __func__, ino);
|
befs_debug(sb, "---> %s inode = %lu", __func__, ino);
|
||||||
|
|
||||||
|
@ -318,7 +317,7 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
|
||||||
befs_ino->i_inode_num.allocation_group,
|
befs_ino->i_inode_num.allocation_group,
|
||||||
befs_ino->i_inode_num.start, befs_ino->i_inode_num.len);
|
befs_ino->i_inode_num.start, befs_ino->i_inode_num.len);
|
||||||
|
|
||||||
bh = befs_bread(sb, inode->i_ino);
|
bh = sb_bread(sb, inode->i_ino);
|
||||||
if (!bh) {
|
if (!bh) {
|
||||||
befs_error(sb, "unable to read inode block - "
|
befs_error(sb, "unable to read inode block - "
|
||||||
"inode = %lu", inode->i_ino);
|
"inode = %lu", inode->i_ino);
|
||||||
|
@ -421,7 +420,7 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
|
||||||
unacquire_none:
|
unacquire_none:
|
||||||
iget_failed(inode);
|
iget_failed(inode);
|
||||||
befs_debug(sb, "<--- %s - Bad inode", __func__);
|
befs_debug(sb, "<--- %s - Bad inode", __func__);
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(-EIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the inode cache. Called at fs setup.
|
/* Initialize the inode cache. Called at fs setup.
|
||||||
|
@ -436,10 +435,9 @@ befs_init_inodecache(void)
|
||||||
0, (SLAB_RECLAIM_ACCOUNT|
|
0, (SLAB_RECLAIM_ACCOUNT|
|
||||||
SLAB_MEM_SPREAD|SLAB_ACCOUNT),
|
SLAB_MEM_SPREAD|SLAB_ACCOUNT),
|
||||||
init_once);
|
init_once);
|
||||||
if (befs_inode_cachep == NULL) {
|
if (befs_inode_cachep == NULL)
|
||||||
pr_err("%s: Couldn't initialize inode slabcache\n", __func__);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,8 +522,6 @@ befs_utf2nls(struct super_block *sb, const char *in,
|
||||||
|
|
||||||
*out = result = kmalloc(maxlen, GFP_NOFS);
|
*out = result = kmalloc(maxlen, GFP_NOFS);
|
||||||
if (!*out) {
|
if (!*out) {
|
||||||
befs_error(sb, "%s cannot allocate memory", __func__);
|
|
||||||
*out_len = 0;
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,7 +600,6 @@ befs_nls2utf(struct super_block *sb, const char *in,
|
||||||
|
|
||||||
*out = result = kmalloc(maxlen, GFP_NOFS);
|
*out = result = kmalloc(maxlen, GFP_NOFS);
|
||||||
if (!*out) {
|
if (!*out) {
|
||||||
befs_error(sb, "%s cannot allocate memory", __func__);
|
|
||||||
*out_len = 0;
|
*out_len = 0;
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -637,10 +632,6 @@ befs_nls2utf(struct super_block *sb, const char *in,
|
||||||
return -EILSEQ;
|
return -EILSEQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Use the
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
enum {
|
enum {
|
||||||
Opt_uid, Opt_gid, Opt_charset, Opt_debug, Opt_err,
|
Opt_uid, Opt_gid, Opt_charset, Opt_debug, Opt_err,
|
||||||
};
|
};
|
||||||
|
@ -760,18 +751,18 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
long ret = -EINVAL;
|
long ret = -EINVAL;
|
||||||
const unsigned long sb_block = 0;
|
const unsigned long sb_block = 0;
|
||||||
const off_t x86_sb_off = 512;
|
const off_t x86_sb_off = 512;
|
||||||
|
int blocksize;
|
||||||
|
|
||||||
save_mount_options(sb, data);
|
save_mount_options(sb, data);
|
||||||
|
|
||||||
sb->s_fs_info = kzalloc(sizeof(*befs_sb), GFP_KERNEL);
|
sb->s_fs_info = kzalloc(sizeof(*befs_sb), GFP_KERNEL);
|
||||||
if (sb->s_fs_info == NULL) {
|
if (sb->s_fs_info == NULL)
|
||||||
pr_err("(%s): Unable to allocate memory for private "
|
|
||||||
"portion of superblock. Bailing.\n", sb->s_id);
|
|
||||||
goto unacquire_none;
|
goto unacquire_none;
|
||||||
}
|
|
||||||
befs_sb = BEFS_SB(sb);
|
befs_sb = BEFS_SB(sb);
|
||||||
|
|
||||||
if (!parse_options((char *) data, &befs_sb->mount_opts)) {
|
if (!parse_options((char *) data, &befs_sb->mount_opts)) {
|
||||||
|
if (!silent)
|
||||||
befs_error(sb, "cannot parse mount options");
|
befs_error(sb, "cannot parse mount options");
|
||||||
goto unacquire_priv_sbp;
|
goto unacquire_priv_sbp;
|
||||||
}
|
}
|
||||||
|
@ -793,9 +784,15 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
* least 1k to get the second 512 bytes of the volume.
|
* least 1k to get the second 512 bytes of the volume.
|
||||||
* -WD 10-26-01
|
* -WD 10-26-01
|
||||||
*/
|
*/
|
||||||
sb_min_blocksize(sb, 1024);
|
blocksize = sb_min_blocksize(sb, 1024);
|
||||||
|
if (!blocksize) {
|
||||||
|
if (!silent)
|
||||||
|
befs_error(sb, "unable to set blocksize");
|
||||||
|
goto unacquire_priv_sbp;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(bh = sb_bread(sb, sb_block))) {
|
if (!(bh = sb_bread(sb, sb_block))) {
|
||||||
|
if (!silent)
|
||||||
befs_error(sb, "unable to read superblock");
|
befs_error(sb, "unable to read superblock");
|
||||||
goto unacquire_priv_sbp;
|
goto unacquire_priv_sbp;
|
||||||
}
|
}
|
||||||
|
@ -820,8 +817,8 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
|
|
||||||
if( befs_sb->num_blocks > ~((sector_t)0) ) {
|
if( befs_sb->num_blocks > ~((sector_t)0) ) {
|
||||||
befs_error(sb, "blocks count: %llu "
|
if (!silent)
|
||||||
"is larger than the host can use",
|
befs_error(sb, "blocks count: %llu is larger than the host can use",
|
||||||
befs_sb->num_blocks);
|
befs_sb->num_blocks);
|
||||||
goto unacquire_priv_sbp;
|
goto unacquire_priv_sbp;
|
||||||
}
|
}
|
||||||
|
@ -841,6 +838,7 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
}
|
}
|
||||||
sb->s_root = d_make_root(root);
|
sb->s_root = d_make_root(root);
|
||||||
if (!sb->s_root) {
|
if (!sb->s_root) {
|
||||||
|
if (!silent)
|
||||||
befs_error(sb, "get root inode failed");
|
befs_error(sb, "get root inode failed");
|
||||||
goto unacquire_priv_sbp;
|
goto unacquire_priv_sbp;
|
||||||
}
|
}
|
||||||
|
@ -870,9 +868,9 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
unacquire_priv_sbp:
|
unacquire_priv_sbp:
|
||||||
kfree(befs_sb->mount_opts.iocharset);
|
kfree(befs_sb->mount_opts.iocharset);
|
||||||
kfree(sb->s_fs_info);
|
kfree(sb->s_fs_info);
|
||||||
|
sb->s_fs_info = NULL;
|
||||||
|
|
||||||
unacquire_none:
|
unacquire_none:
|
||||||
sb->s_fs_info = NULL;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,13 +13,9 @@
|
||||||
#include "befs.h"
|
#include "befs.h"
|
||||||
#include "super.h"
|
#include "super.h"
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* load_befs_sb -- Read from disk and properly byteswap all the fields
|
* befs_load_sb -- Read from disk and properly byteswap all the fields
|
||||||
* of the befs superblock
|
* of the befs superblock
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
befs_load_sb(struct super_block *sb, befs_super_block *disk_sb)
|
befs_load_sb(struct super_block *sb, befs_super_block *disk_sb)
|
||||||
|
@ -45,6 +41,8 @@ befs_load_sb(struct super_block *sb, befs_super_block * disk_sb)
|
||||||
befs_sb->ag_shift = fs32_to_cpu(sb, disk_sb->ag_shift);
|
befs_sb->ag_shift = fs32_to_cpu(sb, disk_sb->ag_shift);
|
||||||
befs_sb->num_ags = fs32_to_cpu(sb, disk_sb->num_ags);
|
befs_sb->num_ags = fs32_to_cpu(sb, disk_sb->num_ags);
|
||||||
|
|
||||||
|
befs_sb->flags = fs32_to_cpu(sb, disk_sb->flags);
|
||||||
|
|
||||||
befs_sb->log_blocks = fsrun_to_cpu(sb, disk_sb->log_blocks);
|
befs_sb->log_blocks = fsrun_to_cpu(sb, disk_sb->log_blocks);
|
||||||
befs_sb->log_start = fs64_to_cpu(sb, disk_sb->log_start);
|
befs_sb->log_start = fs64_to_cpu(sb, disk_sb->log_start);
|
||||||
befs_sb->log_end = fs64_to_cpu(sb, disk_sb->log_end);
|
befs_sb->log_end = fs64_to_cpu(sb, disk_sb->log_end);
|
||||||
|
@ -101,10 +99,18 @@ befs_check_sb(struct super_block *sb)
|
||||||
return BEFS_ERR;
|
return BEFS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (befs_sb->log_start != befs_sb->log_end) {
|
|
||||||
|
/* ag_shift also encodes the same information as blocks_per_ag in a
|
||||||
|
* different way, non-fatal consistency check
|
||||||
|
*/
|
||||||
|
if ((1 << befs_sb->ag_shift) != befs_sb->blocks_per_ag)
|
||||||
|
befs_error(sb, "ag_shift disagrees with blocks_per_ag.");
|
||||||
|
|
||||||
|
if (befs_sb->log_start != befs_sb->log_end ||
|
||||||
|
befs_sb->flags == BEFS_DIRTY) {
|
||||||
befs_error(sb, "Filesystem not clean! There are blocks in the "
|
befs_error(sb, "Filesystem not clean! There are blocks in the "
|
||||||
"journal. You must boot into BeOS and mount this volume "
|
"journal. You must boot into BeOS and mount this "
|
||||||
"to make it clean.");
|
"volume to make it clean.");
|
||||||
return BEFS_ERR;
|
return BEFS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче