Merge tag 'befs-v4.9-rc1' of git://github.com/luisbg/linux-befs
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 15 Oct 2016 19:09:13 +0000 (12:09 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 15 Oct 2016 19:09:13 +0000 (12:09 -0700)
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
  ...

fs/befs/befs.h
fs/befs/btree.c
fs/befs/datastream.c
fs/befs/debug.c
fs/befs/io.c
fs/befs/io.h
fs/befs/linuxvfs.c
fs/befs/super.c

index e0f59263a96d5944c1a5315e17bf9ee872309b9f..c6bad51d8ec7b56d8027c019a98a656596911110 100644 (file)
@@ -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 */
index 307645f9e284c546db0e3d94e989e3064791b343..7e135ea73fddf65295a804502d7c3a57e906cffb 100644 (file)
@@ -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,
index af1bc19b7c85b582e5c87981b92beb65deeefcf5..b4c7ba013c0d6e752296599d6b29597e5dd13512 100644 (file)
@@ -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;
        }
 
index 4de7cffcd66223c4a85a216cb58e5a8e62953e6c..85c13392e9e897dae2ee288f301c88c3067e8303 100644 (file)
@@ -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",
index 523c8af2d770b08473bfa6200d635ae46364b0e2..b4a558126ee1724b0d3bd833f68a1c201833af33 100644 (file)
@@ -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;
-}
index 9b78266b6aa57b73637167d0fb426ccc08be2cff..78d7bc6e60dee4d51fb1ac6325cca8b3929bd9c2 100644 (file)
@@ -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);
-
index bfe9f999493531b3bbbc348e053f6f581db878fe..647a276eba5654593739aafa9a6984ca967d8adf 100644 (file)
@@ -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;
 }
 
index aeafc4d842788ca7cc760599b68e9d5988dd4110..7c50025c99d8ab38f2de8c3abe93a201143e0635 100644 (file)
 #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;
        }