This commit was manufactured by cvs2svn to create branch 'ckrm'.
[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
31 get_exe_path_name(struct task_struct *tsk, char *buf, int buflen)
32 {
33         struct vm_area_struct * vma;
34         struct vfsmount *mnt;
35         struct mm_struct * mm = get_task_mm(tsk);
36         struct dentry *dentry;
37         char *lname;
38         int rc = 0;
39
40         *buf = '\0';
41         if (!mm) {
42                 return -EINVAL;
43         }
44
45         down_read(&mm->mmap_sem);
46         vma = mm->mmap;
47         while (vma) {
48                 if ((vma->vm_flags & VM_EXECUTABLE) &&
49                                 vma->vm_file) {
50                         dentry = dget(vma->vm_file->f_dentry);
51                         mnt = mntget(vma->vm_file->f_vfsmnt);
52                         lname = d_path(dentry, mnt, buf, buflen);
53                         if (! IS_ERR(lname)) {
54                                 strncpy(buf, lname, strlen(lname) + 1);
55                         } else {
56                                 rc = (int) PTR_ERR(lname);
57                         }
58                         mntput(mnt);
59                         dput(dentry);
60                         break;
61                 }
62                 vma = vma->vm_next;
63         }
64         up_read(&mm->mmap_sem);
65         mmput(mm);
66         return rc;
67 }
68
69
70 /*
71  * must be called with cnt_lock of parres held
72  * Caller is responsible for making sure that the new guarantee doesn't
73  * overflow parent's total guarantee.
74  */
75 void
76 child_guarantee_changed(struct ckrm_shares *parent, int cur, int new)
77 {
78         if (new == cur || !parent) {
79                 return;
80         }
81         if (new != CKRM_SHARE_DONTCARE) {
82                 parent->unused_guarantee -= new;
83         }
84         if (cur != CKRM_SHARE_DONTCARE) {
85                 parent->unused_guarantee += cur;
86         }
87         return;
88 }
89
90 /*
91  * must be called with cnt_lock of parres held
92  * Caller is responsible for making sure that the new limit is not more 
93  * than parent's max_limit
94  */
95 void
96 child_maxlimit_changed(struct ckrm_shares *parent, int new_limit)
97 {
98         if (parent && parent->cur_max_limit < new_limit) {
99                 parent->cur_max_limit = new_limit;
100         }
101         return;
102 }
103
104 /*
105  * Caller is responsible for holding any lock to protect the data
106  * structures passed to this function
107  */
108 int
109 set_shares(struct ckrm_shares *new, struct ckrm_shares *cur,
110                 struct ckrm_shares *par)
111 {
112         int rc = -EINVAL;
113         int cur_usage_guar = cur->total_guarantee - cur->unused_guarantee;
114         int increase_by = new->my_guarantee - cur->my_guarantee;
115
116         // Check total_guarantee for correctness
117         if (new->total_guarantee <= CKRM_SHARE_DONTCARE) {
118                 goto set_share_err;
119         } else if (new->total_guarantee == CKRM_SHARE_UNCHANGED) {
120                 ;// do nothing
121         } else if (cur_usage_guar > new->total_guarantee) {
122                 goto set_share_err;
123         }
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
134         // Check my_guarantee for correctness
135         if (new->my_guarantee == CKRM_SHARE_UNCHANGED) {
136                 ; // do nothing
137         } else if (new->my_guarantee == CKRM_SHARE_DONTCARE) {
138                 ; // do nothing
139         } else if (par && increase_by > par->unused_guarantee) {
140                 goto set_share_err;
141         }
142
143         // Check my_limit for correctness
144         if (new->my_limit == CKRM_SHARE_UNCHANGED) {
145                 ; // do nothing
146         } else if (new->my_limit == CKRM_SHARE_DONTCARE) {
147                 ; // do nothing
148         } else if (par && new->my_limit > par->max_limit) {
149                 // I can't get more limit than my parent's limit
150                 goto set_share_err;
151                 
152         }
153
154         // make sure guarantee is lesser than limit
155         if (new->my_limit == CKRM_SHARE_DONTCARE) {
156                 ; // do nothing
157         } else if (new->my_limit == CKRM_SHARE_UNCHANGED) {
158                 if (new->my_guarantee == CKRM_SHARE_DONTCARE) {
159                         ; // do nothing
160                 } else if (new->my_guarantee == CKRM_SHARE_UNCHANGED) {
161                         ; // do nothing earlier setting would 've taken care of it
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
177         if (new->my_guarantee != CKRM_SHARE_UNCHANGED) {
178                 child_guarantee_changed(par, cur->my_guarantee,
179                                 new->my_guarantee);
180                 cur->my_guarantee = new->my_guarantee;
181         }
182
183         if (new->my_limit != CKRM_SHARE_UNCHANGED) {
184                 child_maxlimit_changed(par, new->my_limit);
185                 cur->my_limit = new->my_limit;
186         }
187
188         if (new->total_guarantee != CKRM_SHARE_UNCHANGED) {
189                 cur->unused_guarantee = new->total_guarantee - cur_usage_guar;
190                 cur->total_guarantee = new->total_guarantee;
191         }
192
193         if (new->max_limit != CKRM_SHARE_UNCHANGED) {
194                 cur->max_limit = new->max_limit;
195         }
196
197         rc = 0;
198 set_share_err:
199         return rc;
200 }
201
202 EXPORT_SYMBOL(get_exe_path_name);
203 EXPORT_SYMBOL(child_guarantee_changed);
204 EXPORT_SYMBOL(child_maxlimit_changed);
205 EXPORT_SYMBOL(set_shares);
206
207