예제 #1
0
/*
 * Replace the key node from rbtree for new container
 *    replace node from rbtree, return old node pointer
 */
struct container * container_replace(struct rb_root *root, const void *key, struct container *cont, int (*cmp)(const void *x, const void *y))
{
    struct container *find = container_search(root, key, cmp);
    if (!find)
        return 0;
    rb_replace_node(&(find->rb_node), &cont->rb_node, root);
    return find;
}
예제 #2
0
파일: rb_tree.c 프로젝트: inolen/redream
/*  n          r
      r  ->  n
    l          l */
static void rb_rotate_left(struct rb_tree *t, struct rb_node *n,
                           struct rb_callbacks *cb) {
  struct rb_node *r = n->right;
  rb_replace_node(t, n, r);
  n->right = r->left;
  if (n->right) {
    n->right->parent = n;
  }
  r->left = n;
  r->left->parent = r;

  if (cb && cb->rotate) {
    cb->rotate(t, n, r);
  }
}
예제 #3
0
static void rb_rotate_left(struct rb_root* root, struct rb_node* node)
{
  struct rb_node* right = node->rb_right;

  rb_replace_node(root, node, right);

  node->rb_right = right->rb_left;

  if (right->rb_left != NULL)
  {
    right->rb_left->rb_parent = node;
  }
  right->rb_left = node;
  node->rb_parent = right;
}
예제 #4
0
파일: rb_tree.c 프로젝트: inolen/redream
/*   n         l
   l      ->     n
     r         r */
static void rb_rotate_right(struct rb_tree *t, struct rb_node *n,
                            struct rb_callbacks *cb) {
  struct rb_node *l = n->left;
  struct rb_node *r = l->right;
  rb_replace_node(t, n, l);
  n->left = r;
  if (n->left) {
    n->left->parent = n;
  }
  l->right = n;
  l->right->parent = l;

  if (cb && cb->rotate) {
    cb->rotate(t, n, l);
  }
}
예제 #5
0
static void rb_rotate_right(struct rb_root *root, struct rb_node* node)
{
  struct rb_node* left = node->rb_left;
  
  rb_replace_node(root, node, left);

  node->rb_left = left->rb_right;

  if (left->rb_right != NULL)
  {
    left->rb_right->rb_parent = node;
  }

  left->rb_right = node;
  node->rb_parent = left;
}
예제 #6
0
파일: rb_tree.c 프로젝트: inolen/redream
void rb_unlink(struct rb_tree *t, struct rb_node *n, struct rb_callbacks *cb) {
  CHECK(!rb_empty_node(n));

  /* when deleting a node with two non-leaf children, we swap the node with
     its in-order predecessor (the maximum or rightmost element in the left
     subtree), and then delete the original node which now has only one
     non-leaf child */
  if (n->left && n->right) {
    struct rb_node *pred = rb_max(n->left);
    rb_swap_node(t, n, pred);
  }

  /* a node with at most one non-leaf child can simply be replaced with its
     non-leaf child */
  CHECK(!n->left || !n->right);
  struct rb_node *child = n->right ? n->right : n->left;
  if (rb_color(n) == RB_BLACK) {
    rb_unlink_1(t, n, cb);
  }
  rb_replace_node(t, n, child);

  /* force root to black */
  if (t->root) {
    t->root->color = RB_BLACK;
  }

  /* fix up each node in the parent chain */
  if (cb && cb->propagate) {
    cb->propagate(t, n->parent);
  }

  /* clear node state to support rb_empty_node */
  memset(n, 0, sizeof(*n));

#if VERIFY_TREE
  rb_verify(t->root);
#endif
}
예제 #7
0
/*
 * This function is used when we read an inode. Data nodes arrive in
 * arbitrary order -- they may be older or newer than the nodes which
 * are already in the tree. Where overlaps occur, the older node can
 * be discarded as long as the newer passes the CRC check. We don't
 * bother to keep track of holes in this rbtree, and neither do we deal
 * with frags -- we can have multiple entries starting at the same
 * offset, and the one with the smallest length will come first in the
 * ordering.
 *
 * Returns 0 if the node was handled (including marking it obsolete)
 *	 < 0 an if error occurred
 */
static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
				struct jffs2_readinode_info *rii,
				struct jffs2_tmp_dnode_info *tn)
{
	uint32_t fn_end = tn->fn->ofs + tn->fn->size;
	struct jffs2_tmp_dnode_info *this, *ptn;

	dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw));

	/* If a node has zero dsize, we only have to keep if it if it might be the
	   node with highest version -- i.e. the one which will end up as f->metadata.
	   Note that such nodes won't be REF_UNCHECKED since there are no data to
	   check anyway. */
	if (!tn->fn->size) {
		if (rii->mdata_tn) {
			if (rii->mdata_tn->version < tn->version) {
				/* We had a candidate mdata node already */
				dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version);
				jffs2_kill_tn(c, rii->mdata_tn);
			} else {
				dbg_readinode("kill new mdata with ver %d (older than existing %d\n",
					      tn->version, rii->mdata_tn->version);
				jffs2_kill_tn(c, tn);
				return 0;
			}
		}
		rii->mdata_tn = tn;
		dbg_readinode("keep new mdata with ver %d\n", tn->version);
		return 0;
	}

	/* Find the earliest node which _may_ be relevant to this one */
	this = jffs2_lookup_tn(&rii->tn_root, tn->fn->ofs);
	if (this) {
		/* If the node is coincident with another at a lower address,
		   back up until the other node is found. It may be relevant */
		while (this->overlapped) {
			ptn = tn_prev(this);
			if (!ptn) {
				/*
				 * We killed a node which set the overlapped
				 * flags during the scan. Fix it up.
				 */
				this->overlapped = 0;
				break;
			}
			this = ptn;
		}
		dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole");
	}

	while (this) {
		if (this->fn->ofs > fn_end)
			break;
		dbg_readinode("Ponder this ver %d, 0x%x-0x%x\n",
			      this->version, this->fn->ofs, this->fn->size);

		if (this->version == tn->version) {
			/* Version number collision means REF_PRISTINE GC. Accept either of them
			   as long as the CRC is correct. Check the one we have already...  */
			if (!check_tn_node(c, this)) {
				/* The one we already had was OK. Keep it and throw away the new one */
				dbg_readinode("Like old node. Throw away new\n");
				jffs2_kill_tn(c, tn);
				return 0;
			} else {
				/* Who cares if the new one is good; keep it for now anyway. */
				dbg_readinode("Like new node. Throw away old\n");
				rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
				jffs2_kill_tn(c, this);
				/* Same overlapping from in front and behind */
				return 0;
			}
		}
		if (this->version < tn->version &&
		    this->fn->ofs >= tn->fn->ofs &&
		    this->fn->ofs + this->fn->size <= fn_end) {
			/* New node entirely overlaps 'this' */
			if (check_tn_node(c, tn)) {
				dbg_readinode("new node bad CRC\n");
				jffs2_kill_tn(c, tn);
				return 0;
			}
			/* ... and is good. Kill 'this' and any subsequent nodes which are also overlapped */
			while (this && this->fn->ofs + this->fn->size <= fn_end) {
				struct jffs2_tmp_dnode_info *next = tn_next(this);
				if (this->version < tn->version) {
					tn_erase(this, &rii->tn_root);
					dbg_readinode("Kill overlapped ver %d, 0x%x-0x%x\n",
						      this->version, this->fn->ofs,
						      this->fn->ofs+this->fn->size);
					jffs2_kill_tn(c, this);
				}
				this = next;
			}
			dbg_readinode("Done killing overlapped nodes\n");
			continue;
		}
		if (this->version > tn->version &&
		    this->fn->ofs <= tn->fn->ofs &&
		    this->fn->ofs+this->fn->size >= fn_end) {
			/* New node entirely overlapped by 'this' */
			if (!check_tn_node(c, this)) {
				dbg_readinode("Good CRC on old node. Kill new\n");
				jffs2_kill_tn(c, tn);
				return 0;
			}
			/* ... but 'this' was bad. Replace it... */
			dbg_readinode("Bad CRC on old overlapping node. Kill it\n");
			tn_erase(this, &rii->tn_root);
			jffs2_kill_tn(c, this);
			break;
		}

		this = tn_next(this);
	}

	/* We neither completely obsoleted nor were completely
	   obsoleted by an earlier node. Insert into the tree */
	{
		struct rb_node *parent;
		struct rb_node **link = &rii->tn_root.rb_node;
		struct jffs2_tmp_dnode_info *insert_point = NULL;

		while (*link) {
			parent = *link;
			insert_point = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
			if (tn->fn->ofs > insert_point->fn->ofs)
				link = &insert_point->rb.rb_right;
			else if (tn->fn->ofs < insert_point->fn->ofs ||
				 tn->fn->size < insert_point->fn->size)
				link = &insert_point->rb.rb_left;
			else
				link = &insert_point->rb.rb_right;
		}
		rb_link_node(&tn->rb, &insert_point->rb, link);
		rb_insert_color(&tn->rb, &rii->tn_root);
	}

	/* If there's anything behind that overlaps us, note it */
	this = tn_prev(tn);
	if (this) {
		while (1) {
			if (this->fn->ofs + this->fn->size > tn->fn->ofs) {
				dbg_readinode("Node is overlapped by %p (v %d, 0x%x-0x%x)\n",
					      this, this->version, this->fn->ofs,
					      this->fn->ofs+this->fn->size);
				tn->overlapped = 1;
				break;
			}
			if (!this->overlapped)
				break;

			ptn = tn_prev(this);
			if (!ptn) {
				/*
				 * We killed a node which set the overlapped
				 * flags during the scan. Fix it up.
				 */
				this->overlapped = 0;
				break;
			}
			this = ptn;
		}
	}

	/* If the new node overlaps anything ahead, note it */
	this = tn_next(tn);
	while (this && this->fn->ofs < fn_end) {
		this->overlapped = 1;
		dbg_readinode("Node ver %d, 0x%x-0x%x is overlapped\n",
			      this->version, this->fn->ofs,
			      this->fn->ofs+this->fn->size);
		this = tn_next(this);
	}
	return 0;
}
예제 #8
0
static inline int reliable_ack___save (su_serv_t *psvr,
                                       const frames_t *frame, const void *outbuff, int outbytes)
{
    /* Construct search key */
    rb_key_cache_t key;
    memcpy(&key.destaddr, &frame->srcaddr, sizeof(SAUN));
    key.destlen = frame->srclen;
    key.seq = frame->recvhdr.seq;
    key.sid = frame->recvhdr.sid;

    struct rb_node *cachenode;
    cache_t *cache;

    /* If is no reply content, only replace len value, don't replace node
     * If have a content, must allocating and replacing new node */
    if (outbuff == 0 && outbytes == 0) {
        if ((cachenode = rb_search(&psvr->rbackcache, &key))) {
            cache = rb_entry(cachenode, cache_t, rbn);
            cache->frame.len = 0;
#if defined SU_DEBUG_LIST || defined SU_DEBUG_RBTREE
            pthread_t tid = pthread_self();
            char ipbuff[INET6_ADDRSTRLEN];
            int port;
            su_get_ip_port_f(&cache->frame.srcaddr, ipbuff, sizeof(ipbuff), &port);
            log_msg("serv %x %x time %u key(%s:%d:%u:%u) "
                    ColorRed "+ACK cache %p" ColorEnd ,
                    psvr, tid, cache->ts, ipbuff, port,
                    cache->frame.recvhdr.sid, cache->frame.recvhdr.seq, cache);
#endif
            return 0;
        }
        errno = ENOKEY;
        return -1;
    }

    cache_t * newack;
    newack = calloc(1, sizeof(cache_t) + outbytes);
    if (newack == 0) {
        errno = ENOBUFS;
        return -1;
    }

    /* Construct a new node */
    memcpy(&newack->frame, frame, sizeof(frames_t));
    memcpy(newack->frame.data, outbuff, outbytes);
    newack->frame.len = outbytes;

    /* Find and replace the hold node */
    if ((cachenode = rb_search(&psvr->rbackcache, &key))) {
        rb_replace_node(cachenode, &newack->rbn, &psvr->rbackcache);
        cache = rb_entry(cachenode, cache_t, rbn);
        newack->ts = cache->ts;
        list_remove(&cache->frame.node);
        list_append(&psvr->lsackcache, &newack->frame.node);
#if defined SU_DEBUG_LIST || defined SU_DEBUG_RBTREE
        pthread_t tid = pthread_self();
        char ipbuff[INET6_ADDRSTRLEN];
        int port;
        su_get_ip_port_f(&newack->frame.srcaddr, ipbuff, sizeof(ipbuff), &port);
        log_msg("serv %x %x time %u key(%s:%d:%u:%u) "
                ColorRed "+ACK cache %p Swap %p" ColorEnd ,
                psvr, tid, newack->ts, ipbuff, port,
                frame->recvhdr.sid, frame->recvhdr.seq, cache, newack);
#endif
        free(cache);
        return 0;
    }
    free(newack);
    errno = ENOKEY;
    return -1;
}
예제 #9
0
/* Build a new IP datagram from all its fragments. */
static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
			 struct sk_buff *prev_tail, struct net_device *dev)
{
	struct net *net = container_of(qp->q.net, struct net, ipv4.frags);
	struct iphdr *iph;
	struct sk_buff *fp, *head = skb_rb_first(&qp->q.rb_fragments);
	struct sk_buff **nextp; /* To build frag_list. */
	struct rb_node *rbn;
	int len;
	int ihlen;
	int err;
	u8 ecn;

	ipq_kill(qp);

	ecn = ip_frag_ecn_table[qp->ecn];
	if (unlikely(ecn == 0xff)) {
		err = -EINVAL;
		goto out_fail;
	}
	/* Make the one we just received the head. */
	if (head != skb) {
		fp = skb_clone(skb, GFP_ATOMIC);
		if (!fp)
			goto out_nomem;
		FRAG_CB(fp)->next_frag = FRAG_CB(skb)->next_frag;
		if (RB_EMPTY_NODE(&skb->rbnode))
			FRAG_CB(prev_tail)->next_frag = fp;
		else
			rb_replace_node(&skb->rbnode, &fp->rbnode,
					&qp->q.rb_fragments);
		if (qp->q.fragments_tail == skb)
			qp->q.fragments_tail = fp;
		skb_morph(skb, head);
		FRAG_CB(skb)->next_frag = FRAG_CB(head)->next_frag;
		rb_replace_node(&head->rbnode, &skb->rbnode,
				&qp->q.rb_fragments);
		consume_skb(head);
		head = skb;
	}

	WARN_ON(head->ip_defrag_offset != 0);

	/* Allocate a new buffer for the datagram. */
	ihlen = ip_hdrlen(head);
	len = ihlen + qp->q.len;

	err = -E2BIG;
	if (len > 65535)
		goto out_oversize;

	/* Head of list must not be cloned. */
	if (skb_unclone(head, GFP_ATOMIC))
		goto out_nomem;

	/* If the first fragment is fragmented itself, we split
	 * it to two chunks: the first with data and paged part
	 * and the second, holding only fragments. */
	if (skb_has_frag_list(head)) {
		struct sk_buff *clone;
		int i, plen = 0;

		clone = alloc_skb(0, GFP_ATOMIC);
		if (!clone)
			goto out_nomem;
		skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list;
		skb_frag_list_init(head);
		for (i = 0; i < skb_shinfo(head)->nr_frags; i++)
			plen += skb_frag_size(&skb_shinfo(head)->frags[i]);
		clone->len = clone->data_len = head->data_len - plen;
		head->truesize += clone->truesize;
		clone->csum = 0;
		clone->ip_summed = head->ip_summed;
		add_frag_mem_limit(qp->q.net, clone->truesize);
		skb_shinfo(head)->frag_list = clone;
		nextp = &clone->next;
	} else {
		nextp = &skb_shinfo(head)->frag_list;
	}

	skb_push(head, head->data - skb_network_header(head));

	/* Traverse the tree in order, to build frag_list. */
	fp = FRAG_CB(head)->next_frag;
	rbn = rb_next(&head->rbnode);
	rb_erase(&head->rbnode, &qp->q.rb_fragments);
	while (rbn || fp) {
		/* fp points to the next sk_buff in the current run;
		 * rbn points to the next run.
		 */
		/* Go through the current run. */
		while (fp) {
			*nextp = fp;
			nextp = &fp->next;
			fp->prev = NULL;
			memset(&fp->rbnode, 0, sizeof(fp->rbnode));
			head->data_len += fp->len;
			head->len += fp->len;
			if (head->ip_summed != fp->ip_summed)
				head->ip_summed = CHECKSUM_NONE;
			else if (head->ip_summed == CHECKSUM_COMPLETE)
				head->csum = csum_add(head->csum, fp->csum);
			head->truesize += fp->truesize;
			fp = FRAG_CB(fp)->next_frag;
		}
		/* Move to the next run. */
		if (rbn) {
			struct rb_node *rbnext = rb_next(rbn);

			fp = rb_to_skb(rbn);
			rb_erase(rbn, &qp->q.rb_fragments);
			rbn = rbnext;
		}
	}
	sub_frag_mem_limit(qp->q.net, head->truesize);

	*nextp = NULL;
	head->next = NULL;
	head->prev = NULL;
	head->dev = dev;
	head->tstamp = qp->q.stamp;
	IPCB(head)->frag_max_size = max(qp->max_df_size, qp->q.max_size);

	iph = ip_hdr(head);
	iph->tot_len = htons(len);
	iph->tos |= ecn;

	/* When we set IP_DF on a refragmented skb we must also force a
	 * call to ip_fragment to avoid forwarding a DF-skb of size s while
	 * original sender only sent fragments of size f (where f < s).
	 *
	 * We only set DF/IPSKB_FRAG_PMTU if such DF fragment was the largest
	 * frag seen to avoid sending tiny DF-fragments in case skb was built
	 * from one very small df-fragment and one large non-df frag.
	 */
	if (qp->max_df_size == qp->q.max_size) {
		IPCB(head)->flags |= IPSKB_FRAG_PMTU;
		iph->frag_off = htons(IP_DF);
	} else {
		iph->frag_off = 0;
	}

	ip_send_check(iph);

	__IP_INC_STATS(net, IPSTATS_MIB_REASMOKS);
	qp->q.fragments = NULL;
	qp->q.rb_fragments = RB_ROOT;
	qp->q.fragments_tail = NULL;
	qp->q.last_run_head = NULL;
	return 0;

out_nomem:
	net_dbg_ratelimited("queue_glue: no memory for gluing queue %p\n", qp);
	err = -ENOMEM;
	goto out_fail;
out_oversize:
	net_info_ratelimited("Oversized IP packet from %pI4\n", &qp->q.key.v4.saddr);
out_fail:
	__IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS);
	return err;
}
예제 #10
0
/*
 * Oops, a fragment queue timed out.  Kill it and send an ICMP reply.
 */
static void ip_expire(struct timer_list *t)
{
	struct inet_frag_queue *frag = from_timer(frag, t, timer);
	const struct iphdr *iph;
	struct sk_buff *head = NULL;
	struct net *net;
	struct ipq *qp;
	int err;

	qp = container_of(frag, struct ipq, q);
	net = container_of(qp->q.net, struct net, ipv4.frags);

	rcu_read_lock();
	spin_lock(&qp->q.lock);

	if (qp->q.flags & INET_FRAG_COMPLETE)
		goto out;

	ipq_kill(qp);
	__IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS);
	__IP_INC_STATS(net, IPSTATS_MIB_REASMTIMEOUT);

	if (!(qp->q.flags & INET_FRAG_FIRST_IN))
		goto out;

	/* sk_buff::dev and sk_buff::rbnode are unionized. So we
	 * pull the head out of the tree in order to be able to
	 * deal with head->dev.
	 */
	if (qp->q.fragments) {
		head = qp->q.fragments;
		qp->q.fragments = head->next;
	} else {
		head = skb_rb_first(&qp->q.rb_fragments);
		if (!head)
			goto out;
		if (FRAG_CB(head)->next_frag)
			rb_replace_node(&head->rbnode,
					&FRAG_CB(head)->next_frag->rbnode,
					&qp->q.rb_fragments);
		else
			rb_erase(&head->rbnode, &qp->q.rb_fragments);
		memset(&head->rbnode, 0, sizeof(head->rbnode));
		barrier();
	}
	if (head == qp->q.fragments_tail)
		qp->q.fragments_tail = NULL;

	sub_frag_mem_limit(qp->q.net, head->truesize);

	head->dev = dev_get_by_index_rcu(net, qp->iif);
	if (!head->dev)
		goto out;


	/* skb has no dst, perform route lookup again */
	iph = ip_hdr(head);
	err = ip_route_input_noref(head, iph->daddr, iph->saddr,
					   iph->tos, head->dev);
	if (err)
		goto out;

	/* Only an end host needs to send an ICMP
	 * "Fragment Reassembly Timeout" message, per RFC792.
	 */
	if (frag_expire_skip_icmp(qp->q.key.v4.user) &&
	    (skb_rtable(head)->rt_type != RTN_LOCAL))
		goto out;

	spin_unlock(&qp->q.lock);
	icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
	goto out_rcu_unlock;

out:
	spin_unlock(&qp->q.lock);
out_rcu_unlock:
	rcu_read_unlock();
	if (head)
		kfree_skb(head);
	ipq_put(qp);
}
예제 #11
0
void rb_erase(struct rb_node *node, struct rb_root* root)
{
  struct rb_node *t_node, *tp_node;
  struct rb_node *s_node, *c_node;
  int _switch = 1;

  if ((node->rb_left != NULL)&&(node->rb_right != NULL))
  {
    for (t_node = node; t_node->rb_right != NULL; t_node = t_node->rb_right);

    tp_node = t_node->rb_parent;

    rb_replace_node (root, node, t_node);

    tp_node->rb_right = node;
    node->rb_parent = tp_node;

    tp_node = t_node->rb_left;

    t_node->rb_left = node->rb_left;
    t_node->rb_right = node->rb_right;

    node->rb_left = tp_node;
    node->rb_right = NULL;
  }

  c_node = (node->rb_right == NULL) ? node->rb_left: node->rb_right;
  t_node = node;

  if (node->color == BLACK)
  {
    node->color = c_node->color;

    while (_switch)
    {
      s_node = (node->rb_parent != NULL) ? \
               ((node->rb_parent->rb_left == node) ? node->rb_parent->rb_right : node->rb_parent->rb_left) \
               : NULL;
      switch(_switch)
      {
        case 1:
          if (node->rb_parent == NULL)
          {
            _switch = 0;
            break;
          }
        case 2:
          if (s_node->color == RED)
          {
            node->rb_parent->color = RED;
            s_node->color = BLACK;
            if (node == node->rb_parent->rb_left)
              rb_rotate_left(root, node->rb_parent);
            else
              rb_rotate_right(root, node->rb_parent);
            _switch = 0;
            break;
          }
        case 3:
          if ((node->rb_parent->color == BLACK) && \
              (s_node->color == BLACK) && \
              (s_node->rb_left->color == BLACK) && \
              (s_node->rb_right->color == BLACK))
          {
            s_node->color = RED;
            _switch = 1;
            node = node->rb_parent;
            break;
          }
        case 4:
          if ((node->rb_parent->color == RED) && \
              (s_node->color == BLACK) && \
              (s_node->rb_left->color == BLACK) && \
              (s_node->rb_right->color == BLACK))
          {
            s_node->color = RED;
            node->rb_parent->color = BLACK;
            _switch = 0;
            break;
          }
        case 5:
          if (s_node->color == BLACK)
          {
            if ((node == node->rb_parent->rb_left) && \
                (s_node->rb_right->color == BLACK) && \
                (s_node->rb_left->color == RED))
            {
              s_node->color = RED;
              s_node->rb_left->color = BLACK;
              rb_rotate_right(root, s_node);
            }
            else if((node == node->rb_parent->rb_right) && \
                (s_node->rb_left->color == BLACK) && \
                (s_node->rb_right->color = RED))
            {
              s_node->color = RED;
              s_node->rb_right->color = BLACK;
              rb_rotate_left(root, s_node);
            }
            _switch = 0;
            break;
          }
        case 6:
          s_node->color = node->rb_parent->color;
          node->rb_parent->color = BLACK;

          if (node == node->rb_parent->rb_left)
          {
            s_node->rb_right->color = BLACK;
            rb_rotate_left(root, node->rb_parent);
          }
          else
          {
            s_node->rb_left->color = BLACK;
            rb_rotate_right(root, node->rb_parent);
          }
          _switch = 0;
          break;
        default:
          _switch = 0;
          break;
      }
    }
  }
  rb_replace_node (root, t_node, c_node);
}