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