diff options
Diffstat (limited to 'fs/f2fs/xattr.c')
-rw-r--r-- | fs/f2fs/xattr.c | 131 |
1 files changed, 46 insertions, 85 deletions
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 4de2286c0e4d..06a72dc0191a 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -25,49 +25,37 @@ #include "f2fs.h" #include "xattr.h" -static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list, - size_t list_size, const char *name, size_t len, int type) +static int f2fs_xattr_generic_get(const struct xattr_handler *handler, + struct dentry *dentry, const char *name, void *buffer, + size_t size) { struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb); - int total_len, prefix_len = 0; - const char *prefix = NULL; - switch (type) { + switch (handler->flags) { case F2FS_XATTR_INDEX_USER: if (!test_opt(sbi, XATTR_USER)) return -EOPNOTSUPP; - prefix = XATTR_USER_PREFIX; - prefix_len = XATTR_USER_PREFIX_LEN; break; case F2FS_XATTR_INDEX_TRUSTED: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - prefix = XATTR_TRUSTED_PREFIX; - prefix_len = XATTR_TRUSTED_PREFIX_LEN; break; case F2FS_XATTR_INDEX_SECURITY: - prefix = XATTR_SECURITY_PREFIX; - prefix_len = XATTR_SECURITY_PREFIX_LEN; break; default: return -EINVAL; } - - total_len = prefix_len + len + 1; - if (list && total_len <= list_size) { - memcpy(list, prefix, prefix_len); - memcpy(list + prefix_len, name, len); - list[prefix_len + len] = '\0'; - } - return total_len; + return f2fs_getxattr(d_inode(dentry), handler->flags, name, + buffer, size, NULL); } -static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name, - void *buffer, size_t size, int type) +static int f2fs_xattr_generic_set(const struct xattr_handler *handler, + struct dentry *dentry, const char *name, const void *value, + size_t size, int flags) { struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb); - switch (type) { + switch (handler->flags) { case F2FS_XATTR_INDEX_USER: if (!test_opt(sbi, XATTR_USER)) return -EOPNOTSUPP; @@ -81,72 +69,39 @@ static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name, default: return -EINVAL; } - if (strcmp(name, "") == 0) - return -EINVAL; - return f2fs_getxattr(d_inode(dentry), type, name, buffer, size, NULL); + return f2fs_setxattr(d_inode(dentry), handler->flags, name, + value, size, NULL, flags); } -static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags, int type) +static bool f2fs_xattr_user_list(struct dentry *dentry) { struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb); - switch (type) { - case F2FS_XATTR_INDEX_USER: - if (!test_opt(sbi, XATTR_USER)) - return -EOPNOTSUPP; - break; - case F2FS_XATTR_INDEX_TRUSTED: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - break; - case F2FS_XATTR_INDEX_SECURITY: - break; - default: - return -EINVAL; - } - if (strcmp(name, "") == 0) - return -EINVAL; - - return f2fs_setxattr(d_inode(dentry), type, name, - value, size, NULL, flags); + return test_opt(sbi, XATTR_USER); } -static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list, - size_t list_size, const char *name, size_t len, int type) +static bool f2fs_xattr_trusted_list(struct dentry *dentry) { - const char *xname = F2FS_SYSTEM_ADVISE_PREFIX; - size_t size; - - if (type != F2FS_XATTR_INDEX_ADVISE) - return 0; - - size = strlen(xname) + 1; - if (list && size <= list_size) - memcpy(list, xname, size); - return size; + return capable(CAP_SYS_ADMIN); } -static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name, - void *buffer, size_t size, int type) +static int f2fs_xattr_advise_get(const struct xattr_handler *handler, + struct dentry *dentry, const char *name, void *buffer, + size_t size) { struct inode *inode = d_inode(dentry); - if (strcmp(name, "") != 0) - return -EINVAL; - if (buffer) *((char *)buffer) = F2FS_I(inode)->i_advise; return sizeof(char); } -static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags, int type) +static int f2fs_xattr_advise_set(const struct xattr_handler *handler, + struct dentry *dentry, const char *name, const void *value, + size_t size, int flags) { struct inode *inode = d_inode(dentry); - if (strcmp(name, "") != 0) - return -EINVAL; if (!inode_owner_or_capable(inode)) return -EPERM; if (value == NULL) @@ -185,7 +140,7 @@ int f2fs_init_security(struct inode *inode, struct inode *dir, const struct xattr_handler f2fs_xattr_user_handler = { .prefix = XATTR_USER_PREFIX, .flags = F2FS_XATTR_INDEX_USER, - .list = f2fs_xattr_generic_list, + .list = f2fs_xattr_user_list, .get = f2fs_xattr_generic_get, .set = f2fs_xattr_generic_set, }; @@ -193,15 +148,14 @@ const struct xattr_handler f2fs_xattr_user_handler = { const struct xattr_handler f2fs_xattr_trusted_handler = { .prefix = XATTR_TRUSTED_PREFIX, .flags = F2FS_XATTR_INDEX_TRUSTED, - .list = f2fs_xattr_generic_list, + .list = f2fs_xattr_trusted_list, .get = f2fs_xattr_generic_get, .set = f2fs_xattr_generic_set, }; const struct xattr_handler f2fs_xattr_advise_handler = { - .prefix = F2FS_SYSTEM_ADVISE_PREFIX, + .name = F2FS_SYSTEM_ADVISE_NAME, .flags = F2FS_XATTR_INDEX_ADVISE, - .list = f2fs_xattr_advise_list, .get = f2fs_xattr_advise_get, .set = f2fs_xattr_advise_set, }; @@ -209,7 +163,6 @@ const struct xattr_handler f2fs_xattr_advise_handler = { const struct xattr_handler f2fs_xattr_security_handler = { .prefix = XATTR_SECURITY_PREFIX, .flags = F2FS_XATTR_INDEX_SECURITY, - .list = f2fs_xattr_generic_list, .get = f2fs_xattr_generic_get, .set = f2fs_xattr_generic_set, }; @@ -347,7 +300,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, if (ipage) { inline_addr = inline_xattr_addr(ipage); - f2fs_wait_on_page_writeback(ipage, NODE); + f2fs_wait_on_page_writeback(ipage, NODE, true); } else { page = get_node_page(sbi, inode->i_ino); if (IS_ERR(page)) { @@ -355,7 +308,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, return PTR_ERR(page); } inline_addr = inline_xattr_addr(page); - f2fs_wait_on_page_writeback(page, NODE); + f2fs_wait_on_page_writeback(page, NODE, true); } memcpy(inline_addr, txattr_addr, inline_size); f2fs_put_page(page, 1); @@ -376,7 +329,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, return PTR_ERR(xpage); } f2fs_bug_on(sbi, new_nid); - f2fs_wait_on_page_writeback(xpage, NODE); + f2fs_wait_on_page_writeback(xpage, NODE, true); } else { struct dnode_of_data dn; set_new_dnode(&dn, inode, NULL, NULL, new_nid); @@ -457,20 +410,27 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) list_for_each_xattr(entry, base_addr) { const struct xattr_handler *handler = f2fs_xattr_handler(entry->e_name_index); + const char *prefix; + size_t prefix_len; size_t size; - if (!handler) + if (!handler || (handler->list && !handler->list(dentry))) continue; - size = handler->list(dentry, buffer, rest, entry->e_name, - entry->e_name_len, handler->flags); - if (buffer && size > rest) { - error = -ERANGE; - goto cleanup; + prefix = handler->prefix ?: handler->name; + prefix_len = strlen(prefix); + size = prefix_len + entry->e_name_len + 1; + if (buffer) { + if (size > rest) { + error = -ERANGE; + goto cleanup; + } + memcpy(buffer, prefix, prefix_len); + buffer += prefix_len; + memcpy(buffer, entry->e_name, entry->e_name_len); + buffer += entry->e_name_len; + *buffer++ = 0; } - - if (buffer) - buffer += size; rest -= size; } error = buffer_size - rest; @@ -611,7 +571,7 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name, if (ipage) return __f2fs_setxattr(inode, index, name, value, size, ipage, flags); - f2fs_balance_fs(sbi); + f2fs_balance_fs(sbi, true); f2fs_lock_op(sbi); /* protect xattr_ver */ @@ -620,5 +580,6 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name, up_write(&F2FS_I(inode)->i_sem); f2fs_unlock_op(sbi); + f2fs_update_time(sbi, REQ_TIME); return err; } |