Annotation of prex/usr/server/fs/vfs/vfs_task.c, Revision 1.1.1.1
1.1 nbrk 1: /*-
2: * Copyright (c) 2007, Kohsuke Ohtani All rights reserved.
3: *
4: * Redistribution and use in source and binary forms, with or without
5: * modification, are permitted provided that the following conditions
6: * are met:
7: * 1. Redistributions of source code must retain the above copyright
8: * notice, this list of conditions and the following disclaimer.
9: * 2. Redistributions in binary form must reproduce the above copyright
10: * notice, this list of conditions and the following disclaimer in the
11: * documentation and/or other materials provided with the distribution.
12: * 3. Neither the name of the author nor the names of any co-contributors
13: * may be used to endorse or promote products derived from this software
14: * without specific prior written permission.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: */
28:
29: /*
30: * task.c - Routines to manage the per task data.
31: */
32:
33: #include <prex/prex.h>
34: #include <sys/list.h>
35:
36: #include <limits.h>
37: #include <stdlib.h>
38: #include <string.h>
39: #include <stdio.h>
40: #include <errno.h>
41:
42: #include "vfs.h"
43:
44: #define TASK_MAXBUCKETS 32 /* number of task hash buckets */
45:
46: #define TASKHASH(x) (int)((x) & (TASK_MAXBUCKETS - 1))
47:
48: /*
49: * Hash table for task.
50: */
51: static struct list task_table[TASK_MAXBUCKETS];
52:
53: /*
54: * Global lock for task access.
55: */
56: #if CONFIG_FS_THREADS > 1
57: static mutex_t task_lock = MUTEX_INITIALIZER;
58: #define TASK_LOCK() mutex_lock(&task_lock)
59: #define TASK_UNLOCK() mutex_unlock(&task_lock)
60: #else
61: #define TASK_LOCK()
62: #define TASK_UNLOCK()
63: #endif
64:
65: /*
66: * Convert task ID to a task structure.
67: * Returns locked task. Caller must unlock it after using it.
68: */
69: struct task *
70: task_lookup(task_t task)
71: {
72: list_t head, n;
73: struct task *t;
74:
75: if (task == TASK_NULL)
76: return NULL;
77:
78: TASK_LOCK();
79: head = &task_table[TASKHASH(task)];
80: for (n = list_first(head); n != head; n = list_next(n)) {
81: t = list_entry(n, struct task, link);
82: ASSERT(t->task);
83: if (t->task == task) {
84: TASK_UNLOCK();
85: mutex_lock(&t->lock);
86: return t;
87: }
88: }
89: TASK_UNLOCK();
90:
91: /* Not found */
92: return NULL;
93: }
94:
95: /*
96: * Allocate new task
97: */
98: int
99: task_alloc(task_t task, struct task **pt)
100: {
101: struct task *t;
102:
103: /* Check if specified task already exists. */
104: if (task_lookup(task) != NULL)
105: return EINVAL;
106:
107: if (!(t = malloc(sizeof(struct task))))
108: return ENOMEM;
109: memset(t, 0, sizeof(struct task));
110: t->task = task;
111: strcpy(t->cwd, "/");
112: mutex_init(&t->lock);
113:
114: TASK_LOCK();
115: list_insert(&task_table[TASKHASH(task)], &t->link);
116: TASK_UNLOCK();
117: *pt = t;
118: return 0;
119: }
120:
121: /*
122: * Free needless task.
123: */
124: void
125: task_free(struct task *t)
126: {
127:
128: TASK_LOCK();
129: list_remove(&t->link);
130: mutex_unlock(&t->lock);
131: mutex_destroy(&t->lock);
132: free(t);
133: TASK_UNLOCK();
134: }
135:
136: /*
137: * Update task id of the specified task.
138: */
139: void
140: task_update(struct task *t, task_t task)
141: {
142:
143: TASK_LOCK();
144: list_remove(&t->link);
145: t->task = task;
146: list_insert(&task_table[TASKHASH(task)], &t->link);
147: TASK_UNLOCK();
148: }
149:
150: void
151: task_unlock(struct task *t)
152: {
153:
154: mutex_unlock(&t->lock);
155: }
156:
157: /*
158: * Get file pointer from task/fd pair.
159: */
160: file_t
161: task_getfp(struct task *t, int fd)
162: {
163:
164: if (fd >= OPEN_MAX)
165: return NULL;
166:
167: return t->file[fd];
168: }
169:
170: /*
171: * Get new file descriptor in the task.
172: * Find the smallest empty slot in the fd array.
173: * Returns -1 if there is no empty slot.
174: */
175: int
176: task_newfd(struct task *t)
177: {
178: int fd;
179:
180: for (fd = 0; fd < OPEN_MAX; fd++)
181: if (t->file[fd] == NULL)
182: break;
183: if (fd == OPEN_MAX)
184: return -1; /* slot full */
185:
186: return fd;
187: }
188:
189: /*
190: * Convert to full path from the cwd of task and path.
191: * @t: task structure
192: * @path: target path
193: * @full: full path to be returned
194: */
195: int
196: task_conv(struct task *t, char *path, char *full)
197: {
198: char *src, *tgt, *p, *end, *cwd;
199: size_t len = 0;
200:
201: cwd = t->cwd;
202: path[PATH_MAX - 1] = '\0';
203: len = strlen(path);
204: if (len >= PATH_MAX)
205: return ENAMETOOLONG;
206: if (strlen(cwd) + len >= PATH_MAX)
207: return ENAMETOOLONG;
208: src = path;
209: tgt = full;
210: end = src + len;
211: if (path[0] == '/') {
212: *tgt++ = *src++;
213: len++;
214: } else {
215: strcpy(full, cwd);
216: len = strlen(cwd);
217: tgt += len;
218: if (len > 1 && path[0] != '.') {
219: *tgt = '/';
220: tgt++;
221: len++;
222: }
223: }
224: while (*src) {
225: p = src;
226: while (*p != '/' && *p != '\0')
227: p++;
228: *p = '\0';
229: if (!strcmp(src, "..")) {
230: if (len >= 2) {
231: len -= 2;
232: tgt -= 2; /* skip previous '/' */
233: while (*tgt != '/') {
234: tgt--;
235: len--;
236: }
237: if (len == 0) {
238: tgt++;
239: len++;
240: }
241: }
242: } else if (!strcmp(src, ".")) {
243: /* Ignore "." */
244: } else {
245: while (*src != '\0') {
246: *tgt++ = *src++;
247: len++;
248: }
249: }
250: if (p == end)
251: break;
252: if (len > 0 && *(tgt - 1) != '/') {
253: *tgt++ = '/';
254: len++;
255: }
256: src = p + 1;
257: }
258: *tgt = '\0';
259: return 0;
260: }
261:
262: #ifdef DEBUG
263: void
264: task_dump(void)
265: {
266: #ifdef DEBUG_VFS
267: list_t head, n;
268: struct task *t;
269: int i;
270:
271: TASK_LOCK();
272: dprintf("Dump file data\n");
273: dprintf(" task opens cwd\n");
274: dprintf(" -------- ------- ------------------------------\n");
275: for (i = 0; i < TASK_MAXBUCKETS; i++) {
276: head = &task_table[i];
277: for (n = list_first(head); n != head; n = list_next(n)) {
278: t = list_entry(n, struct task, link);
279: dprintf(" %08x %7x %s\n", (int)t->task, t->nopens,
280: t->cwd);
281: }
282: }
283: dprintf("\n");
284: TASK_UNLOCK();
285: #endif
286: }
287: #endif
288:
289: void
290: task_init(void)
291: {
292: int i;
293:
294: for (i = 0; i < TASK_MAXBUCKETS; i++)
295: list_init(&task_table[i]);
296: }
297:
298: #ifdef DEBUG_VFS
299: void
300: task_debug(void)
301: {
302: int i;
303: list_t head;
304:
305: for (i = 0; i < TASK_MAXBUCKETS; i++) {
306: head = &task_table[i];
307: dprintf("head=%x head->next=%x head->prev=%x\n", head,
308: head->next, head->prev);
309: ASSERT(head->next);
310: ASSERT(head->prev);
311: }
312: }
313: #endif
CVSweb