From 43f03e44dd49fe6a4fd8e3615a707432a14d392c Mon Sep 17 00:00:00 2001 From: Enrico Fraccaroli Date: Tue, 21 Dec 2021 15:10:59 +0100 Subject: [PATCH] Implement file unlinking. --- mentos/src/fs/ext2.c | 524 ++++++++++++++++++++++++++++------------- mentos/src/fs/procfs.c | 23 +- 2 files changed, 370 insertions(+), 177 deletions(-) diff --git a/mentos/src/fs/ext2.c b/mentos/src/fs/ext2.c index 94654ca..c84216e 100644 --- a/mentos/src/fs/ext2.c +++ b/mentos/src/fs/ext2.c @@ -344,6 +344,17 @@ typedef struct ext2_filesystem_t { spinlock_t spinlock; } ext2_filesystem_t; +typedef struct ext2_direntry_search_t { + /// + ext2_dirent_t *direntry; + /// + ino_t parent_inode; + /// + uint32_t block_index; + /// + uint32_t dir_offset; +} ext2_direntry_search_t; + // ============================================================================ // Forward Declaration of Functions // ============================================================================ @@ -360,13 +371,19 @@ static int ext2_read_inode(ext2_filesystem_t *fs, ext2_inode_t *inode, uint32_t static int ext2_write_inode(ext2_filesystem_t *fs, ext2_inode_t *inode, uint32_t inode_index); static vfs_file_t *ext2_open(const char *path, int flags, mode_t mode); +static int ext2_unlink(const char *path); static int ext2_close(vfs_file_t *file); -static int ext2_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, size_t count); static ssize_t ext2_read(vfs_file_t *file, char *buffer, off_t offset, size_t nbyte); static ssize_t ext2_write(vfs_file_t *file, const void *buffer, off_t offset, size_t nbyte); static off_t ext2_lseek(vfs_file_t *file, off_t offset, int whence); static int ext2_fstat(vfs_file_t *file, stat_t *stat); +static int ext2_ioctl(vfs_file_t *file, int request, void *data); +static int ext2_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, size_t count); + +static int ext2_mkdir(const char *path, mode_t mode); +static int ext2_rmdir(const char *path); static int ext2_stat(const char *path, stat_t *stat); + static vfs_file_t *ext2_mount(vfs_file_t *block_device, const char *path); // ============================================================================ @@ -375,21 +392,21 @@ static vfs_file_t *ext2_mount(vfs_file_t *block_device, const char *path); /// Filesystem general operations. static vfs_sys_operations_t ext2_sys_operations = { - .mkdir_f = NULL, - .rmdir_f = NULL, + .mkdir_f = ext2_mkdir, + .rmdir_f = ext2_rmdir, .stat_f = ext2_stat }; /// Filesystem file operations. static vfs_file_operations_t ext2_fs_operations = { .open_f = ext2_open, - .unlink_f = NULL, + .unlink_f = ext2_unlink, .close_f = ext2_close, .read_f = ext2_read, .write_f = ext2_write, .lseek_f = ext2_lseek, .stat_f = ext2_fstat, - .ioctl_f = NULL, + .ioctl_f = ext2_ioctl, .getdents_f = ext2_getdents }; @@ -1337,15 +1354,34 @@ free_cache_return_error: /// @brief Finds the entry with the given `name` inside the `directory`. /// @param directory the directory in which we perform the search. /// @param name the name of the entry we are looking for. -/// @param direntry the output variable where we save the found entry. +/// @param search the output variable where we save the info about the entry. /// @return 0 on success, -1 on failure. -static int ext2_find_entry(ext2_filesystem_t *fs, ino_t ino, const char *name, ext2_dirent_t *direntry) +static int ext2_find_entry( + ext2_filesystem_t *fs, + ino_t ino, + const char *name, + ext2_direntry_search_t *search) { + if (fs == NULL) { + pr_err("You provided a NULL filesystem.\n"); + return -1; + } + if (name == NULL) { + pr_err("You provided a NULL name.\n"); + return -1; + } + if (search == NULL) { + pr_err("You provided a NULL search.\n"); + return -1; + } + if (search->direntry == NULL) { + pr_err("You provided a NULL direntry.\n"); + return -1; + } // Allocate the cache. uint8_t *cache = kmem_cache_alloc(fs->ext2_buffer_cache, GFP_KERNEL); // Clean the cache. memset(cache, 0, fs->block_size); - // Get the inode associated with the file. ext2_inode_t inode; if (ext2_read_inode(fs, &inode, ino) == -1) { @@ -1390,7 +1426,14 @@ static int ext2_find_entry(ext2_filesystem_t *fs, ino_t ino, const char *name, e } if (entry == NULL) goto free_cache_return_error; - memcpy(direntry, entry, sizeof(ext2_dirent_t)); + // Copy the direntry. + memcpy(search->direntry, entry, sizeof(ext2_dirent_t)); + // Copy the index of the block containing the direntry. + search->block_index = block_index; + // Copy the offset of the direntry inside the block. + search->dir_offset = dir_offset; + // Copy the inode of the parent. + search->parent_inode = ino; // Free the cache. kmem_cache_free(cache); return 0; @@ -1400,14 +1443,62 @@ free_cache_return_error: return -1; } +/// @brief Searches the entry specified in `path` starting from `directory`. +/// @param directory the directory from which we start performing the search. +/// @param path the path of the entry we are looking for, it cna be a relative path. +/// @param search the output variable where we save the entry information. +/// @return 0 on success, -1 on failure. +static int ext2_resolve_path(vfs_file_t *directory, char *path, ext2_direntry_search_t *search) +{ + pr_debug("ext2_resolve_path(%s, %s, %p)\n", directory->name, path, search); + // Check the pointers. + if (directory == NULL) { + pr_err("You provided a NULL directory.\n"); + return -1; + } + if (path == NULL) { + pr_err("You provided a NULL path.\n"); + return -1; + } + if (search == NULL) { + pr_err("You provided a NULL search.\n"); + return -1; + } + if (search->direntry == NULL) { + pr_err("You provided a NULL direntry.\n"); + return -1; + } + // Get the filesystem. + ext2_filesystem_t *fs = (ext2_filesystem_t *)directory->device; + if (fs == NULL) { + pr_err("The file does not belong to an EXT2 filesystem `%s`.\n", directory->name); + return -1; + } + // If the path is `/`. + if (strcmp(path, "/") == 0) + return ext2_find_entry(fs, directory->ino, path, search); + ino_t ino = directory->ino; + char *token = strtok(path, "/"); + while (token) { + if (!ext2_find_entry(fs, ino, token, search)) { + ino = search->direntry->inode; + } else { + memset(search->direntry, 0, sizeof(ext2_dirent_t)); + return -1; + } + token = strtok(NULL, "/"); + } + return 0; +} + /// @brief Searches the entry specified in `path` starting from `directory`. /// @param directory the directory from which we start performing the search. /// @param path the path of the entry we are looking for, it cna be a relative path. /// @param direntry the output variable where we save the found entry. /// @return 0 on success, -1 on failure. -static int ext2_resolve_path(vfs_file_t *directory, char *path, ext2_dirent_t *direntry) +static int ext2_resolve_path_direntry(vfs_file_t *directory, char *path, ext2_dirent_t *direntry) { - pr_debug("ext2_resolve_path(%s, %s, %p)\n", directory->name, path, direntry); + pr_debug("ext2_resolve_path_direntry(%s, %s, %p)\n", directory->name, path, direntry); // Check the pointers. if (directory == NULL) { pr_err("You provided a NULL directory.\n"); @@ -1421,28 +1512,52 @@ static int ext2_resolve_path(vfs_file_t *directory, char *path, ext2_dirent_t *d pr_err("You provided a NULL direntry.\n"); return -1; } + // Prepare the structure for the search. + ext2_direntry_search_t search; + memset(&search, 0, sizeof(ext2_direntry_search_t)); + // Initialize the search structure. + search.direntry = direntry; + search.block_index = 0; + search.dir_offset = 0; + return ext2_resolve_path(directory, path, &search); +} + +/// @brief Get the ext2 filesystem object starting from a path. +/// @param absolute_path the absolute path for which we want to find the associated EXT2 filesystem. +/// @return a pointer to the EXT2 filesystem, NULL otherwise. +static ext2_filesystem_t *get_ext2_filesystem(const char *absolute_path) +{ + pr_debug("get_ext2_filesystem(%s)\n", path); + if (absolute_path == NULL) { + pr_err("We received a NULL absolute path.\n"); + return NULL; + } + if (absolute_path[0] != '/') { + pr_err("We did not received an absolute path `%s`.\n", absolute_path); + return NULL; + } + super_block_t *sb = vfs_get_superblock(absolute_path); + if (sb == NULL) { + pr_err("Cannot find the superblock for the absolute path `%s`.\n", absolute_path); + return NULL; + } + vfs_file_t *sb_root = sb->root; + if (sb_root == NULL) { + pr_err("Cannot find the superblock root for the absolute path `%s`.\n", absolute_path); + return NULL; + } // Get the filesystem. - ext2_filesystem_t *fs = (ext2_filesystem_t *)directory->device; + ext2_filesystem_t *fs = (ext2_filesystem_t *)sb_root->device; if (fs == NULL) { - pr_err("The file does not belong to an EXT2 filesystem `%s`.\n", directory->name); - return -1; + pr_err("The file does not belong to an EXT2 filesystem `%s`.\n", sb_root->name); + return NULL; } - if (strcmp(path, "/") == 0) { - ext2_find_entry(fs, directory->ino, path, direntry); - return 0; + // Check the magic number. + if (fs->superblock.magic != EXT2_SUPERBLOCK_MAGIC) { + pr_err("The file does not belong to an EXT2 filesystem `%s`.\n", sb_root->name); + return NULL; } - ino_t ino = directory->ino; - char *token = strtok(path, "/"); - while (token) { - if (!ext2_find_entry(fs, ino, token, direntry)) { - ino = direntry->inode; - } else { - memset(direntry, 0, sizeof(ext2_dirent_t)); - return -1; - } - token = strtok(NULL, "/"); - } - return 0; + return fs; } /// @brief Sets the filesystem root. @@ -1552,43 +1667,31 @@ static int ext2_init_file(ext2_filesystem_t *fs, ext2_inode_t *inode, ext2_diren static vfs_file_t *ext2_open(const char *path, int flags, mode_t mode) { pr_debug("ext2_open(%s, %d, %d)\n", path, flags, mode); - // Allocate a variable for the path. + // Get the absolute path. char absolute_path[PATH_MAX]; // If the first character is not the '/' then get the absolute path. if (!realpath(path, absolute_path)) { - pr_err("ext2_open(%s): Cannot get the absolute path.\n", path); + pr_err("Cannot get the absolute path for path `%s`.\n", path); return NULL; } - super_block_t *sb = vfs_get_superblock(absolute_path); - if (sb == NULL) { - pr_err("ext2_open(%s): Cannot find the superblock!\n", path); - return NULL; - } - vfs_file_t *sb_root = sb->root; - if (sb_root == NULL) { - pr_err("ext2_open(%s): Cannot find the superblock root.\n", path); - return NULL; - } - // Get the filesystem. - ext2_filesystem_t *fs = (ext2_filesystem_t *)sb_root->device; + // Get the EXT2 filesystem. + ext2_filesystem_t *fs = get_ext2_filesystem(absolute_path); if (fs == NULL) { - pr_err("ext2_open(%s): The file does not belong to an EXT2 filesystem `%s`.\n", path, sb_root->name); - return NULL; - } - if (fs->superblock.magic != EXT2_SUPERBLOCK_MAGIC) { - pr_err("ext2_open(%s): The file does not belong to an EXT2 filesystem `%s`.\n", path, sb_root->name); + pr_err("Failed to get the EXT2 filesystem for absolute path `%s`.\n", absolute_path); return NULL; } + // Prepare the structure for the direntry. ext2_dirent_t direntry; memset(&direntry, 0, sizeof(ext2_dirent_t)); - if (ext2_resolve_path(sb_root, absolute_path, &direntry) == -1) { - pr_err("ext2_open(%s): Failed to find path `%s`.\n", path, absolute_path); + // Resolve the path. + if (ext2_resolve_path_direntry(fs->root, absolute_path, &direntry) == -1) { + pr_err("Failed to resolve absolute path `%s`.\n", absolute_path); return NULL; } // Get the inode associated with the directory entry. ext2_inode_t inode; if (ext2_read_inode(fs, &inode, direntry.inode) == -1) { - pr_err("ext2_open(%s): Failed to read the inode of `%s`.\n", path, direntry.name); + pr_err("Failed to read the inode of `%s`.\n", direntry.name); return NULL; } vfs_file_t *file = NULL; @@ -1607,11 +1710,11 @@ static vfs_file_t *ext2_open(const char *path, int flags, mode_t mode) // Allocate the memory for the file. file = kmem_cache_alloc(vfs_file_cache, GFP_KERNEL); if (file == NULL) { - pr_err("ext2_open(%s): Failed to allocate memory for the EXT2 file!\n", path); + pr_err("Failed to allocate memory for the EXT2 file.\n"); return NULL; } if (ext2_init_file(fs, &inode, &direntry, file) == -1) { - pr_err("ext2_open(%s): Failed to properly set the VFS file.\n", path); + pr_err("Failed to properly set the VFS file.\n"); return NULL; } // Add the vfs_file to the list of associated files. @@ -1620,6 +1723,94 @@ static vfs_file_t *ext2_open(const char *path, int flags, mode_t mode) return file; } +static int ext2_unlink(const char *path) +{ + pr_debug("ext2_unlink(%s)\n", path); + // Get the absolute path. + char absolute_path[PATH_MAX]; + // If the first character is not the '/' then get the absolute path. + if (!realpath(path, absolute_path)) { + pr_err("Cannot get the absolute path for path `%s`.\n", path); + return -ENOENT; + } + // Get the name of the entry we want to unlink. + char *name = basename(absolute_path); + if (name == NULL) { + pr_err("Cannot get the basename from the absolute path `%s`.\n", absolute_path); + return -ENOENT; + } + // Get the EXT2 filesystem. + ext2_filesystem_t *fs = get_ext2_filesystem(absolute_path); + if (fs == NULL) { + pr_err("Failed to get the EXT2 filesystem for absolute path `%s`.\n", absolute_path); + return -ENOENT; + } + // Prepare the structure for the direntry. + ext2_dirent_t direntry; + memset(&direntry, 0, sizeof(ext2_dirent_t)); + // Prepare the structure for the search. + ext2_direntry_search_t search; + memset(&search, 0, sizeof(ext2_direntry_search_t)); + // Initialize the search structure. + search.direntry = &direntry; + search.block_index = 0; + search.dir_offset = 0; + search.parent_inode = 0; + // Resolve the path to the directory entry. + if (ext2_resolve_path(fs->root, absolute_path, &search)) { + pr_err("Failed to resolve path `%s`.\n", absolute_path); + return -ENOENT; + } + // Get the inode associated with the parent directory entry. + ext2_inode_t parent_inode; + if (ext2_read_inode(fs, &parent_inode, search.parent_inode) == -1) { + pr_err("ext2_stat(%s): Failed to read the inode of parent of `%s`.\n", path, direntry.name); + return -ENOENT; + } + // Allocate the cache and clean it. + uint8_t *cache = kmem_cache_alloc(fs->ext2_buffer_cache, GFP_KERNEL); + memset(cache, 0, fs->block_size); + // Read the block where the direntry resides. + if (!ext2_read_inode_block(fs, &parent_inode, search.block_index, cache)) { + pr_err("Failed to read the parent inode block `%d`\n", search.block_index); + goto free_cache_return_error; + } + // Get a pointer to the direntry. + ext2_dirent_t *actual_dirent = (ext2_dirent_t *)((uintptr_t)cache + search.dir_offset); + if (actual_dirent == NULL) { + pr_err("We found a NULL ext2_dirent_t\n"); + goto free_cache_return_error; + } + // Set the inode to zero. + actual_dirent->inode = 0; + // Write back the parent directory block. + if (!ext2_write_inode_block(fs, &parent_inode, search.parent_inode, search.block_index, cache)) { + pr_err("Failed to write the inode block `%d`\n", search.block_index); + goto free_cache_return_error; + } + // Read the inode of the actual direntry. + ext2_inode_t inode; + if (ext2_read_inode(fs, &inode, direntry.inode) == -1) { + pr_err("Failed to read the inode of `%s`.\n", direntry.name); + goto free_cache_return_error; + } + if (inode.links_count > 0) { + inode.links_count--; + // Update the inode. + if (ext2_write_inode(fs, &inode, direntry.inode) == -1) { + pr_err("Failed to update the inode of `%s`.\n", direntry.name); + goto free_cache_return_error; + } + } + // Free the cache. + kmem_cache_free(cache); + return 0; +free_cache_return_error: + // Free the cache. + kmem_cache_free(cache); + return -1; +} + /// @brief Closes the given file. /// @param file The file structure. static int ext2_close(vfs_file_t *file) @@ -1642,98 +1833,6 @@ static int ext2_close(vfs_file_t *file) return 0; } -/// @brief Reads contents of the directories to a dirent buffer, updating -/// the offset and returning the number of written bytes in the buffer, -/// it assumes that all paths are well-formed. -/// @param file The directory handler. -/// @param dirp The buffer where the data should be written. -/// @param doff The offset inside the buffer where the data should be written. -/// @param count The maximum length of the buffer. -/// @return The number of written bytes in the buffer. -static int ext2_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, size_t count) -{ - pr_debug("ext2_getdents(%s, %p, %d, %d)\n", file->name, dirp, doff, count); - // Get the filesystem. - ext2_filesystem_t *fs = (ext2_filesystem_t *)file->device; - if (fs == NULL) { - pr_err("The file does not belong to an EXT2 filesystem `%s`.\n", file->name); - return -1; - } - // Get the inode associated with the file. - ext2_inode_t inode; - if (ext2_read_inode(fs, &inode, file->ino) == -1) { - pr_err("Failed to read the inode (%d).\n", file->ino); - return -1; - } - - uint32_t block_index = 0, dir_offset = 0, total_offset = 0, written = 0; - off_t current = 0; - ext2_dirent_t *direntry = NULL; - // Allocate the cache. - uint8_t *cache = kmem_cache_alloc(fs->ext2_buffer_cache, GFP_KERNEL); - // Clean the cache. - memset(cache, 0, fs->block_size); - - // Start by reading the first block of the inode. - if (!ext2_read_inode_block(fs, &inode, block_index, cache)) { - pr_err("Failed to read the inode block `%d`\n", block_index); - goto free_cache_return_error; - } - - // Keep reading until we searched the whole inode. - while ((total_offset < inode.size) && (written < count)) { - // If we exceed the size of a block, move to the next block. - if (dir_offset >= fs->block_size) { - // Increase the block index. - ++block_index; - // Remove the exceeding size, so that we start correctly in the new block. - dir_offset -= fs->block_size; - // Read the new block. - if (!ext2_read_inode_block(fs, &inode, block_index, cache)) { - pr_err("Failed to read the inode block `%d`\n", block_index); - goto free_cache_return_error; - } - } - // Get the directory entry. - direntry = (ext2_dirent_t *)((uintptr_t)cache + dir_offset); - if (direntry == NULL) { - pr_err("We found a NULL ext2_dirent_t\n"); - goto free_cache_return_error; - } - - // Advance the offsets. - dir_offset += direntry->rec_len; - total_offset += direntry->rec_len; - - // Skip if already provided. - current += sizeof(dirent_t); - if (current <= doff) { - continue; - } - - // Write on current directory entry data. - dirp->d_ino = direntry->inode; - dirp->d_type = ext2_file_type_to_vfs_file_type(direntry->file_type); - memset(dirp->d_name, 0, NAME_MAX); - strncpy(dirp->d_name, direntry->name, direntry->name_len); - dirp->d_off = direntry->rec_len; - dirp->d_reclen = direntry->rec_len; - - // Increment the amount written. - written += sizeof(dirent_t); - - // Move to next writing position. - ++dirp; - } - // Free the cache. - kmem_cache_free(cache); - return written; -free_cache_return_error: - // Free the cache. - kmem_cache_free(cache); - return -1; -} - /// @brief Reads from the file identified by the file descriptor. /// @param file The file. /// @param buffer Buffer where the read content must be placed. @@ -1870,6 +1969,113 @@ static int ext2_fstat(vfs_file_t *file, stat_t *stat) return __ext2_stat(&inode, stat); } +static int ext2_ioctl(vfs_file_t *file, int request, void *data) +{ + return -1; +} + +/// @brief Reads contents of the directories to a dirent buffer, updating +/// the offset and returning the number of written bytes in the buffer, +/// it assumes that all paths are well-formed. +/// @param file The directory handler. +/// @param dirp The buffer where the data should be written. +/// @param doff The offset inside the buffer where the data should be written. +/// @param count The maximum length of the buffer. +/// @return The number of written bytes in the buffer. +static int ext2_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, size_t count) +{ + pr_debug("ext2_getdents(%s, %p, %d, %d)\n", file->name, dirp, doff, count); + // Get the filesystem. + ext2_filesystem_t *fs = (ext2_filesystem_t *)file->device; + if (fs == NULL) { + pr_err("The file does not belong to an EXT2 filesystem `%s`.\n", file->name); + return -ENOENT; + } + // Get the inode associated with the file. + ext2_inode_t inode; + if (ext2_read_inode(fs, &inode, file->ino) == -1) { + pr_err("Failed to read the inode (%d).\n", file->ino); + return -ENOENT; + } + + uint32_t block_index = 0, dir_offset = 0, total_offset = 0, written = 0; + off_t current = 0; + ext2_dirent_t *direntry = NULL; + // Allocate the cache. + uint8_t *cache = kmem_cache_alloc(fs->ext2_buffer_cache, GFP_KERNEL); + // Clean the cache. + memset(cache, 0, fs->block_size); + + // Start by reading the first block of the inode. + if (!ext2_read_inode_block(fs, &inode, block_index, cache)) { + pr_err("Failed to read the inode block `%d`\n", block_index); + goto free_cache_return_error; + } + + // Keep reading until we searched the whole inode. + while ((total_offset < inode.size) && (written < count)) { + // If we exceed the size of a block, move to the next block. + if (dir_offset >= fs->block_size) { + // Increase the block index. + ++block_index; + // Remove the exceeding size, so that we start correctly in the new block. + dir_offset -= fs->block_size; + // Read the new block. + if (!ext2_read_inode_block(fs, &inode, block_index, cache)) { + pr_err("Failed to read the inode block `%d`\n", block_index); + goto free_cache_return_error; + } + } + // Get the directory entry. + direntry = (ext2_dirent_t *)((uintptr_t)cache + dir_offset); + if (direntry == NULL) { + pr_err("We found a NULL ext2_dirent_t\n"); + goto free_cache_return_error; + } + + // Advance the offsets. + dir_offset += direntry->rec_len; + total_offset += direntry->rec_len; + + // Skip if already provided. + current += sizeof(dirent_t); + if (current <= doff) { + continue; + } + + // Write on current directory entry data. + dirp->d_ino = direntry->inode; + dirp->d_type = ext2_file_type_to_vfs_file_type(direntry->file_type); + memset(dirp->d_name, 0, NAME_MAX); + strncpy(dirp->d_name, direntry->name, direntry->name_len); + dirp->d_off = direntry->rec_len; + dirp->d_reclen = direntry->rec_len; + + // Increment the amount written. + written += sizeof(dirent_t); + + // Move to next writing position. + ++dirp; + } + // Free the cache. + kmem_cache_free(cache); + return written; +free_cache_return_error: + // Free the cache. + kmem_cache_free(cache); + return -1; +} + +static int ext2_mkdir(const char *path, mode_t mode) +{ + return -1; +} + +static int ext2_rmdir(const char *path) +{ + return -1; +} + /// @brief Retrieves information concerning the file at the given position. /// @param path The path where the file resides. /// @param stat The structure where the information are stored. @@ -1877,33 +2083,25 @@ static int ext2_fstat(vfs_file_t *file, stat_t *stat) static int ext2_stat(const char *path, stat_t *stat) { pr_debug("ext2_stat(%s, %p)\n", path, stat); - // Allocate a variable for the path. + // Get the absolute path. char absolute_path[PATH_MAX]; // If the first character is not the '/' then get the absolute path. if (!realpath(path, absolute_path)) { - pr_err("ext2_stat(%s): Cannot get the absolute path.", path); - return -ENODEV; - } - super_block_t *sb = vfs_get_superblock(absolute_path); - if (sb == NULL) { - pr_err("ext2_stat(%s): Cannot find the superblock!\n", path); - return -ENODEV; - } - vfs_file_t *sb_root = sb->root; - if (sb_root == NULL) { - pr_err("ext2_stat(%s): Cannot find the superblock root.", path); + pr_err("Cannot get the absolute path for path `%s`.\n", path); return -ENOENT; } - // Get the filesystem. - ext2_filesystem_t *fs = (ext2_filesystem_t *)sb_root->device; + // Get the EXT2 filesystem. + ext2_filesystem_t *fs = get_ext2_filesystem(absolute_path); if (fs == NULL) { - pr_err("ext2_stat(%s): The file does not belong to an EXT2 filesystem `%s`.\n", path, sb_root->name); - return -EPERM; + pr_err("Failed to get the EXT2 filesystem for absolute path `%s`.\n", absolute_path); + return -ENOENT; } + // Prepare the structure for the direntry. ext2_dirent_t direntry; memset(&direntry, 0, sizeof(ext2_dirent_t)); - if (ext2_resolve_path(sb_root, absolute_path, &direntry)) { - pr_err("ext2_stat(%s): Failed to find path `%s`.\n", path, absolute_path); + // Resolve the path. + if (ext2_resolve_path_direntry(fs->root, absolute_path, &direntry)) { + pr_err("Failed to resolve path `%s`.\n", absolute_path); return -ENOENT; } // Get the inode associated with the directory entry. diff --git a/mentos/src/fs/procfs.c b/mentos/src/fs/procfs.c index 4d2a546..1330895 100644 --- a/mentos/src/fs/procfs.c +++ b/mentos/src/fs/procfs.c @@ -71,7 +71,7 @@ typedef struct procfs_t { /// List of headers. list_head files; /// Cache for creating new `procfs_file_t`. - kmem_cache_t *procfs_cache; + kmem_cache_t *procfs_file_cache; } procfs_t; procfs_t fs; @@ -233,7 +233,7 @@ static inline int procfs_check_if_empty(const char *path) /// @return a pointer to the new PROCFS file, NULL otherwise. static inline procfs_file_t *procfs_create_file(const char *path, unsigned flags) { - procfs_file_t *procfs_file = (procfs_file_t *)kmem_cache_alloc(fs.procfs_cache, GFP_KERNEL); + procfs_file_t *procfs_file = (procfs_file_t *)kmem_cache_alloc(fs.procfs_file_cache, GFP_KERNEL); if (!procfs_file) { pr_err("Failed to get free entry (%p).\n", procfs_file); return NULL; @@ -336,17 +336,6 @@ static void dump_procfs() } } -/// @brief Initializes the procfs. -static void procfs_init() -{ - // Initialize the procfs. - memset(&fs, 0, sizeof(struct procfs_t)); - // Initialize the cache. - fs.procfs_cache = KMEM_CREATE(procfs_file_t); - // Initialize the list of procfs files. - list_head_init(&fs.files); -} - // ============================================================================ // Virtual FileSystem (VFS) Functions // ============================================================================ @@ -804,7 +793,11 @@ static file_system_type procfs_file_system_type = { int procfs_module_init() { // Initialize the procfs. - procfs_init(); + memset(&fs, 0, sizeof(struct procfs_t)); + // Initialize the cache. + fs.procfs_file_cache = KMEM_CREATE(procfs_file_t); + // Initialize the list of procfs files. + list_head_init(&fs.files); // Register the filesystem. vfs_register_filesystem(&procfs_file_system_type); return 0; @@ -812,6 +805,8 @@ int procfs_module_init() int procfs_cleanup_module() { + // Destroy the cache. + kmem_cache_destroy(fs.procfs_file_cache); // Unregister the filesystem. vfs_register_filesystem(&procfs_file_system_type); return 0;