On 8/4/06, Matt Helsley <[EMAIL PROTECTED]> wrote:
>
> Since the interface looks less elegant than mkdir I think you need to
> support your assertion. No offense but until we see the code I don't
> think we can really see that it's any simpler.
>

Here's the code for the /proc manipulation part - 133 lines for all
the filesystem issues, with no reliance on configfs or sysfs.
(Although I guess it could possibly go in sysfs rather than procfs).

Each class directory that's created has a set of operation files
created in it, such as ".create", ".delete", ".enter", ".status", etc.
Reading or writing on these causes the appropriate callback functions
to be called. The actual operation callbacks themselves don't have
much in the way of filesystem support in them. E.g.
container_op_create() just calls create_proc_entry() to create the
main directory for the resource group, and then init_container_dir()
to create one entry for each control file.

Liveness/refcounting issues between the procfs interface and the
internal objects are handled by having the proc_dir_entry just contain
an id, and having the open() method look up the id in a table of live
containers, and return one with a refcount held if it's found.

Granted, this is simpler than CKRM in that it doesn't have the modular
resource controller support in it, but that wouldn't take much effort
to add.

Paul

static container_op ops[] = {
        { {}, ".enter",  container_op_enter },
        { {}, ".root",   container_op_root },
        { {}, ".kill",   container_op_kill },
        { {}, ".create", container_op_create },
        { {}, ".delete", container_op_delete },
        { {}, ".inode",  container_op_inode },
        { {}, ".status", NULL, container_task_show },
        { {}, ".sockets", NULL, container_sockets_show },
        { {}, ".dirtylimit", container_op_dirtylimit },
};

static int container_proc_open(struct inode *inode, struct file *file) {
        int ret;
        int (*showfn)(struct seq_file *, void *);

        struct proc_dir_entry *pde = PDE(inode);
        container *container;
        container_op *op = (container_op*) file->f_op;

        container_get_by_id((u32)(long)pde->data, &container);
        if (!container) return -ESRCH;

        if (op->showfn) {
                showfn = op->showfn;
        } else {
                showfn = container_empty_show;
        }

        ret = single_open(file, showfn, container);

        if (ret) {
                put_container(&container, "bad open", "", NULL);
        }
        return ret;
}

static ssize_t container_proc_write(struct file *file, const char *ubuf,
                            size_t count, loff_t *off) {

        container_op *op = (container_op *) file->f_op;
        struct seq_file *m = (struct seq_file *)file->private_data;
        container *g = m->private;
        int ret;

#define MAX_CMD 128
        int len = count;
        char kbuf[MAX_CMD];
        if (len >= MAX_CMD) return -EINVAL;

        if (len > 0) {
                if (copy_from_user(kbuf, ubuf, len)) return -EFAULT;

                if (kbuf[len - 1] == '\n') len --;
        }

        kbuf[len] = 0;

        ret = op->writefn(g, kbuf);
        if (!ret) ret = count;

        return ret;
}

static int container_proc_release(struct inode *inode, struct file *file) {
        struct seq_file *m = (struct seq_file *)file->private_data;
        put_container((container **)&m->private, "proc_release", "", NULL);
        return seq_release(inode, file);
}

static struct file_operations container_proc_fops_template = {
        open:    container_proc_open,
        read:    seq_read,
        write:   container_proc_write,
        llseek:  seq_lseek,
        release: container_proc_release,
};

static void zap_container_dir(struct proc_dir_entry *dir) {
        int i;
        for (i = 0; i < sizeof(ops) / sizeof(container_op); i++) {
                container_op *op = &ops[i];
                remove_proc_entry(op->name, dir);
        }
}

static int init_container_dir(struct proc_dir_entry *dir, container *g) {

        int i;
        for (i = 0; i < sizeof(ops) / sizeof(container_op); i++) {

                int mode = 0;
                struct proc_dir_entry *pde;
                container_op *op = &ops[i];

                if (op->showfn) mode |= 0400;
                if (op->writefn) mode |= 0200;

                pde = create_proc_entry(op->name, mode | S_IFREG, dir);

                if (!pde) {
                        printk(KERN_ERR "Error creating %s for container %s\n",
                               op->name, g->name);
                        zap_container_dir(dir);
                        return -EIO;
                }
                pde->data = (void *)(long)g->id;
                pde->proc_fops = &op->fops;
        }

        return 0;

}

static int __init init_container(void) {

        int ret, i;

        container_cache = kmem_cache_create("container_cache",
                                            sizeof(container),
                                            0, SLAB_PANIC, NULL, NULL);

        for (i = 0; i < sizeof(ops) / sizeof(container_op); i++) {
                container_op *op = &ops[i];
                memcpy(&op->fops, &container_proc_fops_template,
sizeof(op->fops));
        }

        ret = container_op_create(NULL, "container");
        if (ret) printk(KERN_ERR "Container init failed!\n");
        return ret;
}

module_init(init_container);

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
ckrm-tech mailing list
https://lists.sourceforge.net/lists/listinfo/ckrm-tech

Reply via email to