9
0
Fork 0

Setting up for mountpoint support

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@250 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2007-05-26 16:05:59 +00:00
parent 26d4a9f993
commit 36525d0171
9 changed files with 409 additions and 272 deletions

View File

@ -43,7 +43,7 @@ AOBJS = $(ASRCS:.S=$(OBJEXT))
CSRCS = fs_open.c fs_close.c fs_read.c fs_write.c fs_ioctl.c fs_dup.c \
fs_opendir.c fs_closedir.c fs_readdir.c fs_readdirr.c \
fs_seekdir.c fs_telldir.c fs_rewinddir.c fs_fsync.c fs_files.c \
fs_inode.c fs_inodefind.c fs_inodefinddir.c fs_inodereserve.c \
fs_inode.c fs_inodefind.c fs_inodereserve.c \
fs_inoderemove.c fs_registerdriver.c fs_unregisterdriver.c \
fs_registerblockdriver.c fs_unregisterblockdriver.c \
fs_mount.c fs_umount.c fs_unlink.c fs_mkdir.c fs_rmdir.c \

View File

@ -77,24 +77,43 @@ int closedir(FAR DIR *dirp)
{
struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
if (!idir)
if (!idir || !idir->root)
{
*get_errno_ptr() = EBADF;
return ERROR;
}
/* Release our references on the contained inodes */
/* The way that we handle the close operation depends on what kind of root
* inode we have open.
*/
if (IS_MOUNTPT_INODE(idir->root))
{
/* The node is a file system mointpoint */
#warning "Mountpoint support not implemented"
*get_errno_ptr() = ENOSYS;
return ERROR;
}
else
{
/* The node is part of the root psuedo file system, release
* our contained reference to the 'next' inode.
*/
if (idir->u.psuedo.next)
{
inode_release(idir->u.psuedo.next);
}
}
/* Release our references on the contained 'root' inode */
if (idir->root)
{
inode_release(idir->root);
}
if (idir->next)
{
inode_release(idir->next);
}
/* Then release the container */
free(idir);

View File

@ -1,129 +0,0 @@
/************************************************************
* fs_inodefinddir.c
*
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* 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. Neither the name Gregory Nutt 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 COPYRIGHT HOLDERS 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
* COPYRIGHT OWNER 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.
*
************************************************************/
/************************************************************
* Included Files
************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <nuttx/fs.h>
#include "fs_internal.h"
#if CONFIG_NFILE_DESCRIPTORS >0
/************************************************************
* Definitions
************************************************************/
/************************************************************
* Private Variables
************************************************************/
/************************************************************
* Public Variables
************************************************************/
/************************************************************
* Private Functions
************************************************************/
/************************************************************
* Public Functions
************************************************************/
/************************************************************
* Name: inode_finddir
*
* Description:
* This is called from the opendir() logic to get a reference
* to the inode associated with a directory. There are no
* real directories in this design; For our purposes, a
* directory inode is simply one that has children.
*
************************************************************/
FAR struct inode *inode_finddir(const char *path)
{
FAR struct inode *node;
FAR struct inode *child = NULL;
/* If we are given 'nothing' then we will interpret this as
* request for the root inode.
*/
if (!path || *path == 0 || strcmp(path, "/") == 0)
{
return root_inode;
}
/* We don't know what to do with relative pathes */
if (*path != '/')
{
return NULL;
}
/* Find the node matching the path. */
inode_semtake();
/* Handle some special cases */
node = inode_search(&path, (FAR void*)NULL, (FAR void*)NULL, (FAR const char**)NULL);
if (node)
{
/* Does the inode have a child? If so that the child
* would be the 'head' of a list of nodes under the
* directory.
*/
child = node->i_child;
if (child)
{
/* If found, then increment the count of
* references on the child node.
*/
child->i_crefs++;
}
}
inode_semgive();
return child;
}
#endif /* CONFIG_NFILE_DESCRIPTORS */

View File

@ -79,12 +79,56 @@
struct internal_dir_s
{
struct inode *root; /* The start inode (in case we
* rewind) */
struct inode *next; /* The inode to use for the next call
* to readdir() */
struct dirent dir; /* Populated using inode when readdir
* is called */
/* This is the node that was opened by opendir. The type of the inode
* determines the way that the readdir() operations are performed. For the
* psuedo root psuedo-file system, it is also used to support rewind.
*
* We hold a reference on this inode so we know that it will persist until
* closedir() is called (although inodes linked to this inode may change).
*/
struct inode *root;
/* This keeps track of the current directory position for telldir */
off_t position;
/* Retained control information depends on the type of file system that
* provides is provides the mountpoint. Ideally this information should
* be hidden behind an opaque, file-system-dependent void *, but we put
* the private definitions in line here for now to reduce allocations.
*/
union
{
/* For the root psuedo-file system, we need retain only the 'next' inode
* need for the next readdir() operation. We hold a reference on this
* inode so we know that it will persist until closedir is called.
*/
struct
{
struct inode *next; /* The inode for the next call to readdir() */
} psuedo;
#ifdef CONFIG_FS_FAT
/* For fat, we need to retun the start cluster, current cluster, current
* sector and current directory index.
*/
struct
{
uint32 startcluster; /* Starting cluster of directory */
uint32 currcluster; /* The current cluster being read */
size_t currsector; /* The current sector being read */
unsigned int dirindex; /* The next directory entry to read */
} fat;
#endif
} u;
/* In any event, this the actual struct dirent that is returned by readdir */
struct dirent dir; /* Populated when readdir is called */
};
/****************************************************************************
@ -128,10 +172,6 @@ EXTERN STATUS inode_remove(const char *path);
EXTERN FAR struct inode *inode_find(const char *path, const char **relpath);
/* fs_inodefinddir.c *********************************************************/
EXTERN FAR struct inode *inode_finddir(const char *path);
/* fs_inodeaddref.c **********************************************************/
EXTERN void inode_addref(FAR struct inode *inode);

View File

@ -41,6 +41,7 @@
#include <sys/types.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <nuttx/fs.h>
#include "fs_internal.h"
@ -49,6 +50,92 @@
* Private Functions
************************************************************/
/************************************************************
* Name: fs_finddirnode
*
* Description:
* This is called from the opendir() logic to get a reference
* to the inode associated with a directory. There are no
* real directories in this design; For our purposes, a
* directory inode is simply one that has children or one
* that is a mountpoint for a "real" file system
*
************************************************************/
static inline FAR struct inode *fs_finddirnode(const char *path, const char **relpath)
{
FAR struct inode *node;
FAR struct inode *root = NULL;
/* If we are given 'nothing' then we will interpret this as
* request for the root inode.
*/
if (!path || *path == 0 || strcmp(path, "/") == 0)
{
return root_inode;
}
/* We don't know what to do with relative pathes */
if (*path != '/')
{
return NULL;
}
/* Find the node matching the path. */
inode_semtake();
node = inode_search(&path, (FAR void*)NULL, (FAR void*)NULL, relpath);
if (node)
{
/* Is this a not in the psuedo filesystem? */
if (INODE_IS_MOUNTPT(node))
{
/* Yes, then return the inode itself as the 'root' of
* the directory. The actually directory is at relpath into the
* mounted filesystem. Increment the count of references
* on the inode.
*/
root = node;
root->i_crefs++;
}
else
{
/* It is a node in the psuedo filesystem. Does the inode have a child?
* If so that the child would be the 'root' of a list of nodes under
* the directory.
*/
root = node->i_child;
if (root)
{
/* If found, then increment the count of
* references on the child node.
*/
root->i_crefs++;
}
}
}
inode_semgive();
return root;
}
/************************************************************
* Name: fs_openmountptdir
************************************************************/
static inline int fs_openmountptdir(struct inode *inode, const char *relpath,
struct internal_dir_s *dir)
{
#warning "Mountpoint support not implemented"
return -ENOSYS;
}
/************************************************************
* Public Functions
************************************************************/
@ -87,18 +174,20 @@ FAR DIR *opendir(const char *path)
{
FAR struct inode *inode;
FAR struct internal_dir_s *dir;
const char *relpath;
int ret;
/* Get an inode corresponding to the path. On successful
* return, we will hold on reference count on the inode.
*/
inode = inode_finddir(path);
inode = fs_finddirnode(path, &relpath);
if (!inode)
{
/* 'path' is not a directory.*/
*get_errno_ptr() = ENOTDIR;
return NULL;
ret = ENOTDIR;
goto errout;
}
/* Allocate a type DIR -- which is little more than an inode
@ -110,17 +199,50 @@ FAR DIR *opendir(const char *path)
{
/* Insufficient memory to complete the operation.*/
*get_errno_ptr() = ENOMEM;
inode_release(inode);
return NULL;
ret = ENOMEM;
goto errout_with_inode;
}
/* Populate the DIR structure and return it to the caller */
/* Populate the DIR structure and return it to the caller. The way that
* we do this depends on whenever this is a "normal" psuedo-file-system
* inode or a file system mountpoint.
*/
dir->root = inode; /* Save the inode where we start */
dir->position = 0; /* This is the position in the read stream */
/* Is this a not in the psuedo filesystem? */
if (INODE_IS_MOUNTPT(inode))
{
/* The node is a file system mointpoint */
ret = fs_openmountptdir(inode, relpath, dir);
if (ret < 0)
{
ret = -ret;
goto errout_with_direntry;
}
}
else
{
/* The node is part of the root psuedo file system */
inode_addref(inode); /* Now we have two references on inode */
dir->u.psuedo.next = inode; /* This is the next node to use for readdir() */
}
dir->root = inode; /* Save where we started in case we rewind */
inode_addref(inode); /* Now we have two references on inode */
dir->next = inode; /* This is the next node to use for readdir() */
return ((DIR*)dir);
/* Nasty goto's make error handling simpler */
errout_with_direntry:
free(dir);
errout_with_inode:
inode_release(inode);
errout:
*get_errno_ptr() = ret;
return NULL;
}
#endif /* CONFIG_NFILE_DESCRIPTORS */

View File

@ -49,6 +49,68 @@
* Private Functions
************************************************************/
/************************************************************
* Name: readpsuedodir
************************************************************/
static inline FAR struct dirent *readpsuedodir(struct internal_dir_s *idir)
{
FAR struct inode *prev;
/* Check if we are at the end of the list */
if (!idir->u.psuedo.next)
{
return NULL;
}
/* Copy the inode name into the dirent structure */
strncpy(idir->dir.d_name, idir->u.psuedo.next->i_name, NAME_MAX+1);
/* If the node has file operations, we will say that it is
* a file.
*/
idir->dir.d_type = 0;
if (idir->u.psuedo.next->u.i_ops)
{
idir->dir.d_type |= DTYPE_FILE;
}
/* If the node has child node(s), then we will say that it
* is a directory. NOTE: that the node can be both!
*/
if (idir->u.psuedo.next->i_child || !idir->u.psuedo.next->u.i_ops)
{
idir->dir.d_type |= DTYPE_DIRECTORY;
}
/* Now get the inode to vist next time that readdir() is called */
inode_semtake();
prev = idir->u.psuedo.next;
idir->u.psuedo.next = prev->i_peer; /* The next node to visit */
if (idir->u.psuedo.next)
{
/* Increment the reference count on this next node */
idir->u.psuedo.next->i_crefs++;
}
inode_semgive();
if (prev)
{
inode_release(prev);
}
return &idir->dir;
}
/************************************************************
* Public Functions
************************************************************/
@ -80,66 +142,34 @@
FAR struct dirent *readdir(DIR *dirp)
{
FAR struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
FAR struct inode *prev;
if (!idir)
/* Sanity checks */
if (!idir || !idir->root)
{
*get_errno_ptr() = EBADF;
return NULL;
}
/* Check if we are at the end of the list */
/* The way we handle the readdir depends on the type of inode
* that we are dealing with.
*/
if (!idir->next)
if (INODE_IS_MOUNTPT(idir->root))
{
/* The node is a file system mointpoint */
#warning "Mountpoint support not implemented"
*get_errno_ptr() = ENOSYS;
return NULL;
}
/* Copy the inode name into the dirent structure */
strncpy(idir->dir.d_name, idir->next->i_name, NAME_MAX+1);
/* If the node has file operations, we will say that it is
* a file.
*/
idir->dir.d_type = 0;
if (idir->next->u.i_ops)
else
{
idir->dir.d_type |= DTYPE_FILE;
/* The node is part of the root psuedo file system, release
* our contained reference to the 'next' inode.
*/
return readpsuedodir(idir);
}
/* If the node has child node(s), then we will say that it
* is a directory. NOTE: that the node can be both!
*/
if (idir->next->i_child || !idir->next->u.i_ops)
{
idir->dir.d_type |= DTYPE_DIRECTORY;
}
/* Now get the inode to vist next time that readdir() is called */
inode_semtake();
prev = idir->next;
idir->next = prev->i_peer; /* The next node to visit */
if (idir->next)
{
/* Increment the reference count on this next node */
idir->next->i_crefs++;
}
inode_semgive();
if (prev)
{
inode_release(prev);
}
return &idir->dir;
}
#endif /* CONFIG_NFILE_DESCRIPTORS */

View File

@ -48,6 +48,35 @@
* Private Functions
************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
static inline void rewindpsuedodir(struct internal_dir_s *idir)
{
struct inode *prev;
inode_semtake();
/* Reset the position to the beginning */
prev = idir->u.psuedo.next; /* (Save to delete later) */
idir->u.psuedo.next = idir->root; /* The next node to visit */
idir->position = 0; /* Reset position */
/* Increment the reference count on the root=next node. We
* should now have two references on the inode.
*/
idir->root->i_crefs++;
inode_semgive();
/* Then release the reference to the old next inode */
if (prev)
{
inode_release(prev);
}
}
/************************************************************
* Public Functions
************************************************************/
@ -68,33 +97,32 @@
*
************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
void rewinddir(FAR DIR *dirp)
{
struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
struct inode *prev;
if (idir)
/* Sanity checks */
if (!idir || !idir->root)
{
inode_semtake();
return;
}
prev = idir->next;
idir->next = idir->root; /* The next node to visit */
/* The way we handle the readdir depends on the type of inode
* that we are dealing with.
*/
if (idir->next)
{
/* Increment the reference count on this next node */
if (INODE_IS_MOUNTPT(idir->root))
{
/* The node is a file system mointpoint */
idir->next->i_crefs++;
}
#warning "Mountpoint support not implemented"
}
else
{
/* The node is part of the root psuedo file system */
inode_semgive();
if (prev)
{
inode_release(prev);
}
rewindpsuedodir(idir);
}
}

View File

@ -48,6 +48,61 @@
* Private Functions
************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
static inline void seekpsuedodir(struct internal_dir_s *idir, off_t offset)
{
struct inode *curr;
struct inode *prev;
off_t pos;
/* Determine a starting point for the seek. If the seek
* is "forward" from the current position, then we will
* start at the current poisition. Otherwise, we will
* "rewind" to the root dir.
*/
if ( offset < idir->position )
{
pos = 0;
curr = idir->root;
}
else
{
pos = idir->position;
curr = idir->u.psuedo.next;
}
/* Traverse the peer list starting at the 'root' of the
* the list until we find the node at 'offset". If devices
* are being registered and unregistered, then this can
* be a very unpredictable operation.
*/
inode_semtake();
for (; curr && pos != offset; pos++, curr = curr->i_peer);
/* Now get the inode to vist next time that readdir() is called */
prev = idir->u.psuedo.next;
idir->u.psuedo.next = curr; /* The next node to visit (might be null) */
idir->position = pos; /* Might be beyond the last dirent */
if (curr)
{
/* Increment the reference count on this next node */
curr->i_crefs++;
}
inode_semgive();
if (prev)
{
inode_release(prev);
}
}
/************************************************************
* Public Functions
************************************************************/
@ -71,46 +126,32 @@
*
************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
void seekdir(FAR DIR *dirp, off_t offset)
{
struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
struct inode *curr;
struct inode *prev;
off_t i;
if (idir)
/* Sanity checks */
if (!idir || !idir->root)
{
/* Traverse the peer list starting at the 'root' of the
* the list until we find the node at 'offset". If devices
* are being registered and unregistered, then this can
* be a very unpredictable operation.
*/
return;
}
inode_semtake();
for (i = 0, curr = idir->root;
curr && i != offset;
i++, curr = curr->i_peer);
/* The way we handle the readdir depends on the type of inode
* that we are dealing with.
*/
/* Now get the inode to vist next time that readdir() is called */
if (INODE_IS_MOUNTPT(idir->root))
{
/* The node is a file system mointpoint */
prev = idir->next;
idir->next = curr; /* The next node to visit */
#warning "Mountpoint support not implemented"
}
else
{
/* The node is part of the root psuedo file system */
if (curr)
{
/* Increment the reference count on this next node */
curr->i_crefs++;
}
inode_semgive();
if (prev)
{
inode_release(prev);
}
seekpsuedodir(idir, offset);
}
}

View File

@ -77,30 +77,16 @@
off_t telldir(FAR DIR *dirp)
{
struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
struct inode *curr;
off_t offs;
if (!idir)
if (!idir || !idir->root)
{
*get_errno_ptr() = EBADF;
return -1;
return (off_t)-1;
}
/* Traverse the peer list starting at the 'root' of the
* the list until we find the 'next' node. If devices
* are being registered and unregistered, then this can
* be a very unpredictable operation.
*/
/* Just return the current position */
inode_semtake();
for (offs = 0, curr = idir->root;
curr && curr != idir->next;
offs++, curr = curr->i_peer);
/* We should have an offset now corresponding to idir->next.*/
inode_semgive();
return offs;
return idir->position;
}
#endif /* CONFIG_NFILE_DESCRIPTORS */