Linux.ChinaUnix.net
ChinaUnix | Linux首页 | 新闻 | 博客 | 文章 | 专栏 | 新手 | 方案 | 图书 | 下载 | 人才 | 手册 | wiki | 搜索     
Linux论坛
  会员: 密码: 免费注册 | 忘记密码 | 会员登录 | 搜索 | 帮助 


Kernel Bug-Vulnerability-Comment library
首页 » CU论坛 » Linux » 汇总贴列表 » 内核源码 »  
[打印] [订阅] [收藏] [本帖文本页] [推荐此主题给朋友,立即获积分]
sisi8408 (linux八哥)
风云使者




UID:509266
注册:2006-12-22
最后登录: 2008-09-21
帖子:617
精华:0

可用积分:567 (稍有积蓄)
信誉积分:100
专家积分:0 (本版:0)
空间积分:0
推广积分:0

状态:...离线...

[资料] [站内短信] [Blog]


91楼 发表于 2008-2-9 12:58 


static void internal_copy_pointers_items(struct buffer_info *dest_bi,
                                         struct buffer_head *src,
                                         int last_first, int cpy_num)
{
        /* ATTENTION! Number of node pointers in DEST is equal to number of items in DEST,
         * as delimiting key have already inserted to buffer dest.
         */
        struct buffer_head *dest = dest_bi->bi_bh;
        int nr_dest, nr_src;
        int dest_order, src_order;
        struct block_head *blkh;
        struct reiserfs_key *key;
        struct disk_child *dc;

        nr_src = B_NR_ITEMS(src);

        RFALSE(dest == NULL || src == NULL,
               "src (%p) or dest (%p) buffer is 0", src, dest);
        /*
        2008-2-9 12:54
        linux-2.6.23.12
       
        RFALSE(dest == NULL || src == NULL,
               "src (%p) or dest (%p) buffer is 0", src, dest);
        nr_src = B_NR_ITEMS(src);
        */
[...]
}




您对本贴的看法:鲜花[0] 臭蛋[0]

__________________________________

东直门外大街
张字85号
丁字96号

积分兑换专区 | IT节能和TPC-E活动获奖名单 | 致电800-858-2903,了解DELL如何为你量身订制笔记本 | 送2G U盘 | 站长如何获得资金?
sisi8408 (linux八哥)
风云使者




UID:509266
注册:2006-12-22
最后登录: 2008-09-21
帖子:617
精华:0

可用积分:567 (稍有积蓄)
信誉积分:100
专家积分:0 (本版:0)
空间积分:0
推广积分:0

状态:...离线...

[资料] [站内短信] [Blog]


92楼 发表于 2008-2-12 17:27 


simple ops in Stree

Unlike ext2, reiserfs is a modner FS and has attrs:
1, logging
2, extent inode attr
3, acl, posix or not
4, Stree, derived from Btree

Like Btree, Stree consists of nodes and manages nodes,
which only contains meta info. there are two kinds of nodes
in Stree: interal and leaf, and for simplicity the internal
is called node here, following the Btree def.

By def in Stree, node, mapped to phyiscal block(block on disk) by BLKH,
is just a array of KEY+DC(block pointer or disk child), though the format
of the array is funny, and Mr HR, i guess, favorates block ops in crazy manner,
which can be understood since the block_sz can be changed acoording to ur taste.

Unlike node, leaf is used to store four types of items,
1, sd, stat data, or inode, the hot element of FS
2, de, dir entry, also hot
3, direct
4, indirect
compared withext2, nothing is new but the way to manage them.

Lets see a rather simple example on linux cmdline

# echo a >> /mnt_HS/Stree/simple
# echo $?
0

/*
* As in the whitepaper by Mr. HR, it is not simple to show Stree chart though
* charmimg like Nina Reiser, here i do what i can.
*/

and the corresponding image in Stree is

        | BLKH[h+2] | P0 | ... | P[h+2] | ... | free space |

where BLKH[h+2] represents the block of block_sz bytes pointed to by root node,
i gas, and P[h+2] to dir `Stree',

        | BLKH[h+1] | P0 | ... | PL[h+1] | P[h+1] | PR[h+1] | ... | free space |

where P[h+1] to regular file `simple' or S in HR's dictionary,
simlarly PL[h+1] to L, and PR[h+1] to R, finally and obviuosly h = 0,
in this simple case.

        | BLKH[h] | IH-0 | IH-1 | free space | I-1 | I-0 |

where IH for Item Header, and IH-0 is of type `sd',
I-0 is the socalled inode of `simple',
IH-1, i gas, is of type `direct', and its body I-1 is just `a'.

After another operation on `simple'

# echo b >> /mnt_HS/Stree/simple

i gas, the only chg in Stree is IH-1 and its body from `a' to `ab',
lets check what HR did in v-3.6 of linux-2.6.23.12,

/* first, ==========================
   ip means Inserting or Pasting
*/
static int ip_check_balance(struct tree_balance *tb, int h)
{
[...]
        if (can_node_be_removed(vn->vn_mode, lfree, sfree, rfree, tb, h)
            == NO_BALANCING_NEEDED)
                /* new item fits into node S[h] without any shifting */
                return NO_BALANCING_NEEDED;
[...]
}

/* second, ==========================
*/
static inline int can_node_be_removed(int mode, int lfree, int sfree, int rfree,
                                      struct tree_balance *tb, int h)
{
        struct buffer_head *Sh = PATH_H_PBUFFER(tb->tb_path, h);
        int levbytes = tb->insert_size[h];

        struct item_head *ih;
        struct reiserfs_key *r_key = NULL;

        ih = B_N_PITEM_HEAD(Sh, 0);

        if (tb->CFR[h])
                r_key = B_N_PDELIM_KEY(tb->CFR[h], tb->rkey[h]);
        /*
         * nicer to understand as:
         * lfree + rfree < MAX_CHILD_SIZE(Sh) - sfree + levbytes
         */
        if (lfree + rfree + sfree < MAX_CHILD_SIZE(Sh) + levbytes
            /* shifting may merge items which might save space */
            - ((!h && op_is_left_mergeable(&ih->ih_key, Sh->b_size)) ? IH_SIZE : 0)
            - ((!h && r_key && op_is_left_mergeable(r_key, Sh->b_size)) ? IH_SIZE : 0)
            + (h ? KEY_SIZE : 0))
        { /* node can not be removed */
                if (sfree >= levbytes) {
                        /* new item fits into node S[h] without any shifting */
                        if (!h)
                                tb->s0num = B_NR_ITEMS(Sh) + ((mode == M_INSERT) ? 1 : 0);
                       
                        set_parameters(tb, h, 0, 0, 1, NULL, -1, -1);
                        return NO_BALANCING_NEEDED;
                }
        }
        PROC_INFO_INC(tb->tb_sb, can_node_be_removed[h]);
        return !NO_BALANCING_NEEDED;
}

Oh Jesus, HR favorates shift much more, and i gas once more,
meta data and balance are concerned by HR much more than file data?

As u see, the code for the two ops, fix_node and do_balance, upon Stree is
hard and harder to read, and i dream dig it no more harder
in v-3.7 in the original track, and U r welcome to my dream.

[ 本帖最后由 sisi8408 于 2008-2-12 17:29 编辑 ]



您对本贴的看法:鲜花[0] 臭蛋[0]

__________________________________

东直门外大街
张字85号
丁字96号

积分兑换专区 | IT节能和TPC-E活动获奖名单 | 致电800-858-2903,了解DELL如何为你量身订制笔记本 | 送2G U盘 | 站长如何获得资金?
sisi8408 (linux八哥)
风云使者




UID:509266
注册:2006-12-22
最后登录: 2008-09-21
帖子:617
精华:0

可用积分:567 (稍有积蓄)
信誉积分:100
专家积分:0 (本版:0)
空间积分:0
推广积分:0

状态:...离线...

[资料] [站内短信] [Blog]


93楼 发表于 2008-2-13 20:15 


static void create_virtual_node(struct tree_balance *tb, int h)
{
        struct item_head *ih;
        struct virtual_node *vn = tb->tb_vn;
        int new_num;
        struct buffer_head *Sh = PATH_H_PBUFFER(tb->tb_path, h);

        if (!h) {
                create_virtual_leaf(tb, h);
                return;
        }
        /* size of v node */
        vn->vn_size = MAX_CHILD_SIZE(Sh) - B_FREE_SPACE(Sh)
                        + tb->insert_size[h];
        vn->vn_nr_item = (vn->vn_size - DC_SIZE) / (DC_SIZE + KEY_SIZE);
}

static void create_virtual_leaf(struct tree_balance *tb, int h)
{
        struct item_head *ih;
        struct virtual_node *vn = tb->tb_vn;
        int new_num;
        struct buffer_head *Sh = PATH_H_PBUFFER(tb->tb_path, h);
       
        vn->vn_size = MAX_CHILD_SIZE(Sh) - B_FREE_SPACE(Sh) + tb->insert_size[h];
       
        /* number of items in v node  */
        vn->vn_nr_item = B_NR_ITEMS(Sh) +
                         ((vn->vn_mode == M_INSERT) ? 1 : 0) -
                             ((vn->vn_mode == M_DELETE) ? 1 : 0);

        /* first v item */
        vn->vn_vi = (struct virtual_item *)(tb->tb_vn + 1);
       
        memset(vn->vn_vi, 0, vn->vn_nr_item * sizeof(struct virtual_item));
       
        vn->vn_free_ptr += vn->vn_nr_item * sizeof(struct virtual_item);
        /*
         * first item in S[h]
         */
        ih = B_N_PITEM_HEAD(Sh, 0);
        /*
         * define the mergeability for 0-th item,
         * if it is not being deleted
         */
        if (op_is_left_mergeable(&ih->ih_key, Sh->b_size)
            && (vn->vn_mode != M_DELETE || vn->vn_affected_item_num))
                vn->vn_vi[0].vi_type |= VI_TYPE_LEFT_MERGEABLE;

        /*
         * go through all items those remain in the virtual node,
         * except for the new (inserted) one
         */
        for (new_num = 0; new_num < vn->vn_nr_item; new_num++) {
                int j;
                struct virtual_item *vi = vn->vn_vi + new_num;
                int is_affected = new_num == vn->vn_affected_item_num;

                if (is_affected && vn->vn_mode == M_INSERT)
                        continue;

                /* get item number in source node */
                j = old_item_num(new_num, vn->vn_affected_item_num, vn->vn_mode);
                /*
                 * vi->vi_item_len += ih_item_len(ih + j) + IH_SIZE;
                 *
                 * and its still amazing why IH_SIZE counted even if !is_affected.
                                 *
                                 * Jesus, its used, at least, by check_left/right

        for (i = 0; i < vn->vn_nr_item;
             i++, ih_size = IH_SIZE, d_size = 0, vi++) {
                d_size += vi->vi_item_len;

        for (i = vn->vn_nr_item - 1; i >= 0;
             i--, d_size = 0, ih_size = IH_SIZE, vi--) {
                d_size += vi->vi_item_len;
                                 *
                                 */
                vi->vi_item_len = ih_item_len(ih + j) + IH_SIZE;
                vi->vi_ih   = ih + j;
                vi->vi_item = B_I_PITEM(Sh, ih + j);
                vi->vi_uarea = vn->vn_free_ptr;
                /*
                 * FIXME: there is no check, that item operation did not
                 * consume too much memory
                 */
                vn->vn_free_ptr +=
                        op_create_vi(vn, vi, is_affected, tb->insert_size[0]);

                if (tb->vn_buf + tb->vn_buf_size < vn->vn_free_ptr)
                        reiserfs_panic(tb->tb_sb,
                                       "vs-8030: create_virtual_node: "
                                       "virtual node space consumed");
               
                if (!is_affected) /* this item is not being changed */
                        continue;

                if (vn->vn_mode == M_PASTE || vn->vn_mode == M_CUT) {
                        /*vn->vn_vi[new_num].vi_item_len += tb->insert_size[0]; */
                        vi->vi_item_len += tb->insert_size[0];
                        vi->vi_new_data = vn->vn_data;
                }
        }

        /* virtual inserted item is not defined yet */
        if (vn->vn_mode == M_INSERT) {
                struct virtual_item *vi = vn->vn_vi + vn->vn_affected_item_num;

                RFALSE(vn->vn_ins_ih == 0,
                       "vs-8040: item header of inserted item is not specified");

                vi->vi_item_len = tb->insert_size[0];
                vi->vi_ih = vn->vn_ins_ih;
                vi->vi_item = vn->vn_data;
                vi->vi_uarea = vn->vn_free_ptr;

                op_create_vi(vn, vi, 0 /*not pasted or cut */ ,
                             tb->insert_size[0]);
        }

        /* set right merge flag we take right delimiting key and
         * check whether it is a mergeable item
         */
        if (tb->CFR[0]) {
                struct reiserfs_key *key;

                key = B_N_PDELIM_KEY(tb->CFR[0], tb->rkey[0]);

                if (op_is_left_mergeable(key, Sh->b_size) &&
                    (vn->vn_mode != M_DELETE ||
                     vn->vn_affected_item_num != B_NR_ITEMS(Sh) - 1))
                        vn->vn_vi[vn->vn_nr_item - 1].vi_type |= VI_TYPE_RIGHT_MERGEABLE;

#ifdef CONFIG_REISERFS_CHECK
                if (op_is_left_mergeable(key, Sh->b_size) &&
                    !(vn->vn_mode != M_DELETE
                      || vn->vn_affected_item_num != B_NR_ITEMS(Sh) - 1)) {
                        /* we delete last item and
                         * it could be merged with right neighbor's first item
                         */
                        if (!
                            (B_NR_ITEMS(Sh) == 1
                             && is_direntry_le_ih(B_N_PITEM_HEAD(Sh, 0))
                             && I_ENTRY_COUNT(B_N_PITEM_HEAD(Sh, 0)) == 1)) {
                                /* node contains more than 1 item, or item is not directory item, or this item contains more than 1 entry */
                                print_block(Sh, 0, -1, -1);
                                reiserfs_panic(tb->tb_sb,
                                               "vs-8045: create_virtual_node: rdkey %k, affected item==%d (mode==%c) Must be %c",
                                               key, vn->vn_affected_item_num,
                                               vn->vn_mode, M_DELETE);
                        }
                }
#endif
        }
}

[ 本帖最后由 sisi8408 于 2008-2-13 20:45 编辑 ]



您对本贴的看法:鲜花[0] 臭蛋[0]

__________________________________

东直门外大街
张字85号
丁字96号

积分兑换专区 | IT节能和TPC-E活动获奖名单 | 致电800-858-2903,了解DELL如何为你量身订制笔记本 | 送2G U盘 | 站长如何获得资金?
daemeon   帅哥
精灵




UID:304570
注册:2005-8-20
最后登录: 2008-09-21
帖子:158
精华:0

可用积分:148 (白手起家)
信誉积分:100
专家积分:0 (本版:0)
空间积分:0
推广积分:0

状态:...离线...

[资料] [站内短信] [Blog]


94楼 发表于 2008-2-15 03:44 
linux-2.6.24/fs/dcache.c

static void switch_names(struct dentry *dentry, struct dentry *target)
{
        if (dname_external(target)) {
                if (dname_external(dentry)) {
                        /*
                         * Both external: swap the pointers
                         */
                        do_switch(target->d_name.name, dentry->d_name.name);
                } else {
                        /*
                         * dentry:internal, target:external.  Steal target's
                         * storage and make target internal.
                         */
                        memcpy(target->d_iname, dentry->d_name.name,
                                        dentry->d_name.len + 1);
                        dentry->d_name.name = target->d_name.name;
                        target->d_name.name = target->d_iname;
                }
        } else {
                if (dname_external(dentry)) {
                        /*
                         * dentry:external, target:internal.  Give dentry's
                         * storage to target and make dentry internal
                         */
                        memcpy(dentry->d_iname, target->d_name.name,
                                        target->d_name.len + 1);
                        target->d_name.name = dentry->d_name.name;
                        dentry->d_name.name = dentry->d_iname;
                } else {
                        /*
                         * Both are internal.  Just copy target to dentry
                         */
                        memcpy(dentry->d_iname, target->d_name.name,
                                        target->d_name.len + 1);

                }
        }
}



您对本贴的看法:鲜花[0] 臭蛋[0]
积分兑换专区 | IT节能和TPC-E活动获奖名单 | 致电800-858-2903,了解DELL如何为你量身订制笔记本 | 送2G U盘 | 站长如何获得资金?
sisi8408 (linux八哥)
风云使者




UID:509266
注册:2006-12-22
最后登录: 2008-09-21
帖子:617
精华:0

可用积分:567 (稍有积蓄)
信誉积分:100
专家积分:0 (本版:0)
空间积分:0
推广积分:0

状态:...离线...

[资料] [站内短信] [Blog]


95楼 发表于 2008-2-16 14:54 
回复 #94 daemeon 的帖子

itis only u, at least uptonow, play cool game like this,
and it sounds cooler if u show ur nice comment.



您对本贴的看法:鲜花[0] 臭蛋[0]

__________________________________

东直门外大街
张字85号
丁字96号

积分兑换专区 | IT节能和TPC-E活动获奖名单 | 致电800-858-2903,了解DELL如何为你量身订制笔记本 | 送2G U盘 | 站长如何获得资金?
sisi8408 (linux八哥)
风云使者




UID:509266
注册:2006-12-22
最后登录: 2008-09-21
帖子:617
精华:0

可用积分:567 (稍有积蓄)
信誉积分:100
专家积分:0 (本版:0)
空间积分:0
推广积分:0

状态:...离线...

[资料] [站内短信] [Blog]


96楼 发表于 2008-2-16 14:56 


static void balance_leaf_do_split(struct tree_balance *tb,
                                   struct item_head *ih,
                                   const char *body,
                                   int flag,
                                   struct item_head *insert_key,
                                   struct buffer_head **insert_ptr)
{
        struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
        /* index of the affected item */
        int item_pos = PATH_LAST_POSITION(tb->tb_path);

        struct buffer_info bi;

        int n, i, ret_val;
        int pos_in_item;
        int zeros_num;

        struct buffer_head *S_new[2];
        int snum[2];
        int sbytes[2];
       
        if (!tb->blknum[0])
                return;

        if (!(flag == M_INSERT || flag == M_PASTE) {
                reiserfs_panic(tb->tb_sb,
                        "PAP-12245: balance_leaf: blknum > 2: unexpectable mode: %s(%d)",
                        (flag == M_DELETE) ? "DELETE" :
                        ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag);
                return;
        }
       
        RFALSE(tb->blknum[0] < 1 || tb->blknum[0] > 3,
                "PAP-12180: blknum can not be %d. It must be in range [1,3]",
                tb->blknum[0]);

        /* Fill new nodes that appear in place of S[0] */
        snum[0] = tb->s1num;
        snum[1] = tb->s2num;
        sbytes[0] = tb->s1bytes;
        sbytes[1] = tb->s2bytes;

        for (i = tb->blknum[0] - 2; i >= 0; i--) {
                RFALSE(!snum[i], "PAP-12200: snum[%d] == %d. Must be > 0", i, snum[i]);
                /* here we shift from S to S_new nodes */
                S_new[i] = get_FEB(tb);
                /* initialized block type and tree level */
                set_blkh_level(B_BLK_HEAD(S_new[i]), DISK_LEAF_NODE_LEVEL);

                n = B_NR_ITEMS(tbS0);
               
                if (flag == M_INSERT) {
                        if (!(n - snum[i] < item_pos)) {
                                /* new item or it part don't falls into S_new[i] */
                                leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
                                                snum[i], sbytes[i], S_new[i]);
                                goto next;
                        }
                        goto long_tail_insert;
                } else {
                        if (!(n - snum[i] <= item_pos)) {
                                /* pasted item doesn't fall into S_new[i] */
                                leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
                                                snum[i], sbytes[i], S_new[i]);
                                goto next;
                        }
                        goto long_tail_paste;
                }

        long_tail_insert:
                if (item_pos == n - snum[i] + 1 && sbytes[i] != -1) {
                        /* part of new item falls into S_new[i] */
                        int old_key_comp, old_len, r_zeros_number;
                        const char *r_body;
                        int version;
                       
                        /* Move snum[i]-1 items from S[0] to S_new[i] */
                        leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
                                        snum[i] -1, -1, S_new[i]);
                        /* Remember key component and item length */
                        version = ih_version(ih);
                        old_key_comp = le_ih_k_offset(ih);
                        old_len = ih_item_len(ih);
                       
                        /*Calculate key component and item length to insert into S_new[i] */
                        set_le_ih_k_offset(ih,
                            le_ih_k_offset(ih) +
                               ((old_len - sbytes[i]) << (is_indirect_le_ih(ih) ?
                                                                 tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT : 0)));
                        put_ih_item_len(ih, sbytes[i]);
                        /* Insert part of the item into S_new[i] before 0-th item */
                        bi.tb = tb;
                        bi.bi_bh = S_new[i];
                        bi.bi_parent = NULL;
                        bi.bi_position = 0;
                       
                        if ((old_len - sbytes[i]) > zeros_num) {
                                r_zeros_number = 0;
                                r_body = body + (old_len - sbytes[i]) - zeros_num;
                        } else {
                                r_body = body;
                                r_zeros_number = zeros_num - (old_len - sbytes[i]);
                                zeros_num -= r_zeros_number;
                        }
                        leaf_insert_into_buf(&bi, 0, ih, r_body, r_zeros_number);
                       
                        /* Calculate key component and item length to insert into S[i] */
                        set_le_ih_k_offset(ih, old_key_comp);
                        put_ih_item_len(ih, old_len - sbytes[i]);
                        tb->insert_size[0] -= sbytes[i];
               
                } else { /* whole new item falls into S_new[i] */
                        /* Shift snum[0] - 1 items to S_new[i] (sbytes[i] of split item) */
                        leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
                                        snum[i] -1, sbytes[i], S_new[i]);
                        /* Insert new item into S_new[i] */
                        bi.tb = tb;
                        bi.bi_bh = S_new[i];
                        bi.bi_parent = NULL;
                        bi.bi_position = 0;
                       
                        leaf_insert_into_buf(&bi, item_pos - n + snum[i] - 1,
                                                ih, body, zeros_num);
                        zeros_num = tb->insert_size[0] = 0;
                }
                goto next;
       
        long_tail_paste:
                if (item_pos == n - snum[i] && sbytes[i] != -1) {
                        /* we must shift part of the appended item */
                        struct item_head *aux_ih;
                       
                        RFALSE(ih, "PAP-12210: ih must be 0");
                       
                        aux_ih = B_N_PITEM_HEAD(tbS0, item_pos);
                        if (is_direntry_le_ih(aux_ih)) {
                                /* we append to directory item */
                                int entry_count = ih_entry_count(aux_ih);
                               
                                if (entry_count - sbytes[i] < pos_in_item
                                    && pos_in_item <= entry_count) {
                                        /* new directory entry falls into S_new[i] */
                                        RFALSE(!tb->insert_size[0],
                                               "PAP-12215: insert_size is already 0");
                                        RFALSE(sbytes[i] - 1 >= entry_count,
                                               "PAP-12220: there are no so much entries (%d), only %d",
                                               sbytes[i] - 1, entry_count);
                                       
                                        /* Shift snum[i]-1 items in whole. Shift sbytes[i] directory entries from directory item number snum[i] */
                                        leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i],
                                                             sbytes[i] - 1, S_new[i]);
                                        /* Paste given directory entry to directory item */
                                        bi.tb = tb;
                                        bi.bi_bh = S_new[i];
                                        bi.bi_parent = NULL;
                                        bi.bi_position = 0;
                                       
                                        leaf_paste_in_buffer(&bi, 0,
                                                pos_in_item - entry_count + sbytes[i] - 1,
                                                tb->insert_size[0], body, zeros_num);
                                       
                                        /* paste new directory entry */
                                        leaf_paste_entries(bi.bi_bh, 0,
                                                pos_in_item - entry_count + sbytes[i] - 1,
                                                1,
                                                (struct reiserfs_de_head *) body,
                                                body + DEH_SIZE, tb->insert_size[0]);
                                       
                                        tb->insert_size[0] = 0;
                                        pos_in_item++;
                                } else {
                                        /* new directory entry doesn't fall into S_new[i] */
                                        leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
                                                snum[i], sbytes[i], S_new[i]);
                                }
                        } else { /* regular object */
                                int n_shift, n_rem, r_zeros_number;
                                const char *r_body;
                               
                                RFALSE(pos_in_item != ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos))
                                       || tb->insert_size[0] <= 0,
                                       "PAP-12225: item too short or insert_size <= 0");
                                /* Calculate number of bytes which must be
                                 * shifted from appended item */
                                n_shift = sbytes[i] - tb->insert_size[0];
                                if (n_shift < 0)
                                        n_shift = 0;
                               
                                leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
                                                snum[i], n_shift, S_new[i]);
                               
                                /* Calculate number of bytes which must remain
                                 * in body after append to S_new[i] */
                                n_rem = tb->insert_size[0] - sbytes[i];
                                if (n_rem < 0)
                                        n_rem = 0;
                                /* Append part of body into S_new[0] */
                                bi.tb = tb;
                                bi.bi_bh = S_new[i];
                                bi.bi_parent = NULL;
                                bi.bi_position = 0;
                               
                                if (n_rem > zeros_num) {
                                        r_zeros_number = 0;
                                        r_body = body + n_rem - zeros_num;
                                } else {
                                        r_body = body;
                                        r_zeros_number = zeros_num - n_rem;
                                        zeros_num -= r_zeros_number;
                                }
                                leaf_paste_in_buffer(&bi, 0, n_shift,
                                                     tb->insert_size[0] - n_rem,
                                                     r_body, r_zeros_number);
                                {
                                        /* 2008-2-16 14:19
                                         * itis not easy to format,
                                         * needless to say to debug HR.
                                         */
                                        struct item_head *tmp;
                                       
                                        tmp = B_N_PITEM_HEAD(S_new[i], 0);
                                        if (is_indirect_le_ih(tmp)) {
                                                set_ih_free_space(tmp, 0);
                                               
                                                set_le_ih_k_offset(tmp,
                                                    le_ih_k_offset(tmp) +
                                                        (n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT)));
                                        } else {
                                                set_le_ih_k_offset(tmp,
                                                    le_ih_k_offset(tmp) + n_rem);
                                        }
                                }
                                tb->insert_size[0] = n_rem;
                                if (!n_rem)
                                        pos_in_item++;
                        }
                } else { /* item falls wholly into S_new[i] */
                        int ret_val;
                        struct item_head *pasted;
#ifdef CONFIG_REISERFS_CHECK
                        struct item_head *ih = B_N_PITEM_HEAD(tbS0, item_pos);
                       
                        if (!is_direntry_le_ih(ih) &&
                            (pos_in_item != ih_item_len(ih)
                             || tb->insert_size[0] <= 0))
                                reiserfs_panic(tb->tb_sb,
                                               "PAP-12235: balance_leaf: pos_in_item must be equal to ih_item_len");
#endif        /* CONFIG_REISERFS_CHECK */
                        ret_val = leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
                                                 snum[i], sbytes[i], S_new[i]);
                        RFALSE(ret_val,
                               "PAP-12240: unexpected value returned by leaf_move_items (%d)",
                               ret_val);
                        /* paste into item */
                        bi.tb = tb;
                        bi.bi_bh = S_new[i];
                        bi.bi_parent = NULL;
                        bi.bi_position = 0;
                       
                        leaf_paste_in_buffer(&bi, item_pos - n + snum[i],
                                             pos_in_item,
                                             tb->insert_size[0],
                                             body, zeros_num);
                       
                        pasted = B_N_PITEM_HEAD(S_new[i], item_pos - n + snum[i]);
                        if (is_direntry_le_ih(pasted))
                                leaf_paste_entries(bi.bi_bh,
                                                   item_pos - n + snum[i],
                                                   pos_in_item, 1,
                                                   (struct reiserfs_de_head *)body,
                                                   body + DEH_SIZE,
                                                   tb->insert_size[0]);
                        /* if we paste to indirect item update ih_free_space */
                        if (is_indirect_le_ih(pasted))
                                set_ih_free_space(pasted, 0);
                        zeros_num = tb->insert_size[0] = 0;
                }
                goto next;
       
        next:
                memcpy(insert_key + i, B_N_PKEY(S_new[i], 0), KEY_SIZE);
                insert_ptr[i] = S_new[i];

                RFALSE(!buffer_journaled(S_new[i])
                       || buffer_journal_dirty(S_new[i])
                       || buffer_dirty(S_new[i]),
                       "PAP-12247: S_new[%d] : (%b)", i, S_new[i]);
        } /* for loop */
}




您对本贴的看法:鲜花[0] 臭蛋[0]

__________________________________

东直门外大街
张字85号
丁字96号

积分兑换专区 | IT节能和TPC-E活动获奖名单 | 致电800-858-2903,了解DELL如何为你量身订制笔记本 | 送2G U盘 | 站长如何获得资金?
sisi8408 (linux八哥)
风云使者




UID:509266
注册:2006-12-22
最后登录: 2008-09-21
帖子:617
精华:0

可用积分:567 (稍有积蓄)
信誉积分:100
专家积分:0 (本版:0)
空间积分:0
推广积分:0

状态:...离线...

[资料] [站内短信] [Blog]


97楼 发表于 2008-2-16 14:57 


static void balance_leaf_shift_right(struct tree_balance *tb,
                                   struct item_head *ih,
                                   const char *body,
                                   int flag,
                                   struct item_head *insert_key,
                                   struct buffer_head **insert_ptr)
{
        struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
        /* index of the affected item */
        int item_pos = PATH_LAST_POSITION(tb->tb_path);
       
        struct buffer_info bi;

        int n, ret_val;
        int pos_in_item;
        int zeros_num;
       
        if (!(tb->rnum[0] > 0)) /* right shift not needed */
                return;
       
        zeros_num = 0;
        if (flag == M_INSERT && body == 0)
                zeros_num = ih_item_len(ih);

        pos_in_item = tb->tb_path->pos_in_item;
        /* for indirect item pos_in_item is measured in unformatted node
         * pointers. Recalculate to bytes
         */
        if (flag != M_INSERT &&
            is_indirect_le_ih(B_N_PITEM_HEAD(tbS0, item_pos)))
                pos_in_item *= UNFM_P_SIZE;

        n = B_NR_ITEMS(tbS0);
       
        if (flag == M_INSERT) {
                if (!(n - tb->rnum[0] < item_pos)) {
                        /* new item or part of it doesn't fall into R[0] */
                        leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
                        return;
                }
                if (!(item_pos == n - tb->rnum[0] + 1 && tb->rbytes != -1)) {
                        /* whole new item falls into R[0] */

                        /* Shift rnum[0]-1 items to R[0] */
                        ret_val = leaf_shift_right(tb, tb->rnum[0] -1, tb->rbytes);
                       
                        /* Insert new item into R[0] */
                        bi.tb = tb;
                        bi.bi_bh = tb->R[0];
                        bi.bi_parent = tb->FR[0];
                        bi.bi_position = get_right_neighbor_position(tb, 0);
                       
                        leaf_insert_into_buf(&bi, item_pos - n + tb->rnum[0] - 1,
                                             ih, body, zeros_num);
                        if (item_pos - n + tb->rnum[0] - 1 == 0) {
                                replace_key(tb, tb->CFR[0], tb->rkey[0],
                                            tb->R[0], 0);
                        }
                        zeros_num = tb->insert_size[0] = 0;
                } else {
                        loff_t old_key_comp, old_len, r_zeros_number;
                        const char *r_body;
                        int version;
                        loff_t offset;
                       
                        leaf_shift_right(tb, tb->rnum[0] -1, -1);
                       
                        version = ih_version(ih);
                        /* Remember key component and item length */
                        old_key_comp = le_ih_k_offset(ih);
                        old_len = ih_item_len(ih);
                       
                        /* Calculate key component and item length to insert into R[0] */
                        offset = le_ih_k_offset(ih) +
                                 ((old_len - tb->rbytes) << (is_indirect_le_ih(ih) ?
                                  tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT : 0));
                        set_le_ih_k_offset(ih, offset);
                        put_ih_item_len(ih, tb->rbytes);
                       
                        /* Insert part of the item into R[0] */
                        bi.tb = tb;
                        bi.bi_bh = tb->R[0];
                        bi.bi_parent = tb->FR[0];
                        bi.bi_position = get_right_neighbor_position(tb, 0);
                       
                        if ((old_len - tb->rbytes) > zeros_num) {
                                r_zeros_number = 0;
                                r_body = body + (old_len - tb->rbytes) - zeros_num;
                        } else {
                                r_body = body;
                                r_zeros_number = zeros_num - (old_len - tb->rbytes);
                                zeros_num -= r_zeros_number;
                        }
                        leaf_insert_into_buf(&bi, 0, ih, r_body, r_zeros_number);
                       
                        /* Replace right delimiting key by first key in R[0] */
                        replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
                       
                        /* Calculate key component and item length to insert into S[0] */
                        set_le_ih_k_offset(ih, old_key_comp);
                        put_ih_item_len(ih, old_len - tb->rbytes);
                       
                        tb->insert_size[0] -= tb->rbytes;
                }
        }
        else if (flag == M_PASTE) {
                if (!(n - tb->rnum[0] <= item_pos)) {
                        /* new item doesn't fall into R[0] */
                        leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
                }
                else if (!(item_pos == n - tb->rnum[0] && tb->rbytes != -1)) {
                        /* pasted item in whole falls into R[0] */
                        struct item_head *pasted;
                       
                        ret_val = leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
                       
                        /* append item in R[0] */
                        /* if (pos_in_item >= 0) */ {
                                bi.tb = tb;
                                bi.bi_bh = tb->R[0];
                                bi.bi_parent = tb->FR[0];
                                bi.bi_position = get_right_neighbor_position(tb, 0);
                               
                                leaf_paste_in_buffer(&bi, item_pos - n + tb->rnum[0],
                                                     pos_in_item, tb->insert_size[0],
                                                     body, zeros_num);
                        }
                        /* paste new entry, if item is directory item */
                        pasted = B_N_PITEM_HEAD(tb->R[0], item_pos - n + tb->rnum[0]);
                       
                        if (is_direntry_le_ih(pasted) && pos_in_item >= 0) {
                                leaf_paste_entries(bi.bi_bh, item_pos - n + tb->rnum[0],
                                                   pos_in_item, 1,
                                                   (struct reiserfs_de_head *)body,
                                                   body + DEH_SIZE,
                                                   tb->insert_size[0]);
                                if (!pos_in_item) {
                                        RFALSE(item_pos - n + tb->rnum[0],
                                               "PAP-12165: directory item must be first item of node when pasting is in 0th position");
                                        /* update delimiting keys */