Commit 34415c1e authored by Dave Kleikamp's avatar Dave Kleikamp

Extended attribute fixes for JFS.

parent aa6ec546
...@@ -52,7 +52,11 @@ struct jfs_ea_list { ...@@ -52,7 +52,11 @@ struct jfs_ea_list {
#define END_EALIST(ealist) \ #define END_EALIST(ealist) \
((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist))) ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist)))
extern int jfs_setxattr(struct dentry *, const char *, void *, size_t, int); extern int __jfs_setxattr(struct inode *, const char *, void *, size_t,
int);
extern int jfs_setxattr(struct dentry *, const char *, void *, size_t,
int);
extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t jfs_listxattr(struct dentry *, char *, size_t); extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
extern int jfs_removexattr(struct dentry *, const char *); extern int jfs_removexattr(struct dentry *, const char *);
......
...@@ -247,7 +247,7 @@ static int ea_write(struct inode *ip, struct jfs_ea_list *ealist, int size, ...@@ -247,7 +247,7 @@ static int ea_write(struct inode *ip, struct jfs_ea_list *ealist, int size,
/* Free up INLINE area */ /* Free up INLINE area */
if (ji->ea.flag & DXD_INLINE) if (ji->ea.flag & DXD_INLINE)
ip->i_mode |= INLINEEA; ji->mode2 |= INLINEEA;
return 0; return 0;
...@@ -577,10 +577,9 @@ static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size) ...@@ -577,10 +577,9 @@ static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size)
return rc; return rc;
} }
int jfs_setxattr(struct dentry *dentry, const char *name, int __jfs_setxattr(struct inode *inode, const char *name, void *value,
void *value, size_t value_len, int flags) size_t value_len, int flags)
{ {
struct inode *inode = dentry->d_inode;
struct jfs_ea_list *ealist; struct jfs_ea_list *ealist;
struct jfs_ea *ea, *old_ea = NULL, *next_ea = NULL; struct jfs_ea *ea, *old_ea = NULL, *next_ea = NULL;
struct ea_buffer ea_buf; struct ea_buffer ea_buf;
...@@ -592,15 +591,10 @@ int jfs_setxattr(struct dentry *dentry, const char *name, ...@@ -592,15 +591,10 @@ int jfs_setxattr(struct dentry *dentry, const char *name,
int rc = 0; int rc = 0;
int length; int length;
if (!value)
value_len = 0;
IWRITE_LOCK(inode);
xattr_size = ea_get(inode, &ea_buf, 0); xattr_size = ea_get(inode, &ea_buf, 0);
if (xattr_size < 0) { if (xattr_size < 0) {
rc = xattr_size; rc = xattr_size;
goto unlock; goto out;
} }
again: again:
...@@ -630,12 +624,12 @@ int jfs_setxattr(struct dentry *dentry, const char *name, ...@@ -630,12 +624,12 @@ int jfs_setxattr(struct dentry *dentry, const char *name,
rc = -ENODATA; rc = -ENODATA;
goto release; goto release;
} }
if (value_len == 0) { if (value == NULL) {
rc = 0; rc = 0;
goto release; goto release;
} }
} }
if (value_len) if (value)
new_size += sizeof (struct jfs_ea) + namelen + 1 + value_len; new_size += sizeof (struct jfs_ea) + namelen + 1 + value_len;
if (new_size > ea_buf.max_size) { if (new_size > ea_buf.max_size) {
...@@ -647,7 +641,7 @@ int jfs_setxattr(struct dentry *dentry, const char *name, ...@@ -647,7 +641,7 @@ int jfs_setxattr(struct dentry *dentry, const char *name,
xattr_size = ea_get(inode, &ea_buf, new_size); xattr_size = ea_get(inode, &ea_buf, new_size);
if (xattr_size < 0) { if (xattr_size < 0) {
rc = xattr_size; rc = xattr_size;
goto unlock; goto out;
} }
goto again; goto again;
} }
...@@ -662,7 +656,7 @@ int jfs_setxattr(struct dentry *dentry, const char *name, ...@@ -662,7 +656,7 @@ int jfs_setxattr(struct dentry *dentry, const char *name,
} }
/* Add new entry to the end */ /* Add new entry to the end */
if (value_len) { if (value) {
if (xattr_size == 0) if (xattr_size == 0)
/* Completely new ea list */ /* Completely new ea list */
xattr_size = sizeof (struct jfs_ea_list); xattr_size = sizeof (struct jfs_ea_list);
...@@ -673,6 +667,7 @@ int jfs_setxattr(struct dentry *dentry, const char *name, ...@@ -673,6 +667,7 @@ int jfs_setxattr(struct dentry *dentry, const char *name,
ea->valuelen = (cpu_to_le16(value_len)); ea->valuelen = (cpu_to_le16(value_len));
memcpy(ea->name, name, namelen); memcpy(ea->name, name, namelen);
ea->name[namelen] = 0; ea->name[namelen] = 0;
if (value_len)
memcpy(&ea->name[namelen + 1], value, value_len); memcpy(&ea->name[namelen + 1], value, value_len);
xattr_size += EA_SIZE(ea); xattr_size += EA_SIZE(ea);
} }
...@@ -683,26 +678,41 @@ int jfs_setxattr(struct dentry *dentry, const char *name, ...@@ -683,26 +678,41 @@ int jfs_setxattr(struct dentry *dentry, const char *name,
"jfs_xsetattr: xattr_size = %d, new_size = %d\n", "jfs_xsetattr: xattr_size = %d, new_size = %d\n",
xattr_size, new_size); xattr_size, new_size);
rc = EINVAL; rc = -EINVAL;
goto release; goto release;
} }
/*
* If we're left with an empty list, there's no ea
*/
if (new_size == sizeof (struct jfs_ea_list))
new_size = 0;
ealist->size = cpu_to_le32(new_size); ealist->size = cpu_to_le32(new_size);
rc = ea_put(inode, &ea_buf, new_size); rc = ea_put(inode, &ea_buf, new_size);
goto unlock; goto out;
release: release:
ea_release(inode, &ea_buf); ea_release(inode, &ea_buf);
unlock: out:
IWRITE_UNLOCK(inode);
return rc; return rc;
} }
ssize_t jfs_getxattr(struct dentry * dentry, const char *name, int jfs_setxattr(struct dentry *dentry, const char *name, void *value,
void *data, size_t buf_size) size_t value_len, int flags)
{
if (value == NULL) { /* empty EA, do not remove */
value = "";
value_len = 0;
}
return __jfs_setxattr(dentry->d_inode, name, value, value_len, flags);
}
ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
size_t buf_size)
{ {
struct inode *inode = dentry->d_inode;
struct jfs_ea_list *ealist; struct jfs_ea_list *ealist;
struct jfs_ea *ea; struct jfs_ea *ea;
struct ea_buffer ea_buf; struct ea_buffer ea_buf;
...@@ -711,18 +721,14 @@ ssize_t jfs_getxattr(struct dentry * dentry, const char *name, ...@@ -711,18 +721,14 @@ ssize_t jfs_getxattr(struct dentry * dentry, const char *name,
int namelen = strlen(name); int namelen = strlen(name);
char *value; char *value;
IREAD_LOCK(inode);
xattr_size = ea_get(inode, &ea_buf, 0); xattr_size = ea_get(inode, &ea_buf, 0);
if (xattr_size < 0) { if (xattr_size < 0) {
size = xattr_size; size = xattr_size;
goto unlock; goto out;
} }
if (xattr_size == 0) { if (xattr_size == 0)
size = 0; goto not_found;
goto release;
}
ealist = (struct jfs_ea_list *) ea_buf.xattr; ealist = (struct jfs_ea_list *) ea_buf.xattr;
...@@ -742,16 +748,21 @@ ssize_t jfs_getxattr(struct dentry * dentry, const char *name, ...@@ -742,16 +748,21 @@ ssize_t jfs_getxattr(struct dentry * dentry, const char *name,
memcpy(data, value, size); memcpy(data, value, size);
goto release; goto release;
} }
/* not found */ not_found:
size = -ENODATA; size = -ENODATA;
release: release:
ea_release(inode, &ea_buf); ea_release(inode, &ea_buf);
unlock: out:
IREAD_UNLOCK(inode);
return size; return size;
} }
ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data,
size_t buf_size)
{
return __jfs_getxattr(dentry->d_inode, name, data, buf_size);
}
ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size) ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
...@@ -762,12 +773,10 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size) ...@@ -762,12 +773,10 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
struct jfs_ea *ea; struct jfs_ea *ea;
struct ea_buffer ea_buf; struct ea_buffer ea_buf;
IREAD_LOCK(inode);
xattr_size = ea_get(inode, &ea_buf, 0); xattr_size = ea_get(inode, &ea_buf, 0);
if (xattr_size < 0) { if (xattr_size < 0) {
size = xattr_size; size = xattr_size;
goto unlock; goto out;
} }
if (xattr_size == 0) if (xattr_size == 0)
...@@ -797,12 +806,11 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size) ...@@ -797,12 +806,11 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
release: release:
ea_release(inode, &ea_buf); ea_release(inode, &ea_buf);
unlock: out:
IREAD_UNLOCK(inode);
return size; return size;
} }
int jfs_removexattr(struct dentry *dentry, const char *name) int jfs_removexattr(struct dentry *dentry, const char *name)
{ {
return jfs_setxattr(dentry, name, 0, 0, XATTR_REPLACE); return __jfs_setxattr(dentry->d_inode, name, 0, 0, XATTR_REPLACE);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment