return entry;
 }
 
+static struct f2fs_xattr_entry *__find_inline_xattr(void *base_addr,
+                                       void **last_addr, int index,
+                                       size_t len, const char *name)
+{
+       struct f2fs_xattr_entry *entry;
+       unsigned int inline_size = F2FS_INLINE_XATTR_ADDRS << 2;
+
+       list_for_each_xattr(entry, base_addr) {
+               if ((void *)entry + sizeof(__u32) > base_addr + inline_size ||
+                       (void *)XATTR_NEXT_ENTRY(entry) + sizeof(__u32) >
+                       base_addr + inline_size) {
+                       *last_addr = entry;
+                       return NULL;
+               }
+               if (entry->e_name_index != index)
+                       continue;
+               if (entry->e_name_len != len)
+                       continue;
+               if (!memcmp(entry->e_name, name, len))
+                       break;
+       }
+       return entry;
+}
+
+static int lookup_all_xattrs(struct inode *inode, struct page *ipage,
+                               unsigned int index, unsigned int len,
+                               const char *name, struct f2fs_xattr_entry **xe,
+                               void **base_addr)
+{
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       void *cur_addr, *txattr_addr, *last_addr = NULL;
+       nid_t xnid = F2FS_I(inode)->i_xattr_nid;
+       unsigned int size = xnid ? VALID_XATTR_BLOCK_SIZE : 0;
+       unsigned int inline_size = 0;
+       int err = 0;
+
+       inline_size = inline_xattr_size(inode);
+
+       if (!size && !inline_size)
+               return -ENODATA;
+
+       txattr_addr = kzalloc(inline_size + size + sizeof(__u32),
+                                                       GFP_F2FS_ZERO);
+       if (!txattr_addr)
+               return -ENOMEM;
+
+       /* read from inline xattr */
+       if (inline_size) {
+               struct page *page = NULL;
+               void *inline_addr;
+
+               if (ipage) {
+                       inline_addr = inline_xattr_addr(ipage);
+               } else {
+                       page = get_node_page(sbi, inode->i_ino);
+                       if (IS_ERR(page)) {
+                               err = PTR_ERR(page);
+                               goto out;
+                       }
+                       inline_addr = inline_xattr_addr(page);
+               }
+               memcpy(txattr_addr, inline_addr, inline_size);
+               f2fs_put_page(page, 1);
+
+               *xe = __find_inline_xattr(txattr_addr, &last_addr,
+                                               index, len, name);
+               if (*xe)
+                       goto check;
+       }
+
+       /* read from xattr node block */
+       if (xnid) {
+               struct page *xpage;
+               void *xattr_addr;
+
+               /* The inode already has an extended attribute block. */
+               xpage = get_node_page(sbi, xnid);
+               if (IS_ERR(xpage)) {
+                       err = PTR_ERR(xpage);
+                       goto out;
+               }
+
+               xattr_addr = page_address(xpage);
+               memcpy(txattr_addr + inline_size, xattr_addr, size);
+               f2fs_put_page(xpage, 1);
+       }
+
+       if (last_addr)
+               cur_addr = XATTR_HDR(last_addr) - 1;
+       else
+               cur_addr = txattr_addr;
+
+       *xe = __find_xattr(cur_addr, index, len, name);
+check:
+       if (IS_XATTR_LAST_ENTRY(*xe)) {
+               err = -ENODATA;
+               goto out;
+       }
+
+       *base_addr = txattr_addr;
+       return 0;
+out:
+       kzfree(txattr_addr);
+       return err;
+}
+
 static int read_all_xattrs(struct inode *inode, struct page *ipage,
                                                        void **base_addr)
 {
        }
 
        xattr_addr = page_address(xpage);
-       memcpy(xattr_addr, txattr_addr + inline_size, PAGE_SIZE -
-                                               sizeof(struct node_footer));
+       memcpy(xattr_addr, txattr_addr + inline_size, MAX_XATTR_BLOCK_SIZE);
        set_page_dirty(xpage);
        f2fs_put_page(xpage, 1);
 
 int f2fs_getxattr(struct inode *inode, int index, const char *name,
                void *buffer, size_t buffer_size, struct page *ipage)
 {
-       struct f2fs_xattr_entry *entry;
-       void *base_addr;
+       struct f2fs_xattr_entry *entry = NULL;
        int error = 0;
-       size_t size, len;
+       unsigned int size, len;
+       char *pval;
+       void *base_addr = NULL;
 
        if (name == NULL)
                return -EINVAL;
        if (len > F2FS_NAME_LEN)
                return -ERANGE;
 
-       error = read_all_xattrs(inode, ipage, &base_addr);
+       error = lookup_all_xattrs(inode, ipage, index, len, name,
+                               &entry, &base_addr);
        if (error)
                return error;
 
-       entry = __find_xattr(base_addr, index, len, name);
-       if (IS_XATTR_LAST_ENTRY(entry)) {
-               error = -ENODATA;
-               goto cleanup;
-       }
-
        size = le16_to_cpu(entry->e_value_size);
 
        if (buffer && size > buffer_size) {
                error = -ERANGE;
-               goto cleanup;
+               goto out;
        }
 
+       pval = entry->e_name + entry->e_name_len;
+
        if (buffer) {
                char *pval = entry->e_name + entry->e_name_len;
                memcpy(buffer, pval, size);
        }
        error = size;
-
-cleanup:
+out:
        kzfree(base_addr);
        return error;
 }