The main thing that I want from the kobj mapper is to add 
the mode_t on the struct kobj_map that reflects with 
permissions are associated with this particular map. This 
mode is to be returned via the kobj_lookup.

I use the FMODE_XXX flags to handle the permissions bits, 
as I will compare these ones to the file->f_mode later.
By default all bits are set (for the initial container).

The additional things I need are kobj_remap() to change 
that permission and kobj_iterate() to walk the map.

The kobj_map_fini() is the roll-back for the kobj_map_init().

Signed-off-by: Pavel Emelyanov <[EMAIL PROTECTED]>

---

diff --git a/drivers/base/map.c b/drivers/base/map.c
index e87017f..1aa2b58 100644
--- a/drivers/base/map.c
+++ b/drivers/base/map.c
@@ -15,11 +15,13 @@
 #include <linux/kdev_t.h>
 #include <linux/kobject.h>
 #include <linux/kobj_map.h>
+#include <linux/fs.h>
 
 struct kobj_map {
        struct probe {
                struct probe *next;
                dev_t dev;
+               mode_t mode;
                unsigned long range;
                struct module *owner;
                kobj_probe_t *get;
@@ -29,9 +31,9 @@ struct kobj_map {
        struct mutex *lock;
 };
 
-int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
-            struct module *module, kobj_probe_t *probe,
-            int (*lock)(dev_t, void *), void *data)
+static int __kobj_map(struct kobj_map *domain, dev_t dev, mode_t mode,
+               unsigned long range, struct module *module,
+               kobj_probe_t *probe, int (*lock)(dev_t, void *), void *data)
 {
        unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
        unsigned index = MAJOR(dev);
@@ -53,8 +55,10 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned 
long range,
                p->dev = dev;
                p->range = range;
                p->data = data;
+               /* we allow these ones always by default */
+               p->mode = mode | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
        }
-       mutex_lock(domain->lock);
+
        for (i = 0, p -= n; i < n; i++, p++, index++) {
                struct probe **s = &domain->probes[index % 255];
                while (*s && (*s)->range < range)
@@ -62,10 +66,57 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned 
long range,
                p->next = *s;
                *s = p;
        }
-       mutex_unlock(domain->lock);
        return 0;
 }
 
+int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
+            struct module *module, kobj_probe_t *probe,
+            int (*lock)(dev_t, void *), void *data)
+{
+       int err;
+
+       mutex_lock(domain->lock);
+       err = __kobj_map(domain, dev, FMODE_READ | FMODE_WRITE, range,
+                       module, probe, lock, data);
+       mutex_unlock(domain->lock);
+       return err;
+}
+
+#ifdef CONFIG_CGROUP_DEVS
+int kobj_remap(struct kobj_map *domain, dev_t dev, mode_t mode,
+               unsigned long range, struct module *module,
+               kobj_probe_t *probe, int (*lock)(dev_t, void *), void *data)
+{
+       unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
+       unsigned index = MAJOR(dev);
+       unsigned i;
+       int err = -ESRCH;
+
+       if (n > 255)
+               n = 255;
+
+       mutex_lock(domain->lock);
+       for (i = 0; i < n; i++, index++) {
+               struct probe **s;
+               for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) {
+                       struct probe *p = *s;
+                       if (p->dev == dev) {
+                               p->mode = mode | FMODE_LSEEK |
+                                       FMODE_PREAD | FMODE_PWRITE;
+                               err = 0;
+                               break;
+                       }
+               }
+       }
+
+       if (err)
+               err = __kobj_map(domain, dev, mode, range, module,
+                               probe, lock, data);
+       mutex_unlock(domain->lock);
+       return err;
+}
+#endif
+
 void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
 {
        unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
@@ -93,7 +144,8 @@ void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned 
long range)
        kfree(found);
 }
 
-struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
+struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, mode_t *mode,
+               int *index)
 {
        struct kobject *kobj;
        struct probe *p;
@@ -125,14 +177,46 @@ retry:
                kobj = probe(dev, index, data);
                /* Currently ->owner protects _only_ ->probe() itself. */
                module_put(owner);
-               if (kobj)
+               if (kobj) {
+                       if (mode)
+                               *mode = p->mode;
                        return kobj;
+               }
                goto retry;
        }
        mutex_unlock(domain->lock);
        return NULL;
 }
 
+#ifdef CONFIG_CGROUP_DEVS
+void kobj_map_iterate(struct kobj_map *domain,
+               int (*fn)(dev_t, int, mode_t, void *), void *arg)
+{
+       int i;
+       struct probe *p;
+       dev_t skip = MKDEV(0, 0);
+
+       mutex_lock(domain->lock);
+       for (i = 0; i < 255; i++) {
+               p = domain->probes[i];
+               while (p != NULL) {
+                       if (p->dev == skip)
+                               goto next;
+                       if (p->dev == MKDEV(0, 1))
+                               goto next;
+
+                       skip = p->dev;
+                       if (fn(p->dev, p->range, p->mode, arg))
+                               goto done;
+next:
+                       p = p->next;
+               }
+       }
+done:
+       mutex_unlock(domain->lock);
+}
+#endif
+
 struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct mutex *lock)
 {
        struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
@@ -153,3 +237,21 @@ struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, 
struct mutex *lock)
        p->lock = lock;
        return p;
 }
+
+void kobj_map_fini(struct kobj_map *map)
+{
+       int i;
+       struct probe *p, *next;
+
+       for (i = 0; i < 256; i++) {
+               p = map->probes[i];
+               while (p->next != NULL) {
+                       next = p->next;
+                       kfree(p);
+                       p = next;
+               }
+       }
+
+       kfree(p);
+       kfree(map);
+}
diff --git a/include/linux/kobj_map.h b/include/linux/kobj_map.h
index bafe178..ecfe772 100644
--- a/include/linux/kobj_map.h
+++ b/include/linux/kobj_map.h
@@ -7,8 +7,13 @@ struct kobj_map;
 
 int kobj_map(struct kobj_map *, dev_t, unsigned long, struct module *,
             kobj_probe_t *, int (*)(dev_t, void *), void *);
+int kobj_remap(struct kobj_map *, dev_t, mode_t, unsigned long, struct module 
*,
+            kobj_probe_t *, int (*)(dev_t, void *), void *);
 void kobj_unmap(struct kobj_map *, dev_t, unsigned long);
-struct kobject *kobj_lookup(struct kobj_map *, dev_t, int *);
+struct kobject *kobj_lookup(struct kobj_map *, dev_t, mode_t *, int *);
+void kobj_map_iterate(struct kobj_map *, int (*fn)(dev_t, int, mode_t, void *),
+               void *);
 struct kobj_map *kobj_map_init(kobj_probe_t *, struct mutex *);
+void kobj_map_fini(struct kobj_map *);
 
 #endif

_______________________________________________
Containers mailing list
[EMAIL PROTECTED]
https://lists.linux-foundation.org/mailman/listinfo/containers

_______________________________________________
Devel mailing list
[email protected]
https://openvz.org/mailman/listinfo/devel

Reply via email to