From a9fa9b765df38cc5319ae734b5148fd47ebbfd8d Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Thu, 18 Feb 2010 00:24:25 +0000 Subject: 2010-02-18 Chris Johns * libfs/src/rfs/rtems-rfs-bitmaps.c, libfs/src/rfs/rtems-rfs-bitmaps.h, libfs/src/rfs/rtems-rfs-bitmaps-ut.c, libfs/src/rfs/rtems-rfs-block.c, libfs/src/rfs/rtems-rfs-block.h, libfs/src/rfs/rtems-rfs-block-pos.h, libfs/src/rfs/rtems-rfs-buffer-bdbuf.c, libfs/src/rfs/rtems-rfs-buffer.c, libfs/src/rfs/rtems-rfs-buffer-devio.c, libfs/src/rfs/rtems-rfs-buffer.h, libfs/src/rfs/rtems-rfs-data.h, libfs/src/rfs/rtems-rfs-dir.c, libfs/src/rfs/rtems-rfs-dir.h, libfs/src/rfs/rtems-rfs-dir-hash.c, libfs/src/rfs/rtems-rfs-dir-hash.h, libfs/src/rfs/rtems-rfs-file.c, libfs/src/rfs/rtems-rfs-file.h, libfs/src/rfs/rtems-rfs-file-system.c, libfs/src/rfs/rtems-rfs-file-system-fwd.h, libfs/src/rfs/rtems-rfs-file-system.h, libfs/src/rfs/rtems-rfs-format.c, libfs/src/rfs/rtems-rfs-format.h, libfs/src/rfs/rtems-rfs-group.c, libfs/src/rfs/rtems-rfs-group.h, libfs/src/rfs/rtems-rfs.h, libfs/src/rfs/rtems-rfs-inode.c, libfs/src/rfs/rtems-rfs-inode.h, libfs/src/rfs/rtems-rfs-link.c, libfs/src/rfs/rtems-rfs-link.h, libfs/src/rfs/rtems-rfs-mutex.c, libfs/src/rfs/rtems-rfs-mutex.h, libfs/src/rfs/rtems-rfs-rtems.c, libfs/src/rfs/rtems-rfs-rtems-dev.c, libfs/src/rfs/rtems-rfs-rtems-dir.c, libfs/src/rfs/rtems-rfs-rtems-file.c, libfs/src/rfs/rtems-rfs-rtems.h, libfs/src/rfs/rtems-rfs-rtems-utils.c, libfs/src/rfs/rtems-rfs-shell.c, libfs/src/rfs/rtems-rfs-shell.h, libfs/src/rfs/rtems-rfs-trace.c, libfs/src/rfs/rtems-rfs-trace.h: New. * Makefile.am, preinstall.am, libfs/Makefile.am, wrapup/Makefile.am: Updated with the RFS support. * libfs/README: Updated after 10 years. * libblock/src/flashdisk.c, libblock/src/nvdisk.c, libblock/src/ramdisk-driver.c: Updated to the new error reporting in libblock. * libmisc/shell/main_ls.c, libmisc/shell/print-ls.c: Fix printing the size in long mode. * libnetworking/nfs/bootp_subr.c, libnetworking/rtems/rtems_bootp.c, libnetworking/rtems/rtems_bsdnet_internal.h: Return the BOOTP/DHCP to the forever behaviour of 4.9 with the ability to call BOOTP and control the process if required. --- cpukit/libfs/src/rfs/rtems-rfs-inode.c | 370 +++++++++++++++++++++++++++++++++ 1 file changed, 370 insertions(+) create mode 100644 cpukit/libfs/src/rfs/rtems-rfs-inode.c (limited to 'cpukit/libfs/src/rfs/rtems-rfs-inode.c') diff --git a/cpukit/libfs/src/rfs/rtems-rfs-inode.c b/cpukit/libfs/src/rfs/rtems-rfs-inode.c new file mode 100644 index 0000000000..b23f09994d --- /dev/null +++ b/cpukit/libfs/src/rfs/rtems-rfs-inode.c @@ -0,0 +1,370 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems-rfs + * + * RTEMS File Systems Inode Routines. + * + * These functions manage inodes in the RFS file system. An inode is part of a + * block that reside after the bitmaps in the group. + */ + +#include +#include +#include +#include + +int +rtems_rfs_inode_alloc (rtems_rfs_file_system* fs, + rtems_rfs_bitmap_bit goal, + rtems_rfs_ino* ino) +{ + rtems_rfs_bitmap_bit bit; + int rc; + rc = rtems_rfs_group_bitmap_alloc (fs, goal, true, &bit); + *ino = bit; + return rc; +} + +int +rtems_rfs_inode_free (rtems_rfs_file_system* fs, + rtems_rfs_ino ino) +{ + rtems_rfs_bitmap_bit bit; + bit = ino; + return rtems_rfs_group_bitmap_free (fs, true, bit); +} + +int +rtems_rfs_inode_open (rtems_rfs_file_system* fs, + rtems_rfs_ino ino, + rtems_rfs_inode_handle* handle, + bool load) +{ + int group; + int gino; + int index; + int rc; + + if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_OPEN)) + printf ("rtems-rfs: inode-open: ino: %lu\n", ino); + + if (ino == RTEMS_RFS_EMPTY_INO) + return EINVAL; + + if ((ino - RTEMS_RFS_ROOT_INO) > rtems_rfs_fs_inodes (fs)) + return EINVAL; + + handle->ino = ino; + handle->node = NULL; + handle->loads = 0; + + gino = ino - RTEMS_RFS_ROOT_INO; + group = gino / fs->group_inodes; + gino = gino % fs->group_inodes; + index = (gino / fs->inodes_per_block) + RTEMS_RFS_GROUP_INODE_BLOCK; + + handle->offset = gino % fs->inodes_per_block; + handle->block = rtems_rfs_group_block (&fs->groups[group], index); + + rc = rtems_rfs_buffer_handle_open (fs, &handle->buffer); + if ((rc == 0) && load) + rc = rtems_rfs_inode_load (fs, handle); + return rc; +} + +int +rtems_rfs_inode_close (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* handle) +{ + int rc; + + if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_CLOSE)) + printf ("rtems-rfs: inode-close: ino: %lu\n", handle->ino); + + rc = rtems_rfs_inode_unload (fs, handle, true); + + if ((rc == 0) && (handle->loads > 0)) + { + if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_CLOSE)) + printf ("rtems-rfs: inode-close: bad loads number: %d\n", + handle->loads); + rc = EIO; + } + + handle->ino = 0; + return rc; +} + +int +rtems_rfs_inode_load (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* handle) +{ + if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_LOAD)) + printf ("rtems-rfs: inode-load: ino=%lu loads=%i loaded=%s\n", + handle->ino, handle->loads, + rtems_rfs_inode_is_loaded (handle) ? "yes" : "no"); + + /* + * An inode does not move so once loaded no need to do again. + */ + + if (!rtems_rfs_inode_is_loaded (handle)) + { + int rc; + + rc = rtems_rfs_buffer_handle_request (fs,&handle->buffer, + handle->block, true); + if (rc > 0) + return rc; + + handle->node = rtems_rfs_buffer_data (&handle->buffer); + handle->node += handle->offset; + } + + handle->loads++; + + return 0; +} + +int +rtems_rfs_inode_unload (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* handle, + bool update_ctime) +{ + int rc = 0; + + if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_UNLOAD)) + printf ("rtems-rfs: inode-unload: ino=%lu loads=%i loaded=%s\n", + handle->ino, handle->loads, + rtems_rfs_inode_is_loaded (handle) ? "yes" : "no"); + + if (rtems_rfs_inode_is_loaded (handle)) + { + if (handle->loads == 0) + return EIO; + + handle->loads--; + + if (handle->loads == 0) + { + /* + * If the buffer is dirty it will be release. Also set the ctime. + */ + if (rtems_rfs_buffer_dirty (&handle->buffer) && update_ctime) + rtems_rfs_inode_set_ctime (handle, time (NULL)); + rc = rtems_rfs_buffer_handle_release (fs, &handle->buffer); + handle->node = NULL; + } + } + + return rc; +} + +int +rtems_rfs_inode_create (rtems_rfs_file_system* fs, + rtems_rfs_ino parent, + const char* name, + size_t length, + uint16_t mode, + uint16_t links, + uid_t uid, + gid_t gid, + rtems_rfs_ino* ino) +{ + rtems_rfs_inode_handle parent_inode; + rtems_rfs_inode_handle inode; + int rc; + + if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_CREATE)) + { + const char* type = "unknown"; + int c; + if (RTEMS_RFS_S_ISDIR (mode)) + type = "dir"; + else if (RTEMS_RFS_S_ISCHR (mode)) + type = "char"; + else if (RTEMS_RFS_S_ISBLK (mode)) + type = "block"; + else if (RTEMS_RFS_S_ISREG (mode)) + type = "file"; + else if (RTEMS_RFS_S_ISLNK (mode)) + type = "link"; + printf("rtems-rfs: inode-create: parent:%lu name:", parent); + for (c = 0; c < length; c++) + printf ("%c", name[c]); + printf (" type:%s mode:%04x (%03o)\n", type, mode, mode & ((1 << 10) - 1)); + } + + rc = rtems_rfs_inode_alloc (fs, parent, ino); + if (rc > 0) + return rc; + + rc = rtems_rfs_inode_open (fs, *ino, &inode, true); + if (rc > 0) + return rc; + + rc = rtems_rfs_inode_initialise (&inode, links, mode, uid, gid); + if (rc > 0) + { + rtems_rfs_inode_close (fs, &inode); + rtems_rfs_inode_free (fs, *ino); + return rc; + } + + /* + * Only handle the specifics of a directory. Let caller handle the others. + */ + if (RTEMS_RFS_S_ISDIR (mode)) + { + rc = rtems_rfs_dir_add_entry (fs, &inode, ".", 1, *ino); + if (rc == 0) + rc = rtems_rfs_dir_add_entry (fs, &inode, "..", 2, parent); + if (rc > 0) + { + rtems_rfs_inode_delete (fs, &inode); + rtems_rfs_inode_close (fs, &inode); + return rc; + } + } + + rc = rtems_rfs_inode_open (fs, parent, &parent_inode, true); + if (rc > 0) + { + rtems_rfs_inode_delete (fs, &inode); + rtems_rfs_inode_close (fs, &inode); + return rc; + } + + rc = rtems_rfs_dir_add_entry (fs, &parent_inode, name, length, *ino); + if (rc > 0) + { + rtems_rfs_inode_delete (fs, &inode); + rtems_rfs_inode_close (fs, &inode); + rtems_rfs_inode_close (fs, &parent_inode); + return rc; + } + + /* + * If the node is a directory update the parent link count as the + * new directory has the '..' link that points to the parent. + */ + if (RTEMS_RFS_S_ISDIR (mode)) + rtems_rfs_inode_set_links (&parent_inode, + rtems_rfs_inode_get_links (&parent_inode) + 1); + + rc = rtems_rfs_inode_close (fs, &parent_inode); + if (rc > 0) + { + rtems_rfs_inode_delete (fs, &inode); + rtems_rfs_inode_close (fs, &inode); + return rc; + } + + rc = rtems_rfs_inode_close (fs, &inode); + if (rc > 0) + { + rtems_rfs_inode_free (fs, *ino); + return rc; + } + + return 0; +} + +int +rtems_rfs_inode_delete (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* handle) +{ + int rc = 0; + if (rtems_rfs_inode_is_loaded (handle)) + { + rtems_rfs_block_map map; + + /* + * Free the ino number. + */ + rc = rtems_rfs_inode_free (fs, handle->ino); + if (rc > 0) + return rc; + + /* + * Free the blocks the inode may have attached. + */ + rc = rtems_rfs_block_map_open (fs, handle, &map); + if (rc == 0) + { + int rrc; + rrc = rtems_rfs_block_map_free_all (fs, &map); + rc = rtems_rfs_block_map_close (fs, &map); + if (rc > 0) + rrc = rc; + memset (handle->node, 0xff, sizeof (rtems_rfs_inode)); + rtems_rfs_buffer_mark_dirty (&handle->buffer); + /* + * Do the release here to avoid the ctime field being set on a + * close. Also if there loads is greater then one then other loads + * active. Forcing the loads count to 0. + */ + rc = rtems_rfs_buffer_handle_release (fs, &handle->buffer); + handle->loads = 0; + handle->node = NULL; + } + } + return rc; +} + +int +rtems_rfs_inode_initialise (rtems_rfs_inode_handle* handle, + uint16_t links, + uint16_t mode, + uid_t uid, + gid_t gid) +{ + int b; + rtems_rfs_inode_set_links (handle, links); + rtems_rfs_inode_set_flags (handle, 0); + rtems_rfs_inode_set_mode (handle, mode); + rtems_rfs_inode_set_uid_gid (handle, uid, gid); + rtems_rfs_inode_set_block_offset (handle, 0); + rtems_rfs_inode_set_block_count (handle, 0); + for (b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++) + rtems_rfs_inode_set_block (handle, b, 0); + rtems_rfs_inode_set_last_map_block (handle, 0); + rtems_rfs_inode_set_last_data_block (handle, 0); + return rtems_rfs_inode_time_stamp_now (handle, true, true); +} + +int +rtems_rfs_inode_time_stamp_now (rtems_rfs_inode_handle* handle, + bool atime, + bool mtime) +{ + time_t now; + if (!rtems_rfs_inode_is_loaded (handle)) + return ENXIO; + now = time (NULL); + if (atime) + rtems_rfs_inode_set_atime (handle, now); + if (mtime) + rtems_rfs_inode_set_mtime (handle, now); + return 0; +} + +rtems_rfs_pos +rtems_rfs_inode_get_size (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* handle) +{ + rtems_rfs_block_size size; + size.count = rtems_rfs_inode_get_block_count (handle); + size.offset = rtems_rfs_inode_get_block_offset (handle); + return rtems_rfs_block_get_size (fs, &size); +} -- cgit v1.2.3