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); }
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; } }
/* * 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; }