提交 df34d04a 编写于 作者: L Linus Torvalds

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
  ...
......@@ -43,7 +43,10 @@ struct befs_sb_info {
u32 ag_shift;
u32 num_ags;
/* jornal log entry */
/* State of the superblock */
u32 flags;
/* Journal log entry */
befs_block_run log_blocks;
befs_off_t log_start;
befs_off_t log_end;
......@@ -79,7 +82,7 @@ enum befs_err {
BEFS_BT_END,
BEFS_BT_EMPTY,
BEFS_BT_MATCH,
BEFS_BT_PARMATCH,
BEFS_BT_OVERFLOW,
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);
}
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"
#endif /* _LINUX_BEFS_H */
......@@ -85,7 +85,7 @@ struct befs_btree_node {
};
/* local constants */
static const befs_off_t befs_bt_inval = 0xffffffffffffffffULL;
static const befs_off_t BEFS_BT_INVAL = 0xffffffffffffffffULL;
/* local functions */
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->data_type = fs32_to_cpu(sb, od_sup->data_type);
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);
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
* makes sure its header fields are in cpu byteorder, byteswapping if
* necessary.
* Note: node->bh must be NULL when this function called first
* time. Don't forget brelse(node->bh) after last call.
* Note: node->bh must be NULL when this function is called the first time.
* Don't forget brelse(node->bh) after last call.
*
* 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.
......@@ -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.
* Drill down through the interior nodes using befs_find_key().
* 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
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)) {
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;
/* if no match, go to overflow node */
if (befs_bt_read_node(sb, ds, this_node, node_off) != BEFS_OK) {
befs_error(sb, "befs_btree_find() failed to read "
"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);
brelse(this_node->bh);
kfree(this_node);
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;
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
* @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
* If no exact match, finds first key in node that is greater
* (alphabetically) than the search key and returns BEFS_BT_PARMATCH
* (for partial match, I guess). Can you think of something better to
* call it?
*
* If no key was a match or greater than the search key, return
* BEFS_BT_NOT_FOUND.
* Finds exact match if one exists, and returns BEFS_BT_MATCH.
* If there is no match and node's value array is too small for key, return
* BEFS_BT_OVERFLOW.
* If no match and node should countain this key, return BEFS_BT_NOT_FOUND.
*
* Use binary search instead of a linear.
* Uses binary search instead of a linear.
*/
static int
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);
*value = 0;
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;
thiskey = befs_bt_get_key(sb, node, last, &keylen);
eq = befs_compare_strings(thiskey, keylen, findkey, findkey_len);
if (eq < 0) {
befs_debug(sb, "<--- %s %s not found", __func__, findkey);
return BEFS_BT_NOT_FOUND;
befs_debug(sb, "<--- node can't contain %s", findkey);
return BEFS_BT_OVERFLOW;
}
valarray = befs_bt_valarray(node);
......@@ -387,12 +379,15 @@ befs_find_key(struct super_block *sb, struct befs_btree_node *node,
else
first = mid + 1;
}
/* return an existing value so caller can arrive to a leaf node */
if (eq < 0)
*value = fs64_to_cpu(sb, valarray[mid + 1]);
else
*value = fs64_to_cpu(sb, valarray[mid]);
befs_debug(sb, "<--- %s found %s at %d", __func__, thiskey, mid);
return BEFS_BT_PARMATCH;
befs_error(sb, "<--- %s %s not found", __func__, findkey);
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
* @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.
* 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).
......@@ -422,7 +417,7 @@ befs_btree_read(struct super_block *sb, const befs_data_stream *ds,
{
struct befs_btree_node *this_node;
befs_btree_super bt_super;
befs_off_t node_off = 0;
befs_off_t node_off;
int cur_key;
fs64 *valarray;
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) {
/* 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;
*value = 0;
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
* by the function.
*
*
* Helper function for btree traverse. Moves the current position to the
* start of the first leaf node.
*
......@@ -608,7 +602,7 @@ static int
befs_leafnode(struct befs_btree_node *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;
else
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 is greater.
* Returns <0 if @key2 is greater..
* Returns <0 if @key2 is greater.
*/
static int
befs_compare_strings(const void *key1, int keylen1,
......
......@@ -22,22 +22,22 @@ const befs_inode_addr BAD_IADDR = { 0, 0, 0 };
static int befs_find_brun_direct(struct super_block *sb,
const befs_data_stream *data,
befs_blocknr_t blockno, befs_block_run * run);
befs_blocknr_t blockno, befs_block_run *run);
static int befs_find_brun_indirect(struct super_block *sb,
const befs_data_stream *data,
befs_blocknr_t blockno,
befs_block_run * run);
befs_block_run *run);
static int befs_find_brun_dblindirect(struct super_block *sb,
const befs_data_stream *data,
befs_blocknr_t blockno,
befs_block_run * run);
befs_block_run *run);
/**
* befs_read_datastream - get buffer_head containing data, starting from pos.
* @sb: Filesystem superblock
* @ds: datastrem to find data with
* @ds: datastream to find data with
* @pos: start of data
* @off: offset of data in buffer_head->b_data
*
......@@ -46,7 +46,7 @@ static int befs_find_brun_dblindirect(struct super_block *sb,
*/
struct buffer_head *
befs_read_datastream(struct super_block *sb, const befs_data_stream *ds,
befs_off_t pos, uint * off)
befs_off_t pos, uint *off)
{
struct buffer_head *bh;
befs_block_run run;
......@@ -75,7 +75,13 @@ befs_read_datastream(struct super_block *sb, const befs_data_stream *ds,
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
* is block number fblock of the file.
*
......@@ -88,7 +94,7 @@ befs_read_datastream(struct super_block *sb, const befs_data_stream *ds,
*/
int
befs_fblock2brun(struct super_block *sb, const befs_data_stream *data,
befs_blocknr_t fblock, befs_block_run * run)
befs_blocknr_t fblock, befs_block_run *run)
{
int err;
befs_off_t pos = fblock << BEFS_SB(sb)->block_shift;
......@@ -115,7 +121,7 @@ befs_fblock2brun(struct super_block *sb, const befs_data_stream *data,
/**
* befs_read_lsmylink - read long symlink from datastream.
* @sb: Filesystem superblock
* @ds: Datastrem to read from
* @ds: Datastream to read from
* @buff: Buffer in which to place long symlink data
* @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 */
u16 plen;
struct buffer_head *bh;
befs_debug(sb, "---> %s length: %llu", __func__, 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;
/*
Double indir block, plus all the indirect blocks it mapps
In the double-indirect range, all block runs of data are
BEFS_DBLINDIR_BRUN_LEN blocks long. Therefore, we know
how many data block runs are in the double-indirect region,
and from that we know how many indirect blocks it takes to
map them. We assume that the indirect blocks are also
BEFS_DBLINDIR_BRUN_LEN blocks long.
* Double indir block, plus all the indirect blocks it maps.
* In the double-indirect range, all block runs of data are
* BEFS_DBLINDIR_BRUN_LEN blocks long. Therefore, we know
* how many data block runs are in the double-indirect region,
* and from that we know how many indirect blocks it takes to
* map them. We assume that the indirect blocks are also
* BEFS_DBLINDIR_BRUN_LEN blocks long.
*/
if (ds->size > ds->max_indirect_range && ds->max_indirect_range != 0) {
uint dbl_bytes;
......@@ -212,58 +219,50 @@ befs_count_blocks(struct super_block *sb, const befs_data_stream *ds)
return blocks;
}
/*
Finds the block run that starts at file block number blockno
in the file represented by the datastream data, if that
blockno is in the direct region of the datastream.
sb: the superblock
data: the datastream
blockno: the blocknumber to find
run: The found run is passed back through this pointer
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
contains the blockno-th filesystem block. This is necessary
because the block runs map variable amounts of data. Simply
keeps a count of the number of blocks searched so far (sum),
incrementing this by the length of each block run as we come
across it. Adds sum to *count before returning (this is so
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
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
*/
/**
* befs_find_brun_direct - find a direct block run in the datastream
* @sb: the superblock
* @data: the datastream
* @blockno: the blocknumber to find
* @run: The found run is passed back through this pointer
*
* Finds the block run that starts at file block number blockno
* 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.
*
* Algorithm:
* Linear search. Checks each element of array[] to see if it
* contains the blockno-th filesystem block. This is necessary
* because the block runs map variable amounts of data. Simply
* keeps a count of the number of blocks searched so far (sum),
* incrementing this by the length of each block run as we come
* across it. Adds sum to *count before returning (this is so
* 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
* of the block run, so that blockno is the start and len is
* still valid (the run ends in the same place).
*/
static int
befs_find_brun_direct(struct super_block *sb, const befs_data_stream *data,
befs_blocknr_t blockno, befs_block_run * run)
befs_blocknr_t blockno, befs_block_run *run)
{
int i;
const befs_block_run *array = data->direct;
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);
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;
sum += array[i].len, i++) {
if (blockno >= sum && blockno < sum + (array[i].len)) {
int offset = blockno - sum;
run->allocation_group = array[i].allocation_group;
run->start = array[i].start + offset;
run->len = array[i].len - offset;
......@@ -275,38 +274,39 @@ 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__);
return BEFS_ERR;
}
/*
Finds the block run that starts at file block number blockno
in the file represented by the datastream data, if that
blockno is in the indirect region of the datastream.
sb: the superblock
data: the datastream
blockno: the blocknumber to find
run: The found run is passed back through this pointer
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
it in and search through it for search_blk.
XXX:
Really should check to make sure blockno is inside indirect
region.
2001-11-15 Will Dyson
*/
/**
* befs_find_brun_indirect - find a block run in the datastream
* @sb: the superblock
* @data: the datastream
* @blockno: the blocknumber to find
* @run: The found run is passed back through this pointer
*
* Finds the block run that starts at file block number blockno
* 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.
*
* Algorithm:
* 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
* region.
*/
static int
befs_find_brun_indirect(struct super_block *sb,
const befs_data_stream *data,
befs_blocknr_t blockno,
befs_block_run * run)
befs_block_run *run)
{
int i, j;
befs_blocknr_t sum = 0;
......@@ -326,11 +326,12 @@ befs_find_brun_indirect(struct super_block *sb,
/* Examine blocks of the indirect run one at a time */
for (i = 0; i < indirect.len; i++) {
indirblock = befs_bread(sb, indirblockno + i);
indirblock = sb_bread(sb, indirblockno + i);
if (indirblock == NULL) {
befs_debug(sb, "---> %s failed to read "
befs_error(sb, "---> %s failed to read "
"disk block %lu from the indirect brun",
__func__, (unsigned long)indirblockno + i);
befs_debug(sb, "<--- %s ERROR", __func__);
return BEFS_ERR;
}
......@@ -370,52 +371,51 @@ befs_find_brun_indirect(struct super_block *sb,
return BEFS_ERR;
}
/*
Finds the block run that starts at file block number blockno
in the file represented by the datastream data, if that
blockno is in the double-indirect region of the datastream.
sb: the superblock
data: the datastream
blockno: the blocknumber to find
run: The found run is passed back through this pointer
Return value is BEFS_OK if the blockrun is found, BEFS_ERR
otherwise.
Algorithm:
The block runs in the double-indirect region are different.
They are always allocated 4 fs blocks at a time, so each
block run maps a constant amount of file data. This means
that we can directly calculate how many block runs into the
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
to the indirect block that contains the mapping for the data,
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
though the double-indirect run may be several blocks long,
we can calculate which of those blocks will contain the index
we are after and only read that one. We then follow it to
the indirect block and perform a similar process to find
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.
2001-11-15 Will Dyson
*/
/**
* befs_find_brun_dblindirect - find a block run in the datastream
* @sb: the superblock
* @data: the datastream
* @blockno: the blocknumber to find
* @run: The found run is passed back through this pointer
*
* Finds the block run that starts at file block number blockno
* 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.
*
* Algorithm:
* The block runs in the double-indirect region are different.
* They are always allocated 4 fs blocks at a time, so each
* block run maps a constant amount of file data. This means
* that we can directly calculate how many block runs into the
* 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
* to the indirect block that contains the mapping for the data,
* 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
* though the double-indirect run may be several blocks long,
* we can calculate which of those blocks will contain the index
* we are after and only read that one. We then follow it to
* the indirect block and perform a similar process to find
* 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.
*/
static int
befs_find_brun_dblindirect(struct super_block *sb,
const befs_data_stream *data,
befs_blocknr_t blockno,
befs_block_run * run)
befs_block_run *run)
{
int dblindir_indx;
int indir_indx;
......@@ -430,10 +430,9 @@ befs_find_brun_dblindirect(struct super_block *sb,
struct buffer_head *indir_block;
befs_block_run indir_run;
befs_disk_inode_addr *iaddr_array;
struct befs_sb_info *befs_sb = BEFS_SB(sb);
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;
......@@ -471,7 +470,7 @@ befs_find_brun_dblindirect(struct super_block *sb,
}
dbl_indir_block =
befs_bread(sb, iaddr2blockno(sb, &data->double_indirect) +
sb_bread(sb, iaddr2blockno(sb, &data->double_indirect) +
dbl_which_block);
if (dbl_indir_block == NULL) {
befs_error(sb, "%s couldn't read the "
......@@ -479,7 +478,6 @@ befs_find_brun_dblindirect(struct super_block *sb,
(unsigned long)
iaddr2blockno(sb, &data->double_indirect) +
dbl_which_block);
brelse(dbl_indir_block);
return BEFS_ERR;
}
......@@ -499,12 +497,11 @@ befs_find_brun_dblindirect(struct super_block *sb,
}
indir_block =
befs_bread(sb, iaddr2blockno(sb, &indir_run) + which_block);
sb_bread(sb, iaddr2blockno(sb, &indir_run) + which_block);
if (indir_block == NULL) {
befs_error(sb, "%s couldn't read the indirect block "
"at blockno %lu", __func__, (unsigned long)
iaddr2blockno(sb, &indir_run) + which_block);
brelse(indir_block);
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, " 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, " blocks_per_ag %u",
......
......@@ -27,7 +27,7 @@ struct buffer_head *
befs_bread_iaddr(struct super_block *sb, befs_inode_addr iaddr)
{
struct buffer_head *bh;
befs_blocknr_t block = 0;
befs_blocknr_t block;
struct befs_sb_info *befs_sb = BEFS_SB(sb);
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__);
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,
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;
befs_data_stream *ds = &BEFS_I(inode)->i_data.ds;
befs_block_run run = BAD_IADDR;
int res = 0;
int res;
ulong disk_off;
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);
} 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) {
befs_debug(sb, "<--- %s %pd not found", __func__, dentry);
d_add(dentry, NULL);
return ERR_PTR(-ENOENT);
} else if (ret != BEFS_OK || offset == 0) {
befs_warning(sb, "<--- %s Error", __func__);
befs_error(sb, "<--- %s Error", __func__);
return ERR_PTR(-ENODATA);
}
......@@ -211,56 +212,55 @@ befs_readdir(struct file *file, struct dir_context *ctx)
befs_off_t value;
int result;
size_t keysize;
unsigned char d_type;
char keybuf[BEFS_NAME_LEN + 1];
befs_debug(sb, "---> %s name %pD, inode %ld, ctx->pos %lld",
__func__, file, inode->i_ino, ctx->pos);
more:
result = befs_btree_read(sb, ds, ctx->pos, BEFS_NAME_LEN + 1,
keybuf, &keysize, &value);
while (1) {
result = befs_btree_read(sb, ds, ctx->pos, BEFS_NAME_LEN + 1,
keybuf, &keysize, &value);
if (result == BEFS_ERR) {
befs_debug(sb, "<--- %s ERROR", __func__);
befs_error(sb, "IO error reading %pD (inode %lu)",
file, inode->i_ino);
return -EIO;
} else if (result == BEFS_BT_END) {
befs_debug(sb, "<--- %s END", __func__);
return 0;
} else if (result == BEFS_BT_EMPTY) {
befs_debug(sb, "<--- %s Empty directory", __func__);
return 0;
}
if (result == BEFS_ERR) {
befs_debug(sb, "<--- %s ERROR", __func__);
befs_error(sb, "IO error reading %pD (inode %lu)",
file, inode->i_ino);
return -EIO;
d_type = DT_UNKNOWN;
} else if (result == BEFS_BT_END) {
befs_debug(sb, "<--- %s END", __func__);
return 0;
/* Convert to NLS */
if (BEFS_SB(sb)->nls) {
char *nlsname;
int nlsnamelen;
result =
befs_utf2nls(sb, keybuf, keysize, &nlsname, &nlsnamelen);
if (result < 0) {
befs_debug(sb, "<--- %s ERROR", __func__);
return result;
} else if (result == BEFS_BT_EMPTY) {
befs_debug(sb, "<--- %s Empty directory", __func__);
return 0;
}
if (!dir_emit(ctx, nlsname, nlsnamelen,
(ino_t) value, d_type)) {
/* Convert to NLS */
if (BEFS_SB(sb)->nls) {
char *nlsname;
int nlsnamelen;
result =
befs_utf2nls(sb, keybuf, keysize, &nlsname,
&nlsnamelen);
if (result < 0) {
befs_debug(sb, "<--- %s ERROR", __func__);
return result;
}
if (!dir_emit(ctx, nlsname, nlsnamelen,
(ino_t) value, DT_UNKNOWN)) {
kfree(nlsname);
return 0;
}
kfree(nlsname);
return 0;
} else {
if (!dir_emit(ctx, keybuf, keysize,
(ino_t) value, DT_UNKNOWN))
return 0;
}
kfree(nlsname);
} else {
if (!dir_emit(ctx, keybuf, keysize,
(ino_t) value, d_type))
return 0;
ctx->pos++;
}
ctx->pos++;
goto more;
}
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_inode_info *befs_ino;
struct inode *inode;
long ret = -EIO;
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.start, befs_ino->i_inode_num.len);
bh = befs_bread(sb, inode->i_ino);
bh = sb_bread(sb, inode->i_ino);
if (!bh) {
befs_error(sb, "unable to read inode block - "
"inode = %lu", inode->i_ino);
......@@ -421,7 +420,7 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
unacquire_none:
iget_failed(inode);
befs_debug(sb, "<--- %s - Bad inode", __func__);
return ERR_PTR(ret);
return ERR_PTR(-EIO);
}
/* Initialize the inode cache. Called at fs setup.
......@@ -436,10 +435,9 @@ befs_init_inodecache(void)
0, (SLAB_RECLAIM_ACCOUNT|
SLAB_MEM_SPREAD|SLAB_ACCOUNT),
init_once);
if (befs_inode_cachep == NULL) {
pr_err("%s: Couldn't initialize inode slabcache\n", __func__);
if (befs_inode_cachep == NULL)
return -ENOMEM;
}
return 0;
}
......@@ -524,8 +522,6 @@ befs_utf2nls(struct super_block *sb, const char *in,
*out = result = kmalloc(maxlen, GFP_NOFS);
if (!*out) {
befs_error(sb, "%s cannot allocate memory", __func__);
*out_len = 0;
return -ENOMEM;
}
......@@ -604,7 +600,6 @@ befs_nls2utf(struct super_block *sb, const char *in,
*out = result = kmalloc(maxlen, GFP_NOFS);
if (!*out) {
befs_error(sb, "%s cannot allocate memory", __func__);
*out_len = 0;
return -ENOMEM;
}
......@@ -637,10 +632,6 @@ befs_nls2utf(struct super_block *sb, const char *in,
return -EILSEQ;
}
/**
* Use the
*
*/
enum {
Opt_uid, Opt_gid, Opt_charset, Opt_debug, Opt_err,
};
......@@ -760,19 +751,19 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
long ret = -EINVAL;
const unsigned long sb_block = 0;
const off_t x86_sb_off = 512;
int blocksize;
save_mount_options(sb, data);
sb->s_fs_info = kzalloc(sizeof(*befs_sb), GFP_KERNEL);
if (sb->s_fs_info == NULL) {
pr_err("(%s): Unable to allocate memory for private "
"portion of superblock. Bailing.\n", sb->s_id);
if (sb->s_fs_info == NULL)
goto unacquire_none;
}
befs_sb = BEFS_SB(sb);
if (!parse_options((char *) data, &befs_sb->mount_opts)) {
befs_error(sb, "cannot parse mount options");
if (!silent)
befs_error(sb, "cannot parse mount options");
goto unacquire_priv_sbp;
}
......@@ -793,10 +784,16 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
* least 1k to get the second 512 bytes of the volume.
* -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))) {
befs_error(sb, "unable to read superblock");
if (!silent)
befs_error(sb, "unable to read superblock");
goto unacquire_priv_sbp;
}
......@@ -820,9 +817,9 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
brelse(bh);
if( befs_sb->num_blocks > ~((sector_t)0) ) {
befs_error(sb, "blocks count: %llu "
"is larger than the host can use",
befs_sb->num_blocks);
if (!silent)
befs_error(sb, "blocks count: %llu is larger than the host can use",
befs_sb->num_blocks);
goto unacquire_priv_sbp;
}
......@@ -841,7 +838,8 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
}
sb->s_root = d_make_root(root);
if (!sb->s_root) {
befs_error(sb, "get root inode failed");
if (!silent)
befs_error(sb, "get root inode failed");
goto unacquire_priv_sbp;
}
......@@ -870,9 +868,9 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
unacquire_priv_sbp:
kfree(befs_sb->mount_opts.iocharset);
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
unacquire_none:
sb->s_fs_info = NULL;
return ret;
}
......
......@@ -13,24 +13,20 @@
#include "befs.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
*
*
*
*
*/
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)
{
struct befs_sb_info *befs_sb = BEFS_SB(sb);
/* Check the byte order of the filesystem */
if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_LE)
befs_sb->byte_order = BEFS_BYTESEX_LE;
befs_sb->byte_order = BEFS_BYTESEX_LE;
else if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_BE)
befs_sb->byte_order = BEFS_BYTESEX_BE;
befs_sb->byte_order = BEFS_BYTESEX_BE;
befs_sb->magic1 = fs32_to_cpu(sb, disk_sb->magic1);
befs_sb->magic2 = fs32_to_cpu(sb, disk_sb->magic2);
......@@ -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->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_start = fs64_to_cpu(sb, disk_sb->log_start);
befs_sb->log_end = fs64_to_cpu(sb, disk_sb->log_end);
......@@ -84,15 +82,15 @@ befs_check_sb(struct super_block *sb)
}
if (befs_sb->block_size > PAGE_SIZE) {
befs_error(sb, "blocksize(%u) cannot be larger"
befs_error(sb, "blocksize(%u) cannot be larger "
"than system pagesize(%lu)", befs_sb->block_size,
PAGE_SIZE);
return BEFS_ERR;
}
/*
* block_shift and block_size encode the same information
* in different ways as a consistency check.
* block_shift and block_size encode the same information
* in different ways as a consistency check.
*/
if ((1 << befs_sb->block_shift) != befs_sb->block_size) {
......@@ -101,10 +99,18 @@ befs_check_sb(struct super_block *sb)
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 "
"journal. You must boot into BeOS and mount this volume "
"to make it clean.");
"journal. You must boot into BeOS and mount this "
"volume to make it clean.");
return BEFS_ERR;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册