[CRIU] Re: [PATCH 10/10] files: Use sys_kcmp to find file descriptor duplicates

Pavel Emelyanov xemul at parallels.com
Mon Feb 27 08:34:38 EST 2012


> +static struct fd_id_entry *
> +lookup_alloc_subtree(struct fd_id_entry *e, u64 genid, pid_t pid, int fd)

OK, I like the overall idea. It should be written on wiki as a separate page,
and a summary comment should be put here.

> +{
> +       struct rb_node *node = e->subtree_root.rb_node;
> +       struct fd_id_entry *sub = NULL;
> +
> +       struct rb_node **new = &e->subtree_root.rb_node;
> +       struct rb_node *parent = NULL;
> +
> +       while (node) {
> +               struct fd_id_entry *this = rb_entry(node, struct fd_id_entry, subtree_node);
> +               int ret = sys_kcmp(this->pid, pid, KCMP_FILE, this->fd, fd);
> +
> +               parent = *new;
> +               if (ret < 0)
> +                       node = node->rb_left, new = &((*new)->rb_left);
> +               else if (ret > 0)
> +                       node = node->rb_right, new = &((*new)->rb_right);
> +               else
> +                       return this;
> +       }
> +
> +       sub = alloc_fd_id_entry(genid, pid, fd);
> +       if (!sub)
> +               goto err;
> +
> +       sub->subid = fd_id_entries_subid++;
> +
> +       rb_link_node(&sub->subtree_node, parent, new);
> +       rb_insert_color(&sub->subtree_node, &e->subtree_root);

Same code in the below function. Merge them.

> +err:
> +       return sub;
> +}
> +
> +static struct fd_id_entry *
> +lookup_alloc(u64 genid, pid_t pid, int fd)
> +{
> +       struct rb_node *node = fd_id_root.rb_node;
> +       struct fd_id_entry *e = NULL;
> +
> +       struct rb_node **new = &fd_id_root.rb_node;
> +       struct rb_node *parent = NULL;
> +
> +       while (node) {
> +               struct fd_id_entry *this = rb_entry(node, struct fd_id_entry, node);
> +
> +               parent = *new;
> +               if (genid < this->genid)
> +                       node = node->rb_left, new = &((*new)->rb_left);
> +               else if (genid > this->genid)
> +                       node = node->rb_right, new = &((*new)->rb_right);
> +               else
> +                       return lookup_alloc_subtree(this, genid, pid, fd);
> +       }
> +
> +       e = alloc_fd_id_entry(genid, pid, fd);
> +       if (!e)
> +               goto err;

Here the subid will be INVALID. This is ... wrong.

> +       rb_link_node(&e->node, parent, new);
> +       rb_insert_color(&e->node, &fd_id_root);
> +err:
> +       return e;
> +}
> +
> +struct fd_id_entry *fd_id_entry_collect(u64 genid, pid_t pid, int fd)
> +{
> +       return lookup_alloc(genid, pid, fd);

:\

> +struct fd_id_entry {
> +       struct rb_node  node;
> +
> +       struct rb_root  subtree_root;
> +       struct rb_node  subtree_node;
> +
> +       u64             genid;  /* generic id, may have duplicates */
> +       u64             subid;  /* subid is always unique */
> +
> +       pid_t           pid;
> +       int             fd;
> +} __aligned(sizeof(long));
> +
> +/* Position in file is u64 so we can't shrink it */
> +#define MAKE_FD_GENID(dev, ino, pos) \
> +       ((u64)(dev) ^ (u64)(ino) ^ (u64)(pos))

Since genid is just a hint, we can make it 32bit and just trim the pos.
So can we make subid be 32 bit and ...

>  struct fdinfo_entry {
>         u8      type;
>         u8      len;
>         u16     flags;
>         u32     pos;
>         u64     addr;
> -       u8      id[FD_ID_SIZE];
> +       u64     genid;
> +       u64     subid;

... make this a single 64bit ID field.

>         u8      name[0];
>  } __packed;


More information about the CRIU mailing list