Пример #1
0
static void __hfsplus_ext_write_extent(struct inode *inode,
		struct hfs_find_data *fd)
{
	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
	int res;

	WARN_ON(!mutex_is_locked(&hip->extents_lock));

	hfsplus_ext_build_key(fd->search_key, inode->i_ino, hip->cached_start,
			      HFSPLUS_IS_RSRC(inode) ?
				HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);

	res = hfs_brec_find(fd);
	if (hip->extent_state & HFSPLUS_EXT_NEW) {
		if (res != -ENOENT)
			return;
		hfs_brec_insert(fd, hip->cached_extents,
				sizeof(hfsplus_extent_rec));
		hip->extent_state &= ~(HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW);
	} else {
		if (res)
			return;
		hfs_bnode_write(fd->bnode, hip->cached_extents,
				fd->entryoffset, fd->entrylength);
		hip->extent_state &= ~HFSPLUS_EXT_DIRTY;
	}

	/*
	 * We can't just use hfsplus_mark_inode_dirty here, because we
	 * also get called from hfsplus_write_inode, which should not
	 * redirty the inode.  Instead the callers have to be careful
	 * to explicily mark the inode dirty, too.
	 */
	set_bit(HFSPLUS_I_EXT_DIRTY, &hip->flags);
}
Пример #2
0
static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data *fd)
{
	int res;

	hfsplus_ext_build_key(fd->search_key, inode->i_ino, HFSPLUS_I(inode).cached_start,
			      HFSPLUS_IS_RSRC(inode) ?  HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);
	res = hfs_brec_find(fd);
	if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_NEW) {
		if (res != -ENOENT)
			return;
		hfs_brec_insert(fd, HFSPLUS_I(inode).cached_extents, sizeof(hfsplus_extent_rec));
		HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW);
	} else {
		if (res)
			return;
		hfs_bnode_write(fd->bnode, HFSPLUS_I(inode).cached_extents, fd->entryoffset, fd->entrylength);
		HFSPLUS_I(inode).flags &= ~HFSPLUS_FLG_EXT_DIRTY;
	}
}
Пример #3
0
/* 
 * The flags XATTR_REPLACE and XATTR_CREATE
 * specify that an extended attribute must exist and must not exist
 * previous to the call, respectively.
 */
int hfsplus_setxattr(struct dentry *dentry, const char *name,
		     const void *value, size_t size, int flags)
{
	struct inode *inode = dentry->d_inode;
	struct hfs_btree *btree = HFSPLUS_SB(inode->i_sb)->attr_tree;
	struct hfs_find_data fd;
	hfsplus_attr_entry *entry = NULL;
	int res = 0, entry_size = 0;

	dprint(DBG_XATTR, "hfs: setattr [%s][%s] [%lu]\n", dentry->d_name.name, name, inode->i_ino);
	
	if (!value) {
		return -EINVAL;
	}
	if (!strcmp(name, SZ_XATTR_NAME_TYPE) ||
		!strcmp(name, SZ_XATTR_NAME_CREATOR) ||
		!strcmp(name, SZ_XATTR_NAME_FINDRINFO)) {
		return hfsplus_setxattr_buildin(dentry, name, value, size, flags);
	} else if (!strcmp(name, SZ_XATTR_NAME_RFORK)) {
		return -EOPNOTSUPP;
	}

#if 0
#define HFSPLUS_MAX_ATTR_LEN (128*1024)
	if (size > HFSPLUS_MAX_ATTR_LEN) {
		return E2BIG;
	}
#endif
	if (size > hfsplus_get_maxinline_attrsize(btree)) {
		return -E2BIG;
	}

	res = hfs_find_init(btree, &fd);
	if (res) {
		return res;
	}
	hfsplus_attr_build_key(inode->i_sb, fd.search_key, cpu_to_be32((u32)(unsigned long)dentry->d_fsdata), name, 0);
	res = hfs_brec_find(&fd);
	if (res == -ENOENT) {
		if (flags & XATTR_REPLACE) {
			res = -ENODATA;
			goto out;
		}
	} else if (res != 0) {
		goto out;
	} else { // res == 0
		if (flags & XATTR_CREATE) {
			res = -EEXIST;
			goto out;
		}
		if ((res = hfs_brec_remove(&fd))) {
			goto out;
		}
		// decrease record count to avoid the next insert worng.
		--fd.record;
		//hfsplus_mark_inode_dirty(btree->inode, HFSPLUS_I_ATTR_DIRTY);
		//if ((res = filemap_write_and_wait(btree->inode->i_mapping))) {
		//	goto out;
		//}
	}
	entry_size = sizeof(struct hfsplus_attr_data) - 2 + size + ((size & 1) ? 1 : 0);
	entry = kmalloc(entry_size * sizeof(char), GFP_NOFS);
	if (!entry) {
		res = -ENOMEM;
		goto out;
	}
	entry->type = cpu_to_be32(kHFSPlusAttrData);
	entry->data.attr_size = cpu_to_be32(size);
	memcpy(entry->data.attr_data, value, size);
	res = hfs_brec_insert(&fd, entry, entry_size);

	// set has attribute bit on file/folder
	hfsplus_set_cat_flag(inode, HFS_HAS_ATTR_MASK, 1);
	inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
	hfsplus_mark_inode_dirty(inode, HFSPLUS_I_ATTR_DIRTY);
	//if ((res = filemap_write_and_wait(btree->inode->i_mapping))) {
	//	goto out;
	//}
out:
	if (entry) {
		kfree(entry);
	}
	hfs_find_exit(&fd);
	return res;
}