]> git.proxmox.com Git - mirror_lxcfs.git/blobdiff - lxcfs.c
add cache types for each procfile type that we provide
[mirror_lxcfs.git] / lxcfs.c
diff --git a/lxcfs.c b/lxcfs.c
index a9f5f104d7c4dc53c6b0b084a5b8e0447f58e4de..162f356445176cc3ab238aefaac91b6d1c50fcdd 100644 (file)
--- a/lxcfs.c
+++ b/lxcfs.c
@@ -44,10 +44,21 @@ struct lxcfs_state {
 };
 #define LXCFS_DATA ((struct lxcfs_state *) fuse_get_context()->private_data)
 
+enum {
+       LXC_TYPE_CGDIR,
+       LXC_TYPE_CGFILE,
+       LXC_TYPE_PROC_MEMINFO,
+       LXC_TYPE_PROC_CPUINFO,
+       LXC_TYPE_PROC_UPTIME,
+       LXC_TYPE_PROC_STAT,
+       LXC_TYPE_PROC_DISKSTATS,
+};
+
 struct file_info {
        char *controller;
        char *cgroup;
-       bool isdir;
+       char *file;
+       int type;
        char *buf;  // unused as of yet
        int buflen;
 };
@@ -575,8 +586,9 @@ static int cg_opendir(const char *path, struct fuse_file_info *fi)
        dir_info = NIH_MUST( nih_alloc(NULL, sizeof(*dir_info)) );
        dir_info->controller = must_copy_string(controller);
        dir_info->cgroup = must_copy_string(cgroup);
-       dir_info->isdir = true;
+       dir_info->type = LXC_TYPE_CGDIR;
        dir_info->buf = NULL;
+       dir_info->file = NULL;
        dir_info->buflen = 0;
 
        fi->fh = (unsigned long)dir_info;
@@ -592,6 +604,10 @@ static int cg_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t
        nih_local char *nextcg = NULL;
        struct fuse_context *fc = fuse_get_context();
 
+       if (d->type != LXC_TYPE_CGDIR) {
+               fprintf(stderr, "Internal error: file cache info used in readdir\n");
+               return -EIO;
+       }
        if (!d->cgroup && !d->controller) {
                // ls /var/lib/lxcfs/cgroup - just show list of controllers
                char **list = LXCFS_DATA ? LXCFS_DATA->subsystems : NULL;
@@ -641,22 +657,26 @@ static int cg_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t
        return 0;
 }
 
+static void do_release_file_info(struct file_info *f)
+{
+       if (f->controller)
+               nih_free(f->controller);
+       if (f->cgroup)
+               nih_free(f->cgroup);
+       if (f->file)
+               nih_free(f->file);
+       free(f->buf);
+       nih_free(f);
+}
+
 static int cg_releasedir(const char *path, struct fuse_file_info *fi)
 {
        struct file_info *d = (struct file_info *)fi->fh;
 
-       if (d->controller)
-               nih_free(d->controller);
-       if (d->cgroup)
-               nih_free(d->cgroup);
-       free(d->buf);
-       nih_free(d);
+       do_release_file_info(d);
        return 0;
 }
 
-/*
- * TODO - cache info here for read/write, release in cg_release.
- */
 static int cg_open(const char *path, struct fuse_file_info *fi)
 {
        nih_local char *controller = NULL;
@@ -664,6 +684,7 @@ static int cg_open(const char *path, struct fuse_file_info *fi)
        char *fpath = NULL, *path1, *path2;
        nih_local char * cgdir = NULL;
        nih_local struct cgm_keys *k = NULL;
+       struct file_info *file_info;
        struct fuse_context *fc = fuse_get_context();
 
        if (!fc)
@@ -685,15 +706,33 @@ static int cg_open(const char *path, struct fuse_file_info *fi)
                path2 = fpath;
        }
 
-       if ((k = get_cgroup_key(controller, path1, path2)) != NULL) {
-               if (!fc_may_access(fc, controller, path1, path2, fi->flags))
-                       // should never get here
-                       return -EACCES;
+       k = get_cgroup_key(controller, path1, path2);
+       if (!k)
+               return -EINVAL;
 
-               return 0;
-       }
+       if (!fc_may_access(fc, controller, path1, path2, fi->flags))
+               // should never get here
+               return -EACCES;
 
-       return -EINVAL;
+       /* we'll free this at cg_release */
+       file_info = NIH_MUST( nih_alloc(NULL, sizeof(*file_info)) );
+       file_info->controller = must_copy_string(controller);
+       file_info->cgroup = must_copy_string(path1);
+       file_info->file = must_copy_string(path2);
+       file_info->type = LXC_TYPE_CGFILE;
+       file_info->buf = NULL;
+       file_info->buflen = 0;
+
+       fi->fh = (unsigned long)file_info;
+       return 0;
+}
+
+static int cg_release(const char *path, struct fuse_file_info *fi)
+{
+       struct file_info *f = (struct file_info *)fi->fh;
+
+       do_release_file_info(f);
+       return 0;
 }
 
 static int msgrecv(int sockfd, void *buf, size_t len)
@@ -1009,52 +1048,41 @@ out:
 static int cg_read(const char *path, char *buf, size_t size, off_t offset,
                struct fuse_file_info *fi)
 {
-       nih_local char *controller = NULL;
-       const char *cgroup;
-       char *fpath = NULL, *path1, *path2;
        struct fuse_context *fc = fuse_get_context();
-       nih_local char * cgdir = NULL;
+       struct file_info *f = (struct file_info *)fi->fh;
        nih_local struct cgm_keys *k = NULL;
 
+       if (f->type != LXC_TYPE_CGFILE) {
+               fprintf(stderr, "Internal error: directory cache info used in cg_read\n");
+               return -EIO;
+       }
+
        if (offset)
                return -EIO;
 
        if (!fc)
                return -EIO;
 
-       controller = pick_controller_from_path(fc, path);
-       if (!controller)
+       if (!f->controller)
                return -EINVAL;
-       cgroup = find_cgroup_in_path(path);
-       if (!cgroup)
-               return -EINVAL;
-
-       get_cgdir_and_path(cgroup, &cgdir, &fpath);
-       if (!fpath) {
-               path1 = "/";
-               path2 = cgdir;
-       } else {
-               path1 = cgdir;
-               path2 = fpath;
-       }
 
-       if ((k = get_cgroup_key(controller, path1, path2)) != NULL) {
+       if ((k = get_cgroup_key(f->controller, f->cgroup, f->file)) != NULL) {
                nih_local char *data = NULL;
                int s;
                bool r;
 
-               if (!fc_may_access(fc, controller, path1, path2, O_RDONLY))
+               if (!fc_may_access(fc, f->controller, f->cgroup, f->file, O_RDONLY))
                        // should never get here
                        return -EACCES;
 
-               if (strcmp(path2, "tasks") == 0 ||
-                               strcmp(path2, "/tasks") == 0 ||
-                               strcmp(path2, "/cgroup.procs") == 0 ||
-                               strcmp(path2, "cgroup.procs") == 0)
+               if (strcmp(f->file, "tasks") == 0 ||
+                               strcmp(f->file, "/tasks") == 0 ||
+                               strcmp(f->file, "/cgroup.procs") == 0 ||
+                               strcmp(f->file, "cgroup.procs") == 0)
                        // special case - we have to translate the pids
-                       r = do_read_pids(fc->pid, controller, path1, path2, &data);
+                       r = do_read_pids(fc->pid, f->controller, f->cgroup, f->file, &data);
                else
-                       r = cgm_get_value(controller, path1, path2, &data);
+                       r = cgm_get_value(f->controller, f->cgroup, f->file, &data);
 
                if (!r)
                        return -EINVAL;
@@ -1241,13 +1269,15 @@ out:
 int cg_write(const char *path, const char *buf, size_t size, off_t offset,
             struct fuse_file_info *fi)
 {
-       nih_local char *controller = NULL;
-       const char *cgroup;
-       char *fpath = NULL, *path1, *path2;
        struct fuse_context *fc = fuse_get_context();
-       nih_local char * cgdir = NULL;
-       nih_local struct cgm_keys *k = NULL;
        nih_local char *localbuf = NULL;
+       nih_local struct cgm_keys *k = NULL;
+       struct file_info *f = (struct file_info *)fi->fh;
+
+       if (f->type != LXC_TYPE_CGFILE) {
+               fprintf(stderr, "Internal error: directory cache info used in cg_write\n");
+               return -EIO;
+       }
 
        if (offset)
                return -EINVAL;
@@ -1258,36 +1288,21 @@ int cg_write(const char *path, const char *buf, size_t size, off_t offset,
        localbuf = NIH_MUST( nih_alloc(NULL, size+1) );
        localbuf[size] = '\0';
        memcpy(localbuf, buf, size);
-       controller = pick_controller_from_path(fc, path);
-       if (!controller)
-               return -EINVAL;
-       cgroup = find_cgroup_in_path(path);
-       if (!cgroup)
-               return -EINVAL;
 
-       get_cgdir_and_path(cgroup, &cgdir, &fpath);
-       if (!fpath) {
-               path1 = "/";
-               path2 = cgdir;
-       } else {
-               path1 = cgdir;
-               path2 = fpath;
-       }
-
-       if ((k = get_cgroup_key(controller, path1, path2)) != NULL) {
+       if ((k = get_cgroup_key(f->controller, f->cgroup, f->file)) != NULL) {
                bool r;
 
-               if (!fc_may_access(fc, controller, path1, path2, O_WRONLY))
+               if (!fc_may_access(fc, f->controller, f->cgroup, f->file, O_WRONLY))
                        return -EACCES;
 
-               if (strcmp(path2, "tasks") == 0 ||
-                               strcmp(path2, "/tasks") == 0 ||
-                               strcmp(path2, "/cgroup.procs") == 0 ||
-                               strcmp(path2, "cgroup.procs") == 0)
+               if (strcmp(f->file, "tasks") == 0 ||
+                               strcmp(f->file, "/tasks") == 0 ||
+                               strcmp(f->file, "/cgroup.procs") == 0 ||
+                               strcmp(f->file, "cgroup.procs") == 0)
                        // special case - we have to translate the pids
-                       r = do_write_pids(fc->pid, controller, path1, path2, localbuf);
+                       r = do_write_pids(fc->pid, f->controller, f->cgroup, f->file, localbuf);
                else
-                       r = cgm_set_value(controller, path1, path2, localbuf);
+                       r = cgm_set_value(f->controller, f->cgroup, f->file, localbuf);
 
                if (!r)
                        return -EINVAL;
@@ -2294,7 +2309,14 @@ static int lxcfs_flush(const char *path, struct fuse_file_info *fi)
 
 static int lxcfs_release(const char *path, struct fuse_file_info *fi)
 {
-       return 0;
+       if (strncmp(path, "/cgroup", 7) == 0)
+               return cg_release(path, fi);
+#if 0
+       if (strncmp(path, "/proc", 5) == 0)
+               return proc_close(path, fi);
+#endif
+
+       return -EINVAL;
 }
 
 static int lxcfs_fsync(const char *path, int datasync, struct fuse_file_info *fi)