return 0;
}
-int hfsplus_create_attr(struct inode *inode,
- const char *name,
- const void *value, size_t size)
+static
+int hfsplus_create_attr_nolock(struct inode *inode, const char *name,
+ const void *value, size_t size,
+ struct hfs_find_data *fd,
+ hfsplus_attr_entry *entry_ptr)
{
struct super_block *sb = inode->i_sb;
- struct hfs_find_data fd;
- hfsplus_attr_entry *entry_ptr;
int entry_size;
int err;
hfs_dbg("name %s, ino %ld\n",
name ? name : NULL, inode->i_ino);
- if (!HFSPLUS_SB(sb)->attr_tree) {
- pr_err("attributes file doesn't exist\n");
- return -EINVAL;
- }
-
- entry_ptr = hfsplus_alloc_attr_entry();
- if (!entry_ptr)
- return -ENOMEM;
-
- err = hfs_find_init(HFSPLUS_SB(sb)->attr_tree, &fd);
- if (err)
- goto failed_init_create_attr;
-
- /* Fail early and avoid ENOSPC during the btree operation */
- err = hfs_bmap_reserve(fd.tree, fd.tree->depth + 1);
- if (err)
- goto failed_create_attr;
-
if (name) {
- err = hfsplus_attr_build_key(sb, fd.search_key,
+ err = hfsplus_attr_build_key(sb, fd->search_key,
inode->i_ino, name);
if (err)
- goto failed_create_attr;
- } else {
- err = -EINVAL;
- goto failed_create_attr;
- }
+ return err;
+ } else
+ return -EINVAL;
/* Mac OS X supports only inline data attributes. */
entry_size = hfsplus_attr_build_record(entry_ptr,
else
err = -EINVAL;
hfs_dbg("unable to store value: err %d\n", err);
- goto failed_create_attr;
+ return err;
}
- err = hfs_brec_find(&fd, hfs_find_rec_by_key);
+ err = hfs_brec_find(fd, hfs_find_rec_by_key);
if (err != -ENOENT) {
if (!err)
err = -EEXIST;
- goto failed_create_attr;
+ return err;
}
- err = hfs_brec_insert(&fd, entry_ptr, entry_size);
+ err = hfs_brec_insert(fd, entry_ptr, entry_size);
if (err) {
hfs_dbg("unable to store value: err %d\n", err);
- goto failed_create_attr;
+ return err;
}
hfsplus_mark_inode_dirty(inode, HFSPLUS_I_ATTR_DIRTY);
+ return 0;
+}
+
+int hfsplus_create_attr(struct inode *inode,
+ const char *name,
+ const void *value, size_t size)
+{
+ struct super_block *sb = inode->i_sb;
+ struct hfs_find_data fd;
+ hfsplus_attr_entry *entry_ptr;
+ int err;
+
+ hfs_dbg("name %s, ino %ld\n",
+ name ? name : NULL, inode->i_ino);
+
+ if (!HFSPLUS_SB(sb)->attr_tree) {
+ pr_err("attributes file doesn't exist\n");
+ return -EINVAL;
+ }
+
+ entry_ptr = hfsplus_alloc_attr_entry();
+ if (!entry_ptr)
+ return -ENOMEM;
+
+ err = hfs_find_init(HFSPLUS_SB(sb)->attr_tree, &fd);
+ if (err)
+ goto failed_init_create_attr;
+
+ /* Fail early and avoid ENOSPC during the btree operation */
+ err = hfs_bmap_reserve(fd.tree, fd.tree->depth + 1);
+ if (err)
+ goto failed_create_attr;
+
+ err = hfsplus_create_attr_nolock(inode, name, value, size,
+ &fd, entry_ptr);
+ if (err)
+ goto failed_create_attr;
+
failed_create_attr:
hfs_find_exit(&fd);
return err;
}
+static
+int hfsplus_delete_attr_nolock(struct inode *inode, const char *name,
+ struct hfs_find_data *fd)
+{
+ struct super_block *sb = inode->i_sb;
+ int err;
+
+ hfs_dbg("name %s, ino %ld\n",
+ name ? name : NULL, inode->i_ino);
+
+ if (name) {
+ err = hfsplus_attr_build_key(sb, fd->search_key,
+ inode->i_ino, name);
+ if (err)
+ return err;
+ } else {
+ pr_err("invalid extended attribute name\n");
+ return -EINVAL;
+ }
+
+ err = hfs_brec_find(fd, hfs_find_rec_by_key);
+ if (err)
+ return err;
+
+ err = __hfsplus_delete_attr(inode, inode->i_ino, fd);
+ if (err)
+ return err;
+
+ return 0;
+}
+
int hfsplus_delete_attr(struct inode *inode, const char *name)
{
int err = 0;
if (err)
goto out;
- if (name) {
- err = hfsplus_attr_build_key(sb, fd.search_key,
- inode->i_ino, name);
- if (err)
- goto out;
- } else {
- pr_err("invalid extended attribute name\n");
- err = -EINVAL;
- goto out;
- }
-
- err = hfs_brec_find(&fd, hfs_find_rec_by_key);
- if (err)
- goto out;
-
- err = __hfsplus_delete_attr(inode, inode->i_ino, &fd);
+ err = hfsplus_delete_attr_nolock(inode, name, &fd);
if (err)
goto out;
hfs_find_exit(&fd);
return err;
}
+
+int hfsplus_replace_attr(struct inode *inode,
+ const char *name,
+ const void *value, size_t size)
+{
+ struct super_block *sb = inode->i_sb;
+ struct hfs_find_data fd;
+ hfsplus_attr_entry *entry_ptr;
+ int err = 0;
+
+ hfs_dbg("name %s, ino %ld\n",
+ name ? name : NULL, inode->i_ino);
+
+ if (!HFSPLUS_SB(sb)->attr_tree) {
+ pr_err("attributes file doesn't exist\n");
+ return -EINVAL;
+ }
+
+ entry_ptr = hfsplus_alloc_attr_entry();
+ if (!entry_ptr)
+ return -ENOMEM;
+
+ err = hfs_find_init(HFSPLUS_SB(sb)->attr_tree, &fd);
+ if (err)
+ goto failed_init_replace_attr;
+
+ /* Fail early and avoid ENOSPC during the btree operation */
+ err = hfs_bmap_reserve(fd.tree, fd.tree->depth + 1);
+ if (err)
+ goto failed_replace_attr;
+
+ err = hfsplus_delete_attr_nolock(inode, name, &fd);
+ if (err)
+ goto failed_replace_attr;
+
+ err = hfsplus_create_attr_nolock(inode, name, value, size,
+ &fd, entry_ptr);
+ if (err)
+ goto failed_replace_attr;
+
+failed_replace_attr:
+ hfs_find_exit(&fd);
+
+failed_init_replace_attr:
+ hfsplus_destroy_attr_entry(entry_ptr);
+ return err;
+}