1f5166768STheodore Ts'o // SPDX-License-Identifier: LGPL-2.1 267cf5b09STao Ma /* 367cf5b09STao Ma * Copyright (c) 2012 Taobao. 467cf5b09STao Ma * Written by Tao Ma <boyu.mt@taobao.com> 567cf5b09STao Ma */ 64bdfc873SMichael Halcrow 77046ae35SAndreas Gruenbacher #include <linux/iomap.h> 84bdfc873SMichael Halcrow #include <linux/fiemap.h> 9ee73f9a5SJeff Layton #include <linux/iversion.h> 104bdfc873SMichael Halcrow 1167cf5b09STao Ma #include "ext4_jbd2.h" 1267cf5b09STao Ma #include "ext4.h" 1367cf5b09STao Ma #include "xattr.h" 14f19d5870STao Ma #include "truncate.h" 1567cf5b09STao Ma 1667cf5b09STao Ma #define EXT4_XATTR_SYSTEM_DATA "data" 1767cf5b09STao Ma #define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS)) 188af0f082STao Ma #define EXT4_INLINE_DOTDOT_OFFSET 2 193c47d541STao Ma #define EXT4_INLINE_DOTDOT_SIZE 4 2067cf5b09STao Ma 21c197855eSStephen Hemminger static int ext4_get_inline_size(struct inode *inode) 2267cf5b09STao Ma { 2367cf5b09STao Ma if (EXT4_I(inode)->i_inline_off) 2467cf5b09STao Ma return EXT4_I(inode)->i_inline_size; 2567cf5b09STao Ma 2667cf5b09STao Ma return 0; 2767cf5b09STao Ma } 2867cf5b09STao Ma 2967cf5b09STao Ma static int get_max_inline_xattr_value_size(struct inode *inode, 3067cf5b09STao Ma struct ext4_iloc *iloc) 3167cf5b09STao Ma { 3267cf5b09STao Ma struct ext4_xattr_ibody_header *header; 3367cf5b09STao Ma struct ext4_xattr_entry *entry; 3467cf5b09STao Ma struct ext4_inode *raw_inode; 3567cf5b09STao Ma int free, min_offs; 3667cf5b09STao Ma 3767cf5b09STao Ma min_offs = EXT4_SB(inode->i_sb)->s_inode_size - 3867cf5b09STao Ma EXT4_GOOD_OLD_INODE_SIZE - 3967cf5b09STao Ma EXT4_I(inode)->i_extra_isize - 4067cf5b09STao Ma sizeof(struct ext4_xattr_ibody_header); 4167cf5b09STao Ma 4267cf5b09STao Ma /* 4367cf5b09STao Ma * We need to subtract another sizeof(__u32) since an in-inode xattr 4467cf5b09STao Ma * needs an empty 4 bytes to indicate the gap between the xattr entry 4567cf5b09STao Ma * and the name/value pair. 4667cf5b09STao Ma */ 4767cf5b09STao Ma if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR)) 4867cf5b09STao Ma return EXT4_XATTR_SIZE(min_offs - 4967cf5b09STao Ma EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA)) - 5067cf5b09STao Ma EXT4_XATTR_ROUND - sizeof(__u32)); 5167cf5b09STao Ma 5267cf5b09STao Ma raw_inode = ext4_raw_inode(iloc); 5367cf5b09STao Ma header = IHDR(inode, raw_inode); 5467cf5b09STao Ma entry = IFIRST(header); 5567cf5b09STao Ma 5667cf5b09STao Ma /* Compute min_offs. */ 5767cf5b09STao Ma for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { 58e50e5129SAndreas Dilger if (!entry->e_value_inum && entry->e_value_size) { 5967cf5b09STao Ma size_t offs = le16_to_cpu(entry->e_value_offs); 6067cf5b09STao Ma if (offs < min_offs) 6167cf5b09STao Ma min_offs = offs; 6267cf5b09STao Ma } 6367cf5b09STao Ma } 6467cf5b09STao Ma free = min_offs - 6567cf5b09STao Ma ((void *)entry - (void *)IFIRST(header)) - sizeof(__u32); 6667cf5b09STao Ma 6767cf5b09STao Ma if (EXT4_I(inode)->i_inline_off) { 6867cf5b09STao Ma entry = (struct ext4_xattr_entry *) 6967cf5b09STao Ma ((void *)raw_inode + EXT4_I(inode)->i_inline_off); 7067cf5b09STao Ma 71c4932dbeSboxi liu free += EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)); 7267cf5b09STao Ma goto out; 7367cf5b09STao Ma } 7467cf5b09STao Ma 7567cf5b09STao Ma free -= EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA)); 7667cf5b09STao Ma 7767cf5b09STao Ma if (free > EXT4_XATTR_ROUND) 7867cf5b09STao Ma free = EXT4_XATTR_SIZE(free - EXT4_XATTR_ROUND); 7967cf5b09STao Ma else 8067cf5b09STao Ma free = 0; 8167cf5b09STao Ma 8267cf5b09STao Ma out: 8367cf5b09STao Ma return free; 8467cf5b09STao Ma } 8567cf5b09STao Ma 8667cf5b09STao Ma /* 8767cf5b09STao Ma * Get the maximum size we now can store in an inode. 8867cf5b09STao Ma * If we can't find the space for a xattr entry, don't use the space 8967cf5b09STao Ma * of the extents since we have no space to indicate the inline data. 9067cf5b09STao Ma */ 9167cf5b09STao Ma int ext4_get_max_inline_size(struct inode *inode) 9267cf5b09STao Ma { 9367cf5b09STao Ma int error, max_inline_size; 9467cf5b09STao Ma struct ext4_iloc iloc; 9567cf5b09STao Ma 9667cf5b09STao Ma if (EXT4_I(inode)->i_extra_isize == 0) 9767cf5b09STao Ma return 0; 9867cf5b09STao Ma 9967cf5b09STao Ma error = ext4_get_inode_loc(inode, &iloc); 10067cf5b09STao Ma if (error) { 10167cf5b09STao Ma ext4_error_inode(inode, __func__, __LINE__, 0, 10267cf5b09STao Ma "can't get inode location %lu", 10367cf5b09STao Ma inode->i_ino); 10467cf5b09STao Ma return 0; 10567cf5b09STao Ma } 10667cf5b09STao Ma 10767cf5b09STao Ma down_read(&EXT4_I(inode)->xattr_sem); 10867cf5b09STao Ma max_inline_size = get_max_inline_xattr_value_size(inode, &iloc); 10967cf5b09STao Ma up_read(&EXT4_I(inode)->xattr_sem); 11067cf5b09STao Ma 11167cf5b09STao Ma brelse(iloc.bh); 11267cf5b09STao Ma 11367cf5b09STao Ma if (!max_inline_size) 11467cf5b09STao Ma return 0; 11567cf5b09STao Ma 11667cf5b09STao Ma return max_inline_size + EXT4_MIN_INLINE_DATA_SIZE; 11767cf5b09STao Ma } 11867cf5b09STao Ma 11967cf5b09STao Ma /* 12067cf5b09STao Ma * this function does not take xattr_sem, which is OK because it is 12167cf5b09STao Ma * currently only used in a code path coming form ext4_iget, before 12267cf5b09STao Ma * the new inode has been unlocked 12367cf5b09STao Ma */ 12467cf5b09STao Ma int ext4_find_inline_data_nolock(struct inode *inode) 12567cf5b09STao Ma { 12667cf5b09STao Ma struct ext4_xattr_ibody_find is = { 12767cf5b09STao Ma .s = { .not_found = -ENODATA, }, 12867cf5b09STao Ma }; 12967cf5b09STao Ma struct ext4_xattr_info i = { 13067cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 13167cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 13267cf5b09STao Ma }; 13367cf5b09STao Ma int error; 13467cf5b09STao Ma 13567cf5b09STao Ma if (EXT4_I(inode)->i_extra_isize == 0) 13667cf5b09STao Ma return 0; 13767cf5b09STao Ma 13867cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 13967cf5b09STao Ma if (error) 14067cf5b09STao Ma return error; 14167cf5b09STao Ma 14267cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 14367cf5b09STao Ma if (error) 14467cf5b09STao Ma goto out; 14567cf5b09STao Ma 14667cf5b09STao Ma if (!is.s.not_found) { 14767cf5b09STao Ma EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here - 14867cf5b09STao Ma (void *)ext4_raw_inode(&is.iloc)); 14967cf5b09STao Ma EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE + 15067cf5b09STao Ma le32_to_cpu(is.s.here->e_value_size); 15167cf5b09STao Ma ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 15267cf5b09STao Ma } 15367cf5b09STao Ma out: 15467cf5b09STao Ma brelse(is.iloc.bh); 15567cf5b09STao Ma return error; 15667cf5b09STao Ma } 15767cf5b09STao Ma 15867cf5b09STao Ma static int ext4_read_inline_data(struct inode *inode, void *buffer, 15967cf5b09STao Ma unsigned int len, 16067cf5b09STao Ma struct ext4_iloc *iloc) 16167cf5b09STao Ma { 16267cf5b09STao Ma struct ext4_xattr_entry *entry; 16367cf5b09STao Ma struct ext4_xattr_ibody_header *header; 16467cf5b09STao Ma int cp_len = 0; 16567cf5b09STao Ma struct ext4_inode *raw_inode; 16667cf5b09STao Ma 16767cf5b09STao Ma if (!len) 16867cf5b09STao Ma return 0; 16967cf5b09STao Ma 17067cf5b09STao Ma BUG_ON(len > EXT4_I(inode)->i_inline_size); 17167cf5b09STao Ma 17267cf5b09STao Ma cp_len = len < EXT4_MIN_INLINE_DATA_SIZE ? 17367cf5b09STao Ma len : EXT4_MIN_INLINE_DATA_SIZE; 17467cf5b09STao Ma 17567cf5b09STao Ma raw_inode = ext4_raw_inode(iloc); 17667cf5b09STao Ma memcpy(buffer, (void *)(raw_inode->i_block), cp_len); 17767cf5b09STao Ma 17867cf5b09STao Ma len -= cp_len; 17967cf5b09STao Ma buffer += cp_len; 18067cf5b09STao Ma 18167cf5b09STao Ma if (!len) 18267cf5b09STao Ma goto out; 18367cf5b09STao Ma 18467cf5b09STao Ma header = IHDR(inode, raw_inode); 18567cf5b09STao Ma entry = (struct ext4_xattr_entry *)((void *)raw_inode + 18667cf5b09STao Ma EXT4_I(inode)->i_inline_off); 18767cf5b09STao Ma len = min_t(unsigned int, len, 18867cf5b09STao Ma (unsigned int)le32_to_cpu(entry->e_value_size)); 18967cf5b09STao Ma 19067cf5b09STao Ma memcpy(buffer, 19167cf5b09STao Ma (void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs), len); 19267cf5b09STao Ma cp_len += len; 19367cf5b09STao Ma 19467cf5b09STao Ma out: 19567cf5b09STao Ma return cp_len; 19667cf5b09STao Ma } 19767cf5b09STao Ma 19867cf5b09STao Ma /* 19967cf5b09STao Ma * write the buffer to the inline inode. 20067cf5b09STao Ma * If 'create' is set, we don't need to do the extra copy in the xattr 2010d812f77STao Ma * value since it is already handled by ext4_xattr_ibody_inline_set. 2020d812f77STao Ma * That saves us one memcpy. 20367cf5b09STao Ma */ 204c197855eSStephen Hemminger static void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc, 20567cf5b09STao Ma void *buffer, loff_t pos, unsigned int len) 20667cf5b09STao Ma { 20767cf5b09STao Ma struct ext4_xattr_entry *entry; 20867cf5b09STao Ma struct ext4_xattr_ibody_header *header; 20967cf5b09STao Ma struct ext4_inode *raw_inode; 21067cf5b09STao Ma int cp_len = 0; 21167cf5b09STao Ma 2120db1ff22STheodore Ts'o if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) 2130db1ff22STheodore Ts'o return; 2140db1ff22STheodore Ts'o 21567cf5b09STao Ma BUG_ON(!EXT4_I(inode)->i_inline_off); 21667cf5b09STao Ma BUG_ON(pos + len > EXT4_I(inode)->i_inline_size); 21767cf5b09STao Ma 21867cf5b09STao Ma raw_inode = ext4_raw_inode(iloc); 21967cf5b09STao Ma buffer += pos; 22067cf5b09STao Ma 22167cf5b09STao Ma if (pos < EXT4_MIN_INLINE_DATA_SIZE) { 22267cf5b09STao Ma cp_len = pos + len > EXT4_MIN_INLINE_DATA_SIZE ? 22367cf5b09STao Ma EXT4_MIN_INLINE_DATA_SIZE - pos : len; 22467cf5b09STao Ma memcpy((void *)raw_inode->i_block + pos, buffer, cp_len); 22567cf5b09STao Ma 22667cf5b09STao Ma len -= cp_len; 22767cf5b09STao Ma buffer += cp_len; 22867cf5b09STao Ma pos += cp_len; 22967cf5b09STao Ma } 23067cf5b09STao Ma 23167cf5b09STao Ma if (!len) 23267cf5b09STao Ma return; 23367cf5b09STao Ma 23467cf5b09STao Ma pos -= EXT4_MIN_INLINE_DATA_SIZE; 23567cf5b09STao Ma header = IHDR(inode, raw_inode); 23667cf5b09STao Ma entry = (struct ext4_xattr_entry *)((void *)raw_inode + 23767cf5b09STao Ma EXT4_I(inode)->i_inline_off); 23867cf5b09STao Ma 23967cf5b09STao Ma memcpy((void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs) + pos, 24067cf5b09STao Ma buffer, len); 24167cf5b09STao Ma } 24267cf5b09STao Ma 24367cf5b09STao Ma static int ext4_create_inline_data(handle_t *handle, 24467cf5b09STao Ma struct inode *inode, unsigned len) 24567cf5b09STao Ma { 24667cf5b09STao Ma int error; 24767cf5b09STao Ma void *value = NULL; 24867cf5b09STao Ma struct ext4_xattr_ibody_find is = { 24967cf5b09STao Ma .s = { .not_found = -ENODATA, }, 25067cf5b09STao Ma }; 25167cf5b09STao Ma struct ext4_xattr_info i = { 25267cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 25367cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 25467cf5b09STao Ma }; 25567cf5b09STao Ma 25667cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 25767cf5b09STao Ma if (error) 25867cf5b09STao Ma return error; 25967cf5b09STao Ma 2605d601255Sliang xie BUFFER_TRACE(is.iloc.bh, "get_write_access"); 26167cf5b09STao Ma error = ext4_journal_get_write_access(handle, is.iloc.bh); 26267cf5b09STao Ma if (error) 26367cf5b09STao Ma goto out; 26467cf5b09STao Ma 26567cf5b09STao Ma if (len > EXT4_MIN_INLINE_DATA_SIZE) { 266bd9926e8STheodore Ts'o value = EXT4_ZERO_XATTR_VALUE; 26767cf5b09STao Ma len -= EXT4_MIN_INLINE_DATA_SIZE; 26867cf5b09STao Ma } else { 26967cf5b09STao Ma value = ""; 27067cf5b09STao Ma len = 0; 27167cf5b09STao Ma } 27267cf5b09STao Ma 27367cf5b09STao Ma /* Insert the the xttr entry. */ 27467cf5b09STao Ma i.value = value; 27567cf5b09STao Ma i.value_len = len; 27667cf5b09STao Ma 27767cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 27867cf5b09STao Ma if (error) 27967cf5b09STao Ma goto out; 28067cf5b09STao Ma 28167cf5b09STao Ma BUG_ON(!is.s.not_found); 28267cf5b09STao Ma 2830d812f77STao Ma error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); 28467cf5b09STao Ma if (error) { 28567cf5b09STao Ma if (error == -ENOSPC) 28667cf5b09STao Ma ext4_clear_inode_state(inode, 28767cf5b09STao Ma EXT4_STATE_MAY_INLINE_DATA); 28867cf5b09STao Ma goto out; 28967cf5b09STao Ma } 29067cf5b09STao Ma 29167cf5b09STao Ma memset((void *)ext4_raw_inode(&is.iloc)->i_block, 29267cf5b09STao Ma 0, EXT4_MIN_INLINE_DATA_SIZE); 29367cf5b09STao Ma 29467cf5b09STao Ma EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here - 29567cf5b09STao Ma (void *)ext4_raw_inode(&is.iloc)); 29667cf5b09STao Ma EXT4_I(inode)->i_inline_size = len + EXT4_MIN_INLINE_DATA_SIZE; 29767cf5b09STao Ma ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS); 29867cf5b09STao Ma ext4_set_inode_flag(inode, EXT4_INODE_INLINE_DATA); 29967cf5b09STao Ma get_bh(is.iloc.bh); 30067cf5b09STao Ma error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); 30167cf5b09STao Ma 30267cf5b09STao Ma out: 30367cf5b09STao Ma brelse(is.iloc.bh); 30467cf5b09STao Ma return error; 30567cf5b09STao Ma } 30667cf5b09STao Ma 30767cf5b09STao Ma static int ext4_update_inline_data(handle_t *handle, struct inode *inode, 30867cf5b09STao Ma unsigned int len) 30967cf5b09STao Ma { 31067cf5b09STao Ma int error; 31167cf5b09STao Ma void *value = NULL; 31267cf5b09STao Ma struct ext4_xattr_ibody_find is = { 31367cf5b09STao Ma .s = { .not_found = -ENODATA, }, 31467cf5b09STao Ma }; 31567cf5b09STao Ma struct ext4_xattr_info i = { 31667cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 31767cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 31867cf5b09STao Ma }; 31967cf5b09STao Ma 32067cf5b09STao Ma /* If the old space is ok, write the data directly. */ 32167cf5b09STao Ma if (len <= EXT4_I(inode)->i_inline_size) 32267cf5b09STao Ma return 0; 32367cf5b09STao Ma 32467cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 32567cf5b09STao Ma if (error) 32667cf5b09STao Ma return error; 32767cf5b09STao Ma 32867cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 32967cf5b09STao Ma if (error) 33067cf5b09STao Ma goto out; 33167cf5b09STao Ma 33267cf5b09STao Ma BUG_ON(is.s.not_found); 33367cf5b09STao Ma 33467cf5b09STao Ma len -= EXT4_MIN_INLINE_DATA_SIZE; 33567cf5b09STao Ma value = kzalloc(len, GFP_NOFS); 336578620f4SDan Carpenter if (!value) { 337578620f4SDan Carpenter error = -ENOMEM; 33867cf5b09STao Ma goto out; 339578620f4SDan Carpenter } 34067cf5b09STao Ma 34167cf5b09STao Ma error = ext4_xattr_ibody_get(inode, i.name_index, i.name, 34267cf5b09STao Ma value, len); 34367cf5b09STao Ma if (error == -ENODATA) 34467cf5b09STao Ma goto out; 34567cf5b09STao Ma 3465d601255Sliang xie BUFFER_TRACE(is.iloc.bh, "get_write_access"); 34767cf5b09STao Ma error = ext4_journal_get_write_access(handle, is.iloc.bh); 34867cf5b09STao Ma if (error) 34967cf5b09STao Ma goto out; 35067cf5b09STao Ma 35167cf5b09STao Ma /* Update the xttr entry. */ 35267cf5b09STao Ma i.value = value; 35367cf5b09STao Ma i.value_len = len; 35467cf5b09STao Ma 3550d812f77STao Ma error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); 35667cf5b09STao Ma if (error) 35767cf5b09STao Ma goto out; 35867cf5b09STao Ma 35967cf5b09STao Ma EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here - 36067cf5b09STao Ma (void *)ext4_raw_inode(&is.iloc)); 36167cf5b09STao Ma EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE + 36267cf5b09STao Ma le32_to_cpu(is.s.here->e_value_size); 36367cf5b09STao Ma ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 36467cf5b09STao Ma get_bh(is.iloc.bh); 36567cf5b09STao Ma error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); 36667cf5b09STao Ma 36767cf5b09STao Ma out: 36867cf5b09STao Ma kfree(value); 36967cf5b09STao Ma brelse(is.iloc.bh); 37067cf5b09STao Ma return error; 37167cf5b09STao Ma } 37267cf5b09STao Ma 373c197855eSStephen Hemminger static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode, 37467cf5b09STao Ma unsigned int len) 37567cf5b09STao Ma { 376c755e251STheodore Ts'o int ret, size, no_expand; 37767cf5b09STao Ma struct ext4_inode_info *ei = EXT4_I(inode); 37867cf5b09STao Ma 37967cf5b09STao Ma if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) 38067cf5b09STao Ma return -ENOSPC; 38167cf5b09STao Ma 38267cf5b09STao Ma size = ext4_get_max_inline_size(inode); 38367cf5b09STao Ma if (size < len) 38467cf5b09STao Ma return -ENOSPC; 38567cf5b09STao Ma 386c755e251STheodore Ts'o ext4_write_lock_xattr(inode, &no_expand); 38767cf5b09STao Ma 38867cf5b09STao Ma if (ei->i_inline_off) 38967cf5b09STao Ma ret = ext4_update_inline_data(handle, inode, len); 39067cf5b09STao Ma else 39167cf5b09STao Ma ret = ext4_create_inline_data(handle, inode, len); 39267cf5b09STao Ma 393c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 39467cf5b09STao Ma return ret; 39567cf5b09STao Ma } 39667cf5b09STao Ma 39767cf5b09STao Ma static int ext4_destroy_inline_data_nolock(handle_t *handle, 39867cf5b09STao Ma struct inode *inode) 39967cf5b09STao Ma { 40067cf5b09STao Ma struct ext4_inode_info *ei = EXT4_I(inode); 40167cf5b09STao Ma struct ext4_xattr_ibody_find is = { 40267cf5b09STao Ma .s = { .not_found = 0, }, 40367cf5b09STao Ma }; 40467cf5b09STao Ma struct ext4_xattr_info i = { 40567cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 40667cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 40767cf5b09STao Ma .value = NULL, 40867cf5b09STao Ma .value_len = 0, 40967cf5b09STao Ma }; 41067cf5b09STao Ma int error; 41167cf5b09STao Ma 41267cf5b09STao Ma if (!ei->i_inline_off) 41367cf5b09STao Ma return 0; 41467cf5b09STao Ma 41567cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 41667cf5b09STao Ma if (error) 41767cf5b09STao Ma return error; 41867cf5b09STao Ma 41967cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 42067cf5b09STao Ma if (error) 42167cf5b09STao Ma goto out; 42267cf5b09STao Ma 4235d601255Sliang xie BUFFER_TRACE(is.iloc.bh, "get_write_access"); 42467cf5b09STao Ma error = ext4_journal_get_write_access(handle, is.iloc.bh); 42567cf5b09STao Ma if (error) 42667cf5b09STao Ma goto out; 42767cf5b09STao Ma 4280d812f77STao Ma error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); 42967cf5b09STao Ma if (error) 43067cf5b09STao Ma goto out; 43167cf5b09STao Ma 43267cf5b09STao Ma memset((void *)ext4_raw_inode(&is.iloc)->i_block, 43367cf5b09STao Ma 0, EXT4_MIN_INLINE_DATA_SIZE); 43467cf5b09STao Ma 435e2b911c5SDarrick J. Wong if (ext4_has_feature_extents(inode->i_sb)) { 43667cf5b09STao Ma if (S_ISDIR(inode->i_mode) || 43767cf5b09STao Ma S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) { 43867cf5b09STao Ma ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS); 43967cf5b09STao Ma ext4_ext_tree_init(handle, inode); 44067cf5b09STao Ma } 44167cf5b09STao Ma } 44267cf5b09STao Ma ext4_clear_inode_flag(inode, EXT4_INODE_INLINE_DATA); 44367cf5b09STao Ma 44467cf5b09STao Ma get_bh(is.iloc.bh); 44567cf5b09STao Ma error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); 44667cf5b09STao Ma 44767cf5b09STao Ma EXT4_I(inode)->i_inline_off = 0; 44867cf5b09STao Ma EXT4_I(inode)->i_inline_size = 0; 44967cf5b09STao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 45067cf5b09STao Ma out: 45167cf5b09STao Ma brelse(is.iloc.bh); 45267cf5b09STao Ma if (error == -ENODATA) 45367cf5b09STao Ma error = 0; 45467cf5b09STao Ma return error; 45567cf5b09STao Ma } 45667cf5b09STao Ma 45746c7f254STao Ma static int ext4_read_inline_page(struct inode *inode, struct page *page) 45846c7f254STao Ma { 45946c7f254STao Ma void *kaddr; 46046c7f254STao Ma int ret = 0; 46146c7f254STao Ma size_t len; 46246c7f254STao Ma struct ext4_iloc iloc; 46346c7f254STao Ma 46446c7f254STao Ma BUG_ON(!PageLocked(page)); 46546c7f254STao Ma BUG_ON(!ext4_has_inline_data(inode)); 46646c7f254STao Ma BUG_ON(page->index); 46746c7f254STao Ma 46846c7f254STao Ma if (!EXT4_I(inode)->i_inline_off) { 46946c7f254STao Ma ext4_warning(inode->i_sb, "inode %lu doesn't have inline data.", 47046c7f254STao Ma inode->i_ino); 47146c7f254STao Ma goto out; 47246c7f254STao Ma } 47346c7f254STao Ma 47446c7f254STao Ma ret = ext4_get_inode_loc(inode, &iloc); 47546c7f254STao Ma if (ret) 47646c7f254STao Ma goto out; 47746c7f254STao Ma 47846c7f254STao Ma len = min_t(size_t, ext4_get_inline_size(inode), i_size_read(inode)); 47946c7f254STao Ma kaddr = kmap_atomic(page); 48046c7f254STao Ma ret = ext4_read_inline_data(inode, kaddr, len, &iloc); 48146c7f254STao Ma flush_dcache_page(page); 48246c7f254STao Ma kunmap_atomic(kaddr); 48309cbfeafSKirill A. Shutemov zero_user_segment(page, len, PAGE_SIZE); 48446c7f254STao Ma SetPageUptodate(page); 48546c7f254STao Ma brelse(iloc.bh); 48646c7f254STao Ma 48746c7f254STao Ma out: 48846c7f254STao Ma return ret; 48946c7f254STao Ma } 49046c7f254STao Ma 49146c7f254STao Ma int ext4_readpage_inline(struct inode *inode, struct page *page) 49246c7f254STao Ma { 49346c7f254STao Ma int ret = 0; 49446c7f254STao Ma 49546c7f254STao Ma down_read(&EXT4_I(inode)->xattr_sem); 49646c7f254STao Ma if (!ext4_has_inline_data(inode)) { 49746c7f254STao Ma up_read(&EXT4_I(inode)->xattr_sem); 49846c7f254STao Ma return -EAGAIN; 49946c7f254STao Ma } 50046c7f254STao Ma 50146c7f254STao Ma /* 50246c7f254STao Ma * Current inline data can only exist in the 1st page, 50346c7f254STao Ma * So for all the other pages, just set them uptodate. 50446c7f254STao Ma */ 50546c7f254STao Ma if (!page->index) 50646c7f254STao Ma ret = ext4_read_inline_page(inode, page); 50746c7f254STao Ma else if (!PageUptodate(page)) { 50809cbfeafSKirill A. Shutemov zero_user_segment(page, 0, PAGE_SIZE); 50946c7f254STao Ma SetPageUptodate(page); 51046c7f254STao Ma } 51146c7f254STao Ma 51246c7f254STao Ma up_read(&EXT4_I(inode)->xattr_sem); 51346c7f254STao Ma 51446c7f254STao Ma unlock_page(page); 51546c7f254STao Ma return ret >= 0 ? 0 : ret; 51646c7f254STao Ma } 51746c7f254STao Ma 518f19d5870STao Ma static int ext4_convert_inline_data_to_extent(struct address_space *mapping, 519f19d5870STao Ma struct inode *inode, 520f19d5870STao Ma unsigned flags) 521f19d5870STao Ma { 522c755e251STheodore Ts'o int ret, needed_blocks, no_expand; 523f19d5870STao Ma handle_t *handle = NULL; 524f19d5870STao Ma int retries = 0, sem_held = 0; 525f19d5870STao Ma struct page *page = NULL; 526f19d5870STao Ma unsigned from, to; 527f19d5870STao Ma struct ext4_iloc iloc; 528f19d5870STao Ma 529f19d5870STao Ma if (!ext4_has_inline_data(inode)) { 530f19d5870STao Ma /* 531f19d5870STao Ma * clear the flag so that no new write 532f19d5870STao Ma * will trap here again. 533f19d5870STao Ma */ 534f19d5870STao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 535f19d5870STao Ma return 0; 536f19d5870STao Ma } 537f19d5870STao Ma 538f19d5870STao Ma needed_blocks = ext4_writepage_trans_blocks(inode); 539f19d5870STao Ma 540f19d5870STao Ma ret = ext4_get_inode_loc(inode, &iloc); 541f19d5870STao Ma if (ret) 542f19d5870STao Ma return ret; 543f19d5870STao Ma 544f19d5870STao Ma retry: 5459924a92aSTheodore Ts'o handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, needed_blocks); 546f19d5870STao Ma if (IS_ERR(handle)) { 547f19d5870STao Ma ret = PTR_ERR(handle); 548f19d5870STao Ma handle = NULL; 549f19d5870STao Ma goto out; 550f19d5870STao Ma } 551f19d5870STao Ma 552f19d5870STao Ma /* We cannot recurse into the filesystem as the transaction is already 553f19d5870STao Ma * started */ 554f19d5870STao Ma flags |= AOP_FLAG_NOFS; 555f19d5870STao Ma 556f19d5870STao Ma page = grab_cache_page_write_begin(mapping, 0, flags); 557f19d5870STao Ma if (!page) { 558f19d5870STao Ma ret = -ENOMEM; 559f19d5870STao Ma goto out; 560f19d5870STao Ma } 561f19d5870STao Ma 562c755e251STheodore Ts'o ext4_write_lock_xattr(inode, &no_expand); 563f19d5870STao Ma sem_held = 1; 564f19d5870STao Ma /* If some one has already done this for us, just exit. */ 565f19d5870STao Ma if (!ext4_has_inline_data(inode)) { 566f19d5870STao Ma ret = 0; 567f19d5870STao Ma goto out; 568f19d5870STao Ma } 569f19d5870STao Ma 570f19d5870STao Ma from = 0; 571f19d5870STao Ma to = ext4_get_inline_size(inode); 572f19d5870STao Ma if (!PageUptodate(page)) { 573f19d5870STao Ma ret = ext4_read_inline_page(inode, page); 574f19d5870STao Ma if (ret < 0) 575f19d5870STao Ma goto out; 576f19d5870STao Ma } 577f19d5870STao Ma 578f19d5870STao Ma ret = ext4_destroy_inline_data_nolock(handle, inode); 579f19d5870STao Ma if (ret) 580f19d5870STao Ma goto out; 581f19d5870STao Ma 582705965bdSJan Kara if (ext4_should_dioread_nolock(inode)) { 583705965bdSJan Kara ret = __block_write_begin(page, from, to, 584705965bdSJan Kara ext4_get_block_unwritten); 585705965bdSJan Kara } else 586f19d5870STao Ma ret = __block_write_begin(page, from, to, ext4_get_block); 587f19d5870STao Ma 588f19d5870STao Ma if (!ret && ext4_should_journal_data(inode)) { 589f19d5870STao Ma ret = ext4_walk_page_buffers(handle, page_buffers(page), 590f19d5870STao Ma from, to, NULL, 591f19d5870STao Ma do_journal_get_write_access); 592f19d5870STao Ma } 593f19d5870STao Ma 594f19d5870STao Ma if (ret) { 595f19d5870STao Ma unlock_page(page); 59609cbfeafSKirill A. Shutemov put_page(page); 597684de574SDarrick J. Wong page = NULL; 598f19d5870STao Ma ext4_orphan_add(handle, inode); 599c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 600f19d5870STao Ma sem_held = 0; 601f19d5870STao Ma ext4_journal_stop(handle); 602f19d5870STao Ma handle = NULL; 603f19d5870STao Ma ext4_truncate_failed_write(inode); 604f19d5870STao Ma /* 605f19d5870STao Ma * If truncate failed early the inode might 606f19d5870STao Ma * still be on the orphan list; we need to 607f19d5870STao Ma * make sure the inode is removed from the 608f19d5870STao Ma * orphan list in that case. 609f19d5870STao Ma */ 610f19d5870STao Ma if (inode->i_nlink) 611f19d5870STao Ma ext4_orphan_del(NULL, inode); 612f19d5870STao Ma } 613f19d5870STao Ma 614f19d5870STao Ma if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) 615f19d5870STao Ma goto retry; 616f19d5870STao Ma 617684de574SDarrick J. Wong if (page) 618f19d5870STao Ma block_commit_write(page, from, to); 619f19d5870STao Ma out: 620f19d5870STao Ma if (page) { 621f19d5870STao Ma unlock_page(page); 62209cbfeafSKirill A. Shutemov put_page(page); 623f19d5870STao Ma } 624f19d5870STao Ma if (sem_held) 625c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 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 */ 6609924a92aSTheodore Ts'o handle = ext4_journal_start(inode, EXT4_HT_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); 69109cbfeafSKirill A. Shutemov put_page(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 { 718c755e251STheodore Ts'o int ret, no_expand; 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 736c755e251STheodore Ts'o ext4_write_lock_xattr(inode, &no_expand); 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 746c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 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 { 757c755e251STheodore Ts'o int ret, no_expand; 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 767c755e251STheodore Ts'o ext4_write_lock_xattr(inode, &no_expand); 7683fdcfb66STao Ma kaddr = kmap_atomic(page); 7693fdcfb66STao Ma ext4_write_inline_data(inode, &iloc, kaddr, 0, len); 7703fdcfb66STao Ma kunmap_atomic(kaddr); 771c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 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) { 81450db71abSDmitry Monakhov up_read(&EXT4_I(inode)->xattr_sem); 81550db71abSDmitry Monakhov unlock_page(page); 81609cbfeafSKirill A. Shutemov put_page(page); 8179c3569b5STao Ma ext4_truncate_failed_write(inode); 81850db71abSDmitry Monakhov return ret; 8199c3569b5STao Ma } 8209c3569b5STao Ma 8219c3569b5STao Ma SetPageDirty(page); 8229c3569b5STao Ma SetPageUptodate(page); 8239c3569b5STao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 8249c3569b5STao Ma *fsdata = (void *)CONVERT_INLINE_DATA; 8259c3569b5STao Ma 8269c3569b5STao Ma out: 8279c3569b5STao Ma up_read(&EXT4_I(inode)->xattr_sem); 8289c3569b5STao Ma if (page) { 8299c3569b5STao Ma unlock_page(page); 83009cbfeafSKirill A. Shutemov put_page(page); 8319c3569b5STao Ma } 8329c3569b5STao Ma return ret; 8339c3569b5STao Ma } 8349c3569b5STao Ma 8359c3569b5STao Ma /* 8369c3569b5STao Ma * Prepare the write for the inline data. 8379c3569b5STao Ma * If the the data can be written into the inode, we just read 8389c3569b5STao Ma * the page and make it uptodate, and start the journal. 8399c3569b5STao Ma * Otherwise read the page, makes it dirty so that it can be 8409c3569b5STao Ma * handle in writepages(the i_disksize update is left to the 8419c3569b5STao Ma * normal ext4_da_write_end). 8429c3569b5STao Ma */ 8439c3569b5STao Ma int ext4_da_write_inline_data_begin(struct address_space *mapping, 8449c3569b5STao Ma struct inode *inode, 8459c3569b5STao Ma loff_t pos, unsigned len, 8469c3569b5STao Ma unsigned flags, 8479c3569b5STao Ma struct page **pagep, 8489c3569b5STao Ma void **fsdata) 8499c3569b5STao Ma { 8509c3569b5STao Ma int ret, inline_size; 8519c3569b5STao Ma handle_t *handle; 8529c3569b5STao Ma struct page *page; 8539c3569b5STao Ma struct ext4_iloc iloc; 854bc0ca9dfSJan Kara int retries; 8559c3569b5STao Ma 8569c3569b5STao Ma ret = ext4_get_inode_loc(inode, &iloc); 8579c3569b5STao Ma if (ret) 8589c3569b5STao Ma return ret; 8599c3569b5STao Ma 860bc0ca9dfSJan Kara retry_journal: 8619924a92aSTheodore Ts'o handle = ext4_journal_start(inode, EXT4_HT_INODE, 1); 8629c3569b5STao Ma if (IS_ERR(handle)) { 8639c3569b5STao Ma ret = PTR_ERR(handle); 8649c3569b5STao Ma goto out; 8659c3569b5STao Ma } 8669c3569b5STao Ma 8679c3569b5STao Ma inline_size = ext4_get_max_inline_size(inode); 8689c3569b5STao Ma 8699c3569b5STao Ma ret = -ENOSPC; 8709c3569b5STao Ma if (inline_size >= pos + len) { 8719c3569b5STao Ma ret = ext4_prepare_inline_data(handle, inode, pos + len); 8729c3569b5STao Ma if (ret && ret != -ENOSPC) 87352e44777SJan Kara goto out_journal; 8749c3569b5STao Ma } 8759c3569b5STao Ma 8765cc28a9eSDmitry Monakhov /* 8775cc28a9eSDmitry Monakhov * We cannot recurse into the filesystem as the transaction 8785cc28a9eSDmitry Monakhov * is already started. 8795cc28a9eSDmitry Monakhov */ 8805cc28a9eSDmitry Monakhov flags |= AOP_FLAG_NOFS; 8815cc28a9eSDmitry Monakhov 8829c3569b5STao Ma if (ret == -ENOSPC) { 8839c3569b5STao Ma ret = ext4_da_convert_inline_data_to_extent(mapping, 8849c3569b5STao Ma inode, 8859c3569b5STao Ma flags, 8869c3569b5STao Ma fsdata); 887bc0ca9dfSJan Kara ext4_journal_stop(handle); 888bc0ca9dfSJan Kara if (ret == -ENOSPC && 889bc0ca9dfSJan Kara ext4_should_retry_alloc(inode->i_sb, &retries)) 890bc0ca9dfSJan Kara goto retry_journal; 8919c3569b5STao Ma goto out; 8929c3569b5STao Ma } 8939c3569b5STao Ma 8949c3569b5STao Ma 8959c3569b5STao Ma page = grab_cache_page_write_begin(mapping, 0, flags); 8969c3569b5STao Ma if (!page) { 8979c3569b5STao Ma ret = -ENOMEM; 89852e44777SJan Kara goto out_journal; 8999c3569b5STao Ma } 9009c3569b5STao Ma 9019c3569b5STao Ma down_read(&EXT4_I(inode)->xattr_sem); 9029c3569b5STao Ma if (!ext4_has_inline_data(inode)) { 9039c3569b5STao Ma ret = 0; 9049c3569b5STao Ma goto out_release_page; 9059c3569b5STao Ma } 9069c3569b5STao Ma 9079c3569b5STao Ma if (!PageUptodate(page)) { 9089c3569b5STao Ma ret = ext4_read_inline_page(inode, page); 9099c3569b5STao Ma if (ret < 0) 9109c3569b5STao Ma goto out_release_page; 9119c3569b5STao Ma } 9129c3569b5STao Ma 9139c3569b5STao Ma up_read(&EXT4_I(inode)->xattr_sem); 9149c3569b5STao Ma *pagep = page; 9159c3569b5STao Ma brelse(iloc.bh); 9169c3569b5STao Ma return 1; 9179c3569b5STao Ma out_release_page: 9189c3569b5STao Ma up_read(&EXT4_I(inode)->xattr_sem); 9199c3569b5STao Ma unlock_page(page); 92009cbfeafSKirill A. Shutemov put_page(page); 92152e44777SJan Kara out_journal: 9229c3569b5STao Ma ext4_journal_stop(handle); 92352e44777SJan Kara out: 9249c3569b5STao Ma brelse(iloc.bh); 9259c3569b5STao Ma return ret; 9269c3569b5STao Ma } 9279c3569b5STao Ma 9289c3569b5STao Ma int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos, 9299c3569b5STao Ma unsigned len, unsigned copied, 9309c3569b5STao Ma struct page *page) 9319c3569b5STao Ma { 9329c3569b5STao Ma int i_size_changed = 0; 933eb5efbcbSTheodore Ts'o int ret; 9349c3569b5STao Ma 935eb5efbcbSTheodore Ts'o ret = ext4_write_inline_data_end(inode, pos, len, copied, page); 936eb5efbcbSTheodore Ts'o if (ret < 0) { 937eb5efbcbSTheodore Ts'o unlock_page(page); 938eb5efbcbSTheodore Ts'o put_page(page); 939eb5efbcbSTheodore Ts'o return ret; 940eb5efbcbSTheodore Ts'o } 941eb5efbcbSTheodore Ts'o copied = ret; 9429c3569b5STao Ma 9439c3569b5STao Ma /* 9449c3569b5STao Ma * No need to use i_size_read() here, the i_size 9459c3569b5STao Ma * cannot change under us because we hold i_mutex. 9469c3569b5STao Ma * 9479c3569b5STao Ma * But it's important to update i_size while still holding page lock: 9489c3569b5STao Ma * page writeout could otherwise come in and zero beyond i_size. 9499c3569b5STao Ma */ 9509c3569b5STao Ma if (pos+copied > inode->i_size) { 9519c3569b5STao Ma i_size_write(inode, pos+copied); 9529c3569b5STao Ma i_size_changed = 1; 9539c3569b5STao Ma } 9549c3569b5STao Ma unlock_page(page); 95509cbfeafSKirill A. Shutemov put_page(page); 9569c3569b5STao Ma 9579c3569b5STao Ma /* 9589c3569b5STao Ma * Don't mark the inode dirty under page lock. First, it unnecessarily 9599c3569b5STao Ma * makes the holding time of page lock longer. Second, it forces lock 9609c3569b5STao Ma * ordering of page lock and transaction start for journaling 9619c3569b5STao Ma * filesystems. 9629c3569b5STao Ma */ 9639c3569b5STao Ma if (i_size_changed) 9649c3569b5STao Ma mark_inode_dirty(inode); 9659c3569b5STao Ma 9669c3569b5STao Ma return copied; 9679c3569b5STao Ma } 968f19d5870STao Ma 9693c47d541STao Ma #ifdef INLINE_DIR_DEBUG 9703c47d541STao Ma void ext4_show_inline_dir(struct inode *dir, struct buffer_head *bh, 9713c47d541STao Ma void *inline_start, int inline_size) 9723c47d541STao Ma { 9733c47d541STao Ma int offset; 9743c47d541STao Ma unsigned short de_len; 9753c47d541STao Ma struct ext4_dir_entry_2 *de = inline_start; 9763c47d541STao Ma void *dlimit = inline_start + inline_size; 9773c47d541STao Ma 9783c47d541STao Ma trace_printk("inode %lu\n", dir->i_ino); 9793c47d541STao Ma offset = 0; 9803c47d541STao Ma while ((void *)de < dlimit) { 9813c47d541STao Ma de_len = ext4_rec_len_from_disk(de->rec_len, inline_size); 98280cfb71eSRasmus Villemoes trace_printk("de: off %u rlen %u name %.*s nlen %u ino %u\n", 9833c47d541STao Ma offset, de_len, de->name_len, de->name, 9843c47d541STao Ma de->name_len, le32_to_cpu(de->inode)); 9853c47d541STao Ma if (ext4_check_dir_entry(dir, NULL, de, bh, 9863c47d541STao Ma inline_start, inline_size, offset)) 9873c47d541STao Ma BUG(); 9883c47d541STao Ma 9893c47d541STao Ma offset += de_len; 9903c47d541STao Ma de = (struct ext4_dir_entry_2 *) ((char *) de + de_len); 9913c47d541STao Ma } 9923c47d541STao Ma } 9933c47d541STao Ma #else 9943c47d541STao Ma #define ext4_show_inline_dir(dir, bh, inline_start, inline_size) 9953c47d541STao Ma #endif 9963c47d541STao Ma 9973c47d541STao Ma /* 9983c47d541STao Ma * Add a new entry into a inline dir. 9993c47d541STao Ma * It will return -ENOSPC if no space is available, and -EIO 10003c47d541STao Ma * and -EEXIST if directory entry already exists. 10013c47d541STao Ma */ 10023c47d541STao Ma static int ext4_add_dirent_to_inline(handle_t *handle, 10035b643f9cSTheodore Ts'o struct ext4_filename *fname, 100456a04915STheodore Ts'o struct inode *dir, 10053c47d541STao Ma struct inode *inode, 10063c47d541STao Ma struct ext4_iloc *iloc, 10073c47d541STao Ma void *inline_start, int inline_size) 10083c47d541STao Ma { 10093c47d541STao Ma int err; 10103c47d541STao Ma struct ext4_dir_entry_2 *de; 10113c47d541STao Ma 10125b643f9cSTheodore Ts'o err = ext4_find_dest_de(dir, inode, iloc->bh, inline_start, 10135b643f9cSTheodore Ts'o inline_size, fname, &de); 10143c47d541STao Ma if (err) 10153c47d541STao Ma return err; 10163c47d541STao Ma 10175d601255Sliang xie BUFFER_TRACE(iloc->bh, "get_write_access"); 10183c47d541STao Ma err = ext4_journal_get_write_access(handle, iloc->bh); 10193c47d541STao Ma if (err) 10203c47d541STao Ma return err; 10211bc0af60SEric Biggers ext4_insert_dentry(inode, de, inline_size, fname); 10223c47d541STao Ma 10233c47d541STao Ma ext4_show_inline_dir(dir, iloc->bh, inline_start, inline_size); 10243c47d541STao Ma 10253c47d541STao Ma /* 10263c47d541STao Ma * XXX shouldn't update any times until successful 10273c47d541STao Ma * completion of syscall, but too many callers depend 10283c47d541STao Ma * on this. 10293c47d541STao Ma * 10303c47d541STao Ma * XXX similarly, too many callers depend on 10313c47d541STao Ma * ext4_new_inode() setting the times, but error 10323c47d541STao Ma * recovery deletes the inode, so the worst that can 10333c47d541STao Ma * happen is that the times are slightly out of date 10343c47d541STao Ma * and/or different from the directory change time. 10353c47d541STao Ma */ 1036eeca7ea1SDeepa Dinamani dir->i_mtime = dir->i_ctime = current_time(dir); 10373c47d541STao Ma ext4_update_dx_flag(dir); 1038ee73f9a5SJeff Layton inode_inc_iversion(dir); 10393c47d541STao Ma return 1; 10403c47d541STao Ma } 10413c47d541STao Ma 10423c47d541STao Ma static void *ext4_get_inline_xattr_pos(struct inode *inode, 10433c47d541STao Ma struct ext4_iloc *iloc) 10443c47d541STao Ma { 10453c47d541STao Ma struct ext4_xattr_entry *entry; 10463c47d541STao Ma struct ext4_xattr_ibody_header *header; 10473c47d541STao Ma 10483c47d541STao Ma BUG_ON(!EXT4_I(inode)->i_inline_off); 10493c47d541STao Ma 10503c47d541STao Ma header = IHDR(inode, ext4_raw_inode(iloc)); 10513c47d541STao Ma entry = (struct ext4_xattr_entry *)((void *)ext4_raw_inode(iloc) + 10523c47d541STao Ma EXT4_I(inode)->i_inline_off); 10533c47d541STao Ma 10543c47d541STao Ma return (void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs); 10553c47d541STao Ma } 10563c47d541STao Ma 10573c47d541STao Ma /* Set the final de to cover the whole block. */ 10583c47d541STao Ma static void ext4_update_final_de(void *de_buf, int old_size, int new_size) 10593c47d541STao Ma { 10603c47d541STao Ma struct ext4_dir_entry_2 *de, *prev_de; 10613c47d541STao Ma void *limit; 10623c47d541STao Ma int de_len; 10633c47d541STao Ma 10643c47d541STao Ma de = (struct ext4_dir_entry_2 *)de_buf; 10653c47d541STao Ma if (old_size) { 10663c47d541STao Ma limit = de_buf + old_size; 10673c47d541STao Ma do { 10683c47d541STao Ma prev_de = de; 10693c47d541STao Ma de_len = ext4_rec_len_from_disk(de->rec_len, old_size); 10703c47d541STao Ma de_buf += de_len; 10713c47d541STao Ma de = (struct ext4_dir_entry_2 *)de_buf; 10723c47d541STao Ma } while (de_buf < limit); 10733c47d541STao Ma 10743c47d541STao Ma prev_de->rec_len = ext4_rec_len_to_disk(de_len + new_size - 10753c47d541STao Ma old_size, new_size); 10763c47d541STao Ma } else { 10773c47d541STao Ma /* this is just created, so create an empty entry. */ 10783c47d541STao Ma de->inode = 0; 10793c47d541STao Ma de->rec_len = ext4_rec_len_to_disk(new_size, new_size); 10803c47d541STao Ma } 10813c47d541STao Ma } 10823c47d541STao Ma 10833c47d541STao Ma static int ext4_update_inline_dir(handle_t *handle, struct inode *dir, 10843c47d541STao Ma struct ext4_iloc *iloc) 10853c47d541STao Ma { 10863c47d541STao Ma int ret; 10873c47d541STao Ma int old_size = EXT4_I(dir)->i_inline_size - EXT4_MIN_INLINE_DATA_SIZE; 10883c47d541STao Ma int new_size = get_max_inline_xattr_value_size(dir, iloc); 10893c47d541STao Ma 10903c47d541STao Ma if (new_size - old_size <= EXT4_DIR_REC_LEN(1)) 10913c47d541STao Ma return -ENOSPC; 10923c47d541STao Ma 10933c47d541STao Ma ret = ext4_update_inline_data(handle, dir, 10943c47d541STao Ma new_size + EXT4_MIN_INLINE_DATA_SIZE); 10953c47d541STao Ma if (ret) 10963c47d541STao Ma return ret; 10973c47d541STao Ma 10983c47d541STao Ma ext4_update_final_de(ext4_get_inline_xattr_pos(dir, iloc), old_size, 10993c47d541STao Ma EXT4_I(dir)->i_inline_size - 11003c47d541STao Ma EXT4_MIN_INLINE_DATA_SIZE); 11013c47d541STao Ma dir->i_size = EXT4_I(dir)->i_disksize = EXT4_I(dir)->i_inline_size; 11023c47d541STao Ma return 0; 11033c47d541STao Ma } 11043c47d541STao Ma 11053c47d541STao Ma static void ext4_restore_inline_data(handle_t *handle, struct inode *inode, 11063c47d541STao Ma struct ext4_iloc *iloc, 11073c47d541STao Ma void *buf, int inline_size) 11083c47d541STao Ma { 11093c47d541STao Ma ext4_create_inline_data(handle, inode, inline_size); 11103c47d541STao Ma ext4_write_inline_data(inode, iloc, buf, 0, inline_size); 11113c47d541STao Ma ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 11123c47d541STao Ma } 11133c47d541STao Ma 11143c47d541STao Ma static int ext4_finish_convert_inline_dir(handle_t *handle, 11153c47d541STao Ma struct inode *inode, 11163c47d541STao Ma struct buffer_head *dir_block, 11173c47d541STao Ma void *buf, 11183c47d541STao Ma int inline_size) 11193c47d541STao Ma { 11203c47d541STao Ma int err, csum_size = 0, header_size = 0; 11213c47d541STao Ma struct ext4_dir_entry_2 *de; 11223c47d541STao Ma struct ext4_dir_entry_tail *t; 11233c47d541STao Ma void *target = dir_block->b_data; 11243c47d541STao Ma 11253c47d541STao Ma /* 11263c47d541STao Ma * First create "." and ".." and then copy the dir information 11273c47d541STao Ma * back to the block. 11283c47d541STao Ma */ 11293c47d541STao Ma de = (struct ext4_dir_entry_2 *)target; 11303c47d541STao Ma de = ext4_init_dot_dotdot(inode, de, 11313c47d541STao Ma inode->i_sb->s_blocksize, csum_size, 11323c47d541STao Ma le32_to_cpu(((struct ext4_dir_entry_2 *)buf)->inode), 1); 11333c47d541STao Ma header_size = (void *)de - target; 11343c47d541STao Ma 11353c47d541STao Ma memcpy((void *)de, buf + EXT4_INLINE_DOTDOT_SIZE, 11363c47d541STao Ma inline_size - EXT4_INLINE_DOTDOT_SIZE); 11373c47d541STao Ma 11389aa5d32bSDmitry Monakhov if (ext4_has_metadata_csum(inode->i_sb)) 11393c47d541STao Ma csum_size = sizeof(struct ext4_dir_entry_tail); 11403c47d541STao Ma 11413c47d541STao Ma inode->i_size = inode->i_sb->s_blocksize; 11423c47d541STao Ma i_size_write(inode, inode->i_sb->s_blocksize); 11433c47d541STao Ma EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize; 11443c47d541STao Ma ext4_update_final_de(dir_block->b_data, 11453c47d541STao Ma inline_size - EXT4_INLINE_DOTDOT_SIZE + header_size, 11463c47d541STao Ma inode->i_sb->s_blocksize - csum_size); 11473c47d541STao Ma 11483c47d541STao Ma if (csum_size) { 11493c47d541STao Ma t = EXT4_DIRENT_TAIL(dir_block->b_data, 11503c47d541STao Ma inode->i_sb->s_blocksize); 11513c47d541STao Ma initialize_dirent_tail(t, inode->i_sb->s_blocksize); 11523c47d541STao Ma } 11533c47d541STao Ma set_buffer_uptodate(dir_block); 11543c47d541STao Ma err = ext4_handle_dirty_dirent_node(handle, inode, dir_block); 11553c47d541STao Ma if (err) 11563c47d541STao Ma return err; 1157b9cf625dSEric Biggers set_buffer_verified(dir_block); 1158b9cf625dSEric Biggers return ext4_mark_inode_dirty(handle, inode); 11593c47d541STao Ma } 11603c47d541STao Ma 11613c47d541STao Ma static int ext4_convert_inline_data_nolock(handle_t *handle, 11623c47d541STao Ma struct inode *inode, 11633c47d541STao Ma struct ext4_iloc *iloc) 11643c47d541STao Ma { 11653c47d541STao Ma int error; 11663c47d541STao Ma void *buf = NULL; 11673c47d541STao Ma struct buffer_head *data_bh = NULL; 11683c47d541STao Ma struct ext4_map_blocks map; 11693c47d541STao Ma int inline_size; 11703c47d541STao Ma 11713c47d541STao Ma inline_size = ext4_get_inline_size(inode); 11723c47d541STao Ma buf = kmalloc(inline_size, GFP_NOFS); 11733c47d541STao Ma if (!buf) { 11743c47d541STao Ma error = -ENOMEM; 11753c47d541STao Ma goto out; 11763c47d541STao Ma } 11773c47d541STao Ma 11783c47d541STao Ma error = ext4_read_inline_data(inode, buf, inline_size, iloc); 11793c47d541STao Ma if (error < 0) 11803c47d541STao Ma goto out; 11813c47d541STao Ma 118240b163f1SDarrick J. Wong /* 118340b163f1SDarrick J. Wong * Make sure the inline directory entries pass checks before we try to 118440b163f1SDarrick J. Wong * convert them, so that we avoid touching stuff that needs fsck. 118540b163f1SDarrick J. Wong */ 118640b163f1SDarrick J. Wong if (S_ISDIR(inode->i_mode)) { 118740b163f1SDarrick J. Wong error = ext4_check_all_de(inode, iloc->bh, 118840b163f1SDarrick J. Wong buf + EXT4_INLINE_DOTDOT_SIZE, 118940b163f1SDarrick J. Wong inline_size - EXT4_INLINE_DOTDOT_SIZE); 119040b163f1SDarrick J. Wong if (error) 119140b163f1SDarrick J. Wong goto out; 119240b163f1SDarrick J. Wong } 119340b163f1SDarrick J. Wong 11943c47d541STao Ma error = ext4_destroy_inline_data_nolock(handle, inode); 11953c47d541STao Ma if (error) 11963c47d541STao Ma goto out; 11973c47d541STao Ma 11983c47d541STao Ma map.m_lblk = 0; 11993c47d541STao Ma map.m_len = 1; 12003c47d541STao Ma map.m_flags = 0; 12013c47d541STao Ma error = ext4_map_blocks(handle, inode, &map, EXT4_GET_BLOCKS_CREATE); 12023c47d541STao Ma if (error < 0) 12033c47d541STao Ma goto out_restore; 12043c47d541STao Ma if (!(map.m_flags & EXT4_MAP_MAPPED)) { 12053c47d541STao Ma error = -EIO; 12063c47d541STao Ma goto out_restore; 12073c47d541STao Ma } 12083c47d541STao Ma 12093c47d541STao Ma data_bh = sb_getblk(inode->i_sb, map.m_pblk); 12103c47d541STao Ma if (!data_bh) { 1211860d21e2STheodore Ts'o error = -ENOMEM; 12123c47d541STao Ma goto out_restore; 12133c47d541STao Ma } 12143c47d541STao Ma 12153c47d541STao Ma lock_buffer(data_bh); 12163c47d541STao Ma error = ext4_journal_get_create_access(handle, data_bh); 12173c47d541STao Ma if (error) { 12183c47d541STao Ma unlock_buffer(data_bh); 12193c47d541STao Ma error = -EIO; 12203c47d541STao Ma goto out_restore; 12213c47d541STao Ma } 12223c47d541STao Ma memset(data_bh->b_data, 0, inode->i_sb->s_blocksize); 12233c47d541STao Ma 12243c47d541STao Ma if (!S_ISDIR(inode->i_mode)) { 12253c47d541STao Ma memcpy(data_bh->b_data, buf, inline_size); 12263c47d541STao Ma set_buffer_uptodate(data_bh); 12273c47d541STao Ma error = ext4_handle_dirty_metadata(handle, 12283c47d541STao Ma inode, data_bh); 12293c47d541STao Ma } else { 12303c47d541STao Ma error = ext4_finish_convert_inline_dir(handle, inode, data_bh, 12313c47d541STao Ma buf, inline_size); 12323c47d541STao Ma } 12333c47d541STao Ma 12343c47d541STao Ma unlock_buffer(data_bh); 12353c47d541STao Ma out_restore: 12363c47d541STao Ma if (error) 12373c47d541STao Ma ext4_restore_inline_data(handle, inode, iloc, buf, inline_size); 12383c47d541STao Ma 12393c47d541STao Ma out: 12403c47d541STao Ma brelse(data_bh); 12413c47d541STao Ma kfree(buf); 12423c47d541STao Ma return error; 12433c47d541STao Ma } 12443c47d541STao Ma 12453c47d541STao Ma /* 12463c47d541STao Ma * Try to add the new entry to the inline data. 12473c47d541STao Ma * If succeeds, return 0. If not, extended the inline dir and copied data to 12483c47d541STao Ma * the new created block. 12493c47d541STao Ma */ 12505b643f9cSTheodore Ts'o int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname, 125156a04915STheodore Ts'o struct inode *dir, struct inode *inode) 12523c47d541STao Ma { 1253c755e251STheodore Ts'o int ret, inline_size, no_expand; 12543c47d541STao Ma void *inline_start; 12553c47d541STao Ma struct ext4_iloc iloc; 12563c47d541STao Ma 12573c47d541STao Ma ret = ext4_get_inode_loc(dir, &iloc); 12583c47d541STao Ma if (ret) 12593c47d541STao Ma return ret; 12603c47d541STao Ma 1261c755e251STheodore Ts'o ext4_write_lock_xattr(dir, &no_expand); 12623c47d541STao Ma if (!ext4_has_inline_data(dir)) 12633c47d541STao Ma goto out; 12643c47d541STao Ma 12653c47d541STao Ma inline_start = (void *)ext4_raw_inode(&iloc)->i_block + 12663c47d541STao Ma EXT4_INLINE_DOTDOT_SIZE; 12673c47d541STao Ma inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE; 12683c47d541STao Ma 126956a04915STheodore Ts'o ret = ext4_add_dirent_to_inline(handle, fname, dir, inode, &iloc, 12703c47d541STao Ma inline_start, inline_size); 12713c47d541STao Ma if (ret != -ENOSPC) 12723c47d541STao Ma goto out; 12733c47d541STao Ma 12743c47d541STao Ma /* check whether it can be inserted to inline xattr space. */ 12753c47d541STao Ma inline_size = EXT4_I(dir)->i_inline_size - 12763c47d541STao Ma EXT4_MIN_INLINE_DATA_SIZE; 12773c47d541STao Ma if (!inline_size) { 12783c47d541STao Ma /* Try to use the xattr space.*/ 12793c47d541STao Ma ret = ext4_update_inline_dir(handle, dir, &iloc); 12803c47d541STao Ma if (ret && ret != -ENOSPC) 12813c47d541STao Ma goto out; 12823c47d541STao Ma 12833c47d541STao Ma inline_size = EXT4_I(dir)->i_inline_size - 12843c47d541STao Ma EXT4_MIN_INLINE_DATA_SIZE; 12853c47d541STao Ma } 12863c47d541STao Ma 12873c47d541STao Ma if (inline_size) { 12883c47d541STao Ma inline_start = ext4_get_inline_xattr_pos(dir, &iloc); 12893c47d541STao Ma 129056a04915STheodore Ts'o ret = ext4_add_dirent_to_inline(handle, fname, dir, 12915b643f9cSTheodore Ts'o inode, &iloc, inline_start, 12925b643f9cSTheodore Ts'o inline_size); 12933c47d541STao Ma 12943c47d541STao Ma if (ret != -ENOSPC) 12953c47d541STao Ma goto out; 12963c47d541STao Ma } 12973c47d541STao Ma 12983c47d541STao Ma /* 12993c47d541STao Ma * The inline space is filled up, so create a new block for it. 13003c47d541STao Ma * As the extent tree will be created, we have to save the inline 13013c47d541STao Ma * dir first. 13023c47d541STao Ma */ 13033c47d541STao Ma ret = ext4_convert_inline_data_nolock(handle, dir, &iloc); 13043c47d541STao Ma 13053c47d541STao Ma out: 1306c755e251STheodore Ts'o ext4_write_unlock_xattr(dir, &no_expand); 1307b907f2d5STheodore Ts'o ext4_mark_inode_dirty(handle, dir); 13083c47d541STao Ma brelse(iloc.bh); 13093c47d541STao Ma return ret; 13103c47d541STao Ma } 13113c47d541STao Ma 13128af0f082STao Ma /* 13138af0f082STao Ma * This function fills a red-black tree with information from an 13148af0f082STao Ma * inlined dir. It returns the number directory entries loaded 13158af0f082STao Ma * into the tree. If there is an error it is returned in err. 13168af0f082STao Ma */ 13178af0f082STao Ma int htree_inlinedir_to_tree(struct file *dir_file, 13188af0f082STao Ma struct inode *dir, ext4_lblk_t block, 13198af0f082STao Ma struct dx_hash_info *hinfo, 13208af0f082STao Ma __u32 start_hash, __u32 start_minor_hash, 13218af0f082STao Ma int *has_inline_data) 13228af0f082STao Ma { 13238af0f082STao Ma int err = 0, count = 0; 13248af0f082STao Ma unsigned int parent_ino; 13258af0f082STao Ma int pos; 13268af0f082STao Ma struct ext4_dir_entry_2 *de; 13278af0f082STao Ma struct inode *inode = file_inode(dir_file); 13288af0f082STao Ma int ret, inline_size = 0; 13298af0f082STao Ma struct ext4_iloc iloc; 13308af0f082STao Ma void *dir_buf = NULL; 13318af0f082STao Ma struct ext4_dir_entry_2 fake; 1332a7550b30SJaegeuk Kim struct fscrypt_str tmp_str; 13338af0f082STao Ma 13348af0f082STao Ma ret = ext4_get_inode_loc(inode, &iloc); 13358af0f082STao Ma if (ret) 13368af0f082STao Ma return ret; 13378af0f082STao Ma 13388af0f082STao Ma down_read(&EXT4_I(inode)->xattr_sem); 13398af0f082STao Ma if (!ext4_has_inline_data(inode)) { 13408af0f082STao Ma up_read(&EXT4_I(inode)->xattr_sem); 13418af0f082STao Ma *has_inline_data = 0; 13428af0f082STao Ma goto out; 13438af0f082STao Ma } 13448af0f082STao Ma 13458af0f082STao Ma inline_size = ext4_get_inline_size(inode); 13468af0f082STao Ma dir_buf = kmalloc(inline_size, GFP_NOFS); 13478af0f082STao Ma if (!dir_buf) { 13488af0f082STao Ma ret = -ENOMEM; 13498af0f082STao Ma up_read(&EXT4_I(inode)->xattr_sem); 13508af0f082STao Ma goto out; 13518af0f082STao Ma } 13528af0f082STao Ma 13538af0f082STao Ma ret = ext4_read_inline_data(inode, dir_buf, inline_size, &iloc); 13548af0f082STao Ma up_read(&EXT4_I(inode)->xattr_sem); 13558af0f082STao Ma if (ret < 0) 13568af0f082STao Ma goto out; 13578af0f082STao Ma 13588af0f082STao Ma pos = 0; 13598af0f082STao Ma parent_ino = le32_to_cpu(((struct ext4_dir_entry_2 *)dir_buf)->inode); 13608af0f082STao Ma while (pos < inline_size) { 13618af0f082STao Ma /* 13628af0f082STao Ma * As inlined dir doesn't store any information about '.' and 13638af0f082STao Ma * only the inode number of '..' is stored, we have to handle 13648af0f082STao Ma * them differently. 13658af0f082STao Ma */ 13668af0f082STao Ma if (pos == 0) { 13678af0f082STao Ma fake.inode = cpu_to_le32(inode->i_ino); 13688af0f082STao Ma fake.name_len = 1; 13698af0f082STao Ma strcpy(fake.name, "."); 13708af0f082STao Ma fake.rec_len = ext4_rec_len_to_disk( 13718af0f082STao Ma EXT4_DIR_REC_LEN(fake.name_len), 13728af0f082STao Ma inline_size); 13738af0f082STao Ma ext4_set_de_type(inode->i_sb, &fake, S_IFDIR); 13748af0f082STao Ma de = &fake; 13758af0f082STao Ma pos = EXT4_INLINE_DOTDOT_OFFSET; 13768af0f082STao Ma } else if (pos == EXT4_INLINE_DOTDOT_OFFSET) { 13778af0f082STao Ma fake.inode = cpu_to_le32(parent_ino); 13788af0f082STao Ma fake.name_len = 2; 13798af0f082STao Ma strcpy(fake.name, ".."); 13808af0f082STao Ma fake.rec_len = ext4_rec_len_to_disk( 13818af0f082STao Ma EXT4_DIR_REC_LEN(fake.name_len), 13828af0f082STao Ma inline_size); 13838af0f082STao Ma ext4_set_de_type(inode->i_sb, &fake, S_IFDIR); 13848af0f082STao Ma de = &fake; 13858af0f082STao Ma pos = EXT4_INLINE_DOTDOT_SIZE; 13868af0f082STao Ma } else { 13878af0f082STao Ma de = (struct ext4_dir_entry_2 *)(dir_buf + pos); 13888af0f082STao Ma pos += ext4_rec_len_from_disk(de->rec_len, inline_size); 13898af0f082STao Ma if (ext4_check_dir_entry(inode, dir_file, de, 13908af0f082STao Ma iloc.bh, dir_buf, 13918af0f082STao Ma inline_size, pos)) { 13928af0f082STao Ma ret = count; 13938af0f082STao Ma goto out; 13948af0f082STao Ma } 13958af0f082STao Ma } 13968af0f082STao Ma 13978af0f082STao Ma ext4fs_dirhash(de->name, de->name_len, hinfo); 13988af0f082STao Ma if ((hinfo->hash < start_hash) || 13998af0f082STao Ma ((hinfo->hash == start_hash) && 14008af0f082STao Ma (hinfo->minor_hash < start_minor_hash))) 14018af0f082STao Ma continue; 14028af0f082STao Ma if (de->inode == 0) 14038af0f082STao Ma continue; 14042f61830aSTheodore Ts'o tmp_str.name = de->name; 14052f61830aSTheodore Ts'o tmp_str.len = de->name_len; 14062f61830aSTheodore Ts'o err = ext4_htree_store_dirent(dir_file, hinfo->hash, 14072f61830aSTheodore Ts'o hinfo->minor_hash, de, &tmp_str); 14088af0f082STao Ma if (err) { 14098af0f082STao Ma count = err; 14108af0f082STao Ma goto out; 14118af0f082STao Ma } 14128af0f082STao Ma count++; 14138af0f082STao Ma } 14148af0f082STao Ma ret = count; 14158af0f082STao Ma out: 14168af0f082STao Ma kfree(dir_buf); 14178af0f082STao Ma brelse(iloc.bh); 14188af0f082STao Ma return ret; 14198af0f082STao Ma } 14208af0f082STao Ma 1421c4d8b023STao Ma /* 1422c4d8b023STao Ma * So this function is called when the volume is mkfsed with 1423c4d8b023STao Ma * dir_index disabled. In order to keep f_pos persistent 1424c4d8b023STao Ma * after we convert from an inlined dir to a blocked based, 1425c4d8b023STao Ma * we just pretend that we are a normal dir and return the 1426c4d8b023STao Ma * offset as if '.' and '..' really take place. 1427c4d8b023STao Ma * 1428c4d8b023STao Ma */ 1429725bebb2SAl Viro int ext4_read_inline_dir(struct file *file, 1430725bebb2SAl Viro struct dir_context *ctx, 143165d165d9STao Ma int *has_inline_data) 143265d165d9STao Ma { 143365d165d9STao Ma unsigned int offset, parent_ino; 1434725bebb2SAl Viro int i; 143565d165d9STao Ma struct ext4_dir_entry_2 *de; 143665d165d9STao Ma struct super_block *sb; 1437725bebb2SAl Viro struct inode *inode = file_inode(file); 143865d165d9STao Ma int ret, inline_size = 0; 143965d165d9STao Ma struct ext4_iloc iloc; 144065d165d9STao Ma void *dir_buf = NULL; 1441c4d8b023STao Ma int dotdot_offset, dotdot_size, extra_offset, extra_size; 144265d165d9STao Ma 144365d165d9STao Ma ret = ext4_get_inode_loc(inode, &iloc); 144465d165d9STao Ma if (ret) 144565d165d9STao Ma return ret; 144665d165d9STao Ma 144765d165d9STao Ma down_read(&EXT4_I(inode)->xattr_sem); 144865d165d9STao Ma if (!ext4_has_inline_data(inode)) { 144965d165d9STao Ma up_read(&EXT4_I(inode)->xattr_sem); 145065d165d9STao Ma *has_inline_data = 0; 145165d165d9STao Ma goto out; 145265d165d9STao Ma } 145365d165d9STao Ma 145465d165d9STao Ma inline_size = ext4_get_inline_size(inode); 145565d165d9STao Ma dir_buf = kmalloc(inline_size, GFP_NOFS); 145665d165d9STao Ma if (!dir_buf) { 145765d165d9STao Ma ret = -ENOMEM; 145865d165d9STao Ma up_read(&EXT4_I(inode)->xattr_sem); 145965d165d9STao Ma goto out; 146065d165d9STao Ma } 146165d165d9STao Ma 146265d165d9STao Ma ret = ext4_read_inline_data(inode, dir_buf, inline_size, &iloc); 146365d165d9STao Ma up_read(&EXT4_I(inode)->xattr_sem); 146465d165d9STao Ma if (ret < 0) 146565d165d9STao Ma goto out; 146665d165d9STao Ma 146748ffdab1SBoxiLiu ret = 0; 146865d165d9STao Ma sb = inode->i_sb; 146965d165d9STao Ma parent_ino = le32_to_cpu(((struct ext4_dir_entry_2 *)dir_buf)->inode); 1470725bebb2SAl Viro offset = ctx->pos; 147165d165d9STao Ma 1472c4d8b023STao Ma /* 1473c4d8b023STao Ma * dotdot_offset and dotdot_size is the real offset and 1474c4d8b023STao Ma * size for ".." and "." if the dir is block based while 1475c4d8b023STao Ma * the real size for them are only EXT4_INLINE_DOTDOT_SIZE. 1476c4d8b023STao Ma * So we will use extra_offset and extra_size to indicate them 1477c4d8b023STao Ma * during the inline dir iteration. 1478c4d8b023STao Ma */ 1479c4d8b023STao Ma dotdot_offset = EXT4_DIR_REC_LEN(1); 1480c4d8b023STao Ma dotdot_size = dotdot_offset + EXT4_DIR_REC_LEN(2); 1481c4d8b023STao Ma extra_offset = dotdot_size - EXT4_INLINE_DOTDOT_SIZE; 1482c4d8b023STao Ma extra_size = extra_offset + inline_size; 1483c4d8b023STao Ma 148465d165d9STao Ma /* 148565d165d9STao Ma * If the version has changed since the last call to 148665d165d9STao Ma * readdir(2), then we might be pointing to an invalid 148765d165d9STao Ma * dirent right now. Scan from the start of the inline 148865d165d9STao Ma * dir to make sure. 148965d165d9STao Ma */ 1490c472c07bSGoffredo Baroncelli if (!inode_eq_iversion(inode, file->f_version)) { 1491c4d8b023STao Ma for (i = 0; i < extra_size && i < offset;) { 1492c4d8b023STao Ma /* 1493c4d8b023STao Ma * "." is with offset 0 and 1494c4d8b023STao Ma * ".." is dotdot_offset. 1495c4d8b023STao Ma */ 149665d165d9STao Ma if (!i) { 1497c4d8b023STao Ma i = dotdot_offset; 1498c4d8b023STao Ma continue; 1499c4d8b023STao Ma } else if (i == dotdot_offset) { 1500c4d8b023STao Ma i = dotdot_size; 150165d165d9STao Ma continue; 150265d165d9STao Ma } 1503c4d8b023STao Ma /* for other entry, the real offset in 1504c4d8b023STao Ma * the buf has to be tuned accordingly. 1505c4d8b023STao Ma */ 150665d165d9STao Ma de = (struct ext4_dir_entry_2 *) 1507c4d8b023STao Ma (dir_buf + i - extra_offset); 150865d165d9STao Ma /* It's too expensive to do a full 150965d165d9STao Ma * dirent test each time round this 151065d165d9STao Ma * loop, but we do have to test at 151165d165d9STao Ma * least that it is non-zero. A 151265d165d9STao Ma * failure will be detected in the 151365d165d9STao Ma * dirent test below. */ 1514725bebb2SAl Viro if (ext4_rec_len_from_disk(de->rec_len, extra_size) 1515725bebb2SAl Viro < EXT4_DIR_REC_LEN(1)) 151665d165d9STao Ma break; 151765d165d9STao Ma i += ext4_rec_len_from_disk(de->rec_len, 1518c4d8b023STao Ma extra_size); 151965d165d9STao Ma } 152065d165d9STao Ma offset = i; 1521725bebb2SAl Viro ctx->pos = offset; 1522ee73f9a5SJeff Layton file->f_version = inode_query_iversion(inode); 152365d165d9STao Ma } 152465d165d9STao Ma 1525725bebb2SAl Viro while (ctx->pos < extra_size) { 1526725bebb2SAl Viro if (ctx->pos == 0) { 1527725bebb2SAl Viro if (!dir_emit(ctx, ".", 1, inode->i_ino, DT_DIR)) 1528725bebb2SAl Viro goto out; 1529725bebb2SAl Viro ctx->pos = dotdot_offset; 1530c4d8b023STao Ma continue; 1531c4d8b023STao Ma } 153265d165d9STao Ma 1533725bebb2SAl Viro if (ctx->pos == dotdot_offset) { 1534725bebb2SAl Viro if (!dir_emit(ctx, "..", 2, parent_ino, DT_DIR)) 1535725bebb2SAl Viro goto out; 1536725bebb2SAl Viro ctx->pos = dotdot_size; 153765d165d9STao Ma continue; 153865d165d9STao Ma } 153965d165d9STao Ma 1540c4d8b023STao Ma de = (struct ext4_dir_entry_2 *) 1541725bebb2SAl Viro (dir_buf + ctx->pos - extra_offset); 1542725bebb2SAl Viro if (ext4_check_dir_entry(inode, file, de, iloc.bh, dir_buf, 1543725bebb2SAl Viro extra_size, ctx->pos)) 1544725bebb2SAl Viro goto out; 1545725bebb2SAl Viro if (le32_to_cpu(de->inode)) { 1546725bebb2SAl Viro if (!dir_emit(ctx, de->name, de->name_len, 1547725bebb2SAl Viro le32_to_cpu(de->inode), 1548725bebb2SAl Viro get_dtype(sb, de->file_type))) 154965d165d9STao Ma goto out; 155065d165d9STao Ma } 1551725bebb2SAl Viro ctx->pos += ext4_rec_len_from_disk(de->rec_len, extra_size); 155265d165d9STao Ma } 155365d165d9STao Ma out: 155465d165d9STao Ma kfree(dir_buf); 155565d165d9STao Ma brelse(iloc.bh); 155665d165d9STao Ma return ret; 155765d165d9STao Ma } 155865d165d9STao Ma 155932f7f22cSTao Ma struct buffer_head *ext4_get_first_inline_block(struct inode *inode, 156032f7f22cSTao Ma struct ext4_dir_entry_2 **parent_de, 156132f7f22cSTao Ma int *retval) 156232f7f22cSTao Ma { 156332f7f22cSTao Ma struct ext4_iloc iloc; 156432f7f22cSTao Ma 156532f7f22cSTao Ma *retval = ext4_get_inode_loc(inode, &iloc); 156632f7f22cSTao Ma if (*retval) 156732f7f22cSTao Ma return NULL; 156832f7f22cSTao Ma 156932f7f22cSTao Ma *parent_de = (struct ext4_dir_entry_2 *)ext4_raw_inode(&iloc)->i_block; 157032f7f22cSTao Ma 157132f7f22cSTao Ma return iloc.bh; 157232f7f22cSTao Ma } 157332f7f22cSTao Ma 15743c47d541STao Ma /* 15753c47d541STao Ma * Try to create the inline data for the new dir. 15763c47d541STao Ma * If it succeeds, return 0, otherwise return the error. 15773c47d541STao Ma * In case of ENOSPC, the caller should create the normal disk layout dir. 15783c47d541STao Ma */ 15793c47d541STao Ma int ext4_try_create_inline_dir(handle_t *handle, struct inode *parent, 15803c47d541STao Ma struct inode *inode) 15813c47d541STao Ma { 15823c47d541STao Ma int ret, inline_size = EXT4_MIN_INLINE_DATA_SIZE; 15833c47d541STao Ma struct ext4_iloc iloc; 15843c47d541STao Ma struct ext4_dir_entry_2 *de; 15853c47d541STao Ma 15863c47d541STao Ma ret = ext4_get_inode_loc(inode, &iloc); 15873c47d541STao Ma if (ret) 15883c47d541STao Ma return ret; 15893c47d541STao Ma 15903c47d541STao Ma ret = ext4_prepare_inline_data(handle, inode, inline_size); 15913c47d541STao Ma if (ret) 15923c47d541STao Ma goto out; 15933c47d541STao Ma 15943c47d541STao Ma /* 15953c47d541STao Ma * For inline dir, we only save the inode information for the ".." 15963c47d541STao Ma * and create a fake dentry to cover the left space. 15973c47d541STao Ma */ 15983c47d541STao Ma de = (struct ext4_dir_entry_2 *)ext4_raw_inode(&iloc)->i_block; 15993c47d541STao Ma de->inode = cpu_to_le32(parent->i_ino); 16003c47d541STao Ma de = (struct ext4_dir_entry_2 *)((void *)de + EXT4_INLINE_DOTDOT_SIZE); 16013c47d541STao Ma de->inode = 0; 16023c47d541STao Ma de->rec_len = ext4_rec_len_to_disk( 16033c47d541STao Ma inline_size - EXT4_INLINE_DOTDOT_SIZE, 16043c47d541STao Ma inline_size); 16053c47d541STao Ma set_nlink(inode, 2); 16063c47d541STao Ma inode->i_size = EXT4_I(inode)->i_disksize = inline_size; 16073c47d541STao Ma out: 16083c47d541STao Ma brelse(iloc.bh); 16093c47d541STao Ma return ret; 16103c47d541STao Ma } 16113c47d541STao Ma 1612e8e948e7STao Ma struct buffer_head *ext4_find_inline_entry(struct inode *dir, 16135b643f9cSTheodore Ts'o struct ext4_filename *fname, 1614e8e948e7STao Ma struct ext4_dir_entry_2 **res_dir, 1615e8e948e7STao Ma int *has_inline_data) 1616e8e948e7STao Ma { 1617e8e948e7STao Ma int ret; 1618e8e948e7STao Ma struct ext4_iloc iloc; 1619e8e948e7STao Ma void *inline_start; 1620e8e948e7STao Ma int inline_size; 1621e8e948e7STao Ma 1622e8e948e7STao Ma if (ext4_get_inode_loc(dir, &iloc)) 1623e8e948e7STao Ma return NULL; 1624e8e948e7STao Ma 1625e8e948e7STao Ma down_read(&EXT4_I(dir)->xattr_sem); 1626e8e948e7STao Ma if (!ext4_has_inline_data(dir)) { 1627e8e948e7STao Ma *has_inline_data = 0; 1628e8e948e7STao Ma goto out; 1629e8e948e7STao Ma } 1630e8e948e7STao Ma 1631e8e948e7STao Ma inline_start = (void *)ext4_raw_inode(&iloc)->i_block + 1632e8e948e7STao Ma EXT4_INLINE_DOTDOT_SIZE; 1633e8e948e7STao Ma inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE; 16345b643f9cSTheodore Ts'o ret = ext4_search_dir(iloc.bh, inline_start, inline_size, 1635d6b97550SEric Biggers dir, fname, 0, res_dir); 1636e8e948e7STao Ma if (ret == 1) 1637e8e948e7STao Ma goto out_find; 1638e8e948e7STao Ma if (ret < 0) 1639e8e948e7STao Ma goto out; 1640e8e948e7STao Ma 1641e8e948e7STao Ma if (ext4_get_inline_size(dir) == EXT4_MIN_INLINE_DATA_SIZE) 1642e8e948e7STao Ma goto out; 1643e8e948e7STao Ma 1644e8e948e7STao Ma inline_start = ext4_get_inline_xattr_pos(dir, &iloc); 1645e8e948e7STao Ma inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE; 1646e8e948e7STao Ma 16475b643f9cSTheodore Ts'o ret = ext4_search_dir(iloc.bh, inline_start, inline_size, 1648d6b97550SEric Biggers dir, fname, 0, res_dir); 1649e8e948e7STao Ma if (ret == 1) 1650e8e948e7STao Ma goto out_find; 1651e8e948e7STao Ma 1652e8e948e7STao Ma out: 1653e8e948e7STao Ma brelse(iloc.bh); 1654e8e948e7STao Ma iloc.bh = NULL; 1655e8e948e7STao Ma out_find: 1656e8e948e7STao Ma up_read(&EXT4_I(dir)->xattr_sem); 1657e8e948e7STao Ma return iloc.bh; 1658e8e948e7STao Ma } 1659e8e948e7STao Ma 16609f40fe54STao Ma int ext4_delete_inline_entry(handle_t *handle, 16619f40fe54STao Ma struct inode *dir, 16629f40fe54STao Ma struct ext4_dir_entry_2 *de_del, 16639f40fe54STao Ma struct buffer_head *bh, 16649f40fe54STao Ma int *has_inline_data) 16659f40fe54STao Ma { 1666c755e251STheodore Ts'o int err, inline_size, no_expand; 16679f40fe54STao Ma struct ext4_iloc iloc; 16689f40fe54STao Ma void *inline_start; 16699f40fe54STao Ma 16709f40fe54STao Ma err = ext4_get_inode_loc(dir, &iloc); 16719f40fe54STao Ma if (err) 16729f40fe54STao Ma return err; 16739f40fe54STao Ma 1674c755e251STheodore Ts'o ext4_write_lock_xattr(dir, &no_expand); 16759f40fe54STao Ma if (!ext4_has_inline_data(dir)) { 16769f40fe54STao Ma *has_inline_data = 0; 16779f40fe54STao Ma goto out; 16789f40fe54STao Ma } 16799f40fe54STao Ma 16809f40fe54STao Ma if ((void *)de_del - ((void *)ext4_raw_inode(&iloc)->i_block) < 16819f40fe54STao Ma EXT4_MIN_INLINE_DATA_SIZE) { 16829f40fe54STao Ma inline_start = (void *)ext4_raw_inode(&iloc)->i_block + 16839f40fe54STao Ma EXT4_INLINE_DOTDOT_SIZE; 16849f40fe54STao Ma inline_size = EXT4_MIN_INLINE_DATA_SIZE - 16859f40fe54STao Ma EXT4_INLINE_DOTDOT_SIZE; 16869f40fe54STao Ma } else { 16879f40fe54STao Ma inline_start = ext4_get_inline_xattr_pos(dir, &iloc); 16889f40fe54STao Ma inline_size = ext4_get_inline_size(dir) - 16899f40fe54STao Ma EXT4_MIN_INLINE_DATA_SIZE; 16909f40fe54STao Ma } 16919f40fe54STao Ma 16925d601255Sliang xie BUFFER_TRACE(bh, "get_write_access"); 16939f40fe54STao Ma err = ext4_journal_get_write_access(handle, bh); 16949f40fe54STao Ma if (err) 16959f40fe54STao Ma goto out; 16969f40fe54STao Ma 16979f40fe54STao Ma err = ext4_generic_delete_entry(handle, dir, de_del, bh, 16989f40fe54STao Ma inline_start, inline_size, 0); 16999f40fe54STao Ma if (err) 17009f40fe54STao Ma goto out; 17019f40fe54STao Ma 17029f40fe54STao Ma ext4_show_inline_dir(dir, iloc.bh, inline_start, inline_size); 17039f40fe54STao Ma out: 1704c755e251STheodore Ts'o ext4_write_unlock_xattr(dir, &no_expand); 1705b907f2d5STheodore Ts'o if (likely(err == 0)) 1706b907f2d5STheodore Ts'o err = ext4_mark_inode_dirty(handle, dir); 17079f40fe54STao Ma brelse(iloc.bh); 17089f40fe54STao Ma if (err != -ENOENT) 17099f40fe54STao Ma ext4_std_error(dir->i_sb, err); 17109f40fe54STao Ma return err; 17119f40fe54STao Ma } 17129f40fe54STao Ma 171361f86638STao Ma /* 171461f86638STao Ma * Get the inline dentry at offset. 171561f86638STao Ma */ 171661f86638STao Ma static inline struct ext4_dir_entry_2 * 171761f86638STao Ma ext4_get_inline_entry(struct inode *inode, 171861f86638STao Ma struct ext4_iloc *iloc, 171961f86638STao Ma unsigned int offset, 172061f86638STao Ma void **inline_start, 172161f86638STao Ma int *inline_size) 172261f86638STao Ma { 172361f86638STao Ma void *inline_pos; 172461f86638STao Ma 172561f86638STao Ma BUG_ON(offset > ext4_get_inline_size(inode)); 172661f86638STao Ma 172761f86638STao Ma if (offset < EXT4_MIN_INLINE_DATA_SIZE) { 172861f86638STao Ma inline_pos = (void *)ext4_raw_inode(iloc)->i_block; 172961f86638STao Ma *inline_size = EXT4_MIN_INLINE_DATA_SIZE; 173061f86638STao Ma } else { 173161f86638STao Ma inline_pos = ext4_get_inline_xattr_pos(inode, iloc); 173261f86638STao Ma offset -= EXT4_MIN_INLINE_DATA_SIZE; 173361f86638STao Ma *inline_size = ext4_get_inline_size(inode) - 173461f86638STao Ma EXT4_MIN_INLINE_DATA_SIZE; 173561f86638STao Ma } 173661f86638STao Ma 173761f86638STao Ma if (inline_start) 173861f86638STao Ma *inline_start = inline_pos; 173961f86638STao Ma return (struct ext4_dir_entry_2 *)(inline_pos + offset); 174061f86638STao Ma } 174161f86638STao Ma 1742a7550b30SJaegeuk Kim bool empty_inline_dir(struct inode *dir, int *has_inline_data) 174361f86638STao Ma { 174461f86638STao Ma int err, inline_size; 174561f86638STao Ma struct ext4_iloc iloc; 174661f86638STao Ma void *inline_pos; 174761f86638STao Ma unsigned int offset; 174861f86638STao Ma struct ext4_dir_entry_2 *de; 1749a7550b30SJaegeuk Kim bool ret = true; 175061f86638STao Ma 175161f86638STao Ma err = ext4_get_inode_loc(dir, &iloc); 175261f86638STao Ma if (err) { 175361f86638STao Ma EXT4_ERROR_INODE(dir, "error %d getting inode %lu block", 175461f86638STao Ma err, dir->i_ino); 1755a7550b30SJaegeuk Kim return true; 175661f86638STao Ma } 175761f86638STao Ma 175861f86638STao Ma down_read(&EXT4_I(dir)->xattr_sem); 175961f86638STao Ma if (!ext4_has_inline_data(dir)) { 176061f86638STao Ma *has_inline_data = 0; 176161f86638STao Ma goto out; 176261f86638STao Ma } 176361f86638STao Ma 176461f86638STao Ma de = (struct ext4_dir_entry_2 *)ext4_raw_inode(&iloc)->i_block; 176561f86638STao Ma if (!le32_to_cpu(de->inode)) { 176661f86638STao Ma ext4_warning(dir->i_sb, 176761f86638STao Ma "bad inline directory (dir #%lu) - no `..'", 176861f86638STao Ma dir->i_ino); 1769a7550b30SJaegeuk Kim ret = true; 177061f86638STao Ma goto out; 177161f86638STao Ma } 177261f86638STao Ma 177361f86638STao Ma offset = EXT4_INLINE_DOTDOT_SIZE; 177461f86638STao Ma while (offset < dir->i_size) { 177561f86638STao Ma de = ext4_get_inline_entry(dir, &iloc, offset, 177661f86638STao Ma &inline_pos, &inline_size); 177761f86638STao Ma if (ext4_check_dir_entry(dir, NULL, de, 177861f86638STao Ma iloc.bh, inline_pos, 177961f86638STao Ma inline_size, offset)) { 178061f86638STao Ma ext4_warning(dir->i_sb, 178161f86638STao Ma "bad inline directory (dir #%lu) - " 178261f86638STao Ma "inode %u, rec_len %u, name_len %d" 17838d2ae1cbSJakub Wilk "inline size %d", 178461f86638STao Ma dir->i_ino, le32_to_cpu(de->inode), 178561f86638STao Ma le16_to_cpu(de->rec_len), de->name_len, 178661f86638STao Ma inline_size); 1787a7550b30SJaegeuk Kim ret = true; 178861f86638STao Ma goto out; 178961f86638STao Ma } 179061f86638STao Ma if (le32_to_cpu(de->inode)) { 1791a7550b30SJaegeuk Kim ret = false; 179261f86638STao Ma goto out; 179361f86638STao Ma } 179461f86638STao Ma offset += ext4_rec_len_from_disk(de->rec_len, inline_size); 179561f86638STao Ma } 179661f86638STao Ma 179761f86638STao Ma out: 179861f86638STao Ma up_read(&EXT4_I(dir)->xattr_sem); 179961f86638STao Ma brelse(iloc.bh); 180061f86638STao Ma return ret; 180161f86638STao Ma } 180261f86638STao Ma 180367cf5b09STao Ma int ext4_destroy_inline_data(handle_t *handle, struct inode *inode) 180467cf5b09STao Ma { 1805c755e251STheodore Ts'o int ret, no_expand; 180667cf5b09STao Ma 1807c755e251STheodore Ts'o ext4_write_lock_xattr(inode, &no_expand); 180867cf5b09STao Ma ret = ext4_destroy_inline_data_nolock(handle, inode); 1809c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 181067cf5b09STao Ma 181167cf5b09STao Ma return ret; 181267cf5b09STao Ma } 181394191985STao Ma 18147046ae35SAndreas Gruenbacher int ext4_inline_data_iomap(struct inode *inode, struct iomap *iomap) 18157046ae35SAndreas Gruenbacher { 18167046ae35SAndreas Gruenbacher __u64 addr; 18177046ae35SAndreas Gruenbacher int error = -EAGAIN; 18187046ae35SAndreas Gruenbacher struct ext4_iloc iloc; 18197046ae35SAndreas Gruenbacher 18207046ae35SAndreas Gruenbacher down_read(&EXT4_I(inode)->xattr_sem); 18217046ae35SAndreas Gruenbacher if (!ext4_has_inline_data(inode)) 18227046ae35SAndreas Gruenbacher goto out; 18237046ae35SAndreas Gruenbacher 18247046ae35SAndreas Gruenbacher error = ext4_get_inode_loc(inode, &iloc); 18257046ae35SAndreas Gruenbacher if (error) 18267046ae35SAndreas Gruenbacher goto out; 18277046ae35SAndreas Gruenbacher 18287046ae35SAndreas Gruenbacher addr = (__u64)iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits; 18297046ae35SAndreas Gruenbacher addr += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data; 18307046ae35SAndreas Gruenbacher addr += offsetof(struct ext4_inode, i_block); 18317046ae35SAndreas Gruenbacher 18327046ae35SAndreas Gruenbacher brelse(iloc.bh); 18337046ae35SAndreas Gruenbacher 18347046ae35SAndreas Gruenbacher iomap->addr = addr; 18357046ae35SAndreas Gruenbacher iomap->offset = 0; 18367046ae35SAndreas Gruenbacher iomap->length = min_t(loff_t, ext4_get_inline_size(inode), 18377046ae35SAndreas Gruenbacher i_size_read(inode)); 1838*19319b53SChristoph Hellwig iomap->type = IOMAP_INLINE; 1839*19319b53SChristoph Hellwig iomap->flags = 0; 18407046ae35SAndreas Gruenbacher 18417046ae35SAndreas Gruenbacher out: 18427046ae35SAndreas Gruenbacher up_read(&EXT4_I(inode)->xattr_sem); 18437046ae35SAndreas Gruenbacher return error; 18447046ae35SAndreas Gruenbacher } 18457046ae35SAndreas Gruenbacher 184694191985STao Ma int ext4_inline_data_fiemap(struct inode *inode, 184794191985STao Ma struct fiemap_extent_info *fieinfo, 1848d952d69eSDmitry Monakhov int *has_inline, __u64 start, __u64 len) 184994191985STao Ma { 185094191985STao Ma __u64 physical = 0; 1851d952d69eSDmitry Monakhov __u64 inline_len; 1852d952d69eSDmitry Monakhov __u32 flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED | 1853d952d69eSDmitry Monakhov FIEMAP_EXTENT_LAST; 185494191985STao Ma int error = 0; 185594191985STao Ma struct ext4_iloc iloc; 185694191985STao Ma 185794191985STao Ma down_read(&EXT4_I(inode)->xattr_sem); 185894191985STao Ma if (!ext4_has_inline_data(inode)) { 185994191985STao Ma *has_inline = 0; 186094191985STao Ma goto out; 186194191985STao Ma } 1862d952d69eSDmitry Monakhov inline_len = min_t(size_t, ext4_get_inline_size(inode), 1863d952d69eSDmitry Monakhov i_size_read(inode)); 1864d952d69eSDmitry Monakhov if (start >= inline_len) 1865d952d69eSDmitry Monakhov goto out; 1866d952d69eSDmitry Monakhov if (start + len < inline_len) 1867d952d69eSDmitry Monakhov inline_len = start + len; 1868d952d69eSDmitry Monakhov inline_len -= start; 186994191985STao Ma 187094191985STao Ma error = ext4_get_inode_loc(inode, &iloc); 187194191985STao Ma if (error) 187294191985STao Ma goto out; 187394191985STao Ma 1874eaf37937SJan Kara physical = (__u64)iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits; 187594191985STao Ma physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data; 187694191985STao Ma physical += offsetof(struct ext4_inode, i_block); 187794191985STao Ma 187894191985STao Ma if (physical) 1879d952d69eSDmitry Monakhov error = fiemap_fill_next_extent(fieinfo, start, physical, 1880d952d69eSDmitry Monakhov inline_len, flags); 188194191985STao Ma brelse(iloc.bh); 188294191985STao Ma out: 188394191985STao Ma up_read(&EXT4_I(inode)->xattr_sem); 188494191985STao Ma return (error < 0 ? error : 0); 188594191985STao Ma } 18860d812f77STao Ma 18870d812f77STao Ma /* 18880d812f77STao Ma * Called during xattr set, and if we can sparse space 'needed', 18890d812f77STao Ma * just create the extent tree evict the data to the outer block. 18900d812f77STao Ma * 18910d812f77STao Ma * We use jbd2 instead of page cache to move data to the 1st block 18920d812f77STao Ma * so that the whole transaction can be committed as a whole and 18930d812f77STao Ma * the data isn't lost because of the delayed page cache write. 18940d812f77STao Ma */ 18950d812f77STao Ma int ext4_try_to_evict_inline_data(handle_t *handle, 18960d812f77STao Ma struct inode *inode, 18970d812f77STao Ma int needed) 18980d812f77STao Ma { 18990d812f77STao Ma int error; 19000d812f77STao Ma struct ext4_xattr_entry *entry; 19010d812f77STao Ma struct ext4_inode *raw_inode; 19020d812f77STao Ma struct ext4_iloc iloc; 19030d812f77STao Ma 19040d812f77STao Ma error = ext4_get_inode_loc(inode, &iloc); 19050d812f77STao Ma if (error) 19060d812f77STao Ma return error; 19070d812f77STao Ma 19080d812f77STao Ma raw_inode = ext4_raw_inode(&iloc); 19090d812f77STao Ma entry = (struct ext4_xattr_entry *)((void *)raw_inode + 19100d812f77STao Ma EXT4_I(inode)->i_inline_off); 19110d812f77STao Ma if (EXT4_XATTR_LEN(entry->e_name_len) + 19120d812f77STao Ma EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)) < needed) { 19130d812f77STao Ma error = -ENOSPC; 19140d812f77STao Ma goto out; 19150d812f77STao Ma } 19160d812f77STao Ma 19170d812f77STao Ma error = ext4_convert_inline_data_nolock(handle, inode, &iloc); 19180d812f77STao Ma out: 19190d812f77STao Ma brelse(iloc.bh); 19200d812f77STao Ma return error; 19210d812f77STao Ma } 1922aef1c851STao Ma 192301daf945STheodore Ts'o int ext4_inline_data_truncate(struct inode *inode, int *has_inline) 1924aef1c851STao Ma { 1925aef1c851STao Ma handle_t *handle; 192601daf945STheodore Ts'o int inline_size, value_len, needed_blocks, no_expand, err = 0; 1927aef1c851STao Ma size_t i_size; 1928aef1c851STao Ma void *value = NULL; 1929aef1c851STao Ma struct ext4_xattr_ibody_find is = { 1930aef1c851STao Ma .s = { .not_found = -ENODATA, }, 1931aef1c851STao Ma }; 1932aef1c851STao Ma struct ext4_xattr_info i = { 1933aef1c851STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 1934aef1c851STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 1935aef1c851STao Ma }; 1936aef1c851STao Ma 1937aef1c851STao Ma 1938aef1c851STao Ma needed_blocks = ext4_writepage_trans_blocks(inode); 19399924a92aSTheodore Ts'o handle = ext4_journal_start(inode, EXT4_HT_INODE, needed_blocks); 1940aef1c851STao Ma if (IS_ERR(handle)) 194101daf945STheodore Ts'o return PTR_ERR(handle); 1942aef1c851STao Ma 1943c755e251STheodore Ts'o ext4_write_lock_xattr(inode, &no_expand); 1944aef1c851STao Ma if (!ext4_has_inline_data(inode)) { 1945aef1c851STao Ma *has_inline = 0; 1946aef1c851STao Ma ext4_journal_stop(handle); 194701daf945STheodore Ts'o return 0; 1948aef1c851STao Ma } 1949aef1c851STao Ma 195001daf945STheodore Ts'o if ((err = ext4_orphan_add(handle, inode)) != 0) 1951aef1c851STao Ma goto out; 1952aef1c851STao Ma 195301daf945STheodore Ts'o if ((err = ext4_get_inode_loc(inode, &is.iloc)) != 0) 1954aef1c851STao Ma goto out; 1955aef1c851STao Ma 1956aef1c851STao Ma down_write(&EXT4_I(inode)->i_data_sem); 1957aef1c851STao Ma i_size = inode->i_size; 1958aef1c851STao Ma inline_size = ext4_get_inline_size(inode); 1959aef1c851STao Ma EXT4_I(inode)->i_disksize = i_size; 1960aef1c851STao Ma 1961aef1c851STao Ma if (i_size < inline_size) { 1962aef1c851STao Ma /* Clear the content in the xattr space. */ 1963aef1c851STao Ma if (inline_size > EXT4_MIN_INLINE_DATA_SIZE) { 196401daf945STheodore Ts'o if ((err = ext4_xattr_ibody_find(inode, &i, &is)) != 0) 1965aef1c851STao Ma goto out_error; 1966aef1c851STao Ma 1967aef1c851STao Ma BUG_ON(is.s.not_found); 1968aef1c851STao Ma 1969aef1c851STao Ma value_len = le32_to_cpu(is.s.here->e_value_size); 1970aef1c851STao Ma value = kmalloc(value_len, GFP_NOFS); 197101daf945STheodore Ts'o if (!value) { 197201daf945STheodore Ts'o err = -ENOMEM; 1973aef1c851STao Ma goto out_error; 197401daf945STheodore Ts'o } 1975aef1c851STao Ma 197601daf945STheodore Ts'o err = ext4_xattr_ibody_get(inode, i.name_index, 197701daf945STheodore Ts'o i.name, value, value_len); 197801daf945STheodore Ts'o if (err <= 0) 1979aef1c851STao Ma goto out_error; 1980aef1c851STao Ma 1981aef1c851STao Ma i.value = value; 1982aef1c851STao Ma i.value_len = i_size > EXT4_MIN_INLINE_DATA_SIZE ? 1983aef1c851STao Ma i_size - EXT4_MIN_INLINE_DATA_SIZE : 0; 198401daf945STheodore Ts'o err = ext4_xattr_ibody_inline_set(handle, inode, 198501daf945STheodore Ts'o &i, &is); 198601daf945STheodore Ts'o if (err) 1987aef1c851STao Ma goto out_error; 1988aef1c851STao Ma } 1989aef1c851STao Ma 1990aef1c851STao Ma /* Clear the content within i_blocks. */ 199109c455aaSTheodore Ts'o if (i_size < EXT4_MIN_INLINE_DATA_SIZE) { 199209c455aaSTheodore Ts'o void *p = (void *) ext4_raw_inode(&is.iloc)->i_block; 199309c455aaSTheodore Ts'o memset(p + i_size, 0, 1994aef1c851STao Ma EXT4_MIN_INLINE_DATA_SIZE - i_size); 199509c455aaSTheodore Ts'o } 1996aef1c851STao Ma 1997aef1c851STao Ma EXT4_I(inode)->i_inline_size = i_size < 1998aef1c851STao Ma EXT4_MIN_INLINE_DATA_SIZE ? 1999aef1c851STao Ma EXT4_MIN_INLINE_DATA_SIZE : i_size; 2000aef1c851STao Ma } 2001aef1c851STao Ma 2002aef1c851STao Ma out_error: 2003aef1c851STao Ma up_write(&EXT4_I(inode)->i_data_sem); 2004aef1c851STao Ma out: 2005aef1c851STao Ma brelse(is.iloc.bh); 2006c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 2007aef1c851STao Ma kfree(value); 2008aef1c851STao Ma if (inode->i_nlink) 2009aef1c851STao Ma ext4_orphan_del(handle, inode); 2010aef1c851STao Ma 201101daf945STheodore Ts'o if (err == 0) { 2012eeca7ea1SDeepa Dinamani inode->i_mtime = inode->i_ctime = current_time(inode); 201301daf945STheodore Ts'o err = ext4_mark_inode_dirty(handle, inode); 2014aef1c851STao Ma if (IS_SYNC(inode)) 2015aef1c851STao Ma ext4_handle_sync(handle); 201601daf945STheodore Ts'o } 2017aef1c851STao Ma ext4_journal_stop(handle); 201801daf945STheodore Ts'o return err; 2019aef1c851STao Ma } 20200c8d414fSTao Ma 20210c8d414fSTao Ma int ext4_convert_inline_data(struct inode *inode) 20220c8d414fSTao Ma { 2023c755e251STheodore Ts'o int error, needed_blocks, no_expand; 20240c8d414fSTao Ma handle_t *handle; 20250c8d414fSTao Ma struct ext4_iloc iloc; 20260c8d414fSTao Ma 20270c8d414fSTao Ma if (!ext4_has_inline_data(inode)) { 20280c8d414fSTao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 20290c8d414fSTao Ma return 0; 20300c8d414fSTao Ma } 20310c8d414fSTao Ma 20320c8d414fSTao Ma needed_blocks = ext4_writepage_trans_blocks(inode); 20330c8d414fSTao Ma 20340c8d414fSTao Ma iloc.bh = NULL; 20350c8d414fSTao Ma error = ext4_get_inode_loc(inode, &iloc); 20360c8d414fSTao Ma if (error) 20370c8d414fSTao Ma return error; 20380c8d414fSTao Ma 20399924a92aSTheodore Ts'o handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, needed_blocks); 20400c8d414fSTao Ma if (IS_ERR(handle)) { 20410c8d414fSTao Ma error = PTR_ERR(handle); 20420c8d414fSTao Ma goto out_free; 20430c8d414fSTao Ma } 20440c8d414fSTao Ma 2045c755e251STheodore Ts'o ext4_write_lock_xattr(inode, &no_expand); 2046c755e251STheodore Ts'o if (ext4_has_inline_data(inode)) 20470c8d414fSTao Ma error = ext4_convert_inline_data_nolock(handle, inode, &iloc); 2048c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 20490c8d414fSTao Ma ext4_journal_stop(handle); 20500c8d414fSTao Ma out_free: 20510c8d414fSTao Ma brelse(iloc.bh); 20520c8d414fSTao Ma return error; 20530c8d414fSTao Ma } 2054