summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/hfsplus/attributes.c38
-rw-r--r--fs/hfsplus/hfsplus_fs.h7
-rw-r--r--fs/hfsplus/xattr.c6
3 files changed, 38 insertions, 13 deletions
diff --git a/fs/hfsplus/attributes.c b/fs/hfsplus/attributes.c
index 6585bcea731c..704635c65e9a 100644
--- a/fs/hfsplus/attributes.c
+++ b/fs/hfsplus/attributes.c
@@ -153,14 +153,22 @@ int hfsplus_find_attr(struct super_block *sb, u32 cnid,
if (err)
goto failed_find_attr;
err = hfs_brec_find(fd, hfs_find_rec_by_key);
- if (err)
+ if (err == -ENOENT) {
+ /* file exists but xattr is absent */
+ err = -ENODATA;
+ goto failed_find_attr;
+ } else if (err)
goto failed_find_attr;
} else {
err = hfsplus_attr_build_key(sb, fd->search_key, cnid, NULL);
if (err)
goto failed_find_attr;
err = hfs_brec_find(fd, hfs_find_1st_rec_by_cnid);
- if (err)
+ if (err == -ENOENT) {
+ /* file exists but xattr is absent */
+ err = -ENODATA;
+ goto failed_find_attr;
+ } else if (err)
goto failed_find_attr;
}
@@ -174,6 +182,9 @@ int hfsplus_attr_exists(struct inode *inode, const char *name)
struct super_block *sb = inode->i_sb;
struct hfs_find_data fd;
+ hfs_dbg("name %s, ino %ld\n",
+ name ? name : NULL, inode->i_ino);
+
if (!HFSPLUS_SB(sb)->attr_tree)
return 0;
@@ -293,15 +304,16 @@ failed_init_create_attr:
static int __hfsplus_delete_attr(struct inode *inode, u32 cnid,
struct hfs_find_data *fd)
{
- int err = 0;
+ int err;
__be32 found_cnid, record_type;
+ found_cnid = U32_MAX;
hfs_bnode_read(fd->bnode, &found_cnid,
fd->keyoffset +
offsetof(struct hfsplus_attr_key, cnid),
sizeof(__be32));
if (cnid != be32_to_cpu(found_cnid))
- return -ENOENT;
+ return -ENODATA;
hfs_bnode_read(fd->bnode, &record_type,
fd->entryoffset, sizeof(record_type));
@@ -330,7 +342,7 @@ static int __hfsplus_delete_attr(struct inode *inode, u32 cnid,
hfsplus_mark_inode_dirty(HFSPLUS_ATTR_TREE_I(inode->i_sb),
HFSPLUS_I_ATTR_DIRTY);
hfsplus_mark_inode_dirty(inode, HFSPLUS_I_ATTR_DIRTY);
- return err;
+ return 0;
}
static
@@ -354,7 +366,10 @@ int hfsplus_delete_attr_nolock(struct inode *inode, const char *name,
}
err = hfs_brec_find(fd, hfs_find_rec_by_key);
- if (err)
+ if (err == -ENOENT) {
+ /* file exists but xattr is absent */
+ return -ENODATA;
+ } else if (err)
return err;
err = __hfsplus_delete_attr(inode, inode->i_ino, fd);
@@ -414,9 +429,14 @@ int hfsplus_delete_all_attrs(struct inode *dir, u32 cnid)
for (;;) {
err = hfsplus_find_attr(dir->i_sb, cnid, NULL, &fd);
- if (err) {
- if (err != -ENOENT)
- pr_err("xattr search failed\n");
+ if (err == -ENOENT || err == -ENODATA) {
+ /*
+ * xattr has not been found
+ */
+ err = -ENODATA;
+ goto end_delete_all;
+ } else if (err) {
+ pr_err("xattr search failed\n");
goto end_delete_all;
}
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 420dc920e097..caba698814fe 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -571,7 +571,12 @@ hfsplus_btree_lock_class(struct hfs_btree *tree)
static inline
bool is_bnode_offset_valid(struct hfs_bnode *node, u32 off)
{
- bool is_valid = off < node->tree->node_size;
+ bool is_valid;
+
+ if (!node || !node->tree)
+ return false;
+
+ is_valid = off < node->tree->node_size;
if (!is_valid) {
pr_err("requested invalid offset: "
diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
index a824bcaac172..89e2e7e46e96 100644
--- a/fs/hfsplus/xattr.c
+++ b/fs/hfsplus/xattr.c
@@ -562,10 +562,10 @@ ssize_t __hfsplus_getxattr(struct inode *inode, const char *name,
res = hfsplus_find_attr(inode->i_sb, inode->i_ino, name, &fd);
if (res) {
- if (res == -ENOENT)
+ if (res == -ENOENT || res == -ENODATA)
res = -ENODATA;
else
- pr_err("xattr searching failed\n");
+ pr_err("xattr search failed\n");
goto out;
}
@@ -757,7 +757,7 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
err = hfsplus_find_attr(inode->i_sb, inode->i_ino, NULL, &fd);
if (err) {
- if (err == -ENOENT) {
+ if (err == -ENOENT || err == -ENODATA) {
res = 0;
goto end_listxattr;
} else {