📄 directory.c
字号:
of. It walks through the entries in the page, bringing all of the in-use entries to the front of the page. Leave an entry with d_inuse == false at the end containing all the free space. */struct direct *coalesce_page(struct direct *dp){ uint32_t offset = 0; uint32_t bytes = 0; uint32_t free = 0; uint8_t *page_start = (uint8_t *)dp; #ifndef NDEBUG if ((uint32_t) dp & EROS_PAGE_MASK) DEBUG(link) kdprintf(KR_OSTREAM, "coalesce(): start dp 0x%08x not at page boundary\n", dp);#endif while (bytes < EROS_PAGE_SIZE) { if (dp->d_inuse == false) { free += dp->d_inuse; } else { uint32_t truelen = DIRSIZ(dp); uint32_t dp_free = dp->d_reclen - DIRSIZ(dp); if (offset != bytes) { bcopy(dp, page_start + offset, truelen); offset += truelen; } ((struct direct *) (page_start + offset))->d_reclen = truelen; free += dp_free; } bytes += dp->d_reclen; } if (free < 12) DEBUG(link) kdprintf(KR_OSTREAM, "Insufficient free space in page\n"); /* All active entries have now been moved to the front of the page, and FREE now contains the number of free bytes in this page. Create a new, unallocated struct direct at the end of the page which contains all the free space. */ { struct direct *tail; tail = (struct direct *) (page_start + free); tail->d_reclen = free; tail->d_inuse = false; tail->d_namlen = 0; tail->d_name[0] = 0; tail->d_name[1] = 0; tail->d_name[2] = 0; tail->d_name[3] = 0; return tail; }}struct direct *find_space(uint32_t len, state_t *state){ struct direct *dp = first_entry; DEBUG(link) kdprintf(KR_OSTREAM, "find_space(%d)\n", len); while (dp != state->dir_top) { struct direct * page_start_dp = dp; uint32_t bytes = 0; uint32_t free_bytes = 0; while (bytes < EROS_PAGE_SIZE) { uint32_t free = dp->d_reclen - DIRSIZ(dp); DEBUG(link) kdprintf(KR_OSTREAM, "Considering dp=0x%08x sz %d reclen %d inuse? %c\n", dp, DIRSIZ(dp), dp->d_reclen, dp->d_inuse ? 'y' : 'n'); if (dp->d_inuse == false) free += DIRSIZ(dp); if (dp->d_inuse == false && free >= len) return dp; if (dp->d_inuse && free >= len) { /* Fashion a new entry here: */ dp->d_reclen = DIRSIZ(dp); dp = NEXTDIR(dp); dp->d_reclen = free; dp->d_inuse = false; dp->d_namlen = 0; dp->d_name[0] = 0; dp->d_name[1] = 0; dp->d_name[2] = 0; dp->d_name[3] = 0; return dp; } free_bytes += free; bytes += dp->d_reclen; dp = NEXTDIR(dp); } if (len <= free_bytes) { dp = coalesce_page(page_start_dp); return dp; } } return 0;}uint32_tlink(char *name, uint32_t kr, state_t * state){ uint32_t len; struct direct *dp = find(name, state); if (dp) return RC_Directory_Exists; /* This is NOT the standard roundup. if the name is exactly a multiple of 4 bytes, we WANT the trailing 4 bytes to get added: */ len = strlen(name); len += 4; /* round up to NEXT 4 byte multiple */ len &= ~3u; len += 8; /* overhead per dirent */ /* Run through the directory looking for a page that has sufficient space. The dp->d_namlen test works when we overrun the current directory because the VCS will demand allocate a zero page for us. */ dp = first_entry; if ( (dp = find_space(len, state)) == 0 ) { dp = state->dir_top; bcopy(&blank_page, state->dir_top, sizeof(blank_page)); state->dir_top = (struct direct *) ((uint8_t *)state->dir_top + EROS_PAGE_SIZE); } DEBUG(link) kdprintf(KR_OSTREAM, "Inserting dirent at dp=0x%08x\n", dp); if ( insert_dirent(dp, name, kr, state) == false ) return RC_Directory_NoSpace; return RC_OK;}intProcessRequest(Message *msg, state_t *state){ switch (msg->rcv_code) { case OC_Directory_Lookup: DEBUG(op) kprintf(KR_OSTREAM, "DIR: lookup(\"%s\")\n", state->name); msg->snd_code = lookup (state->name, KR_ARG0, state); msg->snd_key0 = KR_ARG0; break; case OC_Directory_Link: DEBUG(op) kprintf(KR_OSTREAM, "DIR: link(\"%s\", <key>)\n", state->name); msg->snd_code = link (state->name, msg->rcv_key0, state); break; case OC_Directory_Unlink: DEBUG(op) kprintf(KR_OSTREAM, "DIR: unlink(\"%s\") => <key>\n", state->name); msg->snd_code = unlink (state->name, msg->rcv_key0, state); break; case OC_KeyType: /* check alleged keytype */ msg->snd_code = RC_OK; msg->snd_w1 = AKT_Directory; break; default: msg->snd_code = RC_UnknownRequest; break; }; return 1;}voidInitialize(state_t *state){ uint32_t result; node_copy(KR_CONSTIT, KC_OSTREAM, KR_OSTREAM); /* Using KR_ARG0, KR_SNODE as scratch registers */ /* Construct the ZS that will hold the actual directory data */ DEBUG(init) kdprintf(KR_OSTREAM, "DIR: Building ZS\n"); node_copy(KR_CONSTIT, KC_ZSF, KR_SNODE); result = constructor_request(KR_SNODE, KR_BANK, KR_SCHED, KR_VOID, KR_SNODE); DEBUG(init) kdprintf(KR_OSTREAM, "DIR: Result is: 0x%08x\n", result); /* Buy the new root node to hold it: */ result = spcbank_buy_nodes(KR_BANK, 1, KR_ARG0, KR_VOID, KR_VOID); if (result != RC_OK) DEBUG(init) kdprintf(KR_OSTREAM, "DIR: spcbank nodes exhausted\n", result); /* make that node LSS=TOP_LSS */ node_make_node_key(KR_ARG0, EROS_ADDRESS_BLSS, KR_ARG0); /* plug in newly allocated ZSF */ DEBUG(init) kdprintf(KR_OSTREAM, "DIR: plugging zsf into new spc root\n", result); node_swap(KR_ARG0, 8, KR_SNODE, KR_VOID); DEBUG(init) kdprintf(KR_OSTREAM, "DIR: fetch my own space\n", result); process_copy(KR_SELF, ProcAddrSpace, KR_SNODE); DEBUG(init) kdprintf(KR_OSTREAM, "DIR: plug self spc into new spc root\n", result); node_swap(KR_ARG0, 0, KR_SNODE, KR_VOID); DEBUG(init) kdprintf(KR_OSTREAM, "DIR: before lobotomy\n", result); process_swap(KR_SELF, ProcAddrSpace, KR_ARG0, KR_VOID); DEBUG(init) kdprintf(KR_OSTREAM, "DIR: post lobotomy\n", result); node_copy(KR_CONSTIT, KC_SNODEC, KR_SNODE); DEBUG(init) kdprintf(KR_OSTREAM, "DIR: buying supernode\n"); result = constructor_request(KR_SNODE, KR_BANK, KR_SCHED, KR_VOID, KR_SNODE); DEBUG(init) kdprintf(KR_OSTREAM, "DIR: Got it. Result 0x%08x\n", result); /* insert key for ".." entry: */ supernode_swap(KR_SNODE, 1, KR_ARG0, KR_VOID); /* make start key to us: */ process_make_start_key(KR_SELF, 0, KR_ARG0); /* insert key for "." entry: */ supernode_swap(KR_SNODE, 0, KR_ARG0, KR_VOID); state->ndirent = 2; state->dir_top = (struct direct *) ((uint8_t *)first_entry+EROS_PAGE_SIZE); bzero(state->freeMap, EROS_PAGE_SIZE * N_FREEMAP_PAGE); bcopy(&template, first_entry, sizeof(template)); DEBUG(init) kdprintf(KR_OSTREAM, "Allocate Initial slots...\n"); (void) alloc_dirent(state); (void) alloc_dirent(state); DEBUG(init) kdprintf(KR_OSTREAM, "Initial slots allocated\n");}intmain(){ state_t state; Message msg; Initialize(&state); process_make_start_key(KR_SELF, 0, KR_ARG0); DEBUG(init) kdprintf(KR_OSTREAM, "DIR: Got start key. Ready to rock and roll\n"); // kdprintf(KR_OSTREAM, "DIR: Got start key. Ready to rock and roll\n"); msg.snd_invKey = KR_RETURN; msg.snd_key0 = KR_ARG0; msg.snd_key1 = KR_VOID; msg.snd_key2 = KR_VOID; msg.snd_key3 = KR_VOID; msg.snd_data = 0; msg.snd_len = 0; msg.snd_code = 0; msg.snd_w1 = 0; msg.snd_w2 = 0; msg.snd_w3 = 0; msg.rcv_key0 = KR_ARG0; msg.rcv_key1 = KR_VOID; msg.rcv_key2 = KR_VOID; msg.rcv_key3 = KR_RETURN; msg.rcv_data = state.name; msg.rcv_len = MAXNAMLEN; msg.rcv_code = 0; msg.rcv_w1 = 0; msg.rcv_w2 = 0; msg.rcv_w3 = 0; do { msg.rcv_len = MAXNAMLEN; RETURN(&msg); ((uint8_t *) msg.rcv_data)[msg.rcv_len] = 0; msg.snd_key0 = KR_VOID; /* until otherwise proven */ kdprintf(KR_OSTREAM, "Before ProcessRequest(): freemap = 0x%08x\n", state.freeMap); } while ( ProcessRequest(&msg, &state) ); return 0;}/* * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)dir.h 8.4 (Berkeley) 8/10/94 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -