arm: tegra: enterprise: Add drivers for flashless XMM modem
[linux-2.6.git] / fs / reiserfs / stree.c
index e23303d..313d39d 100644 (file)
@@ -222,9 +222,6 @@ static inline int bin_search(const void *key,       /* Key to search for. */
        return ITEM_NOT_FOUND;
 }
 
-#ifdef CONFIG_REISERFS_CHECK
-extern struct tree_balance *cur_tb;
-#endif
 
 /* Minimal possible key. It is never in the tree. */
 const struct reiserfs_key MIN_KEY = { 0, 0, {{0, 0},} };
@@ -519,25 +516,48 @@ static int is_tree_node(struct buffer_head *bh, int level)
 
 #define SEARCH_BY_KEY_READA 16
 
-/* The function is NOT SCHEDULE-SAFE! */
-static void search_by_key_reada(struct super_block *s,
+/*
+ * The function is NOT SCHEDULE-SAFE!
+ * It might unlock the write lock if we needed to wait for a block
+ * to be read. Note that in this case it won't recover the lock to avoid
+ * high contention resulting from too much lock requests, especially
+ * the caller (search_by_key) will perform other schedule-unsafe
+ * operations just after calling this function.
+ *
+ * @return true if we have unlocked
+ */
+static bool search_by_key_reada(struct super_block *s,
                                struct buffer_head **bh,
                                b_blocknr_t *b, int num)
 {
        int i, j;
+       bool unlocked = false;
 
        for (i = 0; i < num; i++) {
                bh[i] = sb_getblk(s, b[i]);
        }
+       /*
+        * We are going to read some blocks on which we
+        * have a reference. It's safe, though we might be
+        * reading blocks concurrently changed if we release
+        * the lock. But it's still fine because we check later
+        * if the tree changed
+        */
        for (j = 0; j < i; j++) {
                /*
                 * note, this needs attention if we are getting rid of the BKL
                 * you have to make sure the prepared bit isn't set on this buffer
                 */
-               if (!buffer_uptodate(bh[j]))
+               if (!buffer_uptodate(bh[j])) {
+                       if (!unlocked) {
+                               reiserfs_write_unlock(s);
+                               unlocked = true;
+                       }
                        ll_rw_block(READA, 1, bh + j);
+               }
                brelse(bh[j]);
        }
+       return unlocked;
 }
 
 /**************************************************************************
@@ -625,11 +645,26 @@ int search_by_key(struct super_block *sb, const struct cpu_key *key,      /* Key to s
                   have a pointer to it. */
                if ((bh = last_element->pe_buffer =
                     sb_getblk(sb, block_number))) {
+                       bool unlocked = false;
+
                        if (!buffer_uptodate(bh) && reada_count > 1)
-                               search_by_key_reada(sb, reada_bh,
+                               /* may unlock the write lock */
+                               unlocked = search_by_key_reada(sb, reada_bh,
                                                    reada_blocks, reada_count);
+                       /*
+                        * If we haven't already unlocked the write lock,
+                        * then we need to do that here before reading
+                        * the current block
+                        */
+                       if (!buffer_uptodate(bh) && !unlocked) {
+                               reiserfs_write_unlock(sb);
+                               unlocked = true;
+                       }
                        ll_rw_block(READ, 1, &bh);
                        wait_on_buffer(bh);
+
+                       if (unlocked)
+                               reiserfs_write_lock(sb);
                        if (!buffer_uptodate(bh))
                                goto io_error;
                } else {
@@ -673,7 +708,7 @@ int search_by_key(struct super_block *sb, const struct cpu_key *key,        /* Key to s
                       !key_in_buffer(search_path, key, sb),
                       "PAP-5130: key is not in the buffer");
 #ifdef CONFIG_REISERFS_CHECK
-               if (cur_tb) {
+               if (REISERFS_SB(sb)->cur_tb) {
                        print_cur_tb("5140");
                        reiserfs_panic(sb, "PAP-5140",
                                       "schedule occurred in do_balance!");
@@ -1024,7 +1059,9 @@ static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, st
                        reiserfs_free_block(th, inode, block, 1);
                    }
 
+                   reiserfs_write_unlock(sb);
                    cond_resched();
+                   reiserfs_write_lock(sb);
 
                    if (item_moved (&s_ih, path))  {
                        need_re_search = 1;
@@ -1262,7 +1299,7 @@ int reiserfs_delete_item(struct reiserfs_transaction_handle *th,
                       "reiserquota delete_item(): freeing %u, id=%u type=%c",
                       quota_cut_bytes, inode->i_uid, head2type(&s_ih));
 #endif
-       DQUOT_FREE_SPACE_NODIRTY(inode, quota_cut_bytes);
+       dquot_free_space_nodirty(inode, quota_cut_bytes);
 
        /* Return deleted body length */
        return ret_value;
@@ -1346,7 +1383,7 @@ void reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th,
                                               quota_cut_bytes, inode->i_uid,
                                               key2type(key));
 #endif
-                               DQUOT_FREE_SPACE_NODIRTY(inode,
+                               dquot_free_space_nodirty(inode,
                                                         quota_cut_bytes);
                        }
                        break;
@@ -1696,7 +1733,7 @@ int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th,
                       "reiserquota cut_from_item(): freeing %u id=%u type=%c",
                       quota_cut_bytes, inode->i_uid, '?');
 #endif
-       DQUOT_FREE_SPACE_NODIRTY(inode, quota_cut_bytes);
+       dquot_free_space_nodirty(inode, quota_cut_bytes);
        return ret_value;
 }
 
@@ -1931,9 +1968,10 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree
                       key2type(&(key->on_disk_key)));
 #endif
 
-       if (DQUOT_ALLOC_SPACE_NODIRTY(inode, pasted_size)) {
+       retval = dquot_alloc_space_nodirty(inode, pasted_size);
+       if (retval) {
                pathrelse(search_path);
-               return -EDQUOT;
+               return retval;
        }
        init_tb_struct(th, &s_paste_balance, th->t_super, search_path,
                       pasted_size);
@@ -1987,7 +2025,7 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree
                       pasted_size, inode->i_uid,
                       key2type(&(key->on_disk_key)));
 #endif
-       DQUOT_FREE_SPACE_NODIRTY(inode, pasted_size);
+       dquot_free_space_nodirty(inode, pasted_size);
        return retval;
 }
 
@@ -2025,9 +2063,10 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
 #endif
                /* We can't dirty inode here. It would be immediately written but
                 * appropriate stat item isn't inserted yet... */
-               if (DQUOT_ALLOC_SPACE_NODIRTY(inode, quota_bytes)) {
+               retval = dquot_alloc_space_nodirty(inode, quota_bytes);
+               if (retval) {
                        pathrelse(path);
-                       return -EDQUOT;
+                       return retval;
                }
        }
        init_tb_struct(th, &s_ins_balance, th->t_super, path,
@@ -2076,6 +2115,6 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
                       quota_bytes, inode->i_uid, head2type(ih));
 #endif
        if (inode)
-               DQUOT_FREE_SPACE_NODIRTY(inode, quota_bytes);
+               dquot_free_space_nodirty(inode, quota_bytes);
        return retval;
 }