⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vfs.c

📁 The main purpose of this project is to add a new scheduling algorithm to GeekOS and to implement a s
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Virtual filesystem structures and routines * Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu> * Copyright (c) 2003,2004 David H. Hovemeyer <daveho@cs.umd.edu> * $Revision: 1.46 $ *  * This is free software.  You are permitted to use, * redistribute, and modify it as specified in the file "COPYING". */#include <geekos/errno.h>#include <geekos/list.h>#include <geekos/string.h>#include <geekos/screen.h>#include <geekos/malloc.h>#include <geekos/synch.h>#include <geekos/vfs.h>/* * Notes: * - This is rewritten from Jeff's original VFS implementation. *   It uses vtables to more easily accomodate multiple filesystem types. *//* ---------------------------------------------------------------------- * Private data and functions * ---------------------------------------------------------------------- *//* * We use a single mutex to protect VFS data structures * from concurrent access/modification.  Simple, but not efficient. * Perhaps this should really be a reader/writer lock. */static struct Mutex s_vfsLock;int debugVFS = 0;#define Debug(args...) if (debugVFS) Print("VFS: " args)struct Filesystem;DEFINE_LIST(Mount_Point_List, Mount_Point);IMPLEMENT_LIST(Mount_Point_List, Mount_Point);/* List of mounted filesystems. */static struct Mount_Point_List s_mountPointList;/* A registered filesystem type. */struct Filesystem {    struct Filesystem_Ops *ops;    char fsName[VFS_MAX_FS_NAME_LEN + 1];    DEFINE_LINK(Filesystem_List, Filesystem);};DEFINE_LIST(Filesystem_List, Filesystem);IMPLEMENT_LIST(Filesystem_List, Filesystem);/* List of registered filesystem types. */static struct Filesystem_List s_filesystemList;/* Registered paging device. */static struct Paging_Device *s_pagingDevice;#define MAX_PREFIX_LEN 16/* * Unpack a path into prefix and suffix. * The prefix determines which mounted filesystem * the path resides in.  The suffix is the path within * the filesystem. * Params: *   path - the complete path *   prefix - buffer where prefix will be stored *   pSuffix - stores the pointer to the suffix part of path * Returns: true if path is valid, false if not */static bool Unpack_Path(const char *path, char *prefix, const char **pSuffix){    char *slash;    size_t pfxLen;    Debug("path=%s\n", path);    /* Path must start with '/' */    if (*path != '/')	return false;    ++path;    /* Look for the initial slash. */    slash = strchr(path, '/');    if (slash == 0) {	/*	 * Special case: path of the form "/prefix".	 * It resolves to the root directory of	 * the filesystem mounted on the prefix.	 */	pfxLen = strlen(path);	if (pfxLen == 0 || pfxLen > MAX_PREFIX_LEN)	    return false;	strcpy(prefix, path);	*pSuffix = "/";    } else {	/*	 * Determine length of file prefix.	 * It needs to be non-zero, but less than MAX_PREFIX_LEN.	 */	pfxLen = slash - path;	if (pfxLen == 0 || pfxLen > MAX_PREFIX_LEN)	    return false;	/* Format the path prefix as a string */	memcpy(prefix, path, pfxLen);	prefix[pfxLen] = '\0';	/*	 * Set pointer to "suffix", i.e., the rest of the path	 * after the prefix	 */	*pSuffix = slash;    }    Debug("prefix=%s, suffix=%s\n", prefix, *pSuffix);    KASSERT(**pSuffix == '/');    return true;}/* * Look up given filesystem type. * Params: *   fstype - name of the filesystem type * Returns: the Filesystem object for the filesystem, or null *   if no such filesystem exists. */static struct Filesystem *Lookup_Filesystem(const char *fstype){    struct Filesystem *fs;    Mutex_Lock(&s_vfsLock);    fs = Get_Front_Of_Filesystem_List(&s_filesystemList);    while (fs != 0) {	if (strcmp(fs->fsName, fstype) == 0)	    break;	fs = Get_Next_In_Filesystem_List(fs);    }    Mutex_Unlock(&s_vfsLock);    return fs;}/* * Look up mount point for given prefix. *   prefix - the path prefix * Returns: the mount point, or null if there is no mount point *   matching the prefix */static struct Mount_Point *Lookup_Mount_Point(const char *prefix){    struct Mount_Point *mountPoint;    Mutex_Lock(&s_vfsLock);    /* Look for a mounted filesystem with a matching prefix */    mountPoint = Get_Front_Of_Mount_Point_List(&s_mountPointList);    while (mountPoint != 0) {	Debug("Lookup mount point: %s,%s\n", prefix, mountPoint->pathPrefix);	if (strcmp(prefix, mountPoint->pathPrefix) == 0)	    break;	mountPoint = Get_Next_In_Mount_Point_List(mountPoint);    }    Mutex_Unlock(&s_vfsLock);    return mountPoint;}/* * Common implementation function for Open() and Open_Directory(). */static int Do_Open(    const char *path, int mode, struct File **pFile,    int (*openFunc)(struct Mount_Point *mountPoint, const char *path, int mode, struct File **pFile)){    char prefix[MAX_PREFIX_LEN + 1];    const char *suffix;    struct Mount_Point *mountPoint;    int rc;    if (!Unpack_Path(path, prefix, &suffix))	return ENOTFOUND;    /* Get mount point for path */    mountPoint = Lookup_Mount_Point(prefix);    if (mountPoint == 0)	return ENOTFOUND;    /* Call into actual Open() or Open_Directory() function. */    rc = openFunc(mountPoint, suffix, mode, pFile);    if (rc == 0) {	/* File opened successfully! */	(*pFile)->mode = mode;	(*pFile)->mountPoint = mountPoint;    }    return rc;}/* * Adapter for Open(). */static int Do_Open_File(struct Mount_Point *mountPoint, const char *path, int mode, struct File **pFile){    KASSERT(mountPoint->ops->Open != 0); /* All filesystems must implement Open(). */    return mountPoint->ops->Open(mountPoint, path, mode, pFile);}/* * Adapter for Open_Directory(). */static int Do_Open_Directory(struct Mount_Point *mountPoint, const char *path, int mode, struct File **pDir){    KASSERT(mountPoint->ops->Open_Directory != 0); /* All filesystems must implement Open_Directory(). */    return mountPoint->ops->Open_Directory(mountPoint, path, pDir);}/* ---------------------------------------------------------------------- * Public functions * ---------------------------------------------------------------------- *//* * Register a filesystem. * This should only be called from Main(), before * any processes are started. * Params: *   fsName - name of the filesystem type, e.g. "pfat", "gosfs" *   fsOps - the Filesystem_Ops for the filesystem * Returns true if successful, false if not. */bool Register_Filesystem(const char *fsName, struct Filesystem_Ops *fsOps){    struct Filesystem *fs;    KASSERT(fsName != 0);    KASSERT(fsOps != 0);    KASSERT(fsOps->Mount != 0);    Debug("Registering %s filesystem type\n", fsName);    /* Allocate Filesystem struct */    fs = (struct Filesystem*) Malloc(sizeof(*fs));    if (fs == 0)	return false;    /* Copy filesystem name and vtable. */    fs->ops = fsOps;    strncpy(fs->fsName, fsName, VFS_MAX_FS_NAME_LEN);    fs->fsName[VFS_MAX_FS_NAME_LEN] = '\0';    /* Add the filesystem to the list */    Mutex_Lock(&s_vfsLock);    Add_To_Back_Of_Filesystem_List(&s_filesystemList, fs);    Mutex_Unlock(&s_vfsLock);    return true;}/* * Format a block device using given filesystem type. * Params: *   devname - name of block device to format *   fstype - fstype, e.g. "pfat", "gosfs" * Returns: 0 if successful, error code (< 0) if not */int Format(const char *devname, const char *fstype){    struct Filesystem *fs;    struct Block_Device *dev = 0;    int rc;    /* Find the named filesystem type */    fs = Lookup_Filesystem(fstype);    if (fs == 0)	return ENOFILESYS;    Debug("Found %s filesystem type\n", fstype);    /* The Format() operation is optional. */    if (fs->ops->Format == 0)	return EUNSUPPORTED;    /* Attempt to open the block device */    if ((rc = Open_Block_Device(devname, &dev)) < 0)	return rc;    Debug("Opened device %s\n", dev->name);    /* Dispatch to fs Format() function. */    rc = fs->ops->Format(dev);    Close_Block_Device(dev);    return rc;}/* * Mount a filesystem on a block device. * Params: *   devname - block device name containing filesystem image *   pathPrefix - where to mount the filesystem in the overall namespace *   fstype - filesystem type, e.g. "pfat", "gosfs" * Returns: 0 if successful, error code (< 0) if not */int Mount(const char *devname, const char *pathPrefix, const char *fstype){    struct Filesystem *fs;    struct Block_Device *dev = 0;    struct Mount_Point *mountPoint = 0;    int rc;    /* Skip leading slash character(s) */    while (*pathPrefix == '/')	++pathPrefix;    if (strlen(pathPrefix) > MAX_PREFIX_LEN)	return ENAMETOOLONG;    /* Find the named filesystem type */    fs = Lookup_Filesystem(fstype);    if (fs == 0)	return ENOFILESYS;    KASSERT(fs->ops->Mount != 0); /* All filesystems must implement Mount(). */    /* Attempt to open the block device */    if ((rc = Open_Block_Device(devname, &dev)) < 0)	return rc;    /* Create Mount_Point structure. */    mountPoint = (struct Mount_Point*) Malloc(sizeof(*mountPoint));    if (mountPoint == 0)	goto memfail;    memset(mountPoint, '\0', sizeof(*mountPoint));    mountPoint->dev = dev;    mountPoint->pathPrefix = strdup(pathPrefix);    if (mountPoint->pathPrefix == 0)	goto memfail;    Debug("Mounting %s on %s using %s fs\n", devname, pathPrefix, fstype);    /* Call the filesystem mount function. */    if ((rc = fs->ops->Mount(mountPoint)) < 0)	goto fail;    Debug("Mount succeeded!\n");    /*     * Add filesystem to mount point list.     * It is now ready to receive requests.     * FIXME: should ensure that there aren't any filesystems     * mounted on the same filesystem root.     */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -