[PATCH 06/06]

The following kernel components register a tunable structure and call the
auto-tuning routine:
  . file system
  . shared memory (per namespace)
  . semaphore (per namespace)
  . message queues (per namespace)


Signed-off-by: Nadia Derbey <[EMAIL PROTECTED]>


---
 fs/file_table.c     |   81 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/akt.h |    1 
 include/linux/ipc.h |    6 +++
 init/main.c         |    1 
 ipc/msg.c           |   19 ++++++++++++
 ipc/sem.c           |   41 ++++++++++++++++++++++++++
 ipc/shm.c           |   74 ++++++++++++++++++++++++++++++++++++++++++++---
 7 files changed, 218 insertions(+), 5 deletions(-)

Index: linux-2.6.20-rc4/fs/file_table.c
===================================================================
--- linux-2.6.20-rc4.orig/fs/file_table.c       2007-01-15 13:08:14.000000000 
+0100
+++ linux-2.6.20-rc4/fs/file_table.c    2007-01-15 15:44:39.000000000 +0100
@@ -21,6 +21,8 @@
 #include <linux/fsnotify.h>
 #include <linux/sysctl.h>
 #include <linux/percpu_counter.h>
+#include <linux/akt.h>
+#include <linux/akt_ops.h>
 
 #include <asm/atomic.h>
 
@@ -34,6 +36,71 @@ __cacheline_aligned_in_smp DEFINE_SPINLO
 
 static struct percpu_counter nr_files __cacheline_aligned_in_smp;
 
+#ifdef CONFIG_AKT
+
+static int get_nr_files(void);
+
+/********** automatic tuning **********/
+#define FILPTHRESH 80          /* threshold = 80% */
+
+/*
+ * FUNCTION:    This is the routine called to accomplish auto tuning for the
+ *              max_files tunable.
+ *
+ *              Upwards adjustment:
+ *                  Adjustment is needed if nr_files has reached
+ *                  (threshold / 100 * max_files)
+ *                  In that case, max_files is set to
+ *                  (tunable + max_files * (100 - threshold) / 100)
+ *
+ *              Downards adjustment:
+ *                   Adjustment is needed if nr_files has fallen under
+ *                   (threshold / 100 * max_files previous value)
+ *                   In that case max_files is set back to its previous value,
+ *                   i.e. to (max_files * 100 / (200 - threshold))
+ *
+ * PARAMETERS:  cmd: controls the adjustment direction (up / down)
+ *              params: pointer to the registered tunable structure
+ *
+ * EXECUTION ENVIRONMENT: This routine should be called with the
+ *                        params->tunable_lck lock held
+ *
+ * RETURN VALUE: 1 if tunable has been adjusted
+ *               0 else
+ */
+static inline int maxfiles_auto_tuning(int cmd, struct auto_tune *params)
+{
+       int thr = params->threshold;
+       int min = params->min.value.val_int;
+       int max = params->max.value.val_int;
+       int tun = files_stat.max_files;
+
+       if (cmd == AKT_UP) {
+               if (get_nr_files() >= tun * thr / 100 && tun < max) {
+                       int new = tun * (200 - thr) / 100;
+
+                       files_stat.max_files = min(max, new);
+                       return 1;
+               } else
+                       return 0;
+       }
+
+       if (get_nr_files() < tun * thr / (200 - thr) && tun > min) {
+               int new = tun * 100 / (200 - thr);
+
+               files_stat.max_files = max(min, new);
+               return 1;
+       } else
+               return 0;
+}
+
+#endif /* CONFIG_AKT */
+
+/* The maximum value will be known later on */
+DEFINE_TUNABLE(maxfiles_akt, FILPTHRESH, 0, 0, &files_stat.max_files,
+               &nr_files, int);
+
+
 static inline void file_free_rcu(struct rcu_head *head)
 {
        struct file *f =  container_of(head, struct file, f_u.fu_rcuhead);
@@ -44,6 +111,8 @@ static inline void file_free(struct file
 {
        percpu_counter_dec(&nr_files);
        call_rcu(&f->f_u.fu_rcuhead, file_free_rcu);
+
+       activate_auto_tuning(AKT_DOWN, &maxfiles_akt);
 }
 
 /*
@@ -91,6 +160,8 @@ struct file *get_empty_filp(void)
        static int old_max;
        struct file * f;
 
+       activate_auto_tuning(AKT_UP, &maxfiles_akt);
+
        /*
         * Privileged users can go above max_files
         */
@@ -299,6 +370,16 @@ void __init files_init(unsigned long mem
        files_stat.max_files = n; 
        if (files_stat.max_files < NR_FILE)
                files_stat.max_files = NR_FILE;
+
+       set_tunable_min_max(maxfiles_akt, n, n * 2, int);
+       set_autotuning_routine(&maxfiles_akt, maxfiles_auto_tuning);
+
        files_defer_init();
        percpu_counter_init(&nr_files, 0);
 } 
+
+void __init files_late_init(void)
+{
+       if (register_tunable(&maxfiles_akt))
+               printk(KERN_WARNING "Failed registering tunable file-max\n");
+}
Index: linux-2.6.20-rc4/include/linux/akt.h
===================================================================
--- linux-2.6.20-rc4.orig/include/linux/akt.h   2007-01-15 15:31:44.000000000 
+0100
+++ linux-2.6.20-rc4/include/linux/akt.h        2007-01-15 15:45:29.000000000 
+0100
@@ -295,5 +295,6 @@ static inline void init_auto_tuning(void
 #endif /* CONFIG_AKT */
 
 extern void fork_late_init(void);
+extern void files_late_init(void);
 
 #endif /* AKT_H */
Index: linux-2.6.20-rc4/init/main.c
===================================================================
--- linux-2.6.20-rc4.orig/init/main.c   2007-01-15 15:09:27.000000000 +0100
+++ linux-2.6.20-rc4/init/main.c        2007-01-15 15:46:09.000000000 +0100
@@ -616,6 +616,7 @@ asmlinkage void __init start_kernel(void
        page_writeback_init();
        init_auto_tuning();
        fork_late_init();
+       files_late_init();
 #ifdef CONFIG_PROC_FS
        proc_root_init();
 #endif
Index: linux-2.6.20-rc4/ipc/msg.c
===================================================================
--- linux-2.6.20-rc4.orig/ipc/msg.c     2007-01-15 13:08:15.000000000 +0100
+++ linux-2.6.20-rc4/ipc/msg.c  2007-01-15 15:48:16.000000000 +0100
@@ -36,6 +36,8 @@
 #include <linux/seq_file.h>
 #include <linux/mutex.h>
 #include <linux/nsproxy.h>
+#include <linux/akt.h>
+#include <linux/akt_ops.h>
 
 #include <asm/current.h>
 #include <asm/uaccess.h>
@@ -94,6 +96,11 @@ static void __ipc_init __msg_init_ns(str
        ns->msg_ctlmnb = MSGMNB;
        ns->msg_ctlmni = MSGMNI;
        ipc_init_ids(ids, ns->msg_ctlmni);
+
+#define MSGTHRESH 80
+
+       init_tunable_ipcns(ns, msgmni_akt, MSGTHRESH, MSGMNI, IPCMNI,
+               &ns->msg_ctlmni, &ids->in_use, int);
 }
 
 #ifdef CONFIG_IPC_NS
@@ -133,6 +140,10 @@ void msg_exit_ns(struct ipc_namespace *n
 void __init msg_init(void)
 {
        __msg_init_ns(&init_ipc_ns, &init_msg_ids);
+
+       if (register_tunable(&init_ipc_ns.msgmni_akt))
+               printk(KERN_WARNING " Failed registering tunable msgmni\n");
+
        ipc_init_proc_interface("sysvipc/msg",
                                "       key      msqid perms      cbytes       
qnum lspid lrpid   uid   gid  cuid  cgid      stime      rtime      ctime\n",
                                IPC_MSG_IDS, sysvipc_msg_proc_show);
@@ -262,6 +273,8 @@ asmlinkage long sys_msgget(key_t key, in
 
        ns = current->nsproxy->ipc_ns;
        
+       activate_auto_tuning(AKT_UP, &ns->msgmni_akt);
+
        mutex_lock(&msg_ids(ns).mutex);
        if (key == IPC_PRIVATE) 
                ret = newque(ns, key, msgflg);
@@ -391,6 +404,7 @@ asmlinkage long sys_msgctl(int msqid, in
        struct msg_queue *msq;
        int err, version;
        struct ipc_namespace *ns;
+       int destroyed = 0;
 
        if (msqid < 0 || cmd < 0)
                return -EINVAL;
@@ -555,11 +569,16 @@ asmlinkage long sys_msgctl(int msqid, in
        }
        case IPC_RMID:
                freeque(ns, msq, msqid);
+               destroyed = 1;
                break;
        }
        err = 0;
 out_up:
        mutex_unlock(&msg_ids(ns).mutex);
+
+       if (destroyed)
+               activate_auto_tuning(AKT_DOWN, &ns->msgmni_akt);
+
        return err;
 out_unlock_up:
        msg_unlock(msq);
Index: linux-2.6.20-rc4/ipc/shm.c
===================================================================
--- linux-2.6.20-rc4.orig/ipc/shm.c     2007-01-15 13:08:15.000000000 +0100
+++ linux-2.6.20-rc4/ipc/shm.c  2007-01-15 15:49:00.000000000 +0100
@@ -37,6 +37,8 @@
 #include <linux/seq_file.h>
 #include <linux/mutex.h>
 #include <linux/nsproxy.h>
+#include <linux/akt.h>
+#include <linux/akt_ops.h>
 
 #include <asm/uaccess.h>
 
@@ -75,17 +77,27 @@ static void __ipc_init __shm_init_ns(str
        ns->shm_ctlmni = SHMMNI;
        ns->shm_tot = 0;
        ipc_init_ids(ids, 1);
+
+#define SHMTHRESH 80
+       init_tunable_ipcns(ns, shmmni_akt, SHMTHRESH, SHMMNI, IPCMNI,
+               &ns->shm_ctlmni, &ids->in_use, int);
+       init_tunable_ipcns(ns, shmall_akt, SHMTHRESH, SHMALL,
+               SHMMAX / PAGE_SIZE * (IPCMNI / 16), &ns->shm_ctlall,
+               &ns->shm_tot, size_t);
 }
 
-static void do_shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *shp)
+static int do_shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *shp)
 {
        if (shp->shm_nattch){
                shp->shm_perm.mode |= SHM_DEST;
                /* Do not find it any more */
                shp->shm_perm.key = IPC_PRIVATE;
                shm_unlock(shp);
-       } else
+               return 0;
+       } else {
                shm_destroy(ns, shp);
+               return 1;
+       }
 }
 
 #ifdef CONFIG_IPC_NS
@@ -125,6 +137,13 @@ void shm_exit_ns(struct ipc_namespace *n
 void __init shm_init (void)
 {
        __shm_init_ns(&init_ipc_ns, &init_shm_ids);
+
+       if (register_tunable(&init_ipc_ns.shmmni_akt))
+               printk(KERN_WARNING "Failed registering tunable shmmni\n");
+
+       if (register_tunable(&init_ipc_ns.shmall_akt))
+               printk(KERN_WARNING "Failed registering tunable shmall\n");
+
        ipc_init_proc_interface("sysvipc/shm",
                                "       key      shmid perms       size  cpid  
lpid nattch   uid   gid  cuid  cgid      atime      dtime      ctime\n",
                                IPC_SHM_IDS, sysvipc_shm_proc_show);
@@ -206,6 +225,7 @@ static void shm_close (struct vm_area_st
        int id = file->f_path.dentry->d_inode->i_ino;
        struct shmid_kernel *shp;
        struct ipc_namespace *ns;
+       int destroyed = 0;
 
        ns = shm_file_ns(file);
 
@@ -217,11 +237,27 @@ static void shm_close (struct vm_area_st
        shp->shm_dtim = get_seconds();
        shp->shm_nattch--;
        if(shp->shm_nattch == 0 &&
-          shp->shm_perm.mode & SHM_DEST)
+          shp->shm_perm.mode & SHM_DEST) {
                shm_destroy(ns, shp);
-       else
+               destroyed = 1;
+       } else
                shm_unlock(shp);
        mutex_unlock(&shm_ids(ns).mutex);
+
+       if (destroyed) {
+               int rc;
+
+               rc = activate_auto_tuning(AKT_DOWN, &ns->shmmni_akt);
+               if (rc)
+                       /*
+                        * shm_ctlmni has been adjusted == > change
+                        * shm_ctlall value
+                        */
+                       ns->shm_ctlall = ns->shm_ctlmax / PAGE_SIZE *
+                               (ns->shm_ctlmni / 16);
+
+               activate_auto_tuning(AKT_DOWN, &ns->shmall_akt);
+       }
 }
 
 static int shm_mmap(struct file * file, struct vm_area_struct * vma)
@@ -355,9 +391,20 @@ asmlinkage long sys_shmget (key_t key, s
        struct shmid_kernel *shp;
        int err, id = 0;
        struct ipc_namespace *ns;
+       int rc;
 
        ns = current->nsproxy->ipc_ns;
 
+       rc = activate_auto_tuning(AKT_UP, &ns->shmmni_akt);
+       if (rc)
+               /*
+                * shm_ctlmni has been adjusted == > change shm_ctlall value
+                */
+               ns->shm_ctlall = ns->shm_ctlmax / PAGE_SIZE
+                               * (ns->shm_ctlmni / 16);
+
+       activate_auto_tuning(AKT_UP, &ns->shmall_akt);
+
        mutex_lock(&shm_ids(ns).mutex);
        if (key == IPC_PRIVATE) {
                err = newseg(ns, key, shmflg, size);
@@ -516,6 +563,7 @@ asmlinkage long sys_shmctl (int shmid, i
        struct shmid_kernel *shp;
        int err, version;
        struct ipc_namespace *ns;
+       int destroyed;
 
        if (cmd < 0 || shmid < 0) {
                err = -EINVAL;
@@ -701,8 +749,24 @@ asmlinkage long sys_shmctl (int shmid, i
                if (err)
                        goto out_unlock_up;
 
-               do_shm_rmid(ns, shp);
+               destroyed = do_shm_rmid(ns, shp);
                mutex_unlock(&shm_ids(ns).mutex);
+
+               if (destroyed) {
+                       int rc;
+
+                       rc = activate_auto_tuning(AKT_DOWN, &ns->shmmni_akt);
+                       if (rc)
+                               /*
+                                * shm_ctlmni has been adjusted == > change
+                                * shm_ctlall value
+                                */
+                               ns->shm_ctlall = ns->shm_ctlmax / PAGE_SIZE *
+                                       (ns->shm_ctlmni / 16);
+
+                       activate_auto_tuning(AKT_DOWN, &ns->shmall_akt);
+               }
+
                goto out;
        }
 
Index: linux-2.6.20-rc4/ipc/sem.c
===================================================================
--- linux-2.6.20-rc4.orig/ipc/sem.c     2007-01-15 13:08:15.000000000 +0100
+++ linux-2.6.20-rc4/ipc/sem.c  2007-01-15 15:49:41.000000000 +0100
@@ -83,6 +83,8 @@
 #include <linux/seq_file.h>
 #include <linux/mutex.h>
 #include <linux/nsproxy.h>
+#include <linux/akt.h>
+#include <linux/akt_ops.h>
 
 #include <asm/uaccess.h>
 #include "util.h"
@@ -131,6 +133,12 @@ static void __ipc_init __sem_init_ns(str
        ns->sc_semmni = SEMMNI;
        ns->used_sems = 0;
        ipc_init_ids(ids, ns->sc_semmni);
+
+#define SEMTHRESH 80
+       init_tunable_ipcns(ns, semmni_akt, SEMTHRESH, SEMMNI, IPCMNI,
+               &(ns->sc_semmni), &ids->in_use, int);
+       init_tunable_ipcns(ns, semmns_akt, SEMTHRESH, SEMMNS,
+               IPCMNI * SEMMSL, &(ns->sc_semmns), &ns->used_sems, int);
 }
 
 #ifdef CONFIG_IPC_NS
@@ -170,6 +178,13 @@ void sem_exit_ns(struct ipc_namespace *n
 void __init sem_init (void)
 {
        __sem_init_ns(&init_ipc_ns, &init_sem_ids);
+
+       if (register_tunable(&init_ipc_ns.semmni_akt))
+               printk(KERN_WARNING "Failed registering tunable semmni\n");
+
+       if (register_tunable(&init_ipc_ns.semmns_akt))
+               printk(KERN_WARNING "Failed registering tunable semmns\n");
+
        ipc_init_proc_interface("sysvipc/sem",
                                "       key      semid perms      nsems   uid   
gid  cuid  cgid      otime      ctime\n",
                                IPC_SEM_IDS, sysvipc_sem_proc_show);
@@ -263,11 +278,22 @@ asmlinkage long sys_semget (key_t key, i
        int id, err = -EINVAL;
        struct sem_array *sma;
        struct ipc_namespace *ns;
+       int rc;
 
        ns = current->nsproxy->ipc_ns;
 
        if (nsems < 0 || nsems > ns->sc_semmsl)
                return -EINVAL;
+
+       rc = activate_auto_tuning(AKT_UP, &ns->semmni_akt);
+       if (rc)
+               /*
+                * sc_semmni has been adjusted == > change sc_semmns value
+                */
+               ns->sc_semmns = ns->sc_semmni * ns->sc_semmsl;
+
+       activate_auto_tuning(AKT_UP, &ns->semmns_akt);
+
        mutex_lock(&sem_ids(ns).mutex);
        
        if (key == IPC_PRIVATE) {
@@ -899,6 +925,21 @@ static int semctl_down(struct ipc_namesp
        case IPC_RMID:
                freeary(ns, sma, semid);
                err = 0;
+
+               {
+                       int rc;
+
+                       rc = activate_auto_tuning(AKT_DOWN, &ns->semmni_akt);
+                       if (rc)
+                               /*
+                                * sc_semmni has been adjusted ==>
+                                * change sc_semmns value
+                                */
+                               ns->sc_semmns = ns->sc_semmni * ns->sc_semmsl;
+
+                       activate_auto_tuning(AKT_DOWN, &ns->semmns_akt);
+               }
+
                break;
        case IPC_SET:
                ipcp->uid = setbuf.uid;
Index: linux-2.6.20-rc4/include/linux/ipc.h
===================================================================
--- linux-2.6.20-rc4.orig/include/linux/ipc.h   2007-01-15 13:08:15.000000000 
+0100
+++ linux-2.6.20-rc4/include/linux/ipc.h        2007-01-15 15:52:19.000000000 
+0100
@@ -52,6 +52,7 @@ struct ipc_perm
 #ifdef __KERNEL__
 
 #include <linux/kref.h>
+#include <linux/akt.h>
 
 #define IPCMNI 32768  /* <= MAX_INT limit for ipc arrays (including sysctl 
changes) */
 
@@ -77,15 +78,20 @@ struct ipc_namespace {
 
        int             sem_ctls[4];
        int             used_sems;
+       DECLARE_TUNABLE(semmni_akt);
+       DECLARE_TUNABLE(semmns_akt);
 
        int             msg_ctlmax;
        int             msg_ctlmnb;
        int             msg_ctlmni;
+       DECLARE_TUNABLE(msgmni_akt);
 
        size_t          shm_ctlmax;
        size_t          shm_ctlall;
        int             shm_ctlmni;
        int             shm_tot;
+       DECLARE_TUNABLE(shmmni_akt);
+       DECLARE_TUNABLE(shmall_akt);
 };
 
 extern struct ipc_namespace init_ipc_ns;

--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to