nfsd4: support putpubfh operation
[safe/jmp/linux-2.6] / fs / ubifs / tnc.c
index 66dc571..fa28a84 100644 (file)
@@ -443,6 +443,11 @@ static int tnc_read_node_nm(struct ubifs_info *c, struct ubifs_zbranch *zbr,
  * This function performs that same function as ubifs_read_node except that
  * it does not require that there is actually a node present and instead
  * the return code indicates if a node was read.
+ *
+ * Note, this function does not check CRC of data nodes if @c->no_chk_data_crc
+ * is true (it is controlled by corresponding mount option). However, if
+ * @c->always_chk_crc is true, @c->no_chk_data_crc is ignored and CRC is always
+ * checked.
  */
 static int try_read_node(const struct ubifs_info *c, void *buf, int type,
                         int len, int lnum, int offs)
@@ -470,9 +475,8 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type,
        if (node_len != len)
                return 0;
 
-       if (type == UBIFS_DATA_NODE && !c->always_chk_crc)
-               if (c->no_chk_data_crc)
-                       return 0;
+       if (type == UBIFS_DATA_NODE && !c->always_chk_crc && c->no_chk_data_crc)
+               return 1;
 
        crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
        node_crc = le32_to_cpu(ch->crc);
@@ -1501,7 +1505,12 @@ out:
  * @bu: bulk-read parameters and results
  *
  * Lookup consecutive data node keys for the same inode that reside
- * consecutively in the same LEB.
+ * consecutively in the same LEB. This function returns zero in case of success
+ * and a negative error code in case of failure.
+ *
+ * Note, if the bulk-read buffer length (@bu->buf_len) is known, this function
+ * makes sure bulk-read nodes fit the buffer. Otherwise, this function prepares
+ * maximum possible amount of nodes for bulk-read.
  */
 int ubifs_tnc_get_bu_keys(struct ubifs_info *c, struct bu_info *bu)
 {
@@ -1600,7 +1609,7 @@ out:
         * An enormous hole could cause bulk-read to encompass too many
         * page cache pages, so limit the number here.
         */
-       if (bu->blk_cnt >= UBIFS_MAX_BULK_READ)
+       if (bu->blk_cnt > UBIFS_MAX_BULK_READ)
                bu->blk_cnt = UBIFS_MAX_BULK_READ;
        /*
         * Ensure that bulk-read covers a whole number of page cache
@@ -1962,7 +1971,7 @@ static int tnc_insert(struct ubifs_info *c, struct ubifs_znode *znode,
 {
        struct ubifs_znode *zn, *zi, *zp;
        int i, keep, move, appending = 0;
-       union ubifs_key *key = &zbr->key;
+       union ubifs_key *key = &zbr->key, *key1;
 
        ubifs_assert(n >= 0 && n <= c->fanout);
 
@@ -2003,20 +2012,33 @@ again:
        zn->level = znode->level;
 
        /* Decide where to split */
-       if (znode->level == 0 && n == c->fanout &&
-           key_type(c, key) == UBIFS_DATA_KEY) {
-               union ubifs_key *key1;
-
-               /*
-                * If this is an inode which is being appended - do not split
-                * it because no other zbranches can be inserted between
-                * zbranches of consecutive data nodes anyway.
-                */
-               key1 = &znode->zbranch[n - 1].key;
-               if (key_inum(c, key1) == key_inum(c, key) &&
-                   key_type(c, key1) == UBIFS_DATA_KEY &&
-                   key_block(c, key1) == key_block(c, key) - 1)
-                       appending = 1;
+       if (znode->level == 0 && key_type(c, key) == UBIFS_DATA_KEY) {
+               /* Try not to split consecutive data keys */
+               if (n == c->fanout) {
+                       key1 = &znode->zbranch[n - 1].key;
+                       if (key_inum(c, key1) == key_inum(c, key) &&
+                           key_type(c, key1) == UBIFS_DATA_KEY)
+                               appending = 1;
+               } else
+                       goto check_split;
+       } else if (appending && n != c->fanout) {
+               /* Try not to split consecutive data keys */
+               appending = 0;
+check_split:
+               if (n >= (c->fanout + 1) / 2) {
+                       key1 = &znode->zbranch[0].key;
+                       if (key_inum(c, key1) == key_inum(c, key) &&
+                           key_type(c, key1) == UBIFS_DATA_KEY) {
+                               key1 = &znode->zbranch[n].key;
+                               if (key_inum(c, key1) != key_inum(c, key) ||
+                                   key_type(c, key1) != UBIFS_DATA_KEY) {
+                                       keep = n;
+                                       move = c->fanout - keep;
+                                       zi = znode;
+                                       goto do_split;
+                               }
+                       }
+               }
        }
 
        if (appending) {
@@ -2046,6 +2068,8 @@ again:
                        zbr->znode->parent = zn;
        }
 
+do_split:
+
        __set_bit(DIRTY_ZNODE, &zn->flags);
        atomic_long_inc(&c->dirty_zn_cnt);
 
@@ -2072,14 +2096,11 @@ again:
 
        /* Insert new znode (produced by spitting) into the parent */
        if (zp) {
-               i = n;
+               if (n == 0 && zi == znode && znode->iip == 0)
+                       correct_parent_keys(c, znode);
+
                /* Locate insertion point */
                n = znode->iip + 1;
-               if (appending && n != c->fanout)
-                       appending = 0;
-
-               if (i == 0 && zi == znode && znode->iip == 0)
-                       correct_parent_keys(c, znode);
 
                /* Tail recursion */
                zbr->key = zn->zbranch[0].key;
@@ -2228,12 +2249,11 @@ int ubifs_tnc_replace(struct ubifs_info *c, const union ubifs_key *key,
                        if (found) {
                                /* Ensure the znode is dirtied */
                                if (znode->cnext || !ubifs_zn_dirty(znode)) {
-                                           znode = dirty_cow_bottom_up(c,
-                                                                       znode);
-                                           if (IS_ERR(znode)) {
-                                                   err = PTR_ERR(znode);
-                                                   goto out_unlock;
-                                           }
+                                       znode = dirty_cow_bottom_up(c, znode);
+                                       if (IS_ERR(znode)) {
+                                               err = PTR_ERR(znode);
+                                               goto out_unlock;
+                                       }
                                }
                                zbr = &znode->zbranch[n];
                                lnc_free(zbr);
@@ -2300,11 +2320,11 @@ int ubifs_tnc_add_nm(struct ubifs_info *c, const union ubifs_key *key,
 
                /* Ensure the znode is dirtied */
                if (znode->cnext || !ubifs_zn_dirty(znode)) {
-                           znode = dirty_cow_bottom_up(c, znode);
-                           if (IS_ERR(znode)) {
-                                   err = PTR_ERR(znode);
-                                   goto out_unlock;
-                           }
+                       znode = dirty_cow_bottom_up(c, znode);
+                       if (IS_ERR(znode)) {
+                               err = PTR_ERR(znode);
+                               goto out_unlock;
+                       }
                }
 
                if (found == 1) {
@@ -2610,11 +2630,11 @@ int ubifs_tnc_remove_range(struct ubifs_info *c, union ubifs_key *from_key,
 
                /* Ensure the znode is dirtied */
                if (znode->cnext || !ubifs_zn_dirty(znode)) {
-                           znode = dirty_cow_bottom_up(c, znode);
-                           if (IS_ERR(znode)) {
-                                   err = PTR_ERR(znode);
-                                   goto out_unlock;
-                           }
+                       znode = dirty_cow_bottom_up(c, znode);
+                       if (IS_ERR(znode)) {
+                               err = PTR_ERR(znode);
+                               goto out_unlock;
+                       }
                }
 
                /* Remove all keys in range except the first */
@@ -2665,7 +2685,7 @@ int ubifs_tnc_remove_ino(struct ubifs_info *c, ino_t inum)
        struct ubifs_dent_node *xent, *pxent = NULL;
        struct qstr nm = { .name = NULL };
 
-       dbg_tnc("ino %lu", inum);
+       dbg_tnc("ino %lu", (unsigned long)inum);
 
        /*
         * Walk all extended attribute entries and remove them together with
@@ -2685,7 +2705,8 @@ int ubifs_tnc_remove_ino(struct ubifs_info *c, ino_t inum)
                }
 
                xattr_inum = le64_to_cpu(xent->inum);
-               dbg_tnc("xent '%s', ino %lu", xent->name, xattr_inum);
+               dbg_tnc("xent '%s', ino %lu", xent->name,
+                       (unsigned long)xattr_inum);
 
                nm.name = xent->name;
                nm.len = le16_to_cpu(xent->nlen);