Example #1
0
static void rtems_jffs2_fsunmount(rtems_filesystem_mount_table_entry_t *mt_entry)
{
	rtems_jffs2_fs_info *fs_info = mt_entry->fs_info;
	struct _inode *root_i = mt_entry->mt_fs_root->location.node_access;

	icache_evict(root_i, NULL);
	assert(root_i->i_cache_next == NULL);
	assert(root_i->i_count == 1);
	jffs2_iput(root_i);

	rtems_jffs2_free_directory_entries(root_i);
	free(root_i);

	rtems_jffs2_free_fs_info(fs_info, true);
}
Example #2
0
int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode,
                 struct _inode **new_i)
{
	struct jffs2_raw_inode *ri;
	struct jffs2_inode_info *f, *dir_f;
	struct jffs2_sb_info *c;
	struct _inode *inode;
	int ret;

	ri = jffs2_alloc_raw_inode();
	if (!ri)
		return -ENOMEM;
	
	c = JFFS2_SB_INFO(dir_i->i_sb);

	D1(printk(KERN_DEBUG "jffs2_create()\n"));

	inode = jffs2_new_inode(dir_i, mode, ri);

	if (IS_ERR(inode)) {
		D1(printk(KERN_DEBUG "jffs2_new_inode() failed\n"));
		jffs2_free_raw_inode(ri);
		return PTR_ERR(inode);
	}

	f = JFFS2_INODE_INFO(inode);
	dir_f = JFFS2_INODE_INFO(dir_i);

	ret = jffs2_do_create(c, dir_f, f, ri, 
			      (const char *)d_name, 
                              strlen((char *)d_name));

	if (ret) {
		inode->i_nlink = 0;
		jffs2_iput(inode);
		jffs2_free_raw_inode(ri);
		return ret;
	}

	jffs2_free_raw_inode(ri);

	D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d)\n",
		  inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink));
        *new_i = inode;
	return 0;
}
Example #3
0
static void rtems_jffs2_freenode(const rtems_filesystem_location_info_t *loc)
{
	struct _inode *inode = rtems_jffs2_get_inode_by_location(loc);

	jffs2_iput(inode);
}
Example #4
0
static rtems_filesystem_eval_path_generic_status rtems_jffs2_eval_token(
	rtems_filesystem_eval_path_context_t *ctx,
	void *arg,
	const char *token,
	size_t tokenlen
)
{
	rtems_filesystem_eval_path_generic_status status =
		RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
	rtems_filesystem_location_info_t *currentloc =
		rtems_filesystem_eval_path_get_currentloc(ctx);
	struct _inode *dir_i = rtems_jffs2_get_inode_by_location(currentloc);
	bool access_ok = rtems_filesystem_eval_path_check_access(
		ctx,
		RTEMS_FS_PERMS_EXEC,
		dir_i->i_mode,
		dir_i->i_uid,
		dir_i->i_gid
	);

	if (access_ok) {
		struct _inode *entry_i;

		if (rtems_filesystem_is_current_directory(token, tokenlen)) {
			entry_i = dir_i;
			++entry_i->i_count;
		} else if (rtems_filesystem_is_parent_directory(token, tokenlen)) {
			entry_i = dir_i->i_parent;
			++entry_i->i_count;
		} else {
			entry_i = jffs2_lookup(dir_i, token, (int) tokenlen);
		}

		if (IS_ERR(entry_i)) {
			rtems_filesystem_eval_path_error(ctx, PTR_ERR(entry_i));
		} else if (entry_i != NULL) {
			bool terminal = !rtems_filesystem_eval_path_has_path(ctx);
			int eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
			bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0;

			rtems_filesystem_eval_path_clear_token(ctx);

			if (S_ISLNK(entry_i->i_mode) && (follow_sym_link || !terminal)) {
				struct jffs2_inode_info *f = JFFS2_INODE_INFO(entry_i);
				const char *target = f->target;

				rtems_filesystem_eval_path_recursive(ctx, target, strlen(target));

				jffs2_iput(entry_i);
			} else {
				if (S_ISDIR(entry_i->i_mode) && entry_i->i_parent == NULL) {
					entry_i->i_parent = dir_i;
					++dir_i->i_count;
				}

				jffs2_iput(dir_i);
				rtems_jffs2_set_location(currentloc, entry_i);

				if (rtems_filesystem_eval_path_has_path(ctx)) {
					status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
				}
			}
		} else {
			status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
		}
	}

	return status;
}
Example #5
0
int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode)
{
	struct jffs2_inode_info *f, *dir_f;
	struct jffs2_sb_info *c;
	struct _inode *inode;
	struct jffs2_raw_inode *ri;
	struct jffs2_raw_dirent *rd;
	struct jffs2_full_dnode *fn;
	struct jffs2_full_dirent *fd;
	int namelen;
	uint32_t alloclen, phys_ofs;
	int ret;

	mode |= S_IFDIR;

	ri = jffs2_alloc_raw_inode();
	if (!ri)
		return -ENOMEM;
	
	c = JFFS2_SB_INFO(dir_i->i_sb);

	/* Try to reserve enough space for both node and dirent. 
	 * Just the node will do for now, though 
	 */
	namelen = strlen((char *)d_name);
	ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);

	if (ret) {
		jffs2_free_raw_inode(ri);
		return ret;
	}

	inode = jffs2_new_inode(dir_i, mode, ri);

	if (IS_ERR(inode)) {
		jffs2_free_raw_inode(ri);
		jffs2_complete_reservation(c);
		return PTR_ERR(inode);
	}

	f = JFFS2_INODE_INFO(inode);

	ri->data_crc = cpu_to_je32(0);
	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
	
	fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);

	jffs2_free_raw_inode(ri);

	if (IS_ERR(fn)) {
		/* Eeek. Wave bye bye */
		up(&f->sem);
		jffs2_complete_reservation(c);
		inode->i_nlink = 0;
		jffs2_iput(inode);
		return PTR_ERR(fn);
	}
	/* No data here. Only a metadata node, which will be 
	   obsoleted by the first data write
	*/
	f->metadata = fn;
	up(&f->sem);

	jffs2_complete_reservation(c);
	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
	if (ret) {
		/* Eep. */
		inode->i_nlink = 0;
		jffs2_iput(inode);
		return ret;
	}
	
	rd = jffs2_alloc_raw_dirent();
	if (!rd) {
		/* Argh. Now we treat it like a normal delete */
		jffs2_complete_reservation(c);
		inode->i_nlink = 0;
		jffs2_iput(inode);
		return -ENOMEM;
	}

	dir_f = JFFS2_INODE_INFO(dir_i);
	down(&dir_f->sem);

	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));

	rd->pino = cpu_to_je32(dir_i->i_ino);
	rd->version = cpu_to_je32(++dir_f->highest_version);
	rd->ino = cpu_to_je32(inode->i_ino);
	rd->mctime = cpu_to_je32(jffs2_get_timestamp());
	rd->nsize = namelen;
	rd->type = DT_DIR;
	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
	rd->name_crc = cpu_to_je32(crc32(0, d_name, namelen));

	fd = jffs2_write_dirent(c, dir_f, rd, d_name, namelen, phys_ofs, ALLOC_NORMAL);
	
	jffs2_complete_reservation(c);
	jffs2_free_raw_dirent(rd);
	
	if (IS_ERR(fd)) {
		/* dirent failed to write. Delete the inode normally 
		   as if it were the final unlink() */
		up(&dir_f->sem);
		inode->i_nlink = 0;
		jffs2_iput(inode);
		return PTR_ERR(fd);
	}

	/* Link the fd into the inode's list, obsoleting an old
	   one if necessary. */
	jffs2_add_fd_to_list(c, fd, &dir_f->dents);
	up(&dir_f->sem);

	jffs2_iput(inode);
	return 0;
}