Annotation of prex-old/usr/server/fs/vfs/vfs_task.c, Revision 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: * Lookup task by task id.
! 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 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: * Convert to full path from the cwd of task and path.
! 172: * @t: task structure
! 173: * @path: target path
! 174: * @full: full path to be returned
! 175: */
! 176: int
! 177: task_conv(struct task *t, char *path, char *full)
! 178: {
! 179: char *src, *tgt, *p, *end, *cwd;
! 180: size_t len = 0;
! 181:
! 182: cwd = t->cwd;
! 183: path[PATH_MAX - 1] = '\0';
! 184: len = strlen(path);
! 185: if (len >= PATH_MAX)
! 186: return ENAMETOOLONG;
! 187: if (strlen(cwd) + len >= PATH_MAX)
! 188: return ENAMETOOLONG;
! 189: src = path;
! 190: tgt = full;
! 191: end = src + len;
! 192: if (path[0] == '/') {
! 193: *tgt++ = *src++;
! 194: len++;
! 195: } else {
! 196: strcpy(full, cwd);
! 197: len = strlen(cwd);
! 198: tgt += len;
! 199: if (len > 1 && path[0] != '.') {
! 200: *tgt = '/';
! 201: tgt++;
! 202: len++;
! 203: }
! 204: }
! 205: while (*src) {
! 206: p = src;
! 207: while (*p != '/' && *p != '\0')
! 208: p++;
! 209: *p = '\0';
! 210: if (!strcmp(src, "..")) {
! 211: if (len >= 2) {
! 212: len -= 2;
! 213: tgt -= 2; /* skip previous '/' */
! 214: while (*tgt != '/') {
! 215: tgt--;
! 216: len--;
! 217: }
! 218: if (len == 0) {
! 219: tgt++;
! 220: len++;
! 221: }
! 222: }
! 223: } else if (!strcmp(src, ".")) {
! 224: /* Ignore "." */
! 225: } else {
! 226: while (*src != '\0') {
! 227: *tgt++ = *src++;
! 228: len++;
! 229: }
! 230: }
! 231: if (p == end)
! 232: break;
! 233: if (len > 0 && *(tgt - 1) != '/') {
! 234: *tgt++ = '/';
! 235: len++;
! 236: }
! 237: src = p + 1;
! 238: }
! 239: *tgt = '\0';
! 240: return 0;
! 241: }
! 242:
! 243: #ifdef DEBUG
! 244: void
! 245: task_dump(void)
! 246: {
! 247: #ifdef DEBUG_VFS
! 248: list_t head, n;
! 249: struct task *t;
! 250: int i;
! 251:
! 252: TASK_LOCK();
! 253: printf("Dump file data\n");
! 254: printf(" task nr_open cwd\n");
! 255: printf(" -------- ------- ------------------------------\n");
! 256: for (i = 0; i < TASK_MAXBUCKETS; i++) {
! 257: head = &task_table[i];
! 258: for (n = list_first(head); n != head; n = list_next(n)) {
! 259: t = list_entry(n, struct task, link);
! 260: printf(" %08x %7x %s\n", t->task, t->nr_open, t->cwd);
! 261: }
! 262: }
! 263: printf("\n");
! 264: TASK_UNLOCK();
! 265: #endif
! 266: }
! 267: #endif
! 268:
! 269: void
! 270: task_init(void)
! 271: {
! 272: int i;
! 273:
! 274: for (i = 0; i < TASK_MAXBUCKETS; i++)
! 275: list_init(&task_table[i]);
! 276: }
! 277:
! 278: void
! 279: task_debug(void)
! 280: {
! 281: int i;
! 282: list_t head;
! 283:
! 284: for (i = 0; i < TASK_MAXBUCKETS; i++) {
! 285: head = &task_table[i];
! 286: syslog(LOG_DEBUG, "head=%x head->next=%x head->prev=%x\n",
! 287: head, head->next, head->prev);
! 288: ASSERT(head->next);
! 289: ASSERT(head->prev);
! 290: }
! 291: }
CVSweb