Changelog v2:
 * Use clock_gettime(2) for getting timestamp since a system boot.
 * Change parent_info's memory to dynamic allocation.


This patch is for changing the cgroup of a forked process while parent
changing.

This patch adds the following sequence:
 1. Store both the timestamp and the process-id when changing the cgroup.
 2. If receiving a PROC_EVENT_FORK packet, check its parent-pid and its
    timestamp.
 3. If its parent-pid and the stored process-id are same and its timestamp
    is older than the stored timestamp, change the cgroup of forked process.


Thanks
Ken'ichi Ohmichi
 
Signed-off-by: Ken'ichi Ohmichi <[email protected]>
---
diff -rpuN a/src/daemon/Makefile.in b/src/daemon/Makefile.in
--- a/src/daemon/Makefile.in    2009-04-22 19:18:18.000000000 +0900
+++ b/src/daemon/Makefile.in    2009-05-07 11:03:08.000000000 +0900
@@ -101,7 +101,7 @@ INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LDFLAGS = @LDFLAGS@
+LDFLAGS = @LDFLAGS@ -lrt
 LEX = @LEX@
 LEXLIB = @LEXLIB@
 LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
diff -rpuN a/src/daemon/cgrulesengd.c b/src/daemon/cgrulesengd.c
--- a/src/daemon/cgrulesengd.c  2009-05-07 10:31:17.000000000 +0900
+++ b/src/daemon/cgrulesengd.c  2009-05-07 10:59:53.000000000 +0900
@@ -180,6 +180,91 @@ static int cgre_get_euid_egid_from_statu
        return 0;
 }
 
+struct parent_info {
+       __u64 timestamp;
+       pid_t pid;
+};
+struct array_parent_info {
+       int index;
+       int num_allocation;
+       struct parent_info **parent_info;
+};
+struct array_parent_info array_pi;
+
+static int cgre_store_parent_info(pid_t pid)
+{
+       __u64 uptime_ns;
+       struct timespec tp;
+       struct parent_info *info;
+
+       if (clock_gettime(CLOCK_MONOTONIC, &tp) < 0) {
+               flog(LOG_WARNING, "Failed to get time");
+               return 1;
+       }
+       uptime_ns = ((__u64)tp.tv_sec * 1000 * 1000 * 1000 ) + tp.tv_nsec;
+
+       if (array_pi.index >= array_pi.num_allocation) {
+               array_pi.num_allocation += 100;
+               array_pi.parent_info = realloc(array_pi.parent_info,
+                                       sizeof(info) * array_pi.num_allocation);
+               if (!array_pi.parent_info) {
+                       flog(LOG_WARNING, "Failed to allocate memory");
+                       return 1;
+               }
+       }
+       info = calloc(1, sizeof(struct parent_info));
+       if (!info) {
+               flog(LOG_WARNING, "Failed to allocate memory");
+               return 1;
+       }
+       info->timestamp = uptime_ns;
+       info->pid = pid;
+
+       array_pi.parent_info[array_pi.index] = info;
+       array_pi.index++;
+
+       return 0;
+}
+
+static void cgre_remove_old_parent_info(__u64 key_timestamp)
+{
+       int i, j;
+
+       for (i = 0; i < array_pi.index; i++) {
+               if (key_timestamp < array_pi.parent_info[i]->timestamp)
+                       continue;
+               free(array_pi.parent_info[i]);
+               for (j = i; j < array_pi.index - 1; j++)
+                       array_pi.parent_info[j] = array_pi.parent_info[j + 1];
+               array_pi.index--;
+               i--;
+       }
+       return;
+}
+
+static int cgre_was_parent_changed_when_forking(const struct proc_event *ev)
+{
+       int i;
+       pid_t parent_pid;
+       __u64 timestamp_child;
+       __u64 timestamp_parent;
+
+       parent_pid = ev->event_data.fork.parent_pid;
+       timestamp_child = ev->timestamp_ns;
+
+       cgre_remove_old_parent_info(timestamp_child);
+
+       for (i = 0; i < array_pi.index; i++) {
+               if (parent_pid != array_pi.parent_info[i]->pid)
+                       continue;
+               timestamp_parent = array_pi.parent_info[i]->timestamp;
+               if (timestamp_child > timestamp_parent)
+                       continue;
+               return 1;
+       }
+       return 0;
+}
+
 /**
  * Process an event from the kernel, and determine the correct UID/GID/PID to
  * pass to libcgroup.  Then, libcgroup will decide the cgroup to move the PID
@@ -201,6 +286,15 @@ int cgre_process_event(const struct proc
        case PROC_EVENT_GID:
                pid = ev->event_data.id.process_pid;
                break;
+       case PROC_EVENT_FORK:
+               /*
+                * If this process was forked while changing parent's cgroup,
+                * this process's cgroup also should be changed.
+                */
+               if (!cgre_was_parent_changed_when_forking(ev))
+                       return 0;
+               pid = ev->event_data.fork.child_pid;
+               break;
        default:
                break;
        }
@@ -229,6 +323,12 @@ int cgre_process_event(const struct proc
                                        ev->event_data.id.e.egid,
                                        pid, CGFLAG_USECACHE);
                break;
+       case PROC_EVENT_FORK:
+               log_uid = euid;
+               log_gid = egid;
+               ret = cgroup_change_cgroup_uid_gid_flags(euid,
+                                       egid, pid, CGFLAG_USECACHE);
+               break;
        default:
                break;
        }
@@ -242,6 +342,7 @@ int cgre_process_event(const struct proc
                        " FAILED! (Error Code: %d)", log_pid, log_uid, log_gid,
                        ret);
        } else {
+               ret = cgre_store_parent_info(pid);
                flog(LOG_INFO, "Cgroup change for PID: %d, UID: %d, GID: %d OK",
                        log_pid, log_uid, log_gid);
        }
@@ -282,6 +383,9 @@ int cgre_handle_msg(struct cn_msg *cn_hd
                                ev->event_data.id.e.egid);
                ret = cgre_process_event(ev, PROC_EVENT_GID);
                break;
+       case PROC_EVENT_FORK:
+               ret = cgre_process_event(ev, PROC_EVENT_FORK);
+               break;
        default:
                break;
        }


------------------------------------------------------------------------------
The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your
production scanning environment may not be a perfect world - but thanks to
Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700
Series Scanner you'll get full speed at 300 dpi even with all image 
processing features enabled. http://p.sf.net/sfu/kodak-com
_______________________________________________
Libcg-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libcg-devel

Reply via email to