5e5bf29c8b229879e3df762ac2ed8c9da417f298
[linux-2.6.git] / kernel / ckrm / ckrmutils.c
1 /*
2  * ckrmutils.c - Utility functions for CKRM
3  *
4  * Copyright (C) Chandra Seetharaman,  IBM Corp. 2003
5  *           (C) Hubertus Franke    ,  IBM Corp. 2004
6  * 
7  * Provides simple utility functions for the core module, CE and resource
8  * controllers.
9  *
10  * Latest version, more details at http://ckrm.sf.net
11  * 
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  */
18
19 /*
20  * Changes
21  * 
22  * 13 Nov 2003
23  *        Created
24  */
25
26 #include <linux/mm.h>
27 #include <linux/err.h>
28 #include <linux/mount.h>
29 #include <linux/module.h>
30 #include <linux/ckrm_rc.h>
31
32 int get_exe_path_name(struct task_struct *tsk, char *buf, int buflen)
33 {
34         struct vm_area_struct *vma;
35         struct vfsmount *mnt;
36         struct mm_struct *mm = get_task_mm(tsk);
37         struct dentry *dentry;
38         char *lname;
39         int rc = 0;
40
41         *buf = '\0';
42         if (!mm) {
43                 return -EINVAL;
44         }
45         down_read(&mm->mmap_sem);
46         vma = mm->mmap;
47         while (vma) {
48                 if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
49                         dentry = dget(vma->vm_file->f_dentry);
50                         mnt = mntget(vma->vm_file->f_vfsmnt);
51                         lname = d_path(dentry, mnt, buf, buflen);
52                         if (!IS_ERR(lname)) {
53                                 strncpy(buf, lname, strlen(lname) + 1);
54                         } else {
55                                 rc = (int)PTR_ERR(lname);
56                         }
57                         mntput(mnt);
58                         dput(dentry);
59                         break;
60                 }
61                 vma = vma->vm_next;
62         }
63         up_read(&mm->mmap_sem);
64         mmput(mm);
65         return rc;
66 }
67
68 /*
69  * must be called with cnt_lock of parres held
70  * Caller is responsible for making sure that the new guarantee doesn't
71  * overflow parent's total guarantee.
72  */
73 void child_guarantee_changed(struct ckrm_shares *parent, int cur, int new)
74 {
75         if (new == cur || !parent) {
76                 return;
77         }
78         if (new != CKRM_SHARE_DONTCARE) {
79                 parent->unused_guarantee -= new;
80         }
81         if (cur != CKRM_SHARE_DONTCARE) {
82                 parent->unused_guarantee += cur;
83         }
84         return;
85 }
86
87 /*
88  * must be called with cnt_lock of parres held
89  * Caller is responsible for making sure that the new limit is not more 
90  * than parent's max_limit
91  */
92 void child_maxlimit_changed(struct ckrm_shares *parent, int new_limit)
93 {
94         if (parent && parent->cur_max_limit < new_limit) {
95                 parent->cur_max_limit = new_limit;
96         }
97         return;
98 }
99
100 /*
101  * Caller is responsible for holding any lock to protect the data
102  * structures passed to this function
103  */
104 int
105 set_shares(struct ckrm_shares *new, struct ckrm_shares *cur,
106            struct ckrm_shares *par)
107 {
108         int rc = -EINVAL;
109         int cur_usage_guar = cur->total_guarantee - cur->unused_guarantee;
110         int increase_by;
111
112         if (cur->my_guarantee < 0) // DONTCARE or UNCHANGED
113                 increase_by = new->my_guarantee;
114         else
115                 increase_by = new->my_guarantee - cur->my_guarantee;
116
117         /* Check total_guarantee for correctness */
118         if (new->total_guarantee <= CKRM_SHARE_DONTCARE) {
119                 goto set_share_err;
120         } else if (new->total_guarantee == CKRM_SHARE_UNCHANGED) {
121                 /* do nothing */;
122         } else if (cur_usage_guar > new->total_guarantee) {
123                 goto set_share_err;
124         }
125         /* Check max_limit for correctness */
126         if (new->max_limit <= CKRM_SHARE_DONTCARE) {
127                 goto set_share_err;
128         } else if (new->max_limit == CKRM_SHARE_UNCHANGED) {
129                 /* do nothing */;
130         } else if (cur->cur_max_limit > new->max_limit) {
131                 goto set_share_err;
132         }
133         /* Check my_guarantee for correctness */
134         if (new->my_guarantee == CKRM_SHARE_UNCHANGED) {
135                 /* do nothing */;
136         } else if (new->my_guarantee == CKRM_SHARE_DONTCARE) {
137                 /* do nothing */;
138         } else if (par && increase_by > par->unused_guarantee) {
139                 goto set_share_err;
140         }
141         /* Check my_limit for correctness */
142         if (new->my_limit == CKRM_SHARE_UNCHANGED) {
143                 /* do nothing */;
144         } else if (new->my_limit == CKRM_SHARE_DONTCARE) {
145                 /* do nothing */;
146         } else if (par && new->my_limit > par->max_limit) {
147                 /* I can't get more limit than my parent's limit */
148                 goto set_share_err;
149
150         }
151         /* make sure guarantee is lesser than limit */
152         if (new->my_limit == CKRM_SHARE_DONTCARE) {
153                 /* do nothing */;
154         } else if (new->my_limit == CKRM_SHARE_UNCHANGED) {
155                 if (new->my_guarantee == CKRM_SHARE_DONTCARE) {
156                         /* do nothing */;
157                 } else if (new->my_guarantee == CKRM_SHARE_UNCHANGED) {
158                         /*
159                          * do nothing; earlier setting would have
160                          * taken care of it
161                          */;
162                 } else if (new->my_guarantee > cur->my_limit) {
163                         goto set_share_err;
164                 }
165         } else {                /* new->my_limit has a valid value */
166                 if (new->my_guarantee == CKRM_SHARE_DONTCARE) {
167                         /* do nothing */;
168                 } else if (new->my_guarantee == CKRM_SHARE_UNCHANGED) {
169                         if (cur->my_guarantee > new->my_limit) {
170                                 goto set_share_err;
171                         }
172                 } else if (new->my_guarantee > new->my_limit) {
173                         goto set_share_err;
174                 }
175         }
176         if (new->my_guarantee != CKRM_SHARE_UNCHANGED) {
177                 child_guarantee_changed(par, cur->my_guarantee,
178                                         new->my_guarantee);
179                 cur->my_guarantee = new->my_guarantee;
180         }
181         if (new->my_limit != CKRM_SHARE_UNCHANGED) {
182                 child_maxlimit_changed(par, new->my_limit);
183                 cur->my_limit = new->my_limit;
184         }
185         if (new->total_guarantee != CKRM_SHARE_UNCHANGED) {
186                 cur->unused_guarantee = new->total_guarantee - cur_usage_guar;
187                 cur->total_guarantee = new->total_guarantee;
188         }
189         if (new->max_limit != CKRM_SHARE_UNCHANGED) {
190                 cur->max_limit = new->max_limit;
191         }
192         rc = 0;
193 set_share_err:
194         return rc;
195 }
196
197 EXPORT_SYMBOL_GPL(get_exe_path_name);
198 EXPORT_SYMBOL_GPL(child_guarantee_changed);
199 EXPORT_SYMBOL_GPL(child_maxlimit_changed);
200 EXPORT_SYMBOL_GPL(set_shares);