int open_blockdriver(FAR const char *pathname, int mountflags, FAR struct inode **ppinode) { FAR struct inode *inode; int ret; /* Minimal sanity checks */ #ifdef CONFIG_DEBUG if (!ppinode) { ret = -EINVAL; goto errout; } #endif /* Find the inode associated with this block driver name. find_blockdriver * will perform all additional error checking. */ ret = find_blockdriver(pathname, mountflags, &inode); if (ret < 0) { fdbg("Failed to file %s block driver\n", pathname); goto errout; } /* Open the block driver. Note that no mutually exclusive access * to the driver is enforced here. That must be done in the driver * if needed. */ if (inode->u.i_bops->open) { ret = inode->u.i_bops->open(inode); if (ret < 0) { fdbg("%s driver open failed\n", pathname); goto errout_with_inode; } } *ppinode = inode; return OK; errout_with_inode: inode_release(inode); errout: return ret; }
int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data) { #if defined(BDFS_SUPPORT) || defined(NONBDFS_SUPPORT) #ifdef BDFS_SUPPORT FAR struct inode *blkdrvr_inode = NULL; #endif FAR struct inode *mountpt_inode; FAR const struct mountpt_operations *mops; void *fshandle; int errcode; int status; /* Verify required pointer arguments */ DEBUGASSERT(target && filesystemtype); /* Find the specified filesystem. Try the block driver file systems first */ #ifdef BDFS_SUPPORT if ((mops = mount_findfs(g_bdfsmap, filesystemtype)) != NULL) { /* Make sure that a block driver argument was provided */ DEBUGASSERT(source); /* Find the block driver */ status = find_blockdriver(source, mountflags, &blkdrvr_inode); if (status < 0) { fdbg("Failed to find block driver %s\n", source); errcode = -status; goto errout; } } else #endif /* BDFS_SUPPORT */ #ifdef NONBDFS_SUPPORT if ((mops = mount_findfs(g_nonbdfsmap, filesystemtype)) != NULL) { } else #endif /* NONBDFS_SUPPORT */ { fdbg("Failed to find file system %s\n", filesystemtype); errcode = ENODEV; goto errout; } /* Insert a dummy node -- we need to hold the inode semaphore * to do this because we will have a momentarily bad structure. */ inode_semtake(); mountpt_inode = inode_reserve(target); if (!mountpt_inode) { /* inode_reserve can fail for a couple of reasons, but the most likely * one is that the inode already exists. */ fdbg("Failed to reserve inode\n"); errcode = EBUSY; goto errout_with_semaphore; } /* Bind the block driver to an instance of the file system. The file * system returns a reference to some opaque, fs-dependent structure * that encapsulates this binding. */ if (!mops->bind) { /* The filesystem does not support the bind operation ??? */ fdbg("Filesystem does not support bind\n"); errcode = EINVAL; goto errout_with_mountpt; } /* Increment reference count for the reference we pass to the file system */ #ifdef BDFS_SUPPORT #ifdef NONBDFS_SUPPORT if (blkdrvr_inode) #endif { blkdrvr_inode->i_crefs++; } #endif /* On failure, the bind method returns -errorcode */ #ifdef BDFS_SUPPORT status = mops->bind(blkdrvr_inode, data, &fshandle); #else status = mops->bind(NULL, data, &fshandle); #endif if (status != 0) { /* The inode is unhappy with the blkdrvr for some reason. Back out * the count for the reference we failed to pass and exit with an * error. */ fdbg("Bind method failed: %d\n", status); #ifdef BDFS_SUPPORT #ifdef NONBDFS_SUPPORT if (blkdrvr_inode) #endif { blkdrvr_inode->i_crefs--; } #endif errcode = -status; goto errout_with_mountpt; } /* We have it, now populate it with driver specific information. */ INODE_SET_MOUNTPT(mountpt_inode); mountpt_inode->u.i_mops = mops; #ifdef CONFIG_FILE_MODE mountpt_inode->i_mode = mode; #endif mountpt_inode->i_private = fshandle; inode_semgive(); /* We can release our reference to the blkdrver_inode, if the filesystem * wants to retain the blockdriver inode (which it should), then it must * have called inode_addref(). There is one reference on mountpt_inode * that will persist until umount() is called. */ #ifdef BDFS_SUPPORT #ifdef NONBDFS_SUPPORT if (blkdrvr_inode) #endif { inode_release(blkdrvr_inode); } #endif return OK; /* A lot of goto's! But they make the error handling much simpler */ errout_with_mountpt: mountpt_inode->i_crefs = 0; inode_remove(target); inode_semgive(); #ifdef BDFS_SUPPORT #ifdef NONBDFS_SUPPORT if (blkdrvr_inode) #endif { inode_release(blkdrvr_inode); } #endif inode_release(mountpt_inode); goto errout; errout_with_semaphore: inode_semgive(); #ifdef BDFS_SUPPORT #ifdef NONBDFS_SUPPORT if (blkdrvr_inode) #endif { inode_release(blkdrvr_inode); } #endif errout: errno = errcode; return ERROR; #else fdbg("No filesystems enabled\n"); ernno = ENOSYS; return error; #endif /* BDFS_SUPPORT || NONBDFS_SUPPORT */ }