167cf5b09STao Ma /* 267cf5b09STao Ma * Copyright (c) 2012 Taobao. 367cf5b09STao Ma * Written by Tao Ma <boyu.mt@taobao.com> 467cf5b09STao Ma * 567cf5b09STao Ma * This program is free software; you can redistribute it and/or modify it 667cf5b09STao Ma * under the terms of version 2.1 of the GNU Lesser General Public License 767cf5b09STao Ma * as published by the Free Software Foundation. 867cf5b09STao Ma * 967cf5b09STao Ma * This program is distributed in the hope that it will be useful, 1067cf5b09STao Ma * but WITHOUT ANY WARRANTY; without even the implied warranty of 1167cf5b09STao Ma * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1267cf5b09STao Ma * GNU General Public License for more details. 1367cf5b09STao Ma */ 1467cf5b09STao Ma #include "ext4_jbd2.h" 1567cf5b09STao Ma #include "ext4.h" 1667cf5b09STao Ma #include "xattr.h" 17f19d5870STao Ma #include "truncate.h" 1894191985STao Ma #include <linux/fiemap.h> 1967cf5b09STao Ma 2067cf5b09STao Ma #define EXT4_XATTR_SYSTEM_DATA "data" 2167cf5b09STao Ma #define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS)) 223c47d541STao Ma #define EXT4_INLINE_DOTDOT_SIZE 4 2367cf5b09STao Ma 2467cf5b09STao Ma int ext4_get_inline_size(struct inode *inode) 2567cf5b09STao Ma { 2667cf5b09STao Ma if (EXT4_I(inode)->i_inline_off) 2767cf5b09STao Ma return EXT4_I(inode)->i_inline_size; 2867cf5b09STao Ma 2967cf5b09STao Ma return 0; 3067cf5b09STao Ma } 3167cf5b09STao Ma 3267cf5b09STao Ma static int get_max_inline_xattr_value_size(struct inode *inode, 3367cf5b09STao Ma struct ext4_iloc *iloc) 3467cf5b09STao Ma { 3567cf5b09STao Ma struct ext4_xattr_ibody_header *header; 3667cf5b09STao Ma struct ext4_xattr_entry *entry; 3767cf5b09STao Ma struct ext4_inode *raw_inode; 3867cf5b09STao Ma int free, min_offs; 3967cf5b09STao Ma 4067cf5b09STao Ma min_offs = EXT4_SB(inode->i_sb)->s_inode_size - 4167cf5b09STao Ma EXT4_GOOD_OLD_INODE_SIZE - 4267cf5b09STao Ma EXT4_I(inode)->i_extra_isize - 4367cf5b09STao Ma sizeof(struct ext4_xattr_ibody_header); 4467cf5b09STao Ma 4567cf5b09STao Ma /* 4667cf5b09STao Ma * We need to subtract another sizeof(__u32) since an in-inode xattr 4767cf5b09STao Ma * needs an empty 4 bytes to indicate the gap between the xattr entry 4867cf5b09STao Ma * and the name/value pair. 4967cf5b09STao Ma */ 5067cf5b09STao Ma if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR)) 5167cf5b09STao Ma return EXT4_XATTR_SIZE(min_offs - 5267cf5b09STao Ma EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA)) - 5367cf5b09STao Ma EXT4_XATTR_ROUND - sizeof(__u32)); 5467cf5b09STao Ma 5567cf5b09STao Ma raw_inode = ext4_raw_inode(iloc); 5667cf5b09STao Ma header = IHDR(inode, raw_inode); 5767cf5b09STao Ma entry = IFIRST(header); 5867cf5b09STao Ma 5967cf5b09STao Ma /* Compute min_offs. */ 6067cf5b09STao Ma for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { 6167cf5b09STao Ma if (!entry->e_value_block && entry->e_value_size) { 6267cf5b09STao Ma size_t offs = le16_to_cpu(entry->e_value_offs); 6367cf5b09STao Ma if (offs < min_offs) 6467cf5b09STao Ma min_offs = offs; 6567cf5b09STao Ma } 6667cf5b09STao Ma } 6767cf5b09STao Ma free = min_offs - 6867cf5b09STao Ma ((void *)entry - (void *)IFIRST(header)) - sizeof(__u32); 6967cf5b09STao Ma 7067cf5b09STao Ma if (EXT4_I(inode)->i_inline_off) { 7167cf5b09STao Ma entry = (struct ext4_xattr_entry *) 7267cf5b09STao Ma ((void *)raw_inode + EXT4_I(inode)->i_inline_off); 7367cf5b09STao Ma 7467cf5b09STao Ma free += le32_to_cpu(entry->e_value_size); 7567cf5b09STao Ma goto out; 7667cf5b09STao Ma } 7767cf5b09STao Ma 7867cf5b09STao Ma free -= EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA)); 7967cf5b09STao Ma 8067cf5b09STao Ma if (free > EXT4_XATTR_ROUND) 8167cf5b09STao Ma free = EXT4_XATTR_SIZE(free - EXT4_XATTR_ROUND); 8267cf5b09STao Ma else 8367cf5b09STao Ma free = 0; 8467cf5b09STao Ma 8567cf5b09STao Ma out: 8667cf5b09STao Ma return free; 8767cf5b09STao Ma } 8867cf5b09STao Ma 8967cf5b09STao Ma /* 9067cf5b09STao Ma * Get the maximum size we now can store in an inode. 9167cf5b09STao Ma * If we can't find the space for a xattr entry, don't use the space 9267cf5b09STao Ma * of the extents since we have no space to indicate the inline data. 9367cf5b09STao Ma */ 9467cf5b09STao Ma int ext4_get_max_inline_size(struct inode *inode) 9567cf5b09STao Ma { 9667cf5b09STao Ma int error, max_inline_size; 9767cf5b09STao Ma struct ext4_iloc iloc; 9867cf5b09STao Ma 9967cf5b09STao Ma if (EXT4_I(inode)->i_extra_isize == 0) 10067cf5b09STao Ma return 0; 10167cf5b09STao Ma 10267cf5b09STao Ma error = ext4_get_inode_loc(inode, &iloc); 10367cf5b09STao Ma if (error) { 10467cf5b09STao Ma ext4_error_inode(inode, __func__, __LINE__, 0, 10567cf5b09STao Ma "can't get inode location %lu", 10667cf5b09STao Ma inode->i_ino); 10767cf5b09STao Ma return 0; 10867cf5b09STao Ma } 10967cf5b09STao Ma 11067cf5b09STao Ma down_read(&EXT4_I(inode)->xattr_sem); 11167cf5b09STao Ma max_inline_size = get_max_inline_xattr_value_size(inode, &iloc); 11267cf5b09STao Ma up_read(&EXT4_I(inode)->xattr_sem); 11367cf5b09STao Ma 11467cf5b09STao Ma brelse(iloc.bh); 11567cf5b09STao Ma 11667cf5b09STao Ma if (!max_inline_size) 11767cf5b09STao Ma return 0; 11867cf5b09STao Ma 11967cf5b09STao Ma return max_inline_size + EXT4_MIN_INLINE_DATA_SIZE; 12067cf5b09STao Ma } 12167cf5b09STao Ma 12267cf5b09STao Ma int ext4_has_inline_data(struct inode *inode) 12367cf5b09STao Ma { 12467cf5b09STao Ma return ext4_test_inode_flag(inode, EXT4_INODE_INLINE_DATA) && 12567cf5b09STao Ma EXT4_I(inode)->i_inline_off; 12667cf5b09STao Ma } 12767cf5b09STao Ma 12867cf5b09STao Ma /* 12967cf5b09STao Ma * this function does not take xattr_sem, which is OK because it is 13067cf5b09STao Ma * currently only used in a code path coming form ext4_iget, before 13167cf5b09STao Ma * the new inode has been unlocked 13267cf5b09STao Ma */ 13367cf5b09STao Ma int ext4_find_inline_data_nolock(struct inode *inode) 13467cf5b09STao Ma { 13567cf5b09STao Ma struct ext4_xattr_ibody_find is = { 13667cf5b09STao Ma .s = { .not_found = -ENODATA, }, 13767cf5b09STao Ma }; 13867cf5b09STao Ma struct ext4_xattr_info i = { 13967cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 14067cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 14167cf5b09STao Ma }; 14267cf5b09STao Ma int error; 14367cf5b09STao Ma 14467cf5b09STao Ma if (EXT4_I(inode)->i_extra_isize == 0) 14567cf5b09STao Ma return 0; 14667cf5b09STao Ma 14767cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 14867cf5b09STao Ma if (error) 14967cf5b09STao Ma return error; 15067cf5b09STao Ma 15167cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 15267cf5b09STao Ma if (error) 15367cf5b09STao Ma goto out; 15467cf5b09STao Ma 15567cf5b09STao Ma if (!is.s.not_found) { 15667cf5b09STao Ma EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here - 15767cf5b09STao Ma (void *)ext4_raw_inode(&is.iloc)); 15867cf5b09STao Ma EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE + 15967cf5b09STao Ma le32_to_cpu(is.s.here->e_value_size); 16067cf5b09STao Ma ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 16167cf5b09STao Ma } 16267cf5b09STao Ma out: 16367cf5b09STao Ma brelse(is.iloc.bh); 16467cf5b09STao Ma return error; 16567cf5b09STao Ma } 16667cf5b09STao Ma 16767cf5b09STao Ma static int ext4_read_inline_data(struct inode *inode, void *buffer, 16867cf5b09STao Ma unsigned int len, 16967cf5b09STao Ma struct ext4_iloc *iloc) 17067cf5b09STao Ma { 17167cf5b09STao Ma struct ext4_xattr_entry *entry; 17267cf5b09STao Ma struct ext4_xattr_ibody_header *header; 17367cf5b09STao Ma int cp_len = 0; 17467cf5b09STao Ma struct ext4_inode *raw_inode; 17567cf5b09STao Ma 17667cf5b09STao Ma if (!len) 17767cf5b09STao Ma return 0; 17867cf5b09STao Ma 17967cf5b09STao Ma BUG_ON(len > EXT4_I(inode)->i_inline_size); 18067cf5b09STao Ma 18167cf5b09STao Ma cp_len = len < EXT4_MIN_INLINE_DATA_SIZE ? 18267cf5b09STao Ma len : EXT4_MIN_INLINE_DATA_SIZE; 18367cf5b09STao Ma 18467cf5b09STao Ma raw_inode = ext4_raw_inode(iloc); 18567cf5b09STao Ma memcpy(buffer, (void *)(raw_inode->i_block), cp_len); 18667cf5b09STao Ma 18767cf5b09STao Ma len -= cp_len; 18867cf5b09STao Ma buffer += cp_len; 18967cf5b09STao Ma 19067cf5b09STao Ma if (!len) 19167cf5b09STao Ma goto out; 19267cf5b09STao Ma 19367cf5b09STao Ma header = IHDR(inode, raw_inode); 19467cf5b09STao Ma entry = (struct ext4_xattr_entry *)((void *)raw_inode + 19567cf5b09STao Ma EXT4_I(inode)->i_inline_off); 19667cf5b09STao Ma len = min_t(unsigned int, len, 19767cf5b09STao Ma (unsigned int)le32_to_cpu(entry->e_value_size)); 19867cf5b09STao Ma 19967cf5b09STao Ma memcpy(buffer, 20067cf5b09STao Ma (void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs), len); 20167cf5b09STao Ma cp_len += len; 20267cf5b09STao Ma 20367cf5b09STao Ma out: 20467cf5b09STao Ma return cp_len; 20567cf5b09STao Ma } 20667cf5b09STao Ma 20767cf5b09STao Ma /* 20867cf5b09STao Ma * write the buffer to the inline inode. 20967cf5b09STao Ma * If 'create' is set, we don't need to do the extra copy in the xattr 2100d812f77STao Ma * value since it is already handled by ext4_xattr_ibody_inline_set. 2110d812f77STao Ma * That saves us one memcpy. 21267cf5b09STao Ma */ 21367cf5b09STao Ma void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc, 21467cf5b09STao Ma void *buffer, loff_t pos, unsigned int len) 21567cf5b09STao Ma { 21667cf5b09STao Ma struct ext4_xattr_entry *entry; 21767cf5b09STao Ma struct ext4_xattr_ibody_header *header; 21867cf5b09STao Ma struct ext4_inode *raw_inode; 21967cf5b09STao Ma int cp_len = 0; 22067cf5b09STao Ma 22167cf5b09STao Ma BUG_ON(!EXT4_I(inode)->i_inline_off); 22267cf5b09STao Ma BUG_ON(pos + len > EXT4_I(inode)->i_inline_size); 22367cf5b09STao Ma 22467cf5b09STao Ma raw_inode = ext4_raw_inode(iloc); 22567cf5b09STao Ma buffer += pos; 22667cf5b09STao Ma 22767cf5b09STao Ma if (pos < EXT4_MIN_INLINE_DATA_SIZE) { 22867cf5b09STao Ma cp_len = pos + len > EXT4_MIN_INLINE_DATA_SIZE ? 22967cf5b09STao Ma EXT4_MIN_INLINE_DATA_SIZE - pos : len; 23067cf5b09STao Ma memcpy((void *)raw_inode->i_block + pos, buffer, cp_len); 23167cf5b09STao Ma 23267cf5b09STao Ma len -= cp_len; 23367cf5b09STao Ma buffer += cp_len; 23467cf5b09STao Ma pos += cp_len; 23567cf5b09STao Ma } 23667cf5b09STao Ma 23767cf5b09STao Ma if (!len) 23867cf5b09STao Ma return; 23967cf5b09STao Ma 24067cf5b09STao Ma pos -= EXT4_MIN_INLINE_DATA_SIZE; 24167cf5b09STao Ma header = IHDR(inode, raw_inode); 24267cf5b09STao Ma entry = (struct ext4_xattr_entry *)((void *)raw_inode + 24367cf5b09STao Ma EXT4_I(inode)->i_inline_off); 24467cf5b09STao Ma 24567cf5b09STao Ma memcpy((void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs) + pos, 24667cf5b09STao Ma buffer, len); 24767cf5b09STao Ma } 24867cf5b09STao Ma 24967cf5b09STao Ma static int ext4_create_inline_data(handle_t *handle, 25067cf5b09STao Ma struct inode *inode, unsigned len) 25167cf5b09STao Ma { 25267cf5b09STao Ma int error; 25367cf5b09STao Ma void *value = NULL; 25467cf5b09STao Ma struct ext4_xattr_ibody_find is = { 25567cf5b09STao Ma .s = { .not_found = -ENODATA, }, 25667cf5b09STao Ma }; 25767cf5b09STao Ma struct ext4_xattr_info i = { 25867cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 25967cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 26067cf5b09STao Ma }; 26167cf5b09STao Ma 26267cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 26367cf5b09STao Ma if (error) 26467cf5b09STao Ma return error; 26567cf5b09STao Ma 26667cf5b09STao Ma error = ext4_journal_get_write_access(handle, is.iloc.bh); 26767cf5b09STao Ma if (error) 26867cf5b09STao Ma goto out; 26967cf5b09STao Ma 27067cf5b09STao Ma if (len > EXT4_MIN_INLINE_DATA_SIZE) { 271*bd9926e8STheodore Ts'o value = EXT4_ZERO_XATTR_VALUE; 27267cf5b09STao Ma len -= EXT4_MIN_INLINE_DATA_SIZE; 27367cf5b09STao Ma } else { 27467cf5b09STao Ma value = ""; 27567cf5b09STao Ma len = 0; 27667cf5b09STao Ma } 27767cf5b09STao Ma 27867cf5b09STao Ma /* Insert the the xttr entry. */ 27967cf5b09STao Ma i.value = value; 28067cf5b09STao Ma i.value_len = len; 28167cf5b09STao Ma 28267cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 28367cf5b09STao Ma if (error) 28467cf5b09STao Ma goto out; 28567cf5b09STao Ma 28667cf5b09STao Ma BUG_ON(!is.s.not_found); 28767cf5b09STao Ma 2880d812f77STao Ma error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); 28967cf5b09STao Ma if (error) { 29067cf5b09STao Ma if (error == -ENOSPC) 29167cf5b09STao Ma ext4_clear_inode_state(inode, 29267cf5b09STao Ma EXT4_STATE_MAY_INLINE_DATA); 29367cf5b09STao Ma goto out; 29467cf5b09STao Ma } 29567cf5b09STao Ma 29667cf5b09STao Ma memset((void *)ext4_raw_inode(&is.iloc)->i_block, 29767cf5b09STao Ma 0, EXT4_MIN_INLINE_DATA_SIZE); 29867cf5b09STao Ma 29967cf5b09STao Ma EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here - 30067cf5b09STao Ma (void *)ext4_raw_inode(&is.iloc)); 30167cf5b09STao Ma EXT4_I(inode)->i_inline_size = len + EXT4_MIN_INLINE_DATA_SIZE; 30267cf5b09STao Ma ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS); 30367cf5b09STao Ma ext4_set_inode_flag(inode, EXT4_INODE_INLINE_DATA); 30467cf5b09STao Ma get_bh(is.iloc.bh); 30567cf5b09STao Ma error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); 30667cf5b09STao Ma 30767cf5b09STao Ma out: 30867cf5b09STao Ma brelse(is.iloc.bh); 30967cf5b09STao Ma return error; 31067cf5b09STao Ma } 31167cf5b09STao Ma 31267cf5b09STao Ma static int ext4_update_inline_data(handle_t *handle, struct inode *inode, 31367cf5b09STao Ma unsigned int len) 31467cf5b09STao Ma { 31567cf5b09STao Ma int error; 31667cf5b09STao Ma void *value = NULL; 31767cf5b09STao Ma struct ext4_xattr_ibody_find is = { 31867cf5b09STao Ma .s = { .not_found = -ENODATA, }, 31967cf5b09STao Ma }; 32067cf5b09STao Ma struct ext4_xattr_info i = { 32167cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 32267cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 32367cf5b09STao Ma }; 32467cf5b09STao Ma 32567cf5b09STao Ma /* If the old space is ok, write the data directly. */ 32667cf5b09STao Ma if (len <= EXT4_I(inode)->i_inline_size) 32767cf5b09STao Ma return 0; 32867cf5b09STao Ma 32967cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 33067cf5b09STao Ma if (error) 33167cf5b09STao Ma return error; 33267cf5b09STao Ma 33367cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 33467cf5b09STao Ma if (error) 33567cf5b09STao Ma goto out; 33667cf5b09STao Ma 33767cf5b09STao Ma BUG_ON(is.s.not_found); 33867cf5b09STao Ma 33967cf5b09STao Ma len -= EXT4_MIN_INLINE_DATA_SIZE; 34067cf5b09STao Ma value = kzalloc(len, GFP_NOFS); 34167cf5b09STao Ma if (!value) 34267cf5b09STao Ma goto out; 34367cf5b09STao Ma 34467cf5b09STao Ma error = ext4_xattr_ibody_get(inode, i.name_index, i.name, 34567cf5b09STao Ma value, len); 34667cf5b09STao Ma if (error == -ENODATA) 34767cf5b09STao Ma goto out; 34867cf5b09STao Ma 34967cf5b09STao Ma error = ext4_journal_get_write_access(handle, is.iloc.bh); 35067cf5b09STao Ma if (error) 35167cf5b09STao Ma goto out; 35267cf5b09STao Ma 35367cf5b09STao Ma /* Update the xttr entry. */ 35467cf5b09STao Ma i.value = value; 35567cf5b09STao Ma i.value_len = len; 35667cf5b09STao Ma 3570d812f77STao Ma error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); 35867cf5b09STao Ma if (error) 35967cf5b09STao Ma goto out; 36067cf5b09STao Ma 36167cf5b09STao Ma EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here - 36267cf5b09STao Ma (void *)ext4_raw_inode(&is.iloc)); 36367cf5b09STao Ma EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE + 36467cf5b09STao Ma le32_to_cpu(is.s.here->e_value_size); 36567cf5b09STao Ma ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 36667cf5b09STao Ma get_bh(is.iloc.bh); 36767cf5b09STao Ma error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); 36867cf5b09STao Ma 36967cf5b09STao Ma out: 37067cf5b09STao Ma kfree(value); 37167cf5b09STao Ma brelse(is.iloc.bh); 37267cf5b09STao Ma return error; 37367cf5b09STao Ma } 37467cf5b09STao Ma 37567cf5b09STao Ma int ext4_prepare_inline_data(handle_t *handle, struct inode *inode, 37667cf5b09STao Ma unsigned int len) 37767cf5b09STao Ma { 37867cf5b09STao Ma int ret, size; 37967cf5b09STao Ma struct ext4_inode_info *ei = EXT4_I(inode); 38067cf5b09STao Ma 38167cf5b09STao Ma if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) 38267cf5b09STao Ma return -ENOSPC; 38367cf5b09STao Ma 38467cf5b09STao Ma size = ext4_get_max_inline_size(inode); 38567cf5b09STao Ma if (size < len) 38667cf5b09STao Ma return -ENOSPC; 38767cf5b09STao Ma 38867cf5b09STao Ma down_write(&EXT4_I(inode)->xattr_sem); 38967cf5b09STao Ma 39067cf5b09STao Ma if (ei->i_inline_off) 39167cf5b09STao Ma ret = ext4_update_inline_data(handle, inode, len); 39267cf5b09STao Ma else 39367cf5b09STao Ma ret = ext4_create_inline_data(handle, inode, len); 39467cf5b09STao Ma 39567cf5b09STao Ma up_write(&EXT4_I(inode)->xattr_sem); 39667cf5b09STao Ma 39767cf5b09STao Ma return ret; 39867cf5b09STao Ma } 39967cf5b09STao Ma 40067cf5b09STao Ma static int ext4_destroy_inline_data_nolock(handle_t *handle, 40167cf5b09STao Ma struct inode *inode) 40267cf5b09STao Ma { 40367cf5b09STao Ma struct ext4_inode_info *ei = EXT4_I(inode); 40467cf5b09STao Ma struct ext4_xattr_ibody_find is = { 40567cf5b09STao Ma .s = { .not_found = 0, }, 40667cf5b09STao Ma }; 40767cf5b09STao Ma struct ext4_xattr_info i = { 40867cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 40967cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 41067cf5b09STao Ma .value = NULL, 41167cf5b09STao Ma .value_len = 0, 41267cf5b09STao Ma }; 41367cf5b09STao Ma int error; 41467cf5b09STao Ma 41567cf5b09STao Ma if (!ei->i_inline_off) 41667cf5b09STao Ma return 0; 41767cf5b09STao Ma 41867cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 41967cf5b09STao Ma if (error) 42067cf5b09STao Ma return error; 42167cf5b09STao Ma 42267cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 42367cf5b09STao Ma if (error) 42467cf5b09STao Ma goto out; 42567cf5b09STao Ma 42667cf5b09STao Ma error = ext4_journal_get_write_access(handle, is.iloc.bh); 42767cf5b09STao Ma if (error) 42867cf5b09STao Ma goto out; 42967cf5b09STao Ma 4300d812f77STao Ma error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); 43167cf5b09STao Ma if (error) 43267cf5b09STao Ma goto out; 43367cf5b09STao Ma 43467cf5b09STao Ma memset((void *)ext4_raw_inode(&is.iloc)->i_block, 43567cf5b09STao Ma 0, EXT4_MIN_INLINE_DATA_SIZE); 43667cf5b09STao Ma 43767cf5b09STao Ma if (EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb, 43867cf5b09STao Ma EXT4_FEATURE_INCOMPAT_EXTENTS)) { 43967cf5b09STao Ma if (S_ISDIR(inode->i_mode) || 44067cf5b09STao Ma S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) { 44167cf5b09STao Ma ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS); 44267cf5b09STao Ma ext4_ext_tree_init(handle, inode); 44367cf5b09STao Ma } 44467cf5b09STao Ma } 44567cf5b09STao Ma ext4_clear_inode_flag(inode, EXT4_INODE_INLINE_DATA); 44667cf5b09STao Ma 44767cf5b09STao Ma get_bh(is.iloc.bh); 44867cf5b09STao Ma error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); 44967cf5b09STao Ma 45067cf5b09STao Ma EXT4_I(inode)->i_inline_off = 0; 45167cf5b09STao Ma EXT4_I(inode)->i_inline_size = 0; 45267cf5b09STao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 45367cf5b09STao Ma out: 45467cf5b09STao Ma brelse(is.iloc.bh); 45567cf5b09STao Ma if (error == -ENODATA) 45667cf5b09STao Ma error = 0; 45767cf5b09STao Ma return error; 45867cf5b09STao Ma } 45967cf5b09STao Ma 46046c7f254STao Ma static int ext4_read_inline_page(struct inode *inode, struct page *page) 46146c7f254STao Ma { 46246c7f254STao Ma void *kaddr; 46346c7f254STao Ma int ret = 0; 46446c7f254STao Ma size_t len; 46546c7f254STao Ma struct ext4_iloc iloc; 46646c7f254STao Ma 46746c7f254STao Ma BUG_ON(!PageLocked(page)); 46846c7f254STao Ma BUG_ON(!ext4_has_inline_data(inode)); 46946c7f254STao Ma BUG_ON(page->index); 47046c7f254STao Ma 47146c7f254STao Ma if (!EXT4_I(inode)->i_inline_off) { 47246c7f254STao Ma ext4_warning(inode->i_sb, "inode %lu doesn't have inline data.", 47346c7f254STao Ma inode->i_ino); 47446c7f254STao Ma goto out; 47546c7f254STao Ma } 47646c7f254STao Ma 47746c7f254STao Ma ret = ext4_get_inode_loc(inode, &iloc); 47846c7f254STao Ma if (ret) 47946c7f254STao Ma goto out; 48046c7f254STao Ma 48146c7f254STao Ma len = min_t(size_t, ext4_get_inline_size(inode), i_size_read(inode)); 48246c7f254STao Ma kaddr = kmap_atomic(page); 48346c7f254STao Ma ret = ext4_read_inline_data(inode, kaddr, len, &iloc); 48446c7f254STao Ma flush_dcache_page(page); 48546c7f254STao Ma kunmap_atomic(kaddr); 48646c7f254STao Ma zero_user_segment(page, len, PAGE_CACHE_SIZE); 48746c7f254STao Ma SetPageUptodate(page); 48846c7f254STao Ma brelse(iloc.bh); 48946c7f254STao Ma 49046c7f254STao Ma out: 49146c7f254STao Ma return ret; 49246c7f254STao Ma } 49346c7f254STao Ma 49446c7f254STao Ma int ext4_readpage_inline(struct inode *inode, struct page *page) 49546c7f254STao Ma { 49646c7f254STao Ma int ret = 0; 49746c7f254STao Ma 49846c7f254STao Ma down_read(&EXT4_I(inode)->xattr_sem); 49946c7f254STao Ma if (!ext4_has_inline_data(inode)) { 50046c7f254STao Ma up_read(&EXT4_I(inode)->xattr_sem); 50146c7f254STao Ma return -EAGAIN; 50246c7f254STao Ma } 50346c7f254STao Ma 50446c7f254STao Ma /* 50546c7f254STao Ma * Current inline data can only exist in the 1st page, 50646c7f254STao Ma * So for all the other pages, just set them uptodate. 50746c7f254STao Ma */ 50846c7f254STao Ma if (!page->index) 50946c7f254STao Ma ret = ext4_read_inline_page(inode, page); 51046c7f254STao Ma else if (!PageUptodate(page)) { 51146c7f254STao Ma zero_user_segment(page, 0, PAGE_CACHE_SIZE); 51246c7f254STao Ma SetPageUptodate(page); 51346c7f254STao Ma } 51446c7f254STao Ma 51546c7f254STao Ma up_read(&EXT4_I(inode)->xattr_sem); 51646c7f254STao Ma 51746c7f254STao Ma unlock_page(page); 51846c7f254STao Ma return ret >= 0 ? 0 : ret; 51946c7f254STao Ma } 52046c7f254STao Ma 521f19d5870STao Ma static int ext4_convert_inline_data_to_extent(struct address_space *mapping, 522f19d5870STao Ma struct inode *inode, 523f19d5870STao Ma unsigned flags) 524f19d5870STao Ma { 525f19d5870STao Ma int ret, needed_blocks; 526f19d5870STao Ma handle_t *handle = NULL; 527f19d5870STao Ma int retries = 0, sem_held = 0; 528f19d5870STao Ma struct page *page = NULL; 529f19d5870STao Ma unsigned from, to; 530f19d5870STao Ma struct ext4_iloc iloc; 531f19d5870STao Ma 532f19d5870STao Ma if (!ext4_has_inline_data(inode)) { 533f19d5870STao Ma /* 534f19d5870STao Ma * clear the flag so that no new write 535f19d5870STao Ma * will trap here again. 536f19d5870STao Ma */ 537f19d5870STao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 538f19d5870STao Ma return 0; 539f19d5870STao Ma } 540f19d5870STao Ma 541f19d5870STao Ma needed_blocks = ext4_writepage_trans_blocks(inode); 542f19d5870STao Ma 543f19d5870STao Ma ret = ext4_get_inode_loc(inode, &iloc); 544f19d5870STao Ma if (ret) 545f19d5870STao Ma return ret; 546f19d5870STao Ma 547f19d5870STao Ma retry: 548f19d5870STao Ma handle = ext4_journal_start(inode, needed_blocks); 549f19d5870STao Ma if (IS_ERR(handle)) { 550f19d5870STao Ma ret = PTR_ERR(handle); 551f19d5870STao Ma handle = NULL; 552f19d5870STao Ma goto out; 553f19d5870STao Ma } 554f19d5870STao Ma 555f19d5870STao Ma /* We cannot recurse into the filesystem as the transaction is already 556f19d5870STao Ma * started */ 557f19d5870STao Ma flags |= AOP_FLAG_NOFS; 558f19d5870STao Ma 559f19d5870STao Ma page = grab_cache_page_write_begin(mapping, 0, flags); 560f19d5870STao Ma if (!page) { 561f19d5870STao Ma ret = -ENOMEM; 562f19d5870STao Ma goto out; 563f19d5870STao Ma } 564f19d5870STao Ma 565f19d5870STao Ma down_write(&EXT4_I(inode)->xattr_sem); 566f19d5870STao Ma sem_held = 1; 567f19d5870STao Ma /* If some one has already done this for us, just exit. */ 568f19d5870STao Ma if (!ext4_has_inline_data(inode)) { 569f19d5870STao Ma ret = 0; 570f19d5870STao Ma goto out; 571f19d5870STao Ma } 572f19d5870STao Ma 573f19d5870STao Ma from = 0; 574f19d5870STao Ma to = ext4_get_inline_size(inode); 575f19d5870STao Ma if (!PageUptodate(page)) { 576f19d5870STao Ma ret = ext4_read_inline_page(inode, page); 577f19d5870STao Ma if (ret < 0) 578f19d5870STao Ma goto out; 579f19d5870STao Ma } 580f19d5870STao Ma 581f19d5870STao Ma ret = ext4_destroy_inline_data_nolock(handle, inode); 582f19d5870STao Ma if (ret) 583f19d5870STao Ma goto out; 584f19d5870STao Ma 585f19d5870STao Ma if (ext4_should_dioread_nolock(inode)) 586f19d5870STao Ma ret = __block_write_begin(page, from, to, ext4_get_block_write); 587f19d5870STao Ma else 588f19d5870STao Ma ret = __block_write_begin(page, from, to, ext4_get_block); 589f19d5870STao Ma 590f19d5870STao Ma if (!ret && ext4_should_journal_data(inode)) { 591f19d5870STao Ma ret = ext4_walk_page_buffers(handle, page_buffers(page), 592f19d5870STao Ma from, to, NULL, 593f19d5870STao Ma do_journal_get_write_access); 594f19d5870STao Ma } 595f19d5870STao Ma 596f19d5870STao Ma if (ret) { 597f19d5870STao Ma unlock_page(page); 598f19d5870STao Ma page_cache_release(page); 599f19d5870STao Ma ext4_orphan_add(handle, inode); 600f19d5870STao Ma up_write(&EXT4_I(inode)->xattr_sem); 601f19d5870STao Ma sem_held = 0; 602f19d5870STao Ma ext4_journal_stop(handle); 603f19d5870STao Ma handle = NULL; 604f19d5870STao Ma ext4_truncate_failed_write(inode); 605f19d5870STao Ma /* 606f19d5870STao Ma * If truncate failed early the inode might 607f19d5870STao Ma * still be on the orphan list; we need to 608f19d5870STao Ma * make sure the inode is removed from the 609f19d5870STao Ma * orphan list in that case. 610f19d5870STao Ma */ 611f19d5870STao Ma if (inode->i_nlink) 612f19d5870STao Ma ext4_orphan_del(NULL, inode); 613f19d5870STao Ma } 614f19d5870STao Ma 615f19d5870STao Ma if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) 616f19d5870STao Ma goto retry; 617f19d5870STao Ma 618f19d5870STao Ma block_commit_write(page, from, to); 619f19d5870STao Ma out: 620f19d5870STao Ma if (page) { 621f19d5870STao Ma unlock_page(page); 622f19d5870STao Ma page_cache_release(page); 623f19d5870STao Ma } 624f19d5870STao Ma if (sem_held) 625f19d5870STao Ma up_write(&EXT4_I(inode)->xattr_sem); 626f19d5870STao Ma if (handle) 627f19d5870STao Ma ext4_journal_stop(handle); 628f19d5870STao Ma brelse(iloc.bh); 629f19d5870STao Ma return ret; 630f19d5870STao Ma } 631f19d5870STao Ma 632f19d5870STao Ma /* 633f19d5870STao Ma * Try to write data in the inode. 634f19d5870STao Ma * If the inode has inline data, check whether the new write can be 635f19d5870STao Ma * in the inode also. If not, create the page the handle, move the data 636f19d5870STao Ma * to the page make it update and let the later codes create extent for it. 637f19d5870STao Ma */ 638f19d5870STao Ma int ext4_try_to_write_inline_data(struct address_space *mapping, 639f19d5870STao Ma struct inode *inode, 640f19d5870STao Ma loff_t pos, unsigned len, 641f19d5870STao Ma unsigned flags, 642f19d5870STao Ma struct page **pagep) 643f19d5870STao Ma { 644f19d5870STao Ma int ret; 645f19d5870STao Ma handle_t *handle; 646f19d5870STao Ma struct page *page; 647f19d5870STao Ma struct ext4_iloc iloc; 648f19d5870STao Ma 649f19d5870STao Ma if (pos + len > ext4_get_max_inline_size(inode)) 650f19d5870STao Ma goto convert; 651f19d5870STao Ma 652f19d5870STao Ma ret = ext4_get_inode_loc(inode, &iloc); 653f19d5870STao Ma if (ret) 654f19d5870STao Ma return ret; 655f19d5870STao Ma 656f19d5870STao Ma /* 657f19d5870STao Ma * The possible write could happen in the inode, 658f19d5870STao Ma * so try to reserve the space in inode first. 659f19d5870STao Ma */ 660f19d5870STao Ma handle = ext4_journal_start(inode, 1); 661f19d5870STao Ma if (IS_ERR(handle)) { 662f19d5870STao Ma ret = PTR_ERR(handle); 663f19d5870STao Ma handle = NULL; 664f19d5870STao Ma goto out; 665f19d5870STao Ma } 666f19d5870STao Ma 667f19d5870STao Ma ret = ext4_prepare_inline_data(handle, inode, pos + len); 668f19d5870STao Ma if (ret && ret != -ENOSPC) 669f19d5870STao Ma goto out; 670f19d5870STao Ma 671f19d5870STao Ma /* We don't have space in inline inode, so convert it to extent. */ 672f19d5870STao Ma if (ret == -ENOSPC) { 673f19d5870STao Ma ext4_journal_stop(handle); 674f19d5870STao Ma brelse(iloc.bh); 675f19d5870STao Ma goto convert; 676f19d5870STao Ma } 677f19d5870STao Ma 678f19d5870STao Ma flags |= AOP_FLAG_NOFS; 679f19d5870STao Ma 680f19d5870STao Ma page = grab_cache_page_write_begin(mapping, 0, flags); 681f19d5870STao Ma if (!page) { 682f19d5870STao Ma ret = -ENOMEM; 683f19d5870STao Ma goto out; 684f19d5870STao Ma } 685f19d5870STao Ma 686f19d5870STao Ma *pagep = page; 687f19d5870STao Ma down_read(&EXT4_I(inode)->xattr_sem); 688f19d5870STao Ma if (!ext4_has_inline_data(inode)) { 689f19d5870STao Ma ret = 0; 690f19d5870STao Ma unlock_page(page); 691f19d5870STao Ma page_cache_release(page); 692f19d5870STao Ma goto out_up_read; 693f19d5870STao Ma } 694f19d5870STao Ma 695f19d5870STao Ma if (!PageUptodate(page)) { 696f19d5870STao Ma ret = ext4_read_inline_page(inode, page); 697f19d5870STao Ma if (ret < 0) 698f19d5870STao Ma goto out_up_read; 699f19d5870STao Ma } 700f19d5870STao Ma 701f19d5870STao Ma ret = 1; 702f19d5870STao Ma handle = NULL; 703f19d5870STao Ma out_up_read: 704f19d5870STao Ma up_read(&EXT4_I(inode)->xattr_sem); 705f19d5870STao Ma out: 706f19d5870STao Ma if (handle) 707f19d5870STao Ma ext4_journal_stop(handle); 708f19d5870STao Ma brelse(iloc.bh); 709f19d5870STao Ma return ret; 710f19d5870STao Ma convert: 711f19d5870STao Ma return ext4_convert_inline_data_to_extent(mapping, 712f19d5870STao Ma inode, flags); 713f19d5870STao Ma } 714f19d5870STao Ma 715f19d5870STao Ma int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len, 716f19d5870STao Ma unsigned copied, struct page *page) 717f19d5870STao Ma { 718f19d5870STao Ma int ret; 719f19d5870STao Ma void *kaddr; 720f19d5870STao Ma struct ext4_iloc iloc; 721f19d5870STao Ma 722f19d5870STao Ma if (unlikely(copied < len)) { 723f19d5870STao Ma if (!PageUptodate(page)) { 724f19d5870STao Ma copied = 0; 725f19d5870STao Ma goto out; 726f19d5870STao Ma } 727f19d5870STao Ma } 728f19d5870STao Ma 729f19d5870STao Ma ret = ext4_get_inode_loc(inode, &iloc); 730f19d5870STao Ma if (ret) { 731f19d5870STao Ma ext4_std_error(inode->i_sb, ret); 732f19d5870STao Ma copied = 0; 733f19d5870STao Ma goto out; 734f19d5870STao Ma } 735f19d5870STao Ma 736f19d5870STao Ma down_write(&EXT4_I(inode)->xattr_sem); 737f19d5870STao Ma BUG_ON(!ext4_has_inline_data(inode)); 738f19d5870STao Ma 739f19d5870STao Ma kaddr = kmap_atomic(page); 740f19d5870STao Ma ext4_write_inline_data(inode, &iloc, kaddr, pos, len); 741f19d5870STao Ma kunmap_atomic(kaddr); 742f19d5870STao Ma SetPageUptodate(page); 743f19d5870STao Ma /* clear page dirty so that writepages wouldn't work for us. */ 744f19d5870STao Ma ClearPageDirty(page); 745f19d5870STao Ma 746f19d5870STao Ma up_write(&EXT4_I(inode)->xattr_sem); 747f19d5870STao Ma brelse(iloc.bh); 748f19d5870STao Ma out: 749f19d5870STao Ma return copied; 750f19d5870STao Ma } 751f19d5870STao Ma 7523fdcfb66STao Ma struct buffer_head * 7533fdcfb66STao Ma ext4_journalled_write_inline_data(struct inode *inode, 7543fdcfb66STao Ma unsigned len, 7553fdcfb66STao Ma struct page *page) 7563fdcfb66STao Ma { 7573fdcfb66STao Ma int ret; 7583fdcfb66STao Ma void *kaddr; 7593fdcfb66STao Ma struct ext4_iloc iloc; 7603fdcfb66STao Ma 7613fdcfb66STao Ma ret = ext4_get_inode_loc(inode, &iloc); 7623fdcfb66STao Ma if (ret) { 7633fdcfb66STao Ma ext4_std_error(inode->i_sb, ret); 7643fdcfb66STao Ma return NULL; 7653fdcfb66STao Ma } 7663fdcfb66STao Ma 7673fdcfb66STao Ma down_write(&EXT4_I(inode)->xattr_sem); 7683fdcfb66STao Ma kaddr = kmap_atomic(page); 7693fdcfb66STao Ma ext4_write_inline_data(inode, &iloc, kaddr, 0, len); 7703fdcfb66STao Ma kunmap_atomic(kaddr); 7713fdcfb66STao Ma up_write(&EXT4_I(inode)->xattr_sem); 7723fdcfb66STao Ma 7733fdcfb66STao Ma return iloc.bh; 7743fdcfb66STao Ma } 7753fdcfb66STao Ma 7769c3569b5STao Ma /* 7779c3569b5STao Ma * Try to make the page cache and handle ready for the inline data case. 7789c3569b5STao Ma * We can call this function in 2 cases: 7799c3569b5STao Ma * 1. The inode is created and the first write exceeds inline size. We can 7809c3569b5STao Ma * clear the inode state safely. 7819c3569b5STao Ma * 2. The inode has inline data, then we need to read the data, make it 7829c3569b5STao Ma * update and dirty so that ext4_da_writepages can handle it. We don't 7839c3569b5STao Ma * need to start the journal since the file's metatdata isn't changed now. 7849c3569b5STao Ma */ 7859c3569b5STao Ma static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping, 7869c3569b5STao Ma struct inode *inode, 7879c3569b5STao Ma unsigned flags, 7889c3569b5STao Ma void **fsdata) 7899c3569b5STao Ma { 7909c3569b5STao Ma int ret = 0, inline_size; 7919c3569b5STao Ma struct page *page; 7929c3569b5STao Ma 7939c3569b5STao Ma page = grab_cache_page_write_begin(mapping, 0, flags); 7949c3569b5STao Ma if (!page) 7959c3569b5STao Ma return -ENOMEM; 7969c3569b5STao Ma 7979c3569b5STao Ma down_read(&EXT4_I(inode)->xattr_sem); 7989c3569b5STao Ma if (!ext4_has_inline_data(inode)) { 7999c3569b5STao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 8009c3569b5STao Ma goto out; 8019c3569b5STao Ma } 8029c3569b5STao Ma 8039c3569b5STao Ma inline_size = ext4_get_inline_size(inode); 8049c3569b5STao Ma 8059c3569b5STao Ma if (!PageUptodate(page)) { 8069c3569b5STao Ma ret = ext4_read_inline_page(inode, page); 8079c3569b5STao Ma if (ret < 0) 8089c3569b5STao Ma goto out; 8099c3569b5STao Ma } 8109c3569b5STao Ma 8119c3569b5STao Ma ret = __block_write_begin(page, 0, inline_size, 8129c3569b5STao Ma ext4_da_get_block_prep); 8139c3569b5STao Ma if (ret) { 8149c3569b5STao Ma ext4_truncate_failed_write(inode); 8159c3569b5STao Ma goto out; 8169c3569b5STao Ma } 8179c3569b5STao Ma 8189c3569b5STao Ma SetPageDirty(page); 8199c3569b5STao Ma SetPageUptodate(page); 8209c3569b5STao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 8219c3569b5STao Ma *fsdata = (void *)CONVERT_INLINE_DATA; 8229c3569b5STao Ma 8239c3569b5STao Ma out: 8249c3569b5STao Ma up_read(&EXT4_I(inode)->xattr_sem); 8259c3569b5STao Ma if (page) { 8269c3569b5STao Ma unlock_page(page); 8279c3569b5STao Ma page_cache_release(page); 8289c3569b5STao Ma } 8299c3569b5STao Ma return ret; 8309c3569b5STao Ma } 8319c3569b5STao Ma 8329c3569b5STao Ma /* 8339c3569b5STao Ma * Prepare the write for the inline data. 8349c3569b5STao Ma * If the the data can be written into the inode, we just read 8359c3569b5STao Ma * the page and make it uptodate, and start the journal. 8369c3569b5STao Ma * Otherwise read the page, makes it dirty so that it can be 8379c3569b5STao Ma * handle in writepages(the i_disksize update is left to the 8389c3569b5STao Ma * normal ext4_da_write_end). 8399c3569b5STao Ma */ 8409c3569b5STao Ma int ext4_da_write_inline_data_begin(struct address_space *mapping, 8419c3569b5STao Ma struct inode *inode, 8429c3569b5STao Ma loff_t pos, unsigned len, 8439c3569b5STao Ma unsigned flags, 8449c3569b5STao Ma struct page **pagep, 8459c3569b5STao Ma void **fsdata) 8469c3569b5STao Ma { 8479c3569b5STao Ma int ret, inline_size; 8489c3569b5STao Ma handle_t *handle; 8499c3569b5STao Ma struct page *page; 8509c3569b5STao Ma struct ext4_iloc iloc; 8519c3569b5STao Ma 8529c3569b5STao Ma ret = ext4_get_inode_loc(inode, &iloc); 8539c3569b5STao Ma if (ret) 8549c3569b5STao Ma return ret; 8559c3569b5STao Ma 8569c3569b5STao Ma handle = ext4_journal_start(inode, 1); 8579c3569b5STao Ma if (IS_ERR(handle)) { 8589c3569b5STao Ma ret = PTR_ERR(handle); 8599c3569b5STao Ma handle = NULL; 8609c3569b5STao Ma goto out; 8619c3569b5STao Ma } 8629c3569b5STao Ma 8639c3569b5STao Ma inline_size = ext4_get_max_inline_size(inode); 8649c3569b5STao Ma 8659c3569b5STao Ma ret = -ENOSPC; 8669c3569b5STao Ma if (inline_size >= pos + len) { 8679c3569b5STao Ma ret = ext4_prepare_inline_data(handle, inode, pos + len); 8689c3569b5STao Ma if (ret && ret != -ENOSPC) 8699c3569b5STao Ma goto out; 8709c3569b5STao Ma } 8719c3569b5STao Ma 8729c3569b5STao Ma if (ret == -ENOSPC) { 8739c3569b5STao Ma ret = ext4_da_convert_inline_data_to_extent(mapping, 8749c3569b5STao Ma inode, 8759c3569b5STao Ma flags, 8769c3569b5STao Ma fsdata); 8779c3569b5STao Ma goto out; 8789c3569b5STao Ma } 8799c3569b5STao Ma 8809c3569b5STao Ma /* 8819c3569b5STao Ma * We cannot recurse into the filesystem as the transaction 8829c3569b5STao Ma * is already started. 8839c3569b5STao Ma */ 8849c3569b5STao Ma flags |= AOP_FLAG_NOFS; 8859c3569b5STao Ma 8869c3569b5STao Ma page = grab_cache_page_write_begin(mapping, 0, flags); 8879c3569b5STao Ma if (!page) { 8889c3569b5STao Ma ret = -ENOMEM; 8899c3569b5STao Ma goto out; 8909c3569b5STao Ma } 8919c3569b5STao Ma 8929c3569b5STao Ma down_read(&EXT4_I(inode)->xattr_sem); 8939c3569b5STao Ma if (!ext4_has_inline_data(inode)) { 8949c3569b5STao Ma ret = 0; 8959c3569b5STao Ma goto out_release_page; 8969c3569b5STao Ma } 8979c3569b5STao Ma 8989c3569b5STao Ma if (!PageUptodate(page)) { 8999c3569b5STao Ma ret = ext4_read_inline_page(inode, page); 9009c3569b5STao Ma if (ret < 0) 9019c3569b5STao Ma goto out_release_page; 9029c3569b5STao Ma } 9039c3569b5STao Ma 9049c3569b5STao Ma up_read(&EXT4_I(inode)->xattr_sem); 9059c3569b5STao Ma *pagep = page; 9069c3569b5STao Ma handle = NULL; 9079c3569b5STao Ma brelse(iloc.bh); 9089c3569b5STao Ma return 1; 9099c3569b5STao Ma out_release_page: 9109c3569b5STao Ma up_read(&EXT4_I(inode)->xattr_sem); 9119c3569b5STao Ma unlock_page(page); 9129c3569b5STao Ma page_cache_release(page); 9139c3569b5STao Ma out: 9149c3569b5STao Ma if (handle) 9159c3569b5STao Ma ext4_journal_stop(handle); 9169c3569b5STao Ma brelse(iloc.bh); 9179c3569b5STao Ma return ret; 9189c3569b5STao Ma } 9199c3569b5STao Ma 9209c3569b5STao Ma int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos, 9219c3569b5STao Ma unsigned len, unsigned copied, 9229c3569b5STao Ma struct page *page) 9239c3569b5STao Ma { 9249c3569b5STao Ma int i_size_changed = 0; 9259c3569b5STao Ma 9269c3569b5STao Ma copied = ext4_write_inline_data_end(inode, pos, len, copied, page); 9279c3569b5STao Ma 9289c3569b5STao Ma /* 9299c3569b5STao Ma * No need to use i_size_read() here, the i_size 9309c3569b5STao Ma * cannot change under us because we hold i_mutex. 9319c3569b5STao Ma * 9329c3569b5STao Ma * But it's important to update i_size while still holding page lock: 9339c3569b5STao Ma * page writeout could otherwise come in and zero beyond i_size. 9349c3569b5STao Ma */ 9359c3569b5STao Ma if (pos+copied > inode->i_size) { 9369c3569b5STao Ma i_size_write(inode, pos+copied); 9379c3569b5STao Ma i_size_changed = 1; 9389c3569b5STao Ma } 9399c3569b5STao Ma unlock_page(page); 9409c3569b5STao Ma page_cache_release(page); 9419c3569b5STao Ma 9429c3569b5STao Ma /* 9439c3569b5STao Ma * Don't mark the inode dirty under page lock. First, it unnecessarily 9449c3569b5STao Ma * makes the holding time of page lock longer. Second, it forces lock 9459c3569b5STao Ma * ordering of page lock and transaction start for journaling 9469c3569b5STao Ma * filesystems. 9479c3569b5STao Ma */ 9489c3569b5STao Ma if (i_size_changed) 9499c3569b5STao Ma mark_inode_dirty(inode); 9509c3569b5STao Ma 9519c3569b5STao Ma return copied; 9529c3569b5STao Ma } 953f19d5870STao Ma 9543c47d541STao Ma #ifdef INLINE_DIR_DEBUG 9553c47d541STao Ma void ext4_show_inline_dir(struct inode *dir, struct buffer_head *bh, 9563c47d541STao Ma void *inline_start, int inline_size) 9573c47d541STao Ma { 9583c47d541STao Ma int offset; 9593c47d541STao Ma unsigned short de_len; 9603c47d541STao Ma struct ext4_dir_entry_2 *de = inline_start; 9613c47d541STao Ma void *dlimit = inline_start + inline_size; 9623c47d541STao Ma 9633c47d541STao Ma trace_printk("inode %lu\n", dir->i_ino); 9643c47d541STao Ma offset = 0; 9653c47d541STao Ma while ((void *)de < dlimit) { 9663c47d541STao Ma de_len = ext4_rec_len_from_disk(de->rec_len, inline_size); 9673c47d541STao Ma trace_printk("de: off %u rlen %u name %*.s nlen %u ino %u\n", 9683c47d541STao Ma offset, de_len, de->name_len, de->name, 9693c47d541STao Ma de->name_len, le32_to_cpu(de->inode)); 9703c47d541STao Ma if (ext4_check_dir_entry(dir, NULL, de, bh, 9713c47d541STao Ma inline_start, inline_size, offset)) 9723c47d541STao Ma BUG(); 9733c47d541STao Ma 9743c47d541STao Ma offset += de_len; 9753c47d541STao Ma de = (struct ext4_dir_entry_2 *) ((char *) de + de_len); 9763c47d541STao Ma } 9773c47d541STao Ma } 9783c47d541STao Ma #else 9793c47d541STao Ma #define ext4_show_inline_dir(dir, bh, inline_start, inline_size) 9803c47d541STao Ma #endif 9813c47d541STao Ma 9823c47d541STao Ma /* 9833c47d541STao Ma * Add a new entry into a inline dir. 9843c47d541STao Ma * It will return -ENOSPC if no space is available, and -EIO 9853c47d541STao Ma * and -EEXIST if directory entry already exists. 9863c47d541STao Ma */ 9873c47d541STao Ma static int ext4_add_dirent_to_inline(handle_t *handle, 9883c47d541STao Ma struct dentry *dentry, 9893c47d541STao Ma struct inode *inode, 9903c47d541STao Ma struct ext4_iloc *iloc, 9913c47d541STao Ma void *inline_start, int inline_size) 9923c47d541STao Ma { 9933c47d541STao Ma struct inode *dir = dentry->d_parent->d_inode; 9943c47d541STao Ma const char *name = dentry->d_name.name; 9953c47d541STao Ma int namelen = dentry->d_name.len; 9963c47d541STao Ma unsigned short reclen; 9973c47d541STao Ma int err; 9983c47d541STao Ma struct ext4_dir_entry_2 *de; 9993c47d541STao Ma 10003c47d541STao Ma reclen = EXT4_DIR_REC_LEN(namelen); 10013c47d541STao Ma err = ext4_find_dest_de(dir, inode, iloc->bh, 10023c47d541STao Ma inline_start, inline_size, 10033c47d541STao Ma name, namelen, &de); 10043c47d541STao Ma if (err) 10053c47d541STao Ma return err; 10063c47d541STao Ma 10073c47d541STao Ma err = ext4_journal_get_write_access(handle, iloc->bh); 10083c47d541STao Ma if (err) 10093c47d541STao Ma return err; 10103c47d541STao Ma ext4_insert_dentry(inode, de, inline_size, name, namelen); 10113c47d541STao Ma 10123c47d541STao Ma ext4_show_inline_dir(dir, iloc->bh, inline_start, inline_size); 10133c47d541STao Ma 10143c47d541STao Ma /* 10153c47d541STao Ma * XXX shouldn't update any times until successful 10163c47d541STao Ma * completion of syscall, but too many callers depend 10173c47d541STao Ma * on this. 10183c47d541STao Ma * 10193c47d541STao Ma * XXX similarly, too many callers depend on 10203c47d541STao Ma * ext4_new_inode() setting the times, but error 10213c47d541STao Ma * recovery deletes the inode, so the worst that can 10223c47d541STao Ma * happen is that the times are slightly out of date 10233c47d541STao Ma * and/or different from the directory change time. 10243c47d541STao Ma */ 10253c47d541STao Ma dir->i_mtime = dir->i_ctime = ext4_current_time(dir); 10263c47d541STao Ma ext4_update_dx_flag(dir); 10273c47d541STao Ma dir->i_version++; 10283c47d541STao Ma ext4_mark_inode_dirty(handle, dir); 10293c47d541STao Ma return 1; 10303c47d541STao Ma } 10313c47d541STao Ma 10323c47d541STao Ma static void *ext4_get_inline_xattr_pos(struct inode *inode, 10333c47d541STao Ma struct ext4_iloc *iloc) 10343c47d541STao Ma { 10353c47d541STao Ma struct ext4_xattr_entry *entry; 10363c47d541STao Ma struct ext4_xattr_ibody_header *header; 10373c47d541STao Ma 10383c47d541STao Ma BUG_ON(!EXT4_I(inode)->i_inline_off); 10393c47d541STao Ma 10403c47d541STao Ma header = IHDR(inode, ext4_raw_inode(iloc)); 10413c47d541STao Ma entry = (struct ext4_xattr_entry *)((void *)ext4_raw_inode(iloc) + 10423c47d541STao Ma EXT4_I(inode)->i_inline_off); 10433c47d541STao Ma 10443c47d541STao Ma return (void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs); 10453c47d541STao Ma } 10463c47d541STao Ma 10473c47d541STao Ma /* Set the final de to cover the whole block. */ 10483c47d541STao Ma static void ext4_update_final_de(void *de_buf, int old_size, int new_size) 10493c47d541STao Ma { 10503c47d541STao Ma struct ext4_dir_entry_2 *de, *prev_de; 10513c47d541STao Ma void *limit; 10523c47d541STao Ma int de_len; 10533c47d541STao Ma 10543c47d541STao Ma de = (struct ext4_dir_entry_2 *)de_buf; 10553c47d541STao Ma if (old_size) { 10563c47d541STao Ma limit = de_buf + old_size; 10573c47d541STao Ma do { 10583c47d541STao Ma prev_de = de; 10593c47d541STao Ma de_len = ext4_rec_len_from_disk(de->rec_len, old_size); 10603c47d541STao Ma de_buf += de_len; 10613c47d541STao Ma de = (struct ext4_dir_entry_2 *)de_buf; 10623c47d541STao Ma } while (de_buf < limit); 10633c47d541STao Ma 10643c47d541STao Ma prev_de->rec_len = ext4_rec_len_to_disk(de_len + new_size - 10653c47d541STao Ma old_size, new_size); 10663c47d541STao Ma } else { 10673c47d541STao Ma /* this is just created, so create an empty entry. */ 10683c47d541STao Ma de->inode = 0; 10693c47d541STao Ma de->rec_len = ext4_rec_len_to_disk(new_size, new_size); 10703c47d541STao Ma } 10713c47d541STao Ma } 10723c47d541STao Ma 10733c47d541STao Ma static int ext4_update_inline_dir(handle_t *handle, struct inode *dir, 10743c47d541STao Ma struct ext4_iloc *iloc) 10753c47d541STao Ma { 10763c47d541STao Ma int ret; 10773c47d541STao Ma int old_size = EXT4_I(dir)->i_inline_size - EXT4_MIN_INLINE_DATA_SIZE; 10783c47d541STao Ma int new_size = get_max_inline_xattr_value_size(dir, iloc); 10793c47d541STao Ma 10803c47d541STao Ma if (new_size - old_size <= EXT4_DIR_REC_LEN(1)) 10813c47d541STao Ma return -ENOSPC; 10823c47d541STao Ma 10833c47d541STao Ma ret = ext4_update_inline_data(handle, dir, 10843c47d541STao Ma new_size + EXT4_MIN_INLINE_DATA_SIZE); 10853c47d541STao Ma if (ret) 10863c47d541STao Ma return ret; 10873c47d541STao Ma 10883c47d541STao Ma ext4_update_final_de(ext4_get_inline_xattr_pos(dir, iloc), old_size, 10893c47d541STao Ma EXT4_I(dir)->i_inline_size - 10903c47d541STao Ma EXT4_MIN_INLINE_DATA_SIZE); 10913c47d541STao Ma dir->i_size = EXT4_I(dir)->i_disksize = EXT4_I(dir)->i_inline_size; 10923c47d541STao Ma return 0; 10933c47d541STao Ma } 10943c47d541STao Ma 10953c47d541STao Ma static void ext4_restore_inline_data(handle_t *handle, struct inode *inode, 10963c47d541STao Ma struct ext4_iloc *iloc, 10973c47d541STao Ma void *buf, int inline_size) 10983c47d541STao Ma { 10993c47d541STao Ma ext4_create_inline_data(handle, inode, inline_size); 11003c47d541STao Ma ext4_write_inline_data(inode, iloc, buf, 0, inline_size); 11013c47d541STao Ma ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 11023c47d541STao Ma } 11033c47d541STao Ma 11043c47d541STao Ma static int ext4_finish_convert_inline_dir(handle_t *handle, 11053c47d541STao Ma struct inode *inode, 11063c47d541STao Ma struct buffer_head *dir_block, 11073c47d541STao Ma void *buf, 11083c47d541STao Ma int inline_size) 11093c47d541STao Ma { 11103c47d541STao Ma int err, csum_size = 0, header_size = 0; 11113c47d541STao Ma struct ext4_dir_entry_2 *de; 11123c47d541STao Ma struct ext4_dir_entry_tail *t; 11133c47d541STao Ma void *target = dir_block->b_data; 11143c47d541STao Ma 11153c47d541STao Ma /* 11163c47d541STao Ma * First create "." and ".." and then copy the dir information 11173c47d541STao Ma * back to the block. 11183c47d541STao Ma */ 11193c47d541STao Ma de = (struct ext4_dir_entry_2 *)target; 11203c47d541STao Ma de = ext4_init_dot_dotdot(inode, de, 11213c47d541STao Ma inode->i_sb->s_blocksize, csum_size, 11223c47d541STao Ma le32_to_cpu(((struct ext4_dir_entry_2 *)buf)->inode), 1); 11233c47d541STao Ma header_size = (void *)de - target; 11243c47d541STao Ma 11253c47d541STao Ma memcpy((void *)de, buf + EXT4_INLINE_DOTDOT_SIZE, 11263c47d541STao Ma inline_size - EXT4_INLINE_DOTDOT_SIZE); 11273c47d541STao Ma 11283c47d541STao Ma if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, 11293c47d541STao Ma EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) 11303c47d541STao Ma csum_size = sizeof(struct ext4_dir_entry_tail); 11313c47d541STao Ma 11323c47d541STao Ma inode->i_size = inode->i_sb->s_blocksize; 11333c47d541STao Ma i_size_write(inode, inode->i_sb->s_blocksize); 11343c47d541STao Ma EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize; 11353c47d541STao Ma ext4_update_final_de(dir_block->b_data, 11363c47d541STao Ma inline_size - EXT4_INLINE_DOTDOT_SIZE + header_size, 11373c47d541STao Ma inode->i_sb->s_blocksize - csum_size); 11383c47d541STao Ma 11393c47d541STao Ma if (csum_size) { 11403c47d541STao Ma t = EXT4_DIRENT_TAIL(dir_block->b_data, 11413c47d541STao Ma inode->i_sb->s_blocksize); 11423c47d541STao Ma initialize_dirent_tail(t, inode->i_sb->s_blocksize); 11433c47d541STao Ma } 11443c47d541STao Ma set_buffer_uptodate(dir_block); 11453c47d541STao Ma err = ext4_handle_dirty_dirent_node(handle, inode, dir_block); 11463c47d541STao Ma if (err) 11473c47d541STao Ma goto out; 11483c47d541STao Ma set_buffer_verified(dir_block); 11493c47d541STao Ma out: 11503c47d541STao Ma return err; 11513c47d541STao Ma } 11523c47d541STao Ma 11533c47d541STao Ma static int ext4_convert_inline_data_nolock(handle_t *handle, 11543c47d541STao Ma struct inode *inode, 11553c47d541STao Ma struct ext4_iloc *iloc) 11563c47d541STao Ma { 11573c47d541STao Ma int error; 11583c47d541STao Ma void *buf = NULL; 11593c47d541STao Ma struct buffer_head *data_bh = NULL; 11603c47d541STao Ma struct ext4_map_blocks map; 11613c47d541STao Ma int inline_size; 11623c47d541STao Ma 11633c47d541STao Ma inline_size = ext4_get_inline_size(inode); 11643c47d541STao Ma buf = kmalloc(inline_size, GFP_NOFS); 11653c47d541STao Ma if (!buf) { 11663c47d541STao Ma error = -ENOMEM; 11673c47d541STao Ma goto out; 11683c47d541STao Ma } 11693c47d541STao Ma 11703c47d541STao Ma error = ext4_read_inline_data(inode, buf, inline_size, iloc); 11713c47d541STao Ma if (error < 0) 11723c47d541STao Ma goto out; 11733c47d541STao Ma 11743c47d541STao Ma error = ext4_destroy_inline_data_nolock(handle, inode); 11753c47d541STao Ma if (error) 11763c47d541STao Ma goto out; 11773c47d541STao Ma 11783c47d541STao Ma map.m_lblk = 0; 11793c47d541STao Ma map.m_len = 1; 11803c47d541STao Ma map.m_flags = 0; 11813c47d541STao Ma error = ext4_map_blocks(handle, inode, &map, EXT4_GET_BLOCKS_CREATE); 11823c47d541STao Ma if (error < 0) 11833c47d541STao Ma goto out_restore; 11843c47d541STao Ma if (!(map.m_flags & EXT4_MAP_MAPPED)) { 11853c47d541STao Ma error = -EIO; 11863c47d541STao Ma goto out_restore; 11873c47d541STao Ma } 11883c47d541STao Ma 11893c47d541STao Ma data_bh = sb_getblk(inode->i_sb, map.m_pblk); 11903c47d541STao Ma if (!data_bh) { 11913c47d541STao Ma error = -EIO; 11923c47d541STao Ma goto out_restore; 11933c47d541STao Ma } 11943c47d541STao Ma 11953c47d541STao Ma lock_buffer(data_bh); 11963c47d541STao Ma error = ext4_journal_get_create_access(handle, data_bh); 11973c47d541STao Ma if (error) { 11983c47d541STao Ma unlock_buffer(data_bh); 11993c47d541STao Ma error = -EIO; 12003c47d541STao Ma goto out_restore; 12013c47d541STao Ma } 12023c47d541STao Ma memset(data_bh->b_data, 0, inode->i_sb->s_blocksize); 12033c47d541STao Ma 12043c47d541STao Ma if (!S_ISDIR(inode->i_mode)) { 12053c47d541STao Ma memcpy(data_bh->b_data, buf, inline_size); 12063c47d541STao Ma set_buffer_uptodate(data_bh); 12073c47d541STao Ma error = ext4_handle_dirty_metadata(handle, 12083c47d541STao Ma inode, data_bh); 12093c47d541STao Ma } else { 12103c47d541STao Ma error = ext4_finish_convert_inline_dir(handle, inode, data_bh, 12113c47d541STao Ma buf, inline_size); 12123c47d541STao Ma } 12133c47d541STao Ma 12143c47d541STao Ma unlock_buffer(data_bh); 12153c47d541STao Ma out_restore: 12163c47d541STao Ma if (error) 12173c47d541STao Ma ext4_restore_inline_data(handle, inode, iloc, buf, inline_size); 12183c47d541STao Ma 12193c47d541STao Ma out: 12203c47d541STao Ma brelse(data_bh); 12213c47d541STao Ma kfree(buf); 12223c47d541STao Ma return error; 12233c47d541STao Ma } 12243c47d541STao Ma 12253c47d541STao Ma /* 12263c47d541STao Ma * Try to add the new entry to the inline data. 12273c47d541STao Ma * If succeeds, return 0. If not, extended the inline dir and copied data to 12283c47d541STao Ma * the new created block. 12293c47d541STao Ma */ 12303c47d541STao Ma int ext4_try_add_inline_entry(handle_t *handle, struct dentry *dentry, 12313c47d541STao Ma struct inode *inode) 12323c47d541STao Ma { 12333c47d541STao Ma int ret, inline_size; 12343c47d541STao Ma void *inline_start; 12353c47d541STao Ma struct ext4_iloc iloc; 12363c47d541STao Ma struct inode *dir = dentry->d_parent->d_inode; 12373c47d541STao Ma 12383c47d541STao Ma ret = ext4_get_inode_loc(dir, &iloc); 12393c47d541STao Ma if (ret) 12403c47d541STao Ma return ret; 12413c47d541STao Ma 12423c47d541STao Ma down_write(&EXT4_I(dir)->xattr_sem); 12433c47d541STao Ma if (!ext4_has_inline_data(dir)) 12443c47d541STao Ma goto out; 12453c47d541STao Ma 12463c47d541STao Ma inline_start = (void *)ext4_raw_inode(&iloc)->i_block + 12473c47d541STao Ma EXT4_INLINE_DOTDOT_SIZE; 12483c47d541STao Ma inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE; 12493c47d541STao Ma 12503c47d541STao Ma ret = ext4_add_dirent_to_inline(handle, dentry, inode, &iloc, 12513c47d541STao Ma inline_start, inline_size); 12523c47d541STao Ma if (ret != -ENOSPC) 12533c47d541STao Ma goto out; 12543c47d541STao Ma 12553c47d541STao Ma /* check whether it can be inserted to inline xattr space. */ 12563c47d541STao Ma inline_size = EXT4_I(dir)->i_inline_size - 12573c47d541STao Ma EXT4_MIN_INLINE_DATA_SIZE; 12583c47d541STao Ma if (!inline_size) { 12593c47d541STao Ma /* Try to use the xattr space.*/ 12603c47d541STao Ma ret = ext4_update_inline_dir(handle, dir, &iloc); 12613c47d541STao Ma if (ret && ret != -ENOSPC) 12623c47d541STao Ma goto out; 12633c47d541STao Ma 12643c47d541STao Ma inline_size = EXT4_I(dir)->i_inline_size - 12653c47d541STao Ma EXT4_MIN_INLINE_DATA_SIZE; 12663c47d541STao Ma } 12673c47d541STao Ma 12683c47d541STao Ma if (inline_size) { 12693c47d541STao Ma inline_start = ext4_get_inline_xattr_pos(dir, &iloc); 12703c47d541STao Ma 12713c47d541STao Ma ret = ext4_add_dirent_to_inline(handle, dentry, inode, &iloc, 12723c47d541STao Ma inline_start, inline_size); 12733c47d541STao Ma 12743c47d541STao Ma if (ret != -ENOSPC) 12753c47d541STao Ma goto out; 12763c47d541STao Ma } 12773c47d541STao Ma 12783c47d541STao Ma /* 12793c47d541STao Ma * The inline space is filled up, so create a new block for it. 12803c47d541STao Ma * As the extent tree will be created, we have to save the inline 12813c47d541STao Ma * dir first. 12823c47d541STao Ma */ 12833c47d541STao Ma ret = ext4_convert_inline_data_nolock(handle, dir, &iloc); 12843c47d541STao Ma 12853c47d541STao Ma out: 12863c47d541STao Ma ext4_mark_inode_dirty(handle, dir); 12873c47d541STao Ma up_write(&EXT4_I(dir)->xattr_sem); 12883c47d541STao Ma brelse(iloc.bh); 12893c47d541STao Ma return ret; 12903c47d541STao Ma } 12913c47d541STao Ma 129265d165d9STao Ma int ext4_read_inline_dir(struct file *filp, 129365d165d9STao Ma void *dirent, filldir_t filldir, 129465d165d9STao Ma int *has_inline_data) 129565d165d9STao Ma { 129665d165d9STao Ma int error = 0; 129765d165d9STao Ma unsigned int offset, parent_ino; 129865d165d9STao Ma int i, stored; 129965d165d9STao Ma struct ext4_dir_entry_2 *de; 130065d165d9STao Ma struct super_block *sb; 130165d165d9STao Ma struct inode *inode = filp->f_path.dentry->d_inode; 130265d165d9STao Ma int ret, inline_size = 0; 130365d165d9STao Ma struct ext4_iloc iloc; 130465d165d9STao Ma void *dir_buf = NULL; 130565d165d9STao Ma 130665d165d9STao Ma ret = ext4_get_inode_loc(inode, &iloc); 130765d165d9STao Ma if (ret) 130865d165d9STao Ma return ret; 130965d165d9STao Ma 131065d165d9STao Ma down_read(&EXT4_I(inode)->xattr_sem); 131165d165d9STao Ma if (!ext4_has_inline_data(inode)) { 131265d165d9STao Ma up_read(&EXT4_I(inode)->xattr_sem); 131365d165d9STao Ma *has_inline_data = 0; 131465d165d9STao Ma goto out; 131565d165d9STao Ma } 131665d165d9STao Ma 131765d165d9STao Ma inline_size = ext4_get_inline_size(inode); 131865d165d9STao Ma dir_buf = kmalloc(inline_size, GFP_NOFS); 131965d165d9STao Ma if (!dir_buf) { 132065d165d9STao Ma ret = -ENOMEM; 132165d165d9STao Ma up_read(&EXT4_I(inode)->xattr_sem); 132265d165d9STao Ma goto out; 132365d165d9STao Ma } 132465d165d9STao Ma 132565d165d9STao Ma ret = ext4_read_inline_data(inode, dir_buf, inline_size, &iloc); 132665d165d9STao Ma up_read(&EXT4_I(inode)->xattr_sem); 132765d165d9STao Ma if (ret < 0) 132865d165d9STao Ma goto out; 132965d165d9STao Ma 133065d165d9STao Ma sb = inode->i_sb; 133165d165d9STao Ma stored = 0; 133265d165d9STao Ma parent_ino = le32_to_cpu(((struct ext4_dir_entry_2 *)dir_buf)->inode); 133365d165d9STao Ma 133465d165d9STao Ma while (!error && !stored && filp->f_pos < inode->i_size) { 133565d165d9STao Ma revalidate: 133665d165d9STao Ma /* 133765d165d9STao Ma * If the version has changed since the last call to 133865d165d9STao Ma * readdir(2), then we might be pointing to an invalid 133965d165d9STao Ma * dirent right now. Scan from the start of the inline 134065d165d9STao Ma * dir to make sure. 134165d165d9STao Ma */ 134265d165d9STao Ma if (filp->f_version != inode->i_version) { 134365d165d9STao Ma for (i = 0; 134465d165d9STao Ma i < inode->i_size && i < offset;) { 134565d165d9STao Ma if (!i) { 134665d165d9STao Ma /* skip "." and ".." if needed. */ 134765d165d9STao Ma i += EXT4_INLINE_DOTDOT_SIZE; 134865d165d9STao Ma continue; 134965d165d9STao Ma } 135065d165d9STao Ma de = (struct ext4_dir_entry_2 *) 135165d165d9STao Ma (dir_buf + i); 135265d165d9STao Ma /* It's too expensive to do a full 135365d165d9STao Ma * dirent test each time round this 135465d165d9STao Ma * loop, but we do have to test at 135565d165d9STao Ma * least that it is non-zero. A 135665d165d9STao Ma * failure will be detected in the 135765d165d9STao Ma * dirent test below. */ 135865d165d9STao Ma if (ext4_rec_len_from_disk(de->rec_len, 135965d165d9STao Ma inline_size) < EXT4_DIR_REC_LEN(1)) 136065d165d9STao Ma break; 136165d165d9STao Ma i += ext4_rec_len_from_disk(de->rec_len, 136265d165d9STao Ma inline_size); 136365d165d9STao Ma } 136465d165d9STao Ma offset = i; 136565d165d9STao Ma filp->f_pos = offset; 136665d165d9STao Ma filp->f_version = inode->i_version; 136765d165d9STao Ma } 136865d165d9STao Ma 136965d165d9STao Ma while (!error && filp->f_pos < inode->i_size) { 137065d165d9STao Ma if (filp->f_pos == 0) { 137165d165d9STao Ma error = filldir(dirent, ".", 1, 0, inode->i_ino, 137265d165d9STao Ma DT_DIR); 137365d165d9STao Ma if (error) 137465d165d9STao Ma break; 137565d165d9STao Ma stored++; 137665d165d9STao Ma 137765d165d9STao Ma error = filldir(dirent, "..", 2, 0, parent_ino, 137865d165d9STao Ma DT_DIR); 137965d165d9STao Ma if (error) 138065d165d9STao Ma break; 138165d165d9STao Ma stored++; 138265d165d9STao Ma 138365d165d9STao Ma filp->f_pos = offset = EXT4_INLINE_DOTDOT_SIZE; 138465d165d9STao Ma continue; 138565d165d9STao Ma } 138665d165d9STao Ma 138765d165d9STao Ma de = (struct ext4_dir_entry_2 *)(dir_buf + offset); 138865d165d9STao Ma if (ext4_check_dir_entry(inode, filp, de, 138965d165d9STao Ma iloc.bh, dir_buf, 139065d165d9STao Ma inline_size, offset)) { 139165d165d9STao Ma ret = stored; 139265d165d9STao Ma goto out; 139365d165d9STao Ma } 139465d165d9STao Ma offset += ext4_rec_len_from_disk(de->rec_len, 139565d165d9STao Ma inline_size); 139665d165d9STao Ma if (le32_to_cpu(de->inode)) { 139765d165d9STao Ma /* We might block in the next section 139865d165d9STao Ma * if the data destination is 139965d165d9STao Ma * currently swapped out. So, use a 140065d165d9STao Ma * version stamp to detect whether or 140165d165d9STao Ma * not the directory has been modified 140265d165d9STao Ma * during the copy operation. 140365d165d9STao Ma */ 140465d165d9STao Ma u64 version = filp->f_version; 140565d165d9STao Ma 140665d165d9STao Ma error = filldir(dirent, de->name, 140765d165d9STao Ma de->name_len, 140865d165d9STao Ma filp->f_pos, 140965d165d9STao Ma le32_to_cpu(de->inode), 141065d165d9STao Ma get_dtype(sb, de->file_type)); 141165d165d9STao Ma if (error) 141265d165d9STao Ma break; 141365d165d9STao Ma if (version != filp->f_version) 141465d165d9STao Ma goto revalidate; 141565d165d9STao Ma stored++; 141665d165d9STao Ma } 141765d165d9STao Ma filp->f_pos += ext4_rec_len_from_disk(de->rec_len, 141865d165d9STao Ma inline_size); 141965d165d9STao Ma } 142065d165d9STao Ma offset = 0; 142165d165d9STao Ma } 142265d165d9STao Ma out: 142365d165d9STao Ma kfree(dir_buf); 142465d165d9STao Ma brelse(iloc.bh); 142565d165d9STao Ma return ret; 142665d165d9STao Ma } 142765d165d9STao Ma 142832f7f22cSTao Ma struct buffer_head *ext4_get_first_inline_block(struct inode *inode, 142932f7f22cSTao Ma struct ext4_dir_entry_2 **parent_de, 143032f7f22cSTao Ma int *retval) 143132f7f22cSTao Ma { 143232f7f22cSTao Ma struct ext4_iloc iloc; 143332f7f22cSTao Ma 143432f7f22cSTao Ma *retval = ext4_get_inode_loc(inode, &iloc); 143532f7f22cSTao Ma if (*retval) 143632f7f22cSTao Ma return NULL; 143732f7f22cSTao Ma 143832f7f22cSTao Ma *parent_de = (struct ext4_dir_entry_2 *)ext4_raw_inode(&iloc)->i_block; 143932f7f22cSTao Ma 144032f7f22cSTao Ma return iloc.bh; 144132f7f22cSTao Ma } 144232f7f22cSTao Ma 14433c47d541STao Ma /* 14443c47d541STao Ma * Try to create the inline data for the new dir. 14453c47d541STao Ma * If it succeeds, return 0, otherwise return the error. 14463c47d541STao Ma * In case of ENOSPC, the caller should create the normal disk layout dir. 14473c47d541STao Ma */ 14483c47d541STao Ma int ext4_try_create_inline_dir(handle_t *handle, struct inode *parent, 14493c47d541STao Ma struct inode *inode) 14503c47d541STao Ma { 14513c47d541STao Ma int ret, inline_size = EXT4_MIN_INLINE_DATA_SIZE; 14523c47d541STao Ma struct ext4_iloc iloc; 14533c47d541STao Ma struct ext4_dir_entry_2 *de; 14543c47d541STao Ma 14553c47d541STao Ma ret = ext4_get_inode_loc(inode, &iloc); 14563c47d541STao Ma if (ret) 14573c47d541STao Ma return ret; 14583c47d541STao Ma 14593c47d541STao Ma ret = ext4_prepare_inline_data(handle, inode, inline_size); 14603c47d541STao Ma if (ret) 14613c47d541STao Ma goto out; 14623c47d541STao Ma 14633c47d541STao Ma /* 14643c47d541STao Ma * For inline dir, we only save the inode information for the ".." 14653c47d541STao Ma * and create a fake dentry to cover the left space. 14663c47d541STao Ma */ 14673c47d541STao Ma de = (struct ext4_dir_entry_2 *)ext4_raw_inode(&iloc)->i_block; 14683c47d541STao Ma de->inode = cpu_to_le32(parent->i_ino); 14693c47d541STao Ma de = (struct ext4_dir_entry_2 *)((void *)de + EXT4_INLINE_DOTDOT_SIZE); 14703c47d541STao Ma de->inode = 0; 14713c47d541STao Ma de->rec_len = ext4_rec_len_to_disk( 14723c47d541STao Ma inline_size - EXT4_INLINE_DOTDOT_SIZE, 14733c47d541STao Ma inline_size); 14743c47d541STao Ma set_nlink(inode, 2); 14753c47d541STao Ma inode->i_size = EXT4_I(inode)->i_disksize = inline_size; 14763c47d541STao Ma out: 14773c47d541STao Ma brelse(iloc.bh); 14783c47d541STao Ma return ret; 14793c47d541STao Ma } 14803c47d541STao Ma 1481e8e948e7STao Ma struct buffer_head *ext4_find_inline_entry(struct inode *dir, 1482e8e948e7STao Ma const struct qstr *d_name, 1483e8e948e7STao Ma struct ext4_dir_entry_2 **res_dir, 1484e8e948e7STao Ma int *has_inline_data) 1485e8e948e7STao Ma { 1486e8e948e7STao Ma int ret; 1487e8e948e7STao Ma struct ext4_iloc iloc; 1488e8e948e7STao Ma void *inline_start; 1489e8e948e7STao Ma int inline_size; 1490e8e948e7STao Ma 1491e8e948e7STao Ma if (ext4_get_inode_loc(dir, &iloc)) 1492e8e948e7STao Ma return NULL; 1493e8e948e7STao Ma 1494e8e948e7STao Ma down_read(&EXT4_I(dir)->xattr_sem); 1495e8e948e7STao Ma if (!ext4_has_inline_data(dir)) { 1496e8e948e7STao Ma *has_inline_data = 0; 1497e8e948e7STao Ma goto out; 1498e8e948e7STao Ma } 1499e8e948e7STao Ma 1500e8e948e7STao Ma inline_start = (void *)ext4_raw_inode(&iloc)->i_block + 1501e8e948e7STao Ma EXT4_INLINE_DOTDOT_SIZE; 1502e8e948e7STao Ma inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE; 1503e8e948e7STao Ma ret = search_dir(iloc.bh, inline_start, inline_size, 1504e8e948e7STao Ma dir, d_name, 0, res_dir); 1505e8e948e7STao Ma if (ret == 1) 1506e8e948e7STao Ma goto out_find; 1507e8e948e7STao Ma if (ret < 0) 1508e8e948e7STao Ma goto out; 1509e8e948e7STao Ma 1510e8e948e7STao Ma if (ext4_get_inline_size(dir) == EXT4_MIN_INLINE_DATA_SIZE) 1511e8e948e7STao Ma goto out; 1512e8e948e7STao Ma 1513e8e948e7STao Ma inline_start = ext4_get_inline_xattr_pos(dir, &iloc); 1514e8e948e7STao Ma inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE; 1515e8e948e7STao Ma 1516e8e948e7STao Ma ret = search_dir(iloc.bh, inline_start, inline_size, 1517e8e948e7STao Ma dir, d_name, 0, res_dir); 1518e8e948e7STao Ma if (ret == 1) 1519e8e948e7STao Ma goto out_find; 1520e8e948e7STao Ma 1521e8e948e7STao Ma out: 1522e8e948e7STao Ma brelse(iloc.bh); 1523e8e948e7STao Ma iloc.bh = NULL; 1524e8e948e7STao Ma out_find: 1525e8e948e7STao Ma up_read(&EXT4_I(dir)->xattr_sem); 1526e8e948e7STao Ma return iloc.bh; 1527e8e948e7STao Ma } 1528e8e948e7STao Ma 15299f40fe54STao Ma int ext4_delete_inline_entry(handle_t *handle, 15309f40fe54STao Ma struct inode *dir, 15319f40fe54STao Ma struct ext4_dir_entry_2 *de_del, 15329f40fe54STao Ma struct buffer_head *bh, 15339f40fe54STao Ma int *has_inline_data) 15349f40fe54STao Ma { 15359f40fe54STao Ma int err, inline_size; 15369f40fe54STao Ma struct ext4_iloc iloc; 15379f40fe54STao Ma void *inline_start; 15389f40fe54STao Ma 15399f40fe54STao Ma err = ext4_get_inode_loc(dir, &iloc); 15409f40fe54STao Ma if (err) 15419f40fe54STao Ma return err; 15429f40fe54STao Ma 15439f40fe54STao Ma down_write(&EXT4_I(dir)->xattr_sem); 15449f40fe54STao Ma if (!ext4_has_inline_data(dir)) { 15459f40fe54STao Ma *has_inline_data = 0; 15469f40fe54STao Ma goto out; 15479f40fe54STao Ma } 15489f40fe54STao Ma 15499f40fe54STao Ma if ((void *)de_del - ((void *)ext4_raw_inode(&iloc)->i_block) < 15509f40fe54STao Ma EXT4_MIN_INLINE_DATA_SIZE) { 15519f40fe54STao Ma inline_start = (void *)ext4_raw_inode(&iloc)->i_block + 15529f40fe54STao Ma EXT4_INLINE_DOTDOT_SIZE; 15539f40fe54STao Ma inline_size = EXT4_MIN_INLINE_DATA_SIZE - 15549f40fe54STao Ma EXT4_INLINE_DOTDOT_SIZE; 15559f40fe54STao Ma } else { 15569f40fe54STao Ma inline_start = ext4_get_inline_xattr_pos(dir, &iloc); 15579f40fe54STao Ma inline_size = ext4_get_inline_size(dir) - 15589f40fe54STao Ma EXT4_MIN_INLINE_DATA_SIZE; 15599f40fe54STao Ma } 15609f40fe54STao Ma 15619f40fe54STao Ma err = ext4_journal_get_write_access(handle, bh); 15629f40fe54STao Ma if (err) 15639f40fe54STao Ma goto out; 15649f40fe54STao Ma 15659f40fe54STao Ma err = ext4_generic_delete_entry(handle, dir, de_del, bh, 15669f40fe54STao Ma inline_start, inline_size, 0); 15679f40fe54STao Ma if (err) 15689f40fe54STao Ma goto out; 15699f40fe54STao Ma 15709f40fe54STao Ma BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); 15719f40fe54STao Ma err = ext4_mark_inode_dirty(handle, dir); 15729f40fe54STao Ma if (unlikely(err)) 15739f40fe54STao Ma goto out; 15749f40fe54STao Ma 15759f40fe54STao Ma ext4_show_inline_dir(dir, iloc.bh, inline_start, inline_size); 15769f40fe54STao Ma out: 15779f40fe54STao Ma up_write(&EXT4_I(dir)->xattr_sem); 15789f40fe54STao Ma brelse(iloc.bh); 15799f40fe54STao Ma if (err != -ENOENT) 15809f40fe54STao Ma ext4_std_error(dir->i_sb, err); 15819f40fe54STao Ma return err; 15829f40fe54STao Ma } 15839f40fe54STao Ma 158461f86638STao Ma /* 158561f86638STao Ma * Get the inline dentry at offset. 158661f86638STao Ma */ 158761f86638STao Ma static inline struct ext4_dir_entry_2 * 158861f86638STao Ma ext4_get_inline_entry(struct inode *inode, 158961f86638STao Ma struct ext4_iloc *iloc, 159061f86638STao Ma unsigned int offset, 159161f86638STao Ma void **inline_start, 159261f86638STao Ma int *inline_size) 159361f86638STao Ma { 159461f86638STao Ma void *inline_pos; 159561f86638STao Ma 159661f86638STao Ma BUG_ON(offset > ext4_get_inline_size(inode)); 159761f86638STao Ma 159861f86638STao Ma if (offset < EXT4_MIN_INLINE_DATA_SIZE) { 159961f86638STao Ma inline_pos = (void *)ext4_raw_inode(iloc)->i_block; 160061f86638STao Ma *inline_size = EXT4_MIN_INLINE_DATA_SIZE; 160161f86638STao Ma } else { 160261f86638STao Ma inline_pos = ext4_get_inline_xattr_pos(inode, iloc); 160361f86638STao Ma offset -= EXT4_MIN_INLINE_DATA_SIZE; 160461f86638STao Ma *inline_size = ext4_get_inline_size(inode) - 160561f86638STao Ma EXT4_MIN_INLINE_DATA_SIZE; 160661f86638STao Ma } 160761f86638STao Ma 160861f86638STao Ma if (inline_start) 160961f86638STao Ma *inline_start = inline_pos; 161061f86638STao Ma return (struct ext4_dir_entry_2 *)(inline_pos + offset); 161161f86638STao Ma } 161261f86638STao Ma 161361f86638STao Ma int empty_inline_dir(struct inode *dir, int *has_inline_data) 161461f86638STao Ma { 161561f86638STao Ma int err, inline_size; 161661f86638STao Ma struct ext4_iloc iloc; 161761f86638STao Ma void *inline_pos; 161861f86638STao Ma unsigned int offset; 161961f86638STao Ma struct ext4_dir_entry_2 *de; 162061f86638STao Ma int ret = 1; 162161f86638STao Ma 162261f86638STao Ma err = ext4_get_inode_loc(dir, &iloc); 162361f86638STao Ma if (err) { 162461f86638STao Ma EXT4_ERROR_INODE(dir, "error %d getting inode %lu block", 162561f86638STao Ma err, dir->i_ino); 162661f86638STao Ma return 1; 162761f86638STao Ma } 162861f86638STao Ma 162961f86638STao Ma down_read(&EXT4_I(dir)->xattr_sem); 163061f86638STao Ma if (!ext4_has_inline_data(dir)) { 163161f86638STao Ma *has_inline_data = 0; 163261f86638STao Ma goto out; 163361f86638STao Ma } 163461f86638STao Ma 163561f86638STao Ma de = (struct ext4_dir_entry_2 *)ext4_raw_inode(&iloc)->i_block; 163661f86638STao Ma if (!le32_to_cpu(de->inode)) { 163761f86638STao Ma ext4_warning(dir->i_sb, 163861f86638STao Ma "bad inline directory (dir #%lu) - no `..'", 163961f86638STao Ma dir->i_ino); 164061f86638STao Ma ret = 1; 164161f86638STao Ma goto out; 164261f86638STao Ma } 164361f86638STao Ma 164461f86638STao Ma offset = EXT4_INLINE_DOTDOT_SIZE; 164561f86638STao Ma while (offset < dir->i_size) { 164661f86638STao Ma de = ext4_get_inline_entry(dir, &iloc, offset, 164761f86638STao Ma &inline_pos, &inline_size); 164861f86638STao Ma if (ext4_check_dir_entry(dir, NULL, de, 164961f86638STao Ma iloc.bh, inline_pos, 165061f86638STao Ma inline_size, offset)) { 165161f86638STao Ma ext4_warning(dir->i_sb, 165261f86638STao Ma "bad inline directory (dir #%lu) - " 165361f86638STao Ma "inode %u, rec_len %u, name_len %d" 165461f86638STao Ma "inline size %d\n", 165561f86638STao Ma dir->i_ino, le32_to_cpu(de->inode), 165661f86638STao Ma le16_to_cpu(de->rec_len), de->name_len, 165761f86638STao Ma inline_size); 165861f86638STao Ma ret = 1; 165961f86638STao Ma goto out; 166061f86638STao Ma } 166161f86638STao Ma if (le32_to_cpu(de->inode)) { 166261f86638STao Ma ret = 0; 166361f86638STao Ma goto out; 166461f86638STao Ma } 166561f86638STao Ma offset += ext4_rec_len_from_disk(de->rec_len, inline_size); 166661f86638STao Ma } 166761f86638STao Ma 166861f86638STao Ma out: 166961f86638STao Ma up_read(&EXT4_I(dir)->xattr_sem); 167061f86638STao Ma brelse(iloc.bh); 167161f86638STao Ma return ret; 167261f86638STao Ma } 167361f86638STao Ma 167467cf5b09STao Ma int ext4_destroy_inline_data(handle_t *handle, struct inode *inode) 167567cf5b09STao Ma { 167667cf5b09STao Ma int ret; 167767cf5b09STao Ma 167867cf5b09STao Ma down_write(&EXT4_I(inode)->xattr_sem); 167967cf5b09STao Ma ret = ext4_destroy_inline_data_nolock(handle, inode); 168067cf5b09STao Ma up_write(&EXT4_I(inode)->xattr_sem); 168167cf5b09STao Ma 168267cf5b09STao Ma return ret; 168367cf5b09STao Ma } 168494191985STao Ma 168594191985STao Ma int ext4_inline_data_fiemap(struct inode *inode, 168694191985STao Ma struct fiemap_extent_info *fieinfo, 168794191985STao Ma int *has_inline) 168894191985STao Ma { 168994191985STao Ma __u64 physical = 0; 169094191985STao Ma __u64 length; 169194191985STao Ma __u32 flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_LAST; 169294191985STao Ma int error = 0; 169394191985STao Ma struct ext4_iloc iloc; 169494191985STao Ma 169594191985STao Ma down_read(&EXT4_I(inode)->xattr_sem); 169694191985STao Ma if (!ext4_has_inline_data(inode)) { 169794191985STao Ma *has_inline = 0; 169894191985STao Ma goto out; 169994191985STao Ma } 170094191985STao Ma 170194191985STao Ma error = ext4_get_inode_loc(inode, &iloc); 170294191985STao Ma if (error) 170394191985STao Ma goto out; 170494191985STao Ma 170594191985STao Ma physical = iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits; 170694191985STao Ma physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data; 170794191985STao Ma physical += offsetof(struct ext4_inode, i_block); 170894191985STao Ma length = i_size_read(inode); 170994191985STao Ma 171094191985STao Ma if (physical) 171194191985STao Ma error = fiemap_fill_next_extent(fieinfo, 0, physical, 171294191985STao Ma length, flags); 171394191985STao Ma brelse(iloc.bh); 171494191985STao Ma out: 171594191985STao Ma up_read(&EXT4_I(inode)->xattr_sem); 171694191985STao Ma return (error < 0 ? error : 0); 171794191985STao Ma } 17180d812f77STao Ma 17190d812f77STao Ma /* 17200d812f77STao Ma * Called during xattr set, and if we can sparse space 'needed', 17210d812f77STao Ma * just create the extent tree evict the data to the outer block. 17220d812f77STao Ma * 17230d812f77STao Ma * We use jbd2 instead of page cache to move data to the 1st block 17240d812f77STao Ma * so that the whole transaction can be committed as a whole and 17250d812f77STao Ma * the data isn't lost because of the delayed page cache write. 17260d812f77STao Ma */ 17270d812f77STao Ma int ext4_try_to_evict_inline_data(handle_t *handle, 17280d812f77STao Ma struct inode *inode, 17290d812f77STao Ma int needed) 17300d812f77STao Ma { 17310d812f77STao Ma int error; 17320d812f77STao Ma struct ext4_xattr_entry *entry; 17330d812f77STao Ma struct ext4_xattr_ibody_header *header; 17340d812f77STao Ma struct ext4_inode *raw_inode; 17350d812f77STao Ma struct ext4_iloc iloc; 17360d812f77STao Ma 17370d812f77STao Ma error = ext4_get_inode_loc(inode, &iloc); 17380d812f77STao Ma if (error) 17390d812f77STao Ma return error; 17400d812f77STao Ma 17410d812f77STao Ma raw_inode = ext4_raw_inode(&iloc); 17420d812f77STao Ma header = IHDR(inode, raw_inode); 17430d812f77STao Ma entry = (struct ext4_xattr_entry *)((void *)raw_inode + 17440d812f77STao Ma EXT4_I(inode)->i_inline_off); 17450d812f77STao Ma if (EXT4_XATTR_LEN(entry->e_name_len) + 17460d812f77STao Ma EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)) < needed) { 17470d812f77STao Ma error = -ENOSPC; 17480d812f77STao Ma goto out; 17490d812f77STao Ma } 17500d812f77STao Ma 17510d812f77STao Ma error = ext4_convert_inline_data_nolock(handle, inode, &iloc); 17520d812f77STao Ma out: 17530d812f77STao Ma brelse(iloc.bh); 17540d812f77STao Ma return error; 17550d812f77STao Ma } 1756aef1c851STao Ma 1757aef1c851STao Ma void ext4_inline_data_truncate(struct inode *inode, int *has_inline) 1758aef1c851STao Ma { 1759aef1c851STao Ma handle_t *handle; 1760aef1c851STao Ma int inline_size, value_len, needed_blocks; 1761aef1c851STao Ma size_t i_size; 1762aef1c851STao Ma void *value = NULL; 1763aef1c851STao Ma struct ext4_xattr_ibody_find is = { 1764aef1c851STao Ma .s = { .not_found = -ENODATA, }, 1765aef1c851STao Ma }; 1766aef1c851STao Ma struct ext4_xattr_info i = { 1767aef1c851STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 1768aef1c851STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 1769aef1c851STao Ma }; 1770aef1c851STao Ma 1771aef1c851STao Ma 1772aef1c851STao Ma needed_blocks = ext4_writepage_trans_blocks(inode); 1773aef1c851STao Ma handle = ext4_journal_start(inode, needed_blocks); 1774aef1c851STao Ma if (IS_ERR(handle)) 1775aef1c851STao Ma return; 1776aef1c851STao Ma 1777aef1c851STao Ma down_write(&EXT4_I(inode)->xattr_sem); 1778aef1c851STao Ma if (!ext4_has_inline_data(inode)) { 1779aef1c851STao Ma *has_inline = 0; 1780aef1c851STao Ma ext4_journal_stop(handle); 1781aef1c851STao Ma return; 1782aef1c851STao Ma } 1783aef1c851STao Ma 1784aef1c851STao Ma if (ext4_orphan_add(handle, inode)) 1785aef1c851STao Ma goto out; 1786aef1c851STao Ma 1787aef1c851STao Ma if (ext4_get_inode_loc(inode, &is.iloc)) 1788aef1c851STao Ma goto out; 1789aef1c851STao Ma 1790aef1c851STao Ma down_write(&EXT4_I(inode)->i_data_sem); 1791aef1c851STao Ma i_size = inode->i_size; 1792aef1c851STao Ma inline_size = ext4_get_inline_size(inode); 1793aef1c851STao Ma EXT4_I(inode)->i_disksize = i_size; 1794aef1c851STao Ma 1795aef1c851STao Ma if (i_size < inline_size) { 1796aef1c851STao Ma /* Clear the content in the xattr space. */ 1797aef1c851STao Ma if (inline_size > EXT4_MIN_INLINE_DATA_SIZE) { 1798aef1c851STao Ma if (ext4_xattr_ibody_find(inode, &i, &is)) 1799aef1c851STao Ma goto out_error; 1800aef1c851STao Ma 1801aef1c851STao Ma BUG_ON(is.s.not_found); 1802aef1c851STao Ma 1803aef1c851STao Ma value_len = le32_to_cpu(is.s.here->e_value_size); 1804aef1c851STao Ma value = kmalloc(value_len, GFP_NOFS); 1805aef1c851STao Ma if (!value) 1806aef1c851STao Ma goto out_error; 1807aef1c851STao Ma 1808aef1c851STao Ma if (ext4_xattr_ibody_get(inode, i.name_index, i.name, 1809aef1c851STao Ma value, value_len)) 1810aef1c851STao Ma goto out_error; 1811aef1c851STao Ma 1812aef1c851STao Ma i.value = value; 1813aef1c851STao Ma i.value_len = i_size > EXT4_MIN_INLINE_DATA_SIZE ? 1814aef1c851STao Ma i_size - EXT4_MIN_INLINE_DATA_SIZE : 0; 1815aef1c851STao Ma if (ext4_xattr_ibody_inline_set(handle, inode, &i, &is)) 1816aef1c851STao Ma goto out_error; 1817aef1c851STao Ma } 1818aef1c851STao Ma 1819aef1c851STao Ma /* Clear the content within i_blocks. */ 1820aef1c851STao Ma if (i_size < EXT4_MIN_INLINE_DATA_SIZE) 1821aef1c851STao Ma memset(ext4_raw_inode(&is.iloc)->i_block + i_size, 0, 1822aef1c851STao Ma EXT4_MIN_INLINE_DATA_SIZE - i_size); 1823aef1c851STao Ma 1824aef1c851STao Ma EXT4_I(inode)->i_inline_size = i_size < 1825aef1c851STao Ma EXT4_MIN_INLINE_DATA_SIZE ? 1826aef1c851STao Ma EXT4_MIN_INLINE_DATA_SIZE : i_size; 1827aef1c851STao Ma } 1828aef1c851STao Ma 1829aef1c851STao Ma out_error: 1830aef1c851STao Ma up_write(&EXT4_I(inode)->i_data_sem); 1831aef1c851STao Ma out: 1832aef1c851STao Ma brelse(is.iloc.bh); 1833aef1c851STao Ma up_write(&EXT4_I(inode)->xattr_sem); 1834aef1c851STao Ma kfree(value); 1835aef1c851STao Ma if (inode->i_nlink) 1836aef1c851STao Ma ext4_orphan_del(handle, inode); 1837aef1c851STao Ma 1838aef1c851STao Ma inode->i_mtime = inode->i_ctime = ext4_current_time(inode); 1839aef1c851STao Ma ext4_mark_inode_dirty(handle, inode); 1840aef1c851STao Ma if (IS_SYNC(inode)) 1841aef1c851STao Ma ext4_handle_sync(handle); 1842aef1c851STao Ma 1843aef1c851STao Ma ext4_journal_stop(handle); 1844aef1c851STao Ma return; 1845aef1c851STao Ma } 18460c8d414fSTao Ma 18470c8d414fSTao Ma int ext4_convert_inline_data(struct inode *inode) 18480c8d414fSTao Ma { 18490c8d414fSTao Ma int error, needed_blocks; 18500c8d414fSTao Ma handle_t *handle; 18510c8d414fSTao Ma struct ext4_iloc iloc; 18520c8d414fSTao Ma 18530c8d414fSTao Ma if (!ext4_has_inline_data(inode)) { 18540c8d414fSTao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 18550c8d414fSTao Ma return 0; 18560c8d414fSTao Ma } 18570c8d414fSTao Ma 18580c8d414fSTao Ma needed_blocks = ext4_writepage_trans_blocks(inode); 18590c8d414fSTao Ma 18600c8d414fSTao Ma iloc.bh = NULL; 18610c8d414fSTao Ma error = ext4_get_inode_loc(inode, &iloc); 18620c8d414fSTao Ma if (error) 18630c8d414fSTao Ma return error; 18640c8d414fSTao Ma 18650c8d414fSTao Ma handle = ext4_journal_start(inode, needed_blocks); 18660c8d414fSTao Ma if (IS_ERR(handle)) { 18670c8d414fSTao Ma error = PTR_ERR(handle); 18680c8d414fSTao Ma goto out_free; 18690c8d414fSTao Ma } 18700c8d414fSTao Ma 18710c8d414fSTao Ma down_write(&EXT4_I(inode)->xattr_sem); 18720c8d414fSTao Ma if (!ext4_has_inline_data(inode)) { 18730c8d414fSTao Ma up_write(&EXT4_I(inode)->xattr_sem); 18740c8d414fSTao Ma goto out; 18750c8d414fSTao Ma } 18760c8d414fSTao Ma 18770c8d414fSTao Ma error = ext4_convert_inline_data_nolock(handle, inode, &iloc); 18780c8d414fSTao Ma up_write(&EXT4_I(inode)->xattr_sem); 18790c8d414fSTao Ma out: 18800c8d414fSTao Ma ext4_journal_stop(handle); 18810c8d414fSTao Ma out_free: 18820c8d414fSTao Ma brelse(iloc.bh); 18830c8d414fSTao Ma return error; 18840c8d414fSTao Ma } 1885