X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=ldiskfs%2Fkernel_patches%2Fpatches%2Fsles11sp2%2Fext4-large-eas.patch;h=38e5ff56914d7b021fbb02b55b66d94d19e5a816;hb=892f62c7a20d87954744c6c8937960379a870992;hp=90a3afd997b0120f449a0140fb79af84d0ccab39;hpb=ffd42ff529f5823b5a04529e1db2ea3b32a9f59f;p=fs%2Flustre-release.git diff --git a/ldiskfs/kernel_patches/patches/sles11sp2/ext4-large-eas.patch b/ldiskfs/kernel_patches/patches/sles11sp2/ext4-large-eas.patch index 90a3afd..38e5ff5 100644 --- a/ldiskfs/kernel_patches/patches/sles11sp2/ext4-large-eas.patch +++ b/ldiskfs/kernel_patches/patches/sles11sp2/ext4-large-eas.patch @@ -1,8 +1,14 @@ +This patch implements the large EA support in ext4. If the size of +an EA value is larger than the blocksize, then the EA value would +not be saved in the external EA block, instead it would be saved +in an external EA inode. So, the patch also helps support a larger +number of EAs. + Index: linux-stage/fs/ext4/ext4.h =================================================================== --- linux-stage.orig/fs/ext4/ext4.h +++ linux-stage/fs/ext4/ext4.h -@@ -1412,6 +1412,7 @@ static inline void ext4_clear_state_flag +@@ -1408,6 +1408,7 @@ static inline void ext4_clear_state_flag EXT4_FEATURE_INCOMPAT_EXTENTS| \ EXT4_FEATURE_INCOMPAT_64BIT| \ EXT4_FEATURE_INCOMPAT_FLEX_BG| \ @@ -10,20 +16,7 @@ Index: linux-stage/fs/ext4/ext4.h EXT4_FEATURE_INCOMPAT_MMP| \ EXT4_FEATURE_INCOMPAT_DIRDATA) -@@ -1775,6 +1776,12 @@ struct mmpd_data { - #endif - - /* -+ * Maximum size of xattr attributes for FEATURE_INCOMPAT_EA_INODE 1Mb -+ * This limit is arbitrary, but is reasonable for the xattr API. -+ */ -+#define EXT4_XATTR_MAX_LARGE_EA_SIZE (1024 * 1024) -+ -+/* - * Function prototypes - */ - -@@ -1786,6 +1793,10 @@ struct mmpd_data { +@@ -1775,6 +1782,10 @@ struct mmpd_data { # define ATTRIB_NORET __attribute__((noreturn)) # define NORET_AND noreturn, @@ -34,7 +27,7 @@ Index: linux-stage/fs/ext4/ext4.h /* bitmap.c */ extern unsigned int ext4_count_free(char *bitmap, unsigned numchars); -@@ -1905,6 +1916,7 @@ extern void ext4_set_inode_flags(struct +@@ -1893,6 +1904,7 @@ extern void ext4_set_inode_flags(struct extern void ext4_get_inode_flags(struct ext4_inode_info *); extern int ext4_alloc_da_blocks(struct inode *inode); extern void ext4_set_aops(struct inode *inode); @@ -55,17 +48,7 @@ Index: linux-stage/fs/ext4/inode.c trace_ext4_evict_inode(inode); -@@ -197,6 +199,9 @@ void ext4_evict_inode(struct inode *inod - goto no_delete; - } - -+ if (!IS_NOQUOTA(inode)) -+ extra_credits += 2 * EXT4_QUOTA_DEL_BLOCKS(inode->i_sb); -+ - if (!is_bad_inode(inode)) - dquot_initialize(inode); - -@@ -207,7 +212,10 @@ void ext4_evict_inode(struct inode *inod +@@ -207,7 +209,10 @@ void ext4_evict_inode(struct inode *inod if (is_bad_inode(inode)) goto no_delete; @@ -77,7 +60,7 @@ Index: linux-stage/fs/ext4/inode.c if (IS_ERR(handle)) { ext4_std_error(inode->i_sb, PTR_ERR(handle)); /* -@@ -218,9 +226,30 @@ void ext4_evict_inode(struct inode *inod +@@ -218,9 +223,33 @@ void ext4_evict_inode(struct inode *inod ext4_orphan_del(NULL, inode); goto no_delete; } @@ -92,6 +75,9 @@ Index: linux-stage/fs/ext4/inode.c + goto stop_handle; + } + ++ if (!IS_NOQUOTA(inode)) ++ extra_credits += 2 * EXT4_QUOTA_DEL_BLOCKS(inode->i_sb); ++ + if (!ext4_handle_has_enough_credits(handle, + blocks_for_truncate(inode) + extra_credits)) { + err = ext4_journal_extend(handle, @@ -135,7 +121,7 @@ Index: linux-stage/fs/ext4/inode.c return; no_delete: ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ -@@ -5551,7 +5584,7 @@ static int ext4_index_trans_blocks(struc +@@ -5552,7 +5585,7 @@ static int ext4_index_trans_blocks(struc * * Also account for superblock, inode, quota and xattr blocks */ @@ -159,11 +145,10 @@ Index: linux-stage/fs/ext4/xattr.c size_t value_size = le32_to_cpu(entry->e_value_size); - if (entry->e_value_block != 0 || value_size > size || -- le16_to_cpu(entry->e_value_offs) + value_size > size) -+ if ((entry->e_value_inum == 0) && -+ (le16_to_cpu(entry->e_value_offs) + value_size > size)) ++ if (!entry->e_value_inum && + le16_to_cpu(entry->e_value_offs) + value_size > size) + return -EIO; -+ if (entry->e_value_inum != 0 && ++ if (entry->e_value_inum && + (le32_to_cpu(entry->e_value_inum) < EXT4_FIRST_INO(inode->i_sb) || + le32_to_cpu(entry->e_value_inum) > + le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_inodes_count))) @@ -179,7 +164,7 @@ Index: linux-stage/fs/ext4/xattr.c { struct ext4_xattr_entry *entry; size_t name_len; -@@ -200,11 +207,103 @@ ext4_xattr_find_entry(struct ext4_xattr_ +@@ -200,11 +207,104 @@ ext4_xattr_find_entry(struct ext4_xattr_ break; } *pentry = entry; @@ -226,28 +211,29 @@ Index: linux-stage/fs/ext4/xattr.c + return err; +} + -+struct inode *ext4_xattr_inode_iget(struct inode *parent, int ea_ino, int *err) ++struct inode *ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino, int *err) +{ + struct inode *ea_inode = NULL; + + ea_inode = ext4_iget(parent->i_sb, ea_ino); + if (IS_ERR(ea_inode) || is_bad_inode(ea_inode)) { -+ ext4_error(parent->i_sb, "error while reading EA inode %d", -+ ea_ino); -+ *err = -EIO; ++ int rc = IS_ERR(ea_inode) ? PTR_ERR(ea_inode) : 0; ++ ext4_error(parent->i_sb, "error while reading EA inode %lu " ++ "/ %d %d", ea_ino, rc, is_bad_inode(ea_inode)); ++ *err = rc != 0 ? rc : -EIO; + return NULL; + } + -+ if (ea_inode->i_xattr_inode_parent != parent->i_ino || ++ if (EXT4_XATTR_INODE_GET_PARENT(ea_inode) != parent->i_ino || + ea_inode->i_generation != parent->i_generation) { -+ ext4_error(parent->i_sb, "Backpointer from EA inode %d " ++ ext4_error(parent->i_sb, "Backpointer from EA inode %lu " + "to parent invalid.", ea_ino); + *err = -EINVAL; + goto error; + } + + if (!(EXT4_I(ea_inode)->i_flags & EXT4_EA_INODE_FL)) { -+ ext4_error(parent->i_sb, "EA inode %d does not have " ++ ext4_error(parent->i_sb, "EA inode %lu does not have " + "EXT4_EA_INODE_FL flag set.\n", ea_ino); + *err = -EINVAL; + goto error; @@ -265,7 +251,7 @@ Index: linux-stage/fs/ext4/xattr.c + * Read the value from the EA inode. + */ +static int -+ext4_xattr_inode_get(struct inode *inode, int ea_ino, void *buffer, ++ext4_xattr_inode_get(struct inode *inode, unsigned long ea_ino, void *buffer, + size_t *size) +{ + struct inode *ea_inode = NULL; @@ -300,7 +286,7 @@ Index: linux-stage/fs/ext4/xattr.c goto cleanup; - memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs), - size); -+ if (entry->e_value_inum != 0) { ++ if (entry->e_value_inum) { + error = ext4_xattr_inode_get(inode, + le32_to_cpu(entry->e_value_inum), + buffer, &size); @@ -328,7 +314,7 @@ Index: linux-stage/fs/ext4/xattr.c goto cleanup; - memcpy(buffer, (void *)IFIRST(header) + - le16_to_cpu(entry->e_value_offs), size); -+ if (entry->e_value_inum != 0) { ++ if (entry->e_value_inum) { + error = ext4_xattr_inode_get(inode, + le32_to_cpu(entry->e_value_inum), + buffer, &size); @@ -346,7 +332,7 @@ Index: linux-stage/fs/ext4/xattr.c for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { *total += EXT4_XATTR_LEN(last->e_name_len); - if (!last->e_value_block && last->e_value_size) { -+ if (last->e_value_inum == 0 && last->e_value_size > 0) { ++ if (!last->e_value_inum && last->e_value_size) { size_t offs = le16_to_cpu(last->e_value_offs); if (offs < *min_offs) *min_offs = offs; @@ -452,7 +438,7 @@ Index: linux-stage/fs/ext4/xattr.c + * A back-pointer from EA inode to parent inode will be useful + * for e2fsck. + */ -+ ea_inode->i_xattr_inode_parent = inode->i_ino; ++ EXT4_XATTR_INODE_SET_PARENT(ea_inode, inode->i_ino); + unlock_new_inode(ea_inode); + } + @@ -463,7 +449,7 @@ Index: linux-stage/fs/ext4/xattr.c + * Unlink the inode storing the value of the EA. + */ +int -+ext4_xattr_inode_unlink(struct inode *inode, int ea_ino) ++ext4_xattr_inode_unlink(struct inode *inode, unsigned long ea_ino) +{ + struct inode *ea_inode = NULL; + int err; @@ -482,7 +468,7 @@ Index: linux-stage/fs/ext4/xattr.c + * Add value of the EA in an inode. + */ +static int -+ext4_xattr_inode_set(handle_t *handle, struct inode *inode, int *ea_ino, ++ext4_xattr_inode_set(handle_t *handle, struct inode *inode, unsigned long *ea_ino, + const void *value, size_t value_len) +{ + struct inode *ea_inode = NULL; @@ -536,7 +522,7 @@ Index: linux-stage/fs/ext4/xattr.c last = s->first; for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { - if (!last->e_value_block && last->e_value_size) { -+ if (last->e_value_inum == 0 && last->e_value_size > 0) { ++ if (!last->e_value_inum && last->e_value_size) { size_t offs = le16_to_cpu(last->e_value_offs); if (offs < min_offs) min_offs = offs; @@ -545,8 +531,8 @@ Index: linux-stage/fs/ext4/xattr.c free = min_offs - ((void *)last - s->base) - sizeof(__u32); if (!s->not_found) { - if (!s->here->e_value_block && s->here->e_value_size) { -+ if (!in_inode && s->here->e_value_inum == 0 && -+ s->here->e_value_size > 0) { ++ if (!in_inode && ++ !s->here->e_value_inum && s->here->e_value_size) { size_t size = le32_to_cpu(s->here->e_value_size); free += EXT4_XATTR_SIZE(size); } @@ -571,24 +557,24 @@ Index: linux-stage/fs/ext4/xattr.c memcpy(s->here->e_name, i->name, name_len); } else { - if (!s->here->e_value_block && s->here->e_value_size) { -+ if (s->here->e_value_offs > 0 && s->here->e_value_inum == 0 && -+ s->here->e_value_size > 0) { ++ if (!s->here->e_value_inum && s->here->e_value_size && ++ s->here->e_value_offs > 0) { void *first_val = s->base + min_offs; size_t offs = le16_to_cpu(s->here->e_value_offs); void *val = s->base + offs; -@@ -607,13 +888,17 @@ ext4_xattr_set_entry(struct ext4_xattr_i +@@ -607,13 +888,18 @@ ext4_xattr_set_entry(struct ext4_xattr_i last = s->first; while (!IS_LAST_ENTRY(last)) { size_t o = le16_to_cpu(last->e_value_offs); - if (!last->e_value_block && -- last->e_value_size && o < offs) -+ if (last->e_value_size > 0 && o < offs) ++ if (!last->e_value_inum && + last->e_value_size && o < offs) last->e_value_offs = cpu_to_le16(o + size); last = EXT4_XATTR_NEXT(last); } } -+ if (s->here->e_value_inum != 0) { ++ if (s->here->e_value_inum) { + ext4_xattr_inode_unlink(inode, + le32_to_cpu(s->here->e_value_inum)); + s->here->e_value_inum = 0; @@ -602,7 +588,7 @@ Index: linux-stage/fs/ext4/xattr.c s->here->e_value_size = cpu_to_le32(i->value_len); - if (i->value_len) { + if (in_inode) { -+ int ea_ino = le32_to_cpu(s->here->e_value_inum); ++ unsigned long ea_ino = le32_to_cpu(s->here->e_value_inum); + ext4_xattr_inode_set(handle, inode, &ea_ino, i->value, + i->value_len); + s->here->e_value_inum = cpu_to_le32(ea_ino); @@ -694,7 +680,7 @@ Index: linux-stage/fs/ext4/xattr.c if (error) goto cleanup; if (!is.s.not_found) { -@@ -1089,10 +1388,25 @@ ext4_xattr_set(struct inode *inode, int +@@ -1088,10 +1387,25 @@ ext4_xattr_set(struct inode *inode, int const void *value, size_t value_len, int flags) { handle_t *handle; @@ -721,7 +707,7 @@ Index: linux-stage/fs/ext4/xattr.c if (IS_ERR(handle)) { error = PTR_ERR(handle); } else { -@@ -1102,7 +1416,7 @@ retry: +@@ -1101,7 +1415,7 @@ retry: value, value_len, flags); error2 = ext4_journal_stop(handle); if (error == -ENOSPC && @@ -730,20 +716,19 @@ Index: linux-stage/fs/ext4/xattr.c goto retry; if (error == 0) error = error2; -@@ -1124,7 +1438,7 @@ static void ext4_xattr_shift_entries(str +@@ -1123,7 +1437,7 @@ static void ext4_xattr_shift_entries(str /* Adjust the value offsets of the entries */ for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { - if (!last->e_value_block && last->e_value_size) { -+ if (last->e_value_inum == 0 && last->e_value_size > 0) { ++ if (!last->e_value_inum && last->e_value_size) { new_offs = le16_to_cpu(last->e_value_offs) + value_offs_shift; BUG_ON(new_offs + le32_to_cpu(last->e_value_size) -@@ -1359,20 +1673,92 @@ cleanup: +@@ -1358,22 +1672,135 @@ cleanup: return error; } -- +#define EIA_INCR 16 /* must be 2^n */ +#define EIA_MASK (EIA_INCR - 1) +/* Add the large xattr @ino into @lea_ino_array for later deletion. @@ -779,13 +764,50 @@ Index: linux-stage/fs/ext4/xattr.c + return -ENOMEM; + memcpy(new_array, *lea_ino_array, + offsetof(struct ext4_xattr_ino_array, -+ xia_inodes[count])); ++ xia_inodes[count])); + kfree(*lea_ino_array); + *lea_ino_array = new_array; + } + (*lea_ino_array)->xia_inodes[(*lea_ino_array)->xia_count++] = ino; + return 0; +} ++ ++/** ++ * Add xattr inode to orphan list ++ */ ++static int ++ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode, ++ int credits, struct ext4_xattr_ino_array *lea_ino_array) ++{ ++ struct inode *ea_inode = NULL; ++ int idx = 0, error = 0; ++ ++ if (lea_ino_array == NULL) ++ return 0; + ++ for (; idx < lea_ino_array->xia_count; ++idx) { ++ if (!ext4_handle_has_enough_credits(handle, credits)) { ++ error = ext4_journal_extend(handle, credits); ++ if (error > 0) ++ error = ext4_journal_restart(handle, credits); ++ ++ if (error != 0) { ++ ext4_warning(inode->i_sb, ++ "couldn't extend journal " ++ "(err %d)", error); ++ return error; ++ } ++ } ++ ea_inode = ext4_xattr_inode_iget(inode, ++ lea_ino_array->xia_inodes[idx], &error); ++ if (error) ++ continue; ++ ext4_orphan_add(handle, ea_inode); ++ /* the inode's i_count will be released by caller */ ++ } ++ ++ return 0; ++} /* * ext4_xattr_delete_inode() @@ -810,19 +832,20 @@ Index: linux-stage/fs/ext4/xattr.c + struct ext4_inode *raw_inode; + struct ext4_iloc iloc; + struct ext4_xattr_entry *entry; -+ int error = 0; -+ ++ int credits = 3, error = 0; + +- if (!EXT4_I(inode)->i_file_acl) + if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR)) + goto delete_external_ea; + + error = ext4_get_inode_loc(inode, &iloc); + if (error) -+ goto cleanup; + goto cleanup; + raw_inode = ext4_raw_inode(&iloc); + header = IHDR(inode, raw_inode); -+ entry = IFIRST(header); -+ for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { -+ if (entry->e_value_inum == 0) ++ for (entry = IFIRST(header); !IS_LAST_ENTRY(entry); ++ entry = EXT4_XATTR_NEXT(entry)) { ++ if (!entry->e_value_inum) + continue; + if (ext4_expand_ino_array(lea_ino_array, + entry->e_value_inum) != 0) { @@ -832,19 +855,25 @@ Index: linux-stage/fs/ext4/xattr.c + entry->e_value_inum = 0; + } + brelse(iloc.bh); - ++ +delete_external_ea: - if (!EXT4_I(inode)->i_file_acl) - goto cleanup; ++ if (!EXT4_I(inode)->i_file_acl) { ++ /* add xattr inode to orphan list */ ++ ext4_xattr_inode_orphan_add(handle, inode, credits, ++ *lea_ino_array); ++ goto cleanup; ++ } bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl); -@@ -1387,11 +1770,74 @@ ext4_xattr_delete_inode(handle_t *handle + if (!bh) { + EXT4_ERROR_INODE(inode, "block %llu read error", +@@ -1386,11 +1813,69 @@ ext4_xattr_delete_inode(handle_t *handle EXT4_I(inode)->i_file_acl); goto cleanup; } + -+ entry = BFIRST(bh); -+ for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { -+ if (entry->e_value_inum == 0) ++ for (entry = BFIRST(bh); !IS_LAST_ENTRY(entry); ++ entry = EXT4_XATTR_NEXT(entry)) { ++ if (!entry->e_value_inum) + continue; + if (ext4_expand_ino_array(lea_ino_array, + entry->e_value_inum) != 0) @@ -853,28 +882,22 @@ Index: linux-stage/fs/ext4/xattr.c + } + + /* adding xattr inode to orphan list */ -+ if (*lea_ino_array != NULL) { -+ struct inode *ea_inode = NULL; -+ int idx = (*lea_ino_array)->xia_count; -+ -+ for (idx = 0; idx < (*lea_ino_array)->xia_count; ++idx) { -+ if (!ext4_handle_has_enough_credits(handle, 3)) { -+ error = ext4_journal_extend(handle, 3); -+ if (error > 0) -+ error = ext4_journal_restart(handle, 3); -+ if (error != 0) { -+ ext4_warning(inode->i_sb, -+ "couldn't extend journal " -+ "(err %d)", error); -+ goto cleanup; -+ } -+ } -+ ea_inode = ext4_xattr_inode_iget(inode, -+ (*lea_ino_array)->xia_inodes[idx], &error); -+ if (error) -+ continue; -+ ext4_orphan_add(handle, ea_inode); -+ /* the inode's i_count will be released by caller */ ++ error = ext4_xattr_inode_orphan_add(handle, inode, credits, ++ *lea_ino_array); ++ if (error != 0) ++ goto cleanup; ++ ++ if (!IS_NOQUOTA(inode)) ++ credits += 2 * EXT4_QUOTA_DEL_BLOCKS(inode->i_sb); ++ ++ if (!ext4_handle_has_enough_credits(handle, credits)) { ++ error = ext4_journal_extend(handle, credits); ++ if (error > 0) ++ error = ext4_journal_restart(handle, credits); ++ if (error != 0) { ++ ext4_warning(inode->i_sb, ++ "couldn't extend journal (err %d)", error); ++ goto cleanup; + } + } + @@ -903,16 +926,17 @@ Index: linux-stage/fs/ext4/xattr.c + lea_ino_array->xia_inodes[idx], &err); + if (err) + continue; -+ ea_inode->i_nlink = 0; -+ iput(ea_inode); + /* for inode's i_count get from ext4_xattr_delete_inode */ ++ if (!list_empty(&EXT4_I(ea_inode)->i_orphan)) ++ iput(ea_inode); ++ ea_inode->i_nlink = 0; + iput(ea_inode); + } + kfree(lea_ino_array); } /* -@@ -1461,10 +1907,9 @@ ext4_xattr_cmp(struct ext4_xattr_header +@@ -1460,10 +1945,9 @@ ext4_xattr_cmp(struct ext4_xattr_header entry1->e_name_index != entry2->e_name_index || entry1->e_name_len != entry2->e_name_len || entry1->e_value_size != entry2->e_value_size || @@ -924,12 +948,12 @@ Index: linux-stage/fs/ext4/xattr.c if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), (char *)header2 + le16_to_cpu(entry2->e_value_offs), le32_to_cpu(entry1->e_value_size))) -@@ -1548,7 +1993,7 @@ static inline void ext4_xattr_hash_entry +@@ -1547,7 +2031,7 @@ static inline void ext4_xattr_hash_entry *name++; } - if (entry->e_value_block == 0 && entry->e_value_size != 0) { -+ if (entry->e_value_inum == 0 && entry->e_value_size != 0) { ++ if (!entry->e_value_inum && entry->e_value_size) { __le32 *value = (__le32 *)((char *)header + le16_to_cpu(entry->e_value_offs)); for (n = (le32_to_cpu(entry->e_value_size) + @@ -946,11 +970,22 @@ Index: linux-stage/fs/ext4/xattr.h __le32 e_value_size; /* size of attribute value */ __le32 e_hash; /* hash value of name and value */ char e_name[0]; /* attribute name */ -@@ -63,6 +63,15 @@ struct ext4_xattr_entry { +@@ -63,6 +63,26 @@ struct ext4_xattr_entry { EXT4_I(inode)->i_extra_isize)) #define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1)) -+#define i_xattr_inode_parent i_mtime.tv_sec ++/* ++ * Link EA inode back to parent one using i_mtime field. ++ * Extra integer type conversion added to ignore higher ++ * bits in i_mtime.tv_sec which might be set by ext4_get() ++ */ ++#define EXT4_XATTR_INODE_SET_PARENT(inode, inum) \ ++do { \ ++ (inode)->i_mtime.tv_sec = inum; \ ++} while(0) ++ ++#define EXT4_XATTR_INODE_GET_PARENT(inode) \ ++((__u32)(inode)->i_mtime.tv_sec) + +/* + * The minimum size of EA value when you start storing it in an external inode @@ -967,9 +1002,9 @@ Index: linux-stage/fs/ext4/xattr.h extern int ext4_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int); -extern void ext4_xattr_delete_inode(handle_t *, struct inode *); -+extern struct inode *ext4_xattr_inode_iget(struct inode *parent, int ea_ino, ++extern struct inode *ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino, + int *err); -+extern int ext4_xattr_inode_unlink(struct inode *inode, int ea_ino); ++extern int ext4_xattr_inode_unlink(struct inode *inode, unsigned long ea_ino); +extern int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, + struct ext4_xattr_ino_array **array); +extern void ext4_xattr_inode_array_free(struct inode *inode, @@ -995,7 +1030,7 @@ Index: linux-stage/fs/ext4/ialloc.c =================================================================== --- linux-stage.orig/fs/ext4/ialloc.c +++ linux-stage/fs/ext4/ialloc.c -@@ -222,7 +222,6 @@ void ext4_free_inode(handle_t *handle, s +@@ -221,7 +221,6 @@ void ext4_free_inode(handle_t *handle, s * as writing the quota to disk may need the lock as well. */ dquot_initialize(inode);