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 */ 144bdfc873SMichael Halcrow 154bdfc873SMichael Halcrow #include <linux/fiemap.h> 164bdfc873SMichael Halcrow 1767cf5b09STao Ma #include "ext4_jbd2.h" 1867cf5b09STao Ma #include "ext4.h" 1967cf5b09STao Ma #include "xattr.h" 20f19d5870STao Ma #include "truncate.h" 2167cf5b09STao Ma 2267cf5b09STao Ma #define EXT4_XATTR_SYSTEM_DATA "data" 2367cf5b09STao Ma #define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS)) 248af0f082STao Ma #define EXT4_INLINE_DOTDOT_OFFSET 2 253c47d541STao Ma #define EXT4_INLINE_DOTDOT_SIZE 4 2667cf5b09STao Ma 27c197855eSStephen Hemminger static int ext4_get_inline_size(struct inode *inode) 2867cf5b09STao Ma { 2967cf5b09STao Ma if (EXT4_I(inode)->i_inline_off) 3067cf5b09STao Ma return EXT4_I(inode)->i_inline_size; 3167cf5b09STao Ma 3267cf5b09STao Ma return 0; 3367cf5b09STao Ma } 3467cf5b09STao Ma 3567cf5b09STao Ma static int get_max_inline_xattr_value_size(struct inode *inode, 3667cf5b09STao Ma struct ext4_iloc *iloc) 3767cf5b09STao Ma { 3867cf5b09STao Ma struct ext4_xattr_ibody_header *header; 3967cf5b09STao Ma struct ext4_xattr_entry *entry; 4067cf5b09STao Ma struct ext4_inode *raw_inode; 4167cf5b09STao Ma int free, min_offs; 4267cf5b09STao Ma 4367cf5b09STao Ma min_offs = EXT4_SB(inode->i_sb)->s_inode_size - 4467cf5b09STao Ma EXT4_GOOD_OLD_INODE_SIZE - 4567cf5b09STao Ma EXT4_I(inode)->i_extra_isize - 4667cf5b09STao Ma sizeof(struct ext4_xattr_ibody_header); 4767cf5b09STao Ma 4867cf5b09STao Ma /* 4967cf5b09STao Ma * We need to subtract another sizeof(__u32) since an in-inode xattr 5067cf5b09STao Ma * needs an empty 4 bytes to indicate the gap between the xattr entry 5167cf5b09STao Ma * and the name/value pair. 5267cf5b09STao Ma */ 5367cf5b09STao Ma if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR)) 5467cf5b09STao Ma return EXT4_XATTR_SIZE(min_offs - 5567cf5b09STao Ma EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA)) - 5667cf5b09STao Ma EXT4_XATTR_ROUND - sizeof(__u32)); 5767cf5b09STao Ma 5867cf5b09STao Ma raw_inode = ext4_raw_inode(iloc); 5967cf5b09STao Ma header = IHDR(inode, raw_inode); 6067cf5b09STao Ma entry = IFIRST(header); 6167cf5b09STao Ma 6267cf5b09STao Ma /* Compute min_offs. */ 6367cf5b09STao Ma for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { 6467cf5b09STao Ma if (!entry->e_value_block && entry->e_value_size) { 6567cf5b09STao Ma size_t offs = le16_to_cpu(entry->e_value_offs); 6667cf5b09STao Ma if (offs < min_offs) 6767cf5b09STao Ma min_offs = offs; 6867cf5b09STao Ma } 6967cf5b09STao Ma } 7067cf5b09STao Ma free = min_offs - 7167cf5b09STao Ma ((void *)entry - (void *)IFIRST(header)) - sizeof(__u32); 7267cf5b09STao Ma 7367cf5b09STao Ma if (EXT4_I(inode)->i_inline_off) { 7467cf5b09STao Ma entry = (struct ext4_xattr_entry *) 7567cf5b09STao Ma ((void *)raw_inode + EXT4_I(inode)->i_inline_off); 7667cf5b09STao Ma 77c4932dbeSboxi liu free += EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)); 7867cf5b09STao Ma goto out; 7967cf5b09STao Ma } 8067cf5b09STao Ma 8167cf5b09STao Ma free -= EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA)); 8267cf5b09STao Ma 8367cf5b09STao Ma if (free > EXT4_XATTR_ROUND) 8467cf5b09STao Ma free = EXT4_XATTR_SIZE(free - EXT4_XATTR_ROUND); 8567cf5b09STao Ma else 8667cf5b09STao Ma free = 0; 8767cf5b09STao Ma 8867cf5b09STao Ma out: 8967cf5b09STao Ma return free; 9067cf5b09STao Ma } 9167cf5b09STao Ma 9267cf5b09STao Ma /* 9367cf5b09STao Ma * Get the maximum size we now can store in an inode. 9467cf5b09STao Ma * If we can't find the space for a xattr entry, don't use the space 9567cf5b09STao Ma * of the extents since we have no space to indicate the inline data. 9667cf5b09STao Ma */ 9767cf5b09STao Ma int ext4_get_max_inline_size(struct inode *inode) 9867cf5b09STao Ma { 9967cf5b09STao Ma int error, max_inline_size; 10067cf5b09STao Ma struct ext4_iloc iloc; 10167cf5b09STao Ma 10267cf5b09STao Ma if (EXT4_I(inode)->i_extra_isize == 0) 10367cf5b09STao Ma return 0; 10467cf5b09STao Ma 10567cf5b09STao Ma error = ext4_get_inode_loc(inode, &iloc); 10667cf5b09STao Ma if (error) { 10767cf5b09STao Ma ext4_error_inode(inode, __func__, __LINE__, 0, 10867cf5b09STao Ma "can't get inode location %lu", 10967cf5b09STao Ma inode->i_ino); 11067cf5b09STao Ma return 0; 11167cf5b09STao Ma } 11267cf5b09STao Ma 11367cf5b09STao Ma down_read(&EXT4_I(inode)->xattr_sem); 11467cf5b09STao Ma max_inline_size = get_max_inline_xattr_value_size(inode, &iloc); 11567cf5b09STao Ma up_read(&EXT4_I(inode)->xattr_sem); 11667cf5b09STao Ma 11767cf5b09STao Ma brelse(iloc.bh); 11867cf5b09STao Ma 11967cf5b09STao Ma if (!max_inline_size) 12067cf5b09STao Ma return 0; 12167cf5b09STao Ma 12267cf5b09STao Ma return max_inline_size + EXT4_MIN_INLINE_DATA_SIZE; 12367cf5b09STao Ma } 12467cf5b09STao Ma 12567cf5b09STao Ma /* 12667cf5b09STao Ma * this function does not take xattr_sem, which is OK because it is 12767cf5b09STao Ma * currently only used in a code path coming form ext4_iget, before 12867cf5b09STao Ma * the new inode has been unlocked 12967cf5b09STao Ma */ 13067cf5b09STao Ma int ext4_find_inline_data_nolock(struct inode *inode) 13167cf5b09STao Ma { 13267cf5b09STao Ma struct ext4_xattr_ibody_find is = { 13367cf5b09STao Ma .s = { .not_found = -ENODATA, }, 13467cf5b09STao Ma }; 13567cf5b09STao Ma struct ext4_xattr_info i = { 13667cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 13767cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 13867cf5b09STao Ma }; 13967cf5b09STao Ma int error; 14067cf5b09STao Ma 14167cf5b09STao Ma if (EXT4_I(inode)->i_extra_isize == 0) 14267cf5b09STao Ma return 0; 14367cf5b09STao Ma 14467cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 14567cf5b09STao Ma if (error) 14667cf5b09STao Ma return error; 14767cf5b09STao Ma 14867cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 14967cf5b09STao Ma if (error) 15067cf5b09STao Ma goto out; 15167cf5b09STao Ma 15267cf5b09STao Ma if (!is.s.not_found) { 15367cf5b09STao Ma EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here - 15467cf5b09STao Ma (void *)ext4_raw_inode(&is.iloc)); 15567cf5b09STao Ma EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE + 15667cf5b09STao Ma le32_to_cpu(is.s.here->e_value_size); 15767cf5b09STao Ma ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 15867cf5b09STao Ma } 15967cf5b09STao Ma out: 16067cf5b09STao Ma brelse(is.iloc.bh); 16167cf5b09STao Ma return error; 16267cf5b09STao Ma } 16367cf5b09STao Ma 16467cf5b09STao Ma static int ext4_read_inline_data(struct inode *inode, void *buffer, 16567cf5b09STao Ma unsigned int len, 16667cf5b09STao Ma struct ext4_iloc *iloc) 16767cf5b09STao Ma { 16867cf5b09STao Ma struct ext4_xattr_entry *entry; 16967cf5b09STao Ma struct ext4_xattr_ibody_header *header; 17067cf5b09STao Ma int cp_len = 0; 17167cf5b09STao Ma struct ext4_inode *raw_inode; 17267cf5b09STao Ma 17367cf5b09STao Ma if (!len) 17467cf5b09STao Ma return 0; 17567cf5b09STao Ma 17667cf5b09STao Ma BUG_ON(len > EXT4_I(inode)->i_inline_size); 17767cf5b09STao Ma 17867cf5b09STao Ma cp_len = len < EXT4_MIN_INLINE_DATA_SIZE ? 17967cf5b09STao Ma len : EXT4_MIN_INLINE_DATA_SIZE; 18067cf5b09STao Ma 18167cf5b09STao Ma raw_inode = ext4_raw_inode(iloc); 18267cf5b09STao Ma memcpy(buffer, (void *)(raw_inode->i_block), cp_len); 18367cf5b09STao Ma 18467cf5b09STao Ma len -= cp_len; 18567cf5b09STao Ma buffer += cp_len; 18667cf5b09STao Ma 18767cf5b09STao Ma if (!len) 18867cf5b09STao Ma goto out; 18967cf5b09STao Ma 19067cf5b09STao Ma header = IHDR(inode, raw_inode); 19167cf5b09STao Ma entry = (struct ext4_xattr_entry *)((void *)raw_inode + 19267cf5b09STao Ma EXT4_I(inode)->i_inline_off); 19367cf5b09STao Ma len = min_t(unsigned int, len, 19467cf5b09STao Ma (unsigned int)le32_to_cpu(entry->e_value_size)); 19567cf5b09STao Ma 19667cf5b09STao Ma memcpy(buffer, 19767cf5b09STao Ma (void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs), len); 19867cf5b09STao Ma cp_len += len; 19967cf5b09STao Ma 20067cf5b09STao Ma out: 20167cf5b09STao Ma return cp_len; 20267cf5b09STao Ma } 20367cf5b09STao Ma 20467cf5b09STao Ma /* 20567cf5b09STao Ma * write the buffer to the inline inode. 20667cf5b09STao Ma * If 'create' is set, we don't need to do the extra copy in the xattr 2070d812f77STao Ma * value since it is already handled by ext4_xattr_ibody_inline_set. 2080d812f77STao Ma * That saves us one memcpy. 20967cf5b09STao Ma */ 210c197855eSStephen Hemminger static void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc, 21167cf5b09STao Ma void *buffer, loff_t pos, unsigned int len) 21267cf5b09STao Ma { 21367cf5b09STao Ma struct ext4_xattr_entry *entry; 21467cf5b09STao Ma struct ext4_xattr_ibody_header *header; 21567cf5b09STao Ma struct ext4_inode *raw_inode; 21667cf5b09STao Ma int cp_len = 0; 21767cf5b09STao Ma 21867cf5b09STao Ma BUG_ON(!EXT4_I(inode)->i_inline_off); 21967cf5b09STao Ma BUG_ON(pos + len > EXT4_I(inode)->i_inline_size); 22067cf5b09STao Ma 22167cf5b09STao Ma raw_inode = ext4_raw_inode(iloc); 22267cf5b09STao Ma buffer += pos; 22367cf5b09STao Ma 22467cf5b09STao Ma if (pos < EXT4_MIN_INLINE_DATA_SIZE) { 22567cf5b09STao Ma cp_len = pos + len > EXT4_MIN_INLINE_DATA_SIZE ? 22667cf5b09STao Ma EXT4_MIN_INLINE_DATA_SIZE - pos : len; 22767cf5b09STao Ma memcpy((void *)raw_inode->i_block + pos, buffer, cp_len); 22867cf5b09STao Ma 22967cf5b09STao Ma len -= cp_len; 23067cf5b09STao Ma buffer += cp_len; 23167cf5b09STao Ma pos += cp_len; 23267cf5b09STao Ma } 23367cf5b09STao Ma 23467cf5b09STao Ma if (!len) 23567cf5b09STao Ma return; 23667cf5b09STao Ma 23767cf5b09STao Ma pos -= EXT4_MIN_INLINE_DATA_SIZE; 23867cf5b09STao Ma header = IHDR(inode, raw_inode); 23967cf5b09STao Ma entry = (struct ext4_xattr_entry *)((void *)raw_inode + 24067cf5b09STao Ma EXT4_I(inode)->i_inline_off); 24167cf5b09STao Ma 24267cf5b09STao Ma memcpy((void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs) + pos, 24367cf5b09STao Ma buffer, len); 24467cf5b09STao Ma } 24567cf5b09STao Ma 24667cf5b09STao Ma static int ext4_create_inline_data(handle_t *handle, 24767cf5b09STao Ma struct inode *inode, unsigned len) 24867cf5b09STao Ma { 24967cf5b09STao Ma int error; 25067cf5b09STao Ma void *value = NULL; 25167cf5b09STao Ma struct ext4_xattr_ibody_find is = { 25267cf5b09STao Ma .s = { .not_found = -ENODATA, }, 25367cf5b09STao Ma }; 25467cf5b09STao Ma struct ext4_xattr_info i = { 25567cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 25667cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 25767cf5b09STao Ma }; 25867cf5b09STao Ma 25967cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 26067cf5b09STao Ma if (error) 26167cf5b09STao Ma return error; 26267cf5b09STao Ma 2635d601255Sliang xie BUFFER_TRACE(is.iloc.bh, "get_write_access"); 26467cf5b09STao Ma error = ext4_journal_get_write_access(handle, is.iloc.bh); 26567cf5b09STao Ma if (error) 26667cf5b09STao Ma goto out; 26767cf5b09STao Ma 26867cf5b09STao Ma if (len > EXT4_MIN_INLINE_DATA_SIZE) { 269bd9926e8STheodore Ts'o value = EXT4_ZERO_XATTR_VALUE; 27067cf5b09STao Ma len -= EXT4_MIN_INLINE_DATA_SIZE; 27167cf5b09STao Ma } else { 27267cf5b09STao Ma value = ""; 27367cf5b09STao Ma len = 0; 27467cf5b09STao Ma } 27567cf5b09STao Ma 27667cf5b09STao Ma /* Insert the the xttr entry. */ 27767cf5b09STao Ma i.value = value; 27867cf5b09STao Ma i.value_len = len; 27967cf5b09STao Ma 28067cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 28167cf5b09STao Ma if (error) 28267cf5b09STao Ma goto out; 28367cf5b09STao Ma 28467cf5b09STao Ma BUG_ON(!is.s.not_found); 28567cf5b09STao Ma 2860d812f77STao Ma error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); 28767cf5b09STao Ma if (error) { 28867cf5b09STao Ma if (error == -ENOSPC) 28967cf5b09STao Ma ext4_clear_inode_state(inode, 29067cf5b09STao Ma EXT4_STATE_MAY_INLINE_DATA); 29167cf5b09STao Ma goto out; 29267cf5b09STao Ma } 29367cf5b09STao Ma 29467cf5b09STao Ma memset((void *)ext4_raw_inode(&is.iloc)->i_block, 29567cf5b09STao Ma 0, EXT4_MIN_INLINE_DATA_SIZE); 29667cf5b09STao Ma 29767cf5b09STao Ma EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here - 29867cf5b09STao Ma (void *)ext4_raw_inode(&is.iloc)); 29967cf5b09STao Ma EXT4_I(inode)->i_inline_size = len + EXT4_MIN_INLINE_DATA_SIZE; 30067cf5b09STao Ma ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS); 30167cf5b09STao Ma ext4_set_inode_flag(inode, EXT4_INODE_INLINE_DATA); 302a3caa24bSJan Kara /* 303a3caa24bSJan Kara * Propagate changes to inode->i_flags as well - e.g. S_DAX may 304a3caa24bSJan Kara * get cleared 305a3caa24bSJan Kara */ 306a3caa24bSJan Kara ext4_set_inode_flags(inode); 30767cf5b09STao Ma get_bh(is.iloc.bh); 30867cf5b09STao Ma error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); 30967cf5b09STao Ma 31067cf5b09STao Ma out: 31167cf5b09STao Ma brelse(is.iloc.bh); 31267cf5b09STao Ma return error; 31367cf5b09STao Ma } 31467cf5b09STao Ma 31567cf5b09STao Ma static int ext4_update_inline_data(handle_t *handle, struct inode *inode, 31667cf5b09STao Ma unsigned int len) 31767cf5b09STao Ma { 31867cf5b09STao Ma int error; 31967cf5b09STao Ma void *value = NULL; 32067cf5b09STao Ma struct ext4_xattr_ibody_find is = { 32167cf5b09STao Ma .s = { .not_found = -ENODATA, }, 32267cf5b09STao Ma }; 32367cf5b09STao Ma struct ext4_xattr_info i = { 32467cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 32567cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 32667cf5b09STao Ma }; 32767cf5b09STao Ma 32867cf5b09STao Ma /* If the old space is ok, write the data directly. */ 32967cf5b09STao Ma if (len <= EXT4_I(inode)->i_inline_size) 33067cf5b09STao Ma return 0; 33167cf5b09STao Ma 33267cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 33367cf5b09STao Ma if (error) 33467cf5b09STao Ma return error; 33567cf5b09STao Ma 33667cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 33767cf5b09STao Ma if (error) 33867cf5b09STao Ma goto out; 33967cf5b09STao Ma 34067cf5b09STao Ma BUG_ON(is.s.not_found); 34167cf5b09STao Ma 34267cf5b09STao Ma len -= EXT4_MIN_INLINE_DATA_SIZE; 34367cf5b09STao Ma value = kzalloc(len, GFP_NOFS); 344578620f4SDan Carpenter if (!value) { 345578620f4SDan Carpenter error = -ENOMEM; 34667cf5b09STao Ma goto out; 347578620f4SDan Carpenter } 34867cf5b09STao Ma 34967cf5b09STao Ma error = ext4_xattr_ibody_get(inode, i.name_index, i.name, 35067cf5b09STao Ma value, len); 35167cf5b09STao Ma if (error == -ENODATA) 35267cf5b09STao Ma goto out; 35367cf5b09STao Ma 3545d601255Sliang xie BUFFER_TRACE(is.iloc.bh, "get_write_access"); 35567cf5b09STao Ma error = ext4_journal_get_write_access(handle, is.iloc.bh); 35667cf5b09STao Ma if (error) 35767cf5b09STao Ma goto out; 35867cf5b09STao Ma 35967cf5b09STao Ma /* Update the xttr entry. */ 36067cf5b09STao Ma i.value = value; 36167cf5b09STao Ma i.value_len = len; 36267cf5b09STao Ma 3630d812f77STao Ma error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); 36467cf5b09STao Ma if (error) 36567cf5b09STao Ma goto out; 36667cf5b09STao Ma 36767cf5b09STao Ma EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here - 36867cf5b09STao Ma (void *)ext4_raw_inode(&is.iloc)); 36967cf5b09STao Ma EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE + 37067cf5b09STao Ma le32_to_cpu(is.s.here->e_value_size); 37167cf5b09STao Ma ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 37267cf5b09STao Ma get_bh(is.iloc.bh); 37367cf5b09STao Ma error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); 37467cf5b09STao Ma 37567cf5b09STao Ma out: 37667cf5b09STao Ma kfree(value); 37767cf5b09STao Ma brelse(is.iloc.bh); 37867cf5b09STao Ma return error; 37967cf5b09STao Ma } 38067cf5b09STao Ma 381c197855eSStephen Hemminger static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode, 38267cf5b09STao Ma unsigned int len) 38367cf5b09STao Ma { 384c755e251STheodore Ts'o int ret, size, no_expand; 38567cf5b09STao Ma struct ext4_inode_info *ei = EXT4_I(inode); 38667cf5b09STao Ma 38767cf5b09STao Ma if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) 38867cf5b09STao Ma return -ENOSPC; 38967cf5b09STao Ma 39067cf5b09STao Ma size = ext4_get_max_inline_size(inode); 39167cf5b09STao Ma if (size < len) 39267cf5b09STao Ma return -ENOSPC; 39367cf5b09STao Ma 394c755e251STheodore Ts'o ext4_write_lock_xattr(inode, &no_expand); 39567cf5b09STao Ma 39667cf5b09STao Ma if (ei->i_inline_off) 39767cf5b09STao Ma ret = ext4_update_inline_data(handle, inode, len); 39867cf5b09STao Ma else 39967cf5b09STao Ma ret = ext4_create_inline_data(handle, inode, len); 40067cf5b09STao Ma 401c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 40267cf5b09STao Ma return ret; 40367cf5b09STao Ma } 40467cf5b09STao Ma 40567cf5b09STao Ma static int ext4_destroy_inline_data_nolock(handle_t *handle, 40667cf5b09STao Ma struct inode *inode) 40767cf5b09STao Ma { 40867cf5b09STao Ma struct ext4_inode_info *ei = EXT4_I(inode); 40967cf5b09STao Ma struct ext4_xattr_ibody_find is = { 41067cf5b09STao Ma .s = { .not_found = 0, }, 41167cf5b09STao Ma }; 41267cf5b09STao Ma struct ext4_xattr_info i = { 41367cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 41467cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 41567cf5b09STao Ma .value = NULL, 41667cf5b09STao Ma .value_len = 0, 41767cf5b09STao Ma }; 41867cf5b09STao Ma int error; 41967cf5b09STao Ma 42067cf5b09STao Ma if (!ei->i_inline_off) 42167cf5b09STao Ma return 0; 42267cf5b09STao Ma 42367cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 42467cf5b09STao Ma if (error) 42567cf5b09STao Ma return error; 42667cf5b09STao Ma 42767cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 42867cf5b09STao Ma if (error) 42967cf5b09STao Ma goto out; 43067cf5b09STao Ma 4315d601255Sliang xie BUFFER_TRACE(is.iloc.bh, "get_write_access"); 43267cf5b09STao Ma error = ext4_journal_get_write_access(handle, is.iloc.bh); 43367cf5b09STao Ma if (error) 43467cf5b09STao Ma goto out; 43567cf5b09STao Ma 4360d812f77STao Ma error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); 43767cf5b09STao Ma if (error) 43867cf5b09STao Ma goto out; 43967cf5b09STao Ma 44067cf5b09STao Ma memset((void *)ext4_raw_inode(&is.iloc)->i_block, 44167cf5b09STao Ma 0, EXT4_MIN_INLINE_DATA_SIZE); 44267cf5b09STao Ma 443e2b911c5SDarrick J. Wong if (ext4_has_feature_extents(inode->i_sb)) { 44467cf5b09STao Ma if (S_ISDIR(inode->i_mode) || 44567cf5b09STao Ma S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) { 44667cf5b09STao Ma ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS); 44767cf5b09STao Ma ext4_ext_tree_init(handle, inode); 44867cf5b09STao Ma } 44967cf5b09STao Ma } 45067cf5b09STao Ma ext4_clear_inode_flag(inode, EXT4_INODE_INLINE_DATA); 451a3caa24bSJan Kara /* 452a3caa24bSJan Kara * Propagate changes to inode->i_flags as well - e.g. S_DAX may 453a3caa24bSJan Kara * get set. 454a3caa24bSJan Kara */ 455a3caa24bSJan Kara ext4_set_inode_flags(inode); 45667cf5b09STao Ma 45767cf5b09STao Ma get_bh(is.iloc.bh); 45867cf5b09STao Ma error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); 45967cf5b09STao Ma 46067cf5b09STao Ma EXT4_I(inode)->i_inline_off = 0; 46167cf5b09STao Ma EXT4_I(inode)->i_inline_size = 0; 46267cf5b09STao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 46367cf5b09STao Ma out: 46467cf5b09STao Ma brelse(is.iloc.bh); 46567cf5b09STao Ma if (error == -ENODATA) 46667cf5b09STao Ma error = 0; 46767cf5b09STao Ma return error; 46867cf5b09STao Ma } 46967cf5b09STao Ma 47046c7f254STao Ma static int ext4_read_inline_page(struct inode *inode, struct page *page) 47146c7f254STao Ma { 47246c7f254STao Ma void *kaddr; 47346c7f254STao Ma int ret = 0; 47446c7f254STao Ma size_t len; 47546c7f254STao Ma struct ext4_iloc iloc; 47646c7f254STao Ma 47746c7f254STao Ma BUG_ON(!PageLocked(page)); 47846c7f254STao Ma BUG_ON(!ext4_has_inline_data(inode)); 47946c7f254STao Ma BUG_ON(page->index); 48046c7f254STao Ma 48146c7f254STao Ma if (!EXT4_I(inode)->i_inline_off) { 48246c7f254STao Ma ext4_warning(inode->i_sb, "inode %lu doesn't have inline data.", 48346c7f254STao Ma inode->i_ino); 48446c7f254STao Ma goto out; 48546c7f254STao Ma } 48646c7f254STao Ma 48746c7f254STao Ma ret = ext4_get_inode_loc(inode, &iloc); 48846c7f254STao Ma if (ret) 48946c7f254STao Ma goto out; 49046c7f254STao Ma 49146c7f254STao Ma len = min_t(size_t, ext4_get_inline_size(inode), i_size_read(inode)); 49246c7f254STao Ma kaddr = kmap_atomic(page); 49346c7f254STao Ma ret = ext4_read_inline_data(inode, kaddr, len, &iloc); 49446c7f254STao Ma flush_dcache_page(page); 49546c7f254STao Ma kunmap_atomic(kaddr); 49609cbfeafSKirill A. Shutemov zero_user_segment(page, len, PAGE_SIZE); 49746c7f254STao Ma SetPageUptodate(page); 49846c7f254STao Ma brelse(iloc.bh); 49946c7f254STao Ma 50046c7f254STao Ma out: 50146c7f254STao Ma return ret; 50246c7f254STao Ma } 50346c7f254STao Ma 50446c7f254STao Ma int ext4_readpage_inline(struct inode *inode, struct page *page) 50546c7f254STao Ma { 50646c7f254STao Ma int ret = 0; 50746c7f254STao Ma 50846c7f254STao Ma down_read(&EXT4_I(inode)->xattr_sem); 50946c7f254STao Ma if (!ext4_has_inline_data(inode)) { 51046c7f254STao Ma up_read(&EXT4_I(inode)->xattr_sem); 51146c7f254STao Ma return -EAGAIN; 51246c7f254STao Ma } 51346c7f254STao Ma 51446c7f254STao Ma /* 51546c7f254STao Ma * Current inline data can only exist in the 1st page, 51646c7f254STao Ma * So for all the other pages, just set them uptodate. 51746c7f254STao Ma */ 51846c7f254STao Ma if (!page->index) 51946c7f254STao Ma ret = ext4_read_inline_page(inode, page); 52046c7f254STao Ma else if (!PageUptodate(page)) { 52109cbfeafSKirill A. Shutemov zero_user_segment(page, 0, PAGE_SIZE); 52246c7f254STao Ma SetPageUptodate(page); 52346c7f254STao Ma } 52446c7f254STao Ma 52546c7f254STao Ma up_read(&EXT4_I(inode)->xattr_sem); 52646c7f254STao Ma 52746c7f254STao Ma unlock_page(page); 52846c7f254STao Ma return ret >= 0 ? 0 : ret; 52946c7f254STao Ma } 53046c7f254STao Ma 531f19d5870STao Ma static int ext4_convert_inline_data_to_extent(struct address_space *mapping, 532f19d5870STao Ma struct inode *inode, 533f19d5870STao Ma unsigned flags) 534f19d5870STao Ma { 535c755e251STheodore Ts'o int ret, needed_blocks, no_expand; 536f19d5870STao Ma handle_t *handle = NULL; 537f19d5870STao Ma int retries = 0, sem_held = 0; 538f19d5870STao Ma struct page *page = NULL; 539f19d5870STao Ma unsigned from, to; 540f19d5870STao Ma struct ext4_iloc iloc; 541f19d5870STao Ma 542f19d5870STao Ma if (!ext4_has_inline_data(inode)) { 543f19d5870STao Ma /* 544f19d5870STao Ma * clear the flag so that no new write 545f19d5870STao Ma * will trap here again. 546f19d5870STao Ma */ 547f19d5870STao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 548f19d5870STao Ma return 0; 549f19d5870STao Ma } 550f19d5870STao Ma 551f19d5870STao Ma needed_blocks = ext4_writepage_trans_blocks(inode); 552f19d5870STao Ma 553f19d5870STao Ma ret = ext4_get_inode_loc(inode, &iloc); 554f19d5870STao Ma if (ret) 555f19d5870STao Ma return ret; 556f19d5870STao Ma 557f19d5870STao Ma retry: 5589924a92aSTheodore Ts'o handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, needed_blocks); 559f19d5870STao Ma if (IS_ERR(handle)) { 560f19d5870STao Ma ret = PTR_ERR(handle); 561f19d5870STao Ma handle = NULL; 562f19d5870STao Ma goto out; 563f19d5870STao Ma } 564f19d5870STao Ma 565f19d5870STao Ma /* We cannot recurse into the filesystem as the transaction is already 566f19d5870STao Ma * started */ 567f19d5870STao Ma flags |= AOP_FLAG_NOFS; 568f19d5870STao Ma 569f19d5870STao Ma page = grab_cache_page_write_begin(mapping, 0, flags); 570f19d5870STao Ma if (!page) { 571f19d5870STao Ma ret = -ENOMEM; 572f19d5870STao Ma goto out; 573f19d5870STao Ma } 574f19d5870STao Ma 575c755e251STheodore Ts'o ext4_write_lock_xattr(inode, &no_expand); 576f19d5870STao Ma sem_held = 1; 577f19d5870STao Ma /* If some one has already done this for us, just exit. */ 578f19d5870STao Ma if (!ext4_has_inline_data(inode)) { 579f19d5870STao Ma ret = 0; 580f19d5870STao Ma goto out; 581f19d5870STao Ma } 582f19d5870STao Ma 583f19d5870STao Ma from = 0; 584f19d5870STao Ma to = ext4_get_inline_size(inode); 585f19d5870STao Ma if (!PageUptodate(page)) { 586f19d5870STao Ma ret = ext4_read_inline_page(inode, page); 587f19d5870STao Ma if (ret < 0) 588f19d5870STao Ma goto out; 589f19d5870STao Ma } 590f19d5870STao Ma 591f19d5870STao Ma ret = ext4_destroy_inline_data_nolock(handle, inode); 592f19d5870STao Ma if (ret) 593f19d5870STao Ma goto out; 594f19d5870STao Ma 595705965bdSJan Kara if (ext4_should_dioread_nolock(inode)) { 596705965bdSJan Kara ret = __block_write_begin(page, from, to, 597705965bdSJan Kara ext4_get_block_unwritten); 598705965bdSJan Kara } else 599f19d5870STao Ma ret = __block_write_begin(page, from, to, ext4_get_block); 600f19d5870STao Ma 601f19d5870STao Ma if (!ret && ext4_should_journal_data(inode)) { 602f19d5870STao Ma ret = ext4_walk_page_buffers(handle, page_buffers(page), 603f19d5870STao Ma from, to, NULL, 604f19d5870STao Ma do_journal_get_write_access); 605f19d5870STao Ma } 606f19d5870STao Ma 607f19d5870STao Ma if (ret) { 608f19d5870STao Ma unlock_page(page); 60909cbfeafSKirill A. Shutemov put_page(page); 610684de574SDarrick J. Wong page = NULL; 611f19d5870STao Ma ext4_orphan_add(handle, inode); 612c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 613f19d5870STao Ma sem_held = 0; 614f19d5870STao Ma ext4_journal_stop(handle); 615f19d5870STao Ma handle = NULL; 616f19d5870STao Ma ext4_truncate_failed_write(inode); 617f19d5870STao Ma /* 618f19d5870STao Ma * If truncate failed early the inode might 619f19d5870STao Ma * still be on the orphan list; we need to 620f19d5870STao Ma * make sure the inode is removed from the 621f19d5870STao Ma * orphan list in that case. 622f19d5870STao Ma */ 623f19d5870STao Ma if (inode->i_nlink) 624f19d5870STao Ma ext4_orphan_del(NULL, inode); 625f19d5870STao Ma } 626f19d5870STao Ma 627f19d5870STao Ma if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) 628f19d5870STao Ma goto retry; 629f19d5870STao Ma 630684de574SDarrick J. Wong if (page) 631f19d5870STao Ma block_commit_write(page, from, to); 632f19d5870STao Ma out: 633f19d5870STao Ma if (page) { 634f19d5870STao Ma unlock_page(page); 63509cbfeafSKirill A. Shutemov put_page(page); 636f19d5870STao Ma } 637f19d5870STao Ma if (sem_held) 638c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 639f19d5870STao Ma if (handle) 640f19d5870STao Ma ext4_journal_stop(handle); 641f19d5870STao Ma brelse(iloc.bh); 642f19d5870STao Ma return ret; 643f19d5870STao Ma } 644f19d5870STao Ma 645f19d5870STao Ma /* 646f19d5870STao Ma * Try to write data in the inode. 647f19d5870STao Ma * If the inode has inline data, check whether the new write can be 648f19d5870STao Ma * in the inode also. If not, create the page the handle, move the data 649f19d5870STao Ma * to the page make it update and let the later codes create extent for it. 650f19d5870STao Ma */ 651f19d5870STao Ma int ext4_try_to_write_inline_data(struct address_space *mapping, 652f19d5870STao Ma struct inode *inode, 653f19d5870STao Ma loff_t pos, unsigned len, 654f19d5870STao Ma unsigned flags, 655f19d5870STao Ma struct page **pagep) 656f19d5870STao Ma { 657f19d5870STao Ma int ret; 658f19d5870STao Ma handle_t *handle; 659f19d5870STao Ma struct page *page; 660f19d5870STao Ma struct ext4_iloc iloc; 661f19d5870STao Ma 662f19d5870STao Ma if (pos + len > ext4_get_max_inline_size(inode)) 663f19d5870STao Ma goto convert; 664f19d5870STao Ma 665f19d5870STao Ma ret = ext4_get_inode_loc(inode, &iloc); 666f19d5870STao Ma if (ret) 667f19d5870STao Ma return ret; 668f19d5870STao Ma 669f19d5870STao Ma /* 670f19d5870STao Ma * The possible write could happen in the inode, 671f19d5870STao Ma * so try to reserve the space in inode first. 672f19d5870STao Ma */ 6739924a92aSTheodore Ts'o handle = ext4_journal_start(inode, EXT4_HT_INODE, 1); 674f19d5870STao Ma if (IS_ERR(handle)) { 675f19d5870STao Ma ret = PTR_ERR(handle); 676f19d5870STao Ma handle = NULL; 677f19d5870STao Ma goto out; 678f19d5870STao Ma } 679f19d5870STao Ma 680f19d5870STao Ma ret = ext4_prepare_inline_data(handle, inode, pos + len); 681f19d5870STao Ma if (ret && ret != -ENOSPC) 682f19d5870STao Ma goto out; 683f19d5870STao Ma 684f19d5870STao Ma /* We don't have space in inline inode, so convert it to extent. */ 685f19d5870STao Ma if (ret == -ENOSPC) { 686f19d5870STao Ma ext4_journal_stop(handle); 687f19d5870STao Ma brelse(iloc.bh); 688f19d5870STao Ma goto convert; 689f19d5870STao Ma } 690f19d5870STao Ma 691f19d5870STao Ma flags |= AOP_FLAG_NOFS; 692f19d5870STao Ma 693f19d5870STao Ma page = grab_cache_page_write_begin(mapping, 0, flags); 694f19d5870STao Ma if (!page) { 695f19d5870STao Ma ret = -ENOMEM; 696f19d5870STao Ma goto out; 697f19d5870STao Ma } 698f19d5870STao Ma 699f19d5870STao Ma *pagep = page; 700f19d5870STao Ma down_read(&EXT4_I(inode)->xattr_sem); 701f19d5870STao Ma if (!ext4_has_inline_data(inode)) { 702f19d5870STao Ma ret = 0; 703f19d5870STao Ma unlock_page(page); 70409cbfeafSKirill A. Shutemov put_page(page); 705f19d5870STao Ma goto out_up_read; 706f19d5870STao Ma } 707f19d5870STao Ma 708f19d5870STao Ma if (!PageUptodate(page)) { 709f19d5870STao Ma ret = ext4_read_inline_page(inode, page); 710f19d5870STao Ma if (ret < 0) 711f19d5870STao Ma goto out_up_read; 712f19d5870STao Ma } 713f19d5870STao Ma 714f19d5870STao Ma ret = 1; 715f19d5870STao Ma handle = NULL; 716f19d5870STao Ma out_up_read: 717f19d5870STao Ma up_read(&EXT4_I(inode)->xattr_sem); 718f19d5870STao Ma out: 719f19d5870STao Ma if (handle) 720f19d5870STao Ma ext4_journal_stop(handle); 721f19d5870STao Ma brelse(iloc.bh); 722f19d5870STao Ma return ret; 723f19d5870STao Ma convert: 724f19d5870STao Ma return ext4_convert_inline_data_to_extent(mapping, 725f19d5870STao Ma inode, flags); 726f19d5870STao Ma } 727f19d5870STao Ma 728f19d5870STao Ma int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len, 729f19d5870STao Ma unsigned copied, struct page *page) 730f19d5870STao Ma { 731c755e251STheodore Ts'o int ret, no_expand; 732f19d5870STao Ma void *kaddr; 733f19d5870STao Ma struct ext4_iloc iloc; 734f19d5870STao Ma 735f19d5870STao Ma if (unlikely(copied < len)) { 736f19d5870STao Ma if (!PageUptodate(page)) { 737f19d5870STao Ma copied = 0; 738f19d5870STao Ma goto out; 739f19d5870STao Ma } 740f19d5870STao Ma } 741f19d5870STao Ma 742f19d5870STao Ma ret = ext4_get_inode_loc(inode, &iloc); 743f19d5870STao Ma if (ret) { 744f19d5870STao Ma ext4_std_error(inode->i_sb, ret); 745f19d5870STao Ma copied = 0; 746f19d5870STao Ma goto out; 747f19d5870STao Ma } 748f19d5870STao Ma 749c755e251STheodore Ts'o ext4_write_lock_xattr(inode, &no_expand); 750f19d5870STao Ma BUG_ON(!ext4_has_inline_data(inode)); 751f19d5870STao Ma 752f19d5870STao Ma kaddr = kmap_atomic(page); 753f19d5870STao Ma ext4_write_inline_data(inode, &iloc, kaddr, pos, len); 754f19d5870STao Ma kunmap_atomic(kaddr); 755f19d5870STao Ma SetPageUptodate(page); 756f19d5870STao Ma /* clear page dirty so that writepages wouldn't work for us. */ 757f19d5870STao Ma ClearPageDirty(page); 758f19d5870STao Ma 759c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 760f19d5870STao Ma brelse(iloc.bh); 761f19d5870STao Ma out: 762f19d5870STao Ma return copied; 763f19d5870STao Ma } 764f19d5870STao Ma 7653fdcfb66STao Ma struct buffer_head * 7663fdcfb66STao Ma ext4_journalled_write_inline_data(struct inode *inode, 7673fdcfb66STao Ma unsigned len, 7683fdcfb66STao Ma struct page *page) 7693fdcfb66STao Ma { 770c755e251STheodore Ts'o int ret, no_expand; 7713fdcfb66STao Ma void *kaddr; 7723fdcfb66STao Ma struct ext4_iloc iloc; 7733fdcfb66STao Ma 7743fdcfb66STao Ma ret = ext4_get_inode_loc(inode, &iloc); 7753fdcfb66STao Ma if (ret) { 7763fdcfb66STao Ma ext4_std_error(inode->i_sb, ret); 7773fdcfb66STao Ma return NULL; 7783fdcfb66STao Ma } 7793fdcfb66STao Ma 780c755e251STheodore Ts'o ext4_write_lock_xattr(inode, &no_expand); 7813fdcfb66STao Ma kaddr = kmap_atomic(page); 7823fdcfb66STao Ma ext4_write_inline_data(inode, &iloc, kaddr, 0, len); 7833fdcfb66STao Ma kunmap_atomic(kaddr); 784c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 7853fdcfb66STao Ma 7863fdcfb66STao Ma return iloc.bh; 7873fdcfb66STao Ma } 7883fdcfb66STao Ma 7899c3569b5STao Ma /* 7909c3569b5STao Ma * Try to make the page cache and handle ready for the inline data case. 7919c3569b5STao Ma * We can call this function in 2 cases: 7929c3569b5STao Ma * 1. The inode is created and the first write exceeds inline size. We can 7939c3569b5STao Ma * clear the inode state safely. 7949c3569b5STao Ma * 2. The inode has inline data, then we need to read the data, make it 7959c3569b5STao Ma * update and dirty so that ext4_da_writepages can handle it. We don't 7969c3569b5STao Ma * need to start the journal since the file's metatdata isn't changed now. 7979c3569b5STao Ma */ 7989c3569b5STao Ma static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping, 7999c3569b5STao Ma struct inode *inode, 8009c3569b5STao Ma unsigned flags, 8019c3569b5STao Ma void **fsdata) 8029c3569b5STao Ma { 8039c3569b5STao Ma int ret = 0, inline_size; 8049c3569b5STao Ma struct page *page; 8059c3569b5STao Ma 8069c3569b5STao Ma page = grab_cache_page_write_begin(mapping, 0, flags); 8079c3569b5STao Ma if (!page) 8089c3569b5STao Ma return -ENOMEM; 8099c3569b5STao Ma 8109c3569b5STao Ma down_read(&EXT4_I(inode)->xattr_sem); 8119c3569b5STao Ma if (!ext4_has_inline_data(inode)) { 8129c3569b5STao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 8139c3569b5STao Ma goto out; 8149c3569b5STao Ma } 8159c3569b5STao Ma 8169c3569b5STao Ma inline_size = ext4_get_inline_size(inode); 8179c3569b5STao Ma 8189c3569b5STao Ma if (!PageUptodate(page)) { 8199c3569b5STao Ma ret = ext4_read_inline_page(inode, page); 8209c3569b5STao Ma if (ret < 0) 8219c3569b5STao Ma goto out; 8229c3569b5STao Ma } 8239c3569b5STao Ma 8249c3569b5STao Ma ret = __block_write_begin(page, 0, inline_size, 8259c3569b5STao Ma ext4_da_get_block_prep); 8269c3569b5STao Ma if (ret) { 82750db71abSDmitry Monakhov up_read(&EXT4_I(inode)->xattr_sem); 82850db71abSDmitry Monakhov unlock_page(page); 82909cbfeafSKirill A. Shutemov put_page(page); 8309c3569b5STao Ma ext4_truncate_failed_write(inode); 83150db71abSDmitry Monakhov return ret; 8329c3569b5STao Ma } 8339c3569b5STao Ma 8349c3569b5STao Ma SetPageDirty(page); 8359c3569b5STao Ma SetPageUptodate(page); 8369c3569b5STao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 8379c3569b5STao Ma *fsdata = (void *)CONVERT_INLINE_DATA; 8389c3569b5STao Ma 8399c3569b5STao Ma out: 8409c3569b5STao Ma up_read(&EXT4_I(inode)->xattr_sem); 8419c3569b5STao Ma if (page) { 8429c3569b5STao Ma unlock_page(page); 84309cbfeafSKirill A. Shutemov put_page(page); 8449c3569b5STao Ma } 8459c3569b5STao Ma return ret; 8469c3569b5STao Ma } 8479c3569b5STao Ma 8489c3569b5STao Ma /* 8499c3569b5STao Ma * Prepare the write for the inline data. 8509c3569b5STao Ma * If the the data can be written into the inode, we just read 8519c3569b5STao Ma * the page and make it uptodate, and start the journal. 8529c3569b5STao Ma * Otherwise read the page, makes it dirty so that it can be 8539c3569b5STao Ma * handle in writepages(the i_disksize update is left to the 8549c3569b5STao Ma * normal ext4_da_write_end). 8559c3569b5STao Ma */ 8569c3569b5STao Ma int ext4_da_write_inline_data_begin(struct address_space *mapping, 8579c3569b5STao Ma struct inode *inode, 8589c3569b5STao Ma loff_t pos, unsigned len, 8599c3569b5STao Ma unsigned flags, 8609c3569b5STao Ma struct page **pagep, 8619c3569b5STao Ma void **fsdata) 8629c3569b5STao Ma { 8639c3569b5STao Ma int ret, inline_size; 8649c3569b5STao Ma handle_t *handle; 8659c3569b5STao Ma struct page *page; 8669c3569b5STao Ma struct ext4_iloc iloc; 867bc0ca9dfSJan Kara int retries; 8689c3569b5STao Ma 8699c3569b5STao Ma ret = ext4_get_inode_loc(inode, &iloc); 8709c3569b5STao Ma if (ret) 8719c3569b5STao Ma return ret; 8729c3569b5STao Ma 873bc0ca9dfSJan Kara retry_journal: 8749924a92aSTheodore Ts'o handle = ext4_journal_start(inode, EXT4_HT_INODE, 1); 8759c3569b5STao Ma if (IS_ERR(handle)) { 8769c3569b5STao Ma ret = PTR_ERR(handle); 8779c3569b5STao Ma goto out; 8789c3569b5STao Ma } 8799c3569b5STao Ma 8809c3569b5STao Ma inline_size = ext4_get_max_inline_size(inode); 8819c3569b5STao Ma 8829c3569b5STao Ma ret = -ENOSPC; 8839c3569b5STao Ma if (inline_size >= pos + len) { 8849c3569b5STao Ma ret = ext4_prepare_inline_data(handle, inode, pos + len); 8859c3569b5STao Ma if (ret && ret != -ENOSPC) 88652e44777SJan Kara goto out_journal; 8879c3569b5STao Ma } 8889c3569b5STao Ma 8895cc28a9eSDmitry Monakhov /* 8905cc28a9eSDmitry Monakhov * We cannot recurse into the filesystem as the transaction 8915cc28a9eSDmitry Monakhov * is already started. 8925cc28a9eSDmitry Monakhov */ 8935cc28a9eSDmitry Monakhov flags |= AOP_FLAG_NOFS; 8945cc28a9eSDmitry Monakhov 8959c3569b5STao Ma if (ret == -ENOSPC) { 8969c3569b5STao Ma ret = ext4_da_convert_inline_data_to_extent(mapping, 8979c3569b5STao Ma inode, 8989c3569b5STao Ma flags, 8999c3569b5STao Ma fsdata); 900bc0ca9dfSJan Kara ext4_journal_stop(handle); 901bc0ca9dfSJan Kara if (ret == -ENOSPC && 902bc0ca9dfSJan Kara ext4_should_retry_alloc(inode->i_sb, &retries)) 903bc0ca9dfSJan Kara goto retry_journal; 9049c3569b5STao Ma goto out; 9059c3569b5STao Ma } 9069c3569b5STao Ma 9079c3569b5STao Ma 9089c3569b5STao Ma page = grab_cache_page_write_begin(mapping, 0, flags); 9099c3569b5STao Ma if (!page) { 9109c3569b5STao Ma ret = -ENOMEM; 91152e44777SJan Kara goto out_journal; 9129c3569b5STao Ma } 9139c3569b5STao Ma 9149c3569b5STao Ma down_read(&EXT4_I(inode)->xattr_sem); 9159c3569b5STao Ma if (!ext4_has_inline_data(inode)) { 9169c3569b5STao Ma ret = 0; 9179c3569b5STao Ma goto out_release_page; 9189c3569b5STao Ma } 9199c3569b5STao Ma 9209c3569b5STao Ma if (!PageUptodate(page)) { 9219c3569b5STao Ma ret = ext4_read_inline_page(inode, page); 9229c3569b5STao Ma if (ret < 0) 9239c3569b5STao Ma goto out_release_page; 9249c3569b5STao Ma } 9259c3569b5STao Ma 9269c3569b5STao Ma up_read(&EXT4_I(inode)->xattr_sem); 9279c3569b5STao Ma *pagep = page; 9289c3569b5STao Ma brelse(iloc.bh); 9299c3569b5STao Ma return 1; 9309c3569b5STao Ma out_release_page: 9319c3569b5STao Ma up_read(&EXT4_I(inode)->xattr_sem); 9329c3569b5STao Ma unlock_page(page); 93309cbfeafSKirill A. Shutemov put_page(page); 93452e44777SJan Kara out_journal: 9359c3569b5STao Ma ext4_journal_stop(handle); 93652e44777SJan Kara out: 9379c3569b5STao Ma brelse(iloc.bh); 9389c3569b5STao Ma return ret; 9399c3569b5STao Ma } 9409c3569b5STao Ma 9419c3569b5STao Ma int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos, 9429c3569b5STao Ma unsigned len, unsigned copied, 9439c3569b5STao Ma struct page *page) 9449c3569b5STao Ma { 9459c3569b5STao Ma int i_size_changed = 0; 9469c3569b5STao Ma 9479c3569b5STao Ma copied = ext4_write_inline_data_end(inode, pos, len, copied, page); 9489c3569b5STao Ma 9499c3569b5STao Ma /* 9509c3569b5STao Ma * No need to use i_size_read() here, the i_size 9519c3569b5STao Ma * cannot change under us because we hold i_mutex. 9529c3569b5STao Ma * 9539c3569b5STao Ma * But it's important to update i_size while still holding page lock: 9549c3569b5STao Ma * page writeout could otherwise come in and zero beyond i_size. 9559c3569b5STao Ma */ 9569c3569b5STao Ma if (pos+copied > inode->i_size) { 9579c3569b5STao Ma i_size_write(inode, pos+copied); 9589c3569b5STao Ma i_size_changed = 1; 9599c3569b5STao Ma } 9609c3569b5STao Ma unlock_page(page); 96109cbfeafSKirill A. Shutemov put_page(page); 9629c3569b5STao Ma 9639c3569b5STao Ma /* 9649c3569b5STao Ma * Don't mark the inode dirty under page lock. First, it unnecessarily 9659c3569b5STao Ma * makes the holding time of page lock longer. Second, it forces lock 9669c3569b5STao Ma * ordering of page lock and transaction start for journaling 9679c3569b5STao Ma * filesystems. 9689c3569b5STao Ma */ 9699c3569b5STao Ma if (i_size_changed) 9709c3569b5STao Ma mark_inode_dirty(inode); 9719c3569b5STao Ma 9729c3569b5STao Ma return copied; 9739c3569b5STao Ma } 974f19d5870STao Ma 9753c47d541STao Ma #ifdef INLINE_DIR_DEBUG 9763c47d541STao Ma void ext4_show_inline_dir(struct inode *dir, struct buffer_head *bh, 9773c47d541STao Ma void *inline_start, int inline_size) 9783c47d541STao Ma { 9793c47d541STao Ma int offset; 9803c47d541STao Ma unsigned short de_len; 9813c47d541STao Ma struct ext4_dir_entry_2 *de = inline_start; 9823c47d541STao Ma void *dlimit = inline_start + inline_size; 9833c47d541STao Ma 9843c47d541STao Ma trace_printk("inode %lu\n", dir->i_ino); 9853c47d541STao Ma offset = 0; 9863c47d541STao Ma while ((void *)de < dlimit) { 9873c47d541STao Ma de_len = ext4_rec_len_from_disk(de->rec_len, inline_size); 98880cfb71eSRasmus Villemoes trace_printk("de: off %u rlen %u name %.*s nlen %u ino %u\n", 9893c47d541STao Ma offset, de_len, de->name_len, de->name, 9903c47d541STao Ma de->name_len, le32_to_cpu(de->inode)); 9913c47d541STao Ma if (ext4_check_dir_entry(dir, NULL, de, bh, 9923c47d541STao Ma inline_start, inline_size, offset)) 9933c47d541STao Ma BUG(); 9943c47d541STao Ma 9953c47d541STao Ma offset += de_len; 9963c47d541STao Ma de = (struct ext4_dir_entry_2 *) ((char *) de + de_len); 9973c47d541STao Ma } 9983c47d541STao Ma } 9993c47d541STao Ma #else 10003c47d541STao Ma #define ext4_show_inline_dir(dir, bh, inline_start, inline_size) 10013c47d541STao Ma #endif 10023c47d541STao Ma 10033c47d541STao Ma /* 10043c47d541STao Ma * Add a new entry into a inline dir. 10053c47d541STao Ma * It will return -ENOSPC if no space is available, and -EIO 10063c47d541STao Ma * and -EEXIST if directory entry already exists. 10073c47d541STao Ma */ 10083c47d541STao Ma static int ext4_add_dirent_to_inline(handle_t *handle, 10095b643f9cSTheodore Ts'o struct ext4_filename *fname, 101056a04915STheodore Ts'o struct inode *dir, 10113c47d541STao Ma struct inode *inode, 10123c47d541STao Ma struct ext4_iloc *iloc, 10133c47d541STao Ma void *inline_start, int inline_size) 10143c47d541STao Ma { 10153c47d541STao Ma int err; 10163c47d541STao Ma struct ext4_dir_entry_2 *de; 10173c47d541STao Ma 10185b643f9cSTheodore Ts'o err = ext4_find_dest_de(dir, inode, iloc->bh, inline_start, 10195b643f9cSTheodore Ts'o inline_size, fname, &de); 10203c47d541STao Ma if (err) 10213c47d541STao Ma return err; 10223c47d541STao Ma 10235d601255Sliang xie BUFFER_TRACE(iloc->bh, "get_write_access"); 10243c47d541STao Ma err = ext4_journal_get_write_access(handle, iloc->bh); 10253c47d541STao Ma if (err) 10263c47d541STao Ma return err; 10275b643f9cSTheodore Ts'o ext4_insert_dentry(dir, inode, de, inline_size, fname); 10283c47d541STao Ma 10293c47d541STao Ma ext4_show_inline_dir(dir, iloc->bh, inline_start, inline_size); 10303c47d541STao Ma 10313c47d541STao Ma /* 10323c47d541STao Ma * XXX shouldn't update any times until successful 10333c47d541STao Ma * completion of syscall, but too many callers depend 10343c47d541STao Ma * on this. 10353c47d541STao Ma * 10363c47d541STao Ma * XXX similarly, too many callers depend on 10373c47d541STao Ma * ext4_new_inode() setting the times, but error 10383c47d541STao Ma * recovery deletes the inode, so the worst that can 10393c47d541STao Ma * happen is that the times are slightly out of date 10403c47d541STao Ma * and/or different from the directory change time. 10413c47d541STao Ma */ 1042eeca7ea1SDeepa Dinamani dir->i_mtime = dir->i_ctime = current_time(dir); 10433c47d541STao Ma ext4_update_dx_flag(dir); 10443c47d541STao Ma dir->i_version++; 10453c47d541STao Ma return 1; 10463c47d541STao Ma } 10473c47d541STao Ma 10483c47d541STao Ma static void *ext4_get_inline_xattr_pos(struct inode *inode, 10493c47d541STao Ma struct ext4_iloc *iloc) 10503c47d541STao Ma { 10513c47d541STao Ma struct ext4_xattr_entry *entry; 10523c47d541STao Ma struct ext4_xattr_ibody_header *header; 10533c47d541STao Ma 10543c47d541STao Ma BUG_ON(!EXT4_I(inode)->i_inline_off); 10553c47d541STao Ma 10563c47d541STao Ma header = IHDR(inode, ext4_raw_inode(iloc)); 10573c47d541STao Ma entry = (struct ext4_xattr_entry *)((void *)ext4_raw_inode(iloc) + 10583c47d541STao Ma EXT4_I(inode)->i_inline_off); 10593c47d541STao Ma 10603c47d541STao Ma return (void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs); 10613c47d541STao Ma } 10623c47d541STao Ma 10633c47d541STao Ma /* Set the final de to cover the whole block. */ 10643c47d541STao Ma static void ext4_update_final_de(void *de_buf, int old_size, int new_size) 10653c47d541STao Ma { 10663c47d541STao Ma struct ext4_dir_entry_2 *de, *prev_de; 10673c47d541STao Ma void *limit; 10683c47d541STao Ma int de_len; 10693c47d541STao Ma 10703c47d541STao Ma de = (struct ext4_dir_entry_2 *)de_buf; 10713c47d541STao Ma if (old_size) { 10723c47d541STao Ma limit = de_buf + old_size; 10733c47d541STao Ma do { 10743c47d541STao Ma prev_de = de; 10753c47d541STao Ma de_len = ext4_rec_len_from_disk(de->rec_len, old_size); 10763c47d541STao Ma de_buf += de_len; 10773c47d541STao Ma de = (struct ext4_dir_entry_2 *)de_buf; 10783c47d541STao Ma } while (de_buf < limit); 10793c47d541STao Ma 10803c47d541STao Ma prev_de->rec_len = ext4_rec_len_to_disk(de_len + new_size - 10813c47d541STao Ma old_size, new_size); 10823c47d541STao Ma } else { 10833c47d541STao Ma /* this is just created, so create an empty entry. */ 10843c47d541STao Ma de->inode = 0; 10853c47d541STao Ma de->rec_len = ext4_rec_len_to_disk(new_size, new_size); 10863c47d541STao Ma } 10873c47d541STao Ma } 10883c47d541STao Ma 10893c47d541STao Ma static int ext4_update_inline_dir(handle_t *handle, struct inode *dir, 10903c47d541STao Ma struct ext4_iloc *iloc) 10913c47d541STao Ma { 10923c47d541STao Ma int ret; 10933c47d541STao Ma int old_size = EXT4_I(dir)->i_inline_size - EXT4_MIN_INLINE_DATA_SIZE; 10943c47d541STao Ma int new_size = get_max_inline_xattr_value_size(dir, iloc); 10953c47d541STao Ma 10963c47d541STao Ma if (new_size - old_size <= EXT4_DIR_REC_LEN(1)) 10973c47d541STao Ma return -ENOSPC; 10983c47d541STao Ma 10993c47d541STao Ma ret = ext4_update_inline_data(handle, dir, 11003c47d541STao Ma new_size + EXT4_MIN_INLINE_DATA_SIZE); 11013c47d541STao Ma if (ret) 11023c47d541STao Ma return ret; 11033c47d541STao Ma 11043c47d541STao Ma ext4_update_final_de(ext4_get_inline_xattr_pos(dir, iloc), old_size, 11053c47d541STao Ma EXT4_I(dir)->i_inline_size - 11063c47d541STao Ma EXT4_MIN_INLINE_DATA_SIZE); 11073c47d541STao Ma dir->i_size = EXT4_I(dir)->i_disksize = EXT4_I(dir)->i_inline_size; 11083c47d541STao Ma return 0; 11093c47d541STao Ma } 11103c47d541STao Ma 11113c47d541STao Ma static void ext4_restore_inline_data(handle_t *handle, struct inode *inode, 11123c47d541STao Ma struct ext4_iloc *iloc, 11133c47d541STao Ma void *buf, int inline_size) 11143c47d541STao Ma { 11153c47d541STao Ma ext4_create_inline_data(handle, inode, inline_size); 11163c47d541STao Ma ext4_write_inline_data(inode, iloc, buf, 0, inline_size); 11173c47d541STao Ma ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 11183c47d541STao Ma } 11193c47d541STao Ma 11203c47d541STao Ma static int ext4_finish_convert_inline_dir(handle_t *handle, 11213c47d541STao Ma struct inode *inode, 11223c47d541STao Ma struct buffer_head *dir_block, 11233c47d541STao Ma void *buf, 11243c47d541STao Ma int inline_size) 11253c47d541STao Ma { 11263c47d541STao Ma int err, csum_size = 0, header_size = 0; 11273c47d541STao Ma struct ext4_dir_entry_2 *de; 11283c47d541STao Ma struct ext4_dir_entry_tail *t; 11293c47d541STao Ma void *target = dir_block->b_data; 11303c47d541STao Ma 11313c47d541STao Ma /* 11323c47d541STao Ma * First create "." and ".." and then copy the dir information 11333c47d541STao Ma * back to the block. 11343c47d541STao Ma */ 11353c47d541STao Ma de = (struct ext4_dir_entry_2 *)target; 11363c47d541STao Ma de = ext4_init_dot_dotdot(inode, de, 11373c47d541STao Ma inode->i_sb->s_blocksize, csum_size, 11383c47d541STao Ma le32_to_cpu(((struct ext4_dir_entry_2 *)buf)->inode), 1); 11393c47d541STao Ma header_size = (void *)de - target; 11403c47d541STao Ma 11413c47d541STao Ma memcpy((void *)de, buf + EXT4_INLINE_DOTDOT_SIZE, 11423c47d541STao Ma inline_size - EXT4_INLINE_DOTDOT_SIZE); 11433c47d541STao Ma 11449aa5d32bSDmitry Monakhov if (ext4_has_metadata_csum(inode->i_sb)) 11453c47d541STao Ma csum_size = sizeof(struct ext4_dir_entry_tail); 11463c47d541STao Ma 11473c47d541STao Ma inode->i_size = inode->i_sb->s_blocksize; 11483c47d541STao Ma i_size_write(inode, inode->i_sb->s_blocksize); 11493c47d541STao Ma EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize; 11503c47d541STao Ma ext4_update_final_de(dir_block->b_data, 11513c47d541STao Ma inline_size - EXT4_INLINE_DOTDOT_SIZE + header_size, 11523c47d541STao Ma inode->i_sb->s_blocksize - csum_size); 11533c47d541STao Ma 11543c47d541STao Ma if (csum_size) { 11553c47d541STao Ma t = EXT4_DIRENT_TAIL(dir_block->b_data, 11563c47d541STao Ma inode->i_sb->s_blocksize); 11573c47d541STao Ma initialize_dirent_tail(t, inode->i_sb->s_blocksize); 11583c47d541STao Ma } 11593c47d541STao Ma set_buffer_uptodate(dir_block); 11603c47d541STao Ma err = ext4_handle_dirty_dirent_node(handle, inode, dir_block); 11613c47d541STao Ma if (err) 11623c47d541STao Ma goto out; 11633c47d541STao Ma set_buffer_verified(dir_block); 11643c47d541STao Ma out: 11653c47d541STao Ma return err; 11663c47d541STao Ma } 11673c47d541STao Ma 11683c47d541STao Ma static int ext4_convert_inline_data_nolock(handle_t *handle, 11693c47d541STao Ma struct inode *inode, 11703c47d541STao Ma struct ext4_iloc *iloc) 11713c47d541STao Ma { 11723c47d541STao Ma int error; 11733c47d541STao Ma void *buf = NULL; 11743c47d541STao Ma struct buffer_head *data_bh = NULL; 11753c47d541STao Ma struct ext4_map_blocks map; 11763c47d541STao Ma int inline_size; 11773c47d541STao Ma 11783c47d541STao Ma inline_size = ext4_get_inline_size(inode); 11793c47d541STao Ma buf = kmalloc(inline_size, GFP_NOFS); 11803c47d541STao Ma if (!buf) { 11813c47d541STao Ma error = -ENOMEM; 11823c47d541STao Ma goto out; 11833c47d541STao Ma } 11843c47d541STao Ma 11853c47d541STao Ma error = ext4_read_inline_data(inode, buf, inline_size, iloc); 11863c47d541STao Ma if (error < 0) 11873c47d541STao Ma goto out; 11883c47d541STao Ma 118940b163f1SDarrick J. Wong /* 119040b163f1SDarrick J. Wong * Make sure the inline directory entries pass checks before we try to 119140b163f1SDarrick J. Wong * convert them, so that we avoid touching stuff that needs fsck. 119240b163f1SDarrick J. Wong */ 119340b163f1SDarrick J. Wong if (S_ISDIR(inode->i_mode)) { 119440b163f1SDarrick J. Wong error = ext4_check_all_de(inode, iloc->bh, 119540b163f1SDarrick J. Wong buf + EXT4_INLINE_DOTDOT_SIZE, 119640b163f1SDarrick J. Wong inline_size - EXT4_INLINE_DOTDOT_SIZE); 119740b163f1SDarrick J. Wong if (error) 119840b163f1SDarrick J. Wong goto out; 119940b163f1SDarrick J. Wong } 120040b163f1SDarrick J. Wong 12013c47d541STao Ma error = ext4_destroy_inline_data_nolock(handle, inode); 12023c47d541STao Ma if (error) 12033c47d541STao Ma goto out; 12043c47d541STao Ma 12053c47d541STao Ma map.m_lblk = 0; 12063c47d541STao Ma map.m_len = 1; 12073c47d541STao Ma map.m_flags = 0; 12083c47d541STao Ma error = ext4_map_blocks(handle, inode, &map, EXT4_GET_BLOCKS_CREATE); 12093c47d541STao Ma if (error < 0) 12103c47d541STao Ma goto out_restore; 12113c47d541STao Ma if (!(map.m_flags & EXT4_MAP_MAPPED)) { 12123c47d541STao Ma error = -EIO; 12133c47d541STao Ma goto out_restore; 12143c47d541STao Ma } 12153c47d541STao Ma 12163c47d541STao Ma data_bh = sb_getblk(inode->i_sb, map.m_pblk); 12173c47d541STao Ma if (!data_bh) { 1218860d21e2STheodore Ts'o error = -ENOMEM; 12193c47d541STao Ma goto out_restore; 12203c47d541STao Ma } 12213c47d541STao Ma 12223c47d541STao Ma lock_buffer(data_bh); 12233c47d541STao Ma error = ext4_journal_get_create_access(handle, data_bh); 12243c47d541STao Ma if (error) { 12253c47d541STao Ma unlock_buffer(data_bh); 12263c47d541STao Ma error = -EIO; 12273c47d541STao Ma goto out_restore; 12283c47d541STao Ma } 12293c47d541STao Ma memset(data_bh->b_data, 0, inode->i_sb->s_blocksize); 12303c47d541STao Ma 12313c47d541STao Ma if (!S_ISDIR(inode->i_mode)) { 12323c47d541STao Ma memcpy(data_bh->b_data, buf, inline_size); 12333c47d541STao Ma set_buffer_uptodate(data_bh); 12343c47d541STao Ma error = ext4_handle_dirty_metadata(handle, 12353c47d541STao Ma inode, data_bh); 12363c47d541STao Ma } else { 12373c47d541STao Ma error = ext4_finish_convert_inline_dir(handle, inode, data_bh, 12383c47d541STao Ma buf, inline_size); 12393c47d541STao Ma } 12403c47d541STao Ma 12413c47d541STao Ma unlock_buffer(data_bh); 12423c47d541STao Ma out_restore: 12433c47d541STao Ma if (error) 12443c47d541STao Ma ext4_restore_inline_data(handle, inode, iloc, buf, inline_size); 12453c47d541STao Ma 12463c47d541STao Ma out: 12473c47d541STao Ma brelse(data_bh); 12483c47d541STao Ma kfree(buf); 12493c47d541STao Ma return error; 12503c47d541STao Ma } 12513c47d541STao Ma 12523c47d541STao Ma /* 12533c47d541STao Ma * Try to add the new entry to the inline data. 12543c47d541STao Ma * If succeeds, return 0. If not, extended the inline dir and copied data to 12553c47d541STao Ma * the new created block. 12563c47d541STao Ma */ 12575b643f9cSTheodore Ts'o int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname, 125856a04915STheodore Ts'o struct inode *dir, struct inode *inode) 12593c47d541STao Ma { 1260c755e251STheodore Ts'o int ret, inline_size, no_expand; 12613c47d541STao Ma void *inline_start; 12623c47d541STao Ma struct ext4_iloc iloc; 12633c47d541STao Ma 12643c47d541STao Ma ret = ext4_get_inode_loc(dir, &iloc); 12653c47d541STao Ma if (ret) 12663c47d541STao Ma return ret; 12673c47d541STao Ma 1268c755e251STheodore Ts'o ext4_write_lock_xattr(dir, &no_expand); 12693c47d541STao Ma if (!ext4_has_inline_data(dir)) 12703c47d541STao Ma goto out; 12713c47d541STao Ma 12723c47d541STao Ma inline_start = (void *)ext4_raw_inode(&iloc)->i_block + 12733c47d541STao Ma EXT4_INLINE_DOTDOT_SIZE; 12743c47d541STao Ma inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE; 12753c47d541STao Ma 127656a04915STheodore Ts'o ret = ext4_add_dirent_to_inline(handle, fname, dir, inode, &iloc, 12773c47d541STao Ma inline_start, inline_size); 12783c47d541STao Ma if (ret != -ENOSPC) 12793c47d541STao Ma goto out; 12803c47d541STao Ma 12813c47d541STao Ma /* check whether it can be inserted to inline xattr space. */ 12823c47d541STao Ma inline_size = EXT4_I(dir)->i_inline_size - 12833c47d541STao Ma EXT4_MIN_INLINE_DATA_SIZE; 12843c47d541STao Ma if (!inline_size) { 12853c47d541STao Ma /* Try to use the xattr space.*/ 12863c47d541STao Ma ret = ext4_update_inline_dir(handle, dir, &iloc); 12873c47d541STao Ma if (ret && ret != -ENOSPC) 12883c47d541STao Ma goto out; 12893c47d541STao Ma 12903c47d541STao Ma inline_size = EXT4_I(dir)->i_inline_size - 12913c47d541STao Ma EXT4_MIN_INLINE_DATA_SIZE; 12923c47d541STao Ma } 12933c47d541STao Ma 12943c47d541STao Ma if (inline_size) { 12953c47d541STao Ma inline_start = ext4_get_inline_xattr_pos(dir, &iloc); 12963c47d541STao Ma 129756a04915STheodore Ts'o ret = ext4_add_dirent_to_inline(handle, fname, dir, 12985b643f9cSTheodore Ts'o inode, &iloc, inline_start, 12995b643f9cSTheodore Ts'o inline_size); 13003c47d541STao Ma 13013c47d541STao Ma if (ret != -ENOSPC) 13023c47d541STao Ma goto out; 13033c47d541STao Ma } 13043c47d541STao Ma 13053c47d541STao Ma /* 13063c47d541STao Ma * The inline space is filled up, so create a new block for it. 13073c47d541STao Ma * As the extent tree will be created, we have to save the inline 13083c47d541STao Ma * dir first. 13093c47d541STao Ma */ 13103c47d541STao Ma ret = ext4_convert_inline_data_nolock(handle, dir, &iloc); 13113c47d541STao Ma 13123c47d541STao Ma out: 1313c755e251STheodore Ts'o ext4_write_unlock_xattr(dir, &no_expand); 1314*b907f2d5STheodore Ts'o ext4_mark_inode_dirty(handle, dir); 13153c47d541STao Ma brelse(iloc.bh); 13163c47d541STao Ma return ret; 13173c47d541STao Ma } 13183c47d541STao Ma 13198af0f082STao Ma /* 13208af0f082STao Ma * This function fills a red-black tree with information from an 13218af0f082STao Ma * inlined dir. It returns the number directory entries loaded 13228af0f082STao Ma * into the tree. If there is an error it is returned in err. 13238af0f082STao Ma */ 13248af0f082STao Ma int htree_inlinedir_to_tree(struct file *dir_file, 13258af0f082STao Ma struct inode *dir, ext4_lblk_t block, 13268af0f082STao Ma struct dx_hash_info *hinfo, 13278af0f082STao Ma __u32 start_hash, __u32 start_minor_hash, 13288af0f082STao Ma int *has_inline_data) 13298af0f082STao Ma { 13308af0f082STao Ma int err = 0, count = 0; 13318af0f082STao Ma unsigned int parent_ino; 13328af0f082STao Ma int pos; 13338af0f082STao Ma struct ext4_dir_entry_2 *de; 13348af0f082STao Ma struct inode *inode = file_inode(dir_file); 13358af0f082STao Ma int ret, inline_size = 0; 13368af0f082STao Ma struct ext4_iloc iloc; 13378af0f082STao Ma void *dir_buf = NULL; 13388af0f082STao Ma struct ext4_dir_entry_2 fake; 1339a7550b30SJaegeuk Kim struct fscrypt_str tmp_str; 13408af0f082STao Ma 13418af0f082STao Ma ret = ext4_get_inode_loc(inode, &iloc); 13428af0f082STao Ma if (ret) 13438af0f082STao Ma return ret; 13448af0f082STao Ma 13458af0f082STao Ma down_read(&EXT4_I(inode)->xattr_sem); 13468af0f082STao Ma if (!ext4_has_inline_data(inode)) { 13478af0f082STao Ma up_read(&EXT4_I(inode)->xattr_sem); 13488af0f082STao Ma *has_inline_data = 0; 13498af0f082STao Ma goto out; 13508af0f082STao Ma } 13518af0f082STao Ma 13528af0f082STao Ma inline_size = ext4_get_inline_size(inode); 13538af0f082STao Ma dir_buf = kmalloc(inline_size, GFP_NOFS); 13548af0f082STao Ma if (!dir_buf) { 13558af0f082STao Ma ret = -ENOMEM; 13568af0f082STao Ma up_read(&EXT4_I(inode)->xattr_sem); 13578af0f082STao Ma goto out; 13588af0f082STao Ma } 13598af0f082STao Ma 13608af0f082STao Ma ret = ext4_read_inline_data(inode, dir_buf, inline_size, &iloc); 13618af0f082STao Ma up_read(&EXT4_I(inode)->xattr_sem); 13628af0f082STao Ma if (ret < 0) 13638af0f082STao Ma goto out; 13648af0f082STao Ma 13658af0f082STao Ma pos = 0; 13668af0f082STao Ma parent_ino = le32_to_cpu(((struct ext4_dir_entry_2 *)dir_buf)->inode); 13678af0f082STao Ma while (pos < inline_size) { 13688af0f082STao Ma /* 13698af0f082STao Ma * As inlined dir doesn't store any information about '.' and 13708af0f082STao Ma * only the inode number of '..' is stored, we have to handle 13718af0f082STao Ma * them differently. 13728af0f082STao Ma */ 13738af0f082STao Ma if (pos == 0) { 13748af0f082STao Ma fake.inode = cpu_to_le32(inode->i_ino); 13758af0f082STao Ma fake.name_len = 1; 13768af0f082STao Ma strcpy(fake.name, "."); 13778af0f082STao Ma fake.rec_len = ext4_rec_len_to_disk( 13788af0f082STao Ma EXT4_DIR_REC_LEN(fake.name_len), 13798af0f082STao Ma inline_size); 13808af0f082STao Ma ext4_set_de_type(inode->i_sb, &fake, S_IFDIR); 13818af0f082STao Ma de = &fake; 13828af0f082STao Ma pos = EXT4_INLINE_DOTDOT_OFFSET; 13838af0f082STao Ma } else if (pos == EXT4_INLINE_DOTDOT_OFFSET) { 13848af0f082STao Ma fake.inode = cpu_to_le32(parent_ino); 13858af0f082STao Ma fake.name_len = 2; 13868af0f082STao Ma strcpy(fake.name, ".."); 13878af0f082STao Ma fake.rec_len = ext4_rec_len_to_disk( 13888af0f082STao Ma EXT4_DIR_REC_LEN(fake.name_len), 13898af0f082STao Ma inline_size); 13908af0f082STao Ma ext4_set_de_type(inode->i_sb, &fake, S_IFDIR); 13918af0f082STao Ma de = &fake; 13928af0f082STao Ma pos = EXT4_INLINE_DOTDOT_SIZE; 13938af0f082STao Ma } else { 13948af0f082STao Ma de = (struct ext4_dir_entry_2 *)(dir_buf + pos); 13958af0f082STao Ma pos += ext4_rec_len_from_disk(de->rec_len, inline_size); 13968af0f082STao Ma if (ext4_check_dir_entry(inode, dir_file, de, 13978af0f082STao Ma iloc.bh, dir_buf, 13988af0f082STao Ma inline_size, pos)) { 13998af0f082STao Ma ret = count; 14008af0f082STao Ma goto out; 14018af0f082STao Ma } 14028af0f082STao Ma } 14038af0f082STao Ma 14048af0f082STao Ma ext4fs_dirhash(de->name, de->name_len, hinfo); 14058af0f082STao Ma if ((hinfo->hash < start_hash) || 14068af0f082STao Ma ((hinfo->hash == start_hash) && 14078af0f082STao Ma (hinfo->minor_hash < start_minor_hash))) 14088af0f082STao Ma continue; 14098af0f082STao Ma if (de->inode == 0) 14108af0f082STao Ma continue; 14112f61830aSTheodore Ts'o tmp_str.name = de->name; 14122f61830aSTheodore Ts'o tmp_str.len = de->name_len; 14132f61830aSTheodore Ts'o err = ext4_htree_store_dirent(dir_file, hinfo->hash, 14142f61830aSTheodore Ts'o hinfo->minor_hash, de, &tmp_str); 14158af0f082STao Ma if (err) { 14168af0f082STao Ma count = err; 14178af0f082STao Ma goto out; 14188af0f082STao Ma } 14198af0f082STao Ma count++; 14208af0f082STao Ma } 14218af0f082STao Ma ret = count; 14228af0f082STao Ma out: 14238af0f082STao Ma kfree(dir_buf); 14248af0f082STao Ma brelse(iloc.bh); 14258af0f082STao Ma return ret; 14268af0f082STao Ma } 14278af0f082STao Ma 1428c4d8b023STao Ma /* 1429c4d8b023STao Ma * So this function is called when the volume is mkfsed with 1430c4d8b023STao Ma * dir_index disabled. In order to keep f_pos persistent 1431c4d8b023STao Ma * after we convert from an inlined dir to a blocked based, 1432c4d8b023STao Ma * we just pretend that we are a normal dir and return the 1433c4d8b023STao Ma * offset as if '.' and '..' really take place. 1434c4d8b023STao Ma * 1435c4d8b023STao Ma */ 1436725bebb2SAl Viro int ext4_read_inline_dir(struct file *file, 1437725bebb2SAl Viro struct dir_context *ctx, 143865d165d9STao Ma int *has_inline_data) 143965d165d9STao Ma { 144065d165d9STao Ma unsigned int offset, parent_ino; 1441725bebb2SAl Viro int i; 144265d165d9STao Ma struct ext4_dir_entry_2 *de; 144365d165d9STao Ma struct super_block *sb; 1444725bebb2SAl Viro struct inode *inode = file_inode(file); 144565d165d9STao Ma int ret, inline_size = 0; 144665d165d9STao Ma struct ext4_iloc iloc; 144765d165d9STao Ma void *dir_buf = NULL; 1448c4d8b023STao Ma int dotdot_offset, dotdot_size, extra_offset, extra_size; 144965d165d9STao Ma 145065d165d9STao Ma ret = ext4_get_inode_loc(inode, &iloc); 145165d165d9STao Ma if (ret) 145265d165d9STao Ma return ret; 145365d165d9STao Ma 145465d165d9STao Ma down_read(&EXT4_I(inode)->xattr_sem); 145565d165d9STao Ma if (!ext4_has_inline_data(inode)) { 145665d165d9STao Ma up_read(&EXT4_I(inode)->xattr_sem); 145765d165d9STao Ma *has_inline_data = 0; 145865d165d9STao Ma goto out; 145965d165d9STao Ma } 146065d165d9STao Ma 146165d165d9STao Ma inline_size = ext4_get_inline_size(inode); 146265d165d9STao Ma dir_buf = kmalloc(inline_size, GFP_NOFS); 146365d165d9STao Ma if (!dir_buf) { 146465d165d9STao Ma ret = -ENOMEM; 146565d165d9STao Ma up_read(&EXT4_I(inode)->xattr_sem); 146665d165d9STao Ma goto out; 146765d165d9STao Ma } 146865d165d9STao Ma 146965d165d9STao Ma ret = ext4_read_inline_data(inode, dir_buf, inline_size, &iloc); 147065d165d9STao Ma up_read(&EXT4_I(inode)->xattr_sem); 147165d165d9STao Ma if (ret < 0) 147265d165d9STao Ma goto out; 147365d165d9STao Ma 147448ffdab1SBoxiLiu ret = 0; 147565d165d9STao Ma sb = inode->i_sb; 147665d165d9STao Ma parent_ino = le32_to_cpu(((struct ext4_dir_entry_2 *)dir_buf)->inode); 1477725bebb2SAl Viro offset = ctx->pos; 147865d165d9STao Ma 1479c4d8b023STao Ma /* 1480c4d8b023STao Ma * dotdot_offset and dotdot_size is the real offset and 1481c4d8b023STao Ma * size for ".." and "." if the dir is block based while 1482c4d8b023STao Ma * the real size for them are only EXT4_INLINE_DOTDOT_SIZE. 1483c4d8b023STao Ma * So we will use extra_offset and extra_size to indicate them 1484c4d8b023STao Ma * during the inline dir iteration. 1485c4d8b023STao Ma */ 1486c4d8b023STao Ma dotdot_offset = EXT4_DIR_REC_LEN(1); 1487c4d8b023STao Ma dotdot_size = dotdot_offset + EXT4_DIR_REC_LEN(2); 1488c4d8b023STao Ma extra_offset = dotdot_size - EXT4_INLINE_DOTDOT_SIZE; 1489c4d8b023STao Ma extra_size = extra_offset + inline_size; 1490c4d8b023STao Ma 149165d165d9STao Ma /* 149265d165d9STao Ma * If the version has changed since the last call to 149365d165d9STao Ma * readdir(2), then we might be pointing to an invalid 149465d165d9STao Ma * dirent right now. Scan from the start of the inline 149565d165d9STao Ma * dir to make sure. 149665d165d9STao Ma */ 1497725bebb2SAl Viro if (file->f_version != inode->i_version) { 1498c4d8b023STao Ma for (i = 0; i < extra_size && i < offset;) { 1499c4d8b023STao Ma /* 1500c4d8b023STao Ma * "." is with offset 0 and 1501c4d8b023STao Ma * ".." is dotdot_offset. 1502c4d8b023STao Ma */ 150365d165d9STao Ma if (!i) { 1504c4d8b023STao Ma i = dotdot_offset; 1505c4d8b023STao Ma continue; 1506c4d8b023STao Ma } else if (i == dotdot_offset) { 1507c4d8b023STao Ma i = dotdot_size; 150865d165d9STao Ma continue; 150965d165d9STao Ma } 1510c4d8b023STao Ma /* for other entry, the real offset in 1511c4d8b023STao Ma * the buf has to be tuned accordingly. 1512c4d8b023STao Ma */ 151365d165d9STao Ma de = (struct ext4_dir_entry_2 *) 1514c4d8b023STao Ma (dir_buf + i - extra_offset); 151565d165d9STao Ma /* It's too expensive to do a full 151665d165d9STao Ma * dirent test each time round this 151765d165d9STao Ma * loop, but we do have to test at 151865d165d9STao Ma * least that it is non-zero. A 151965d165d9STao Ma * failure will be detected in the 152065d165d9STao Ma * dirent test below. */ 1521725bebb2SAl Viro if (ext4_rec_len_from_disk(de->rec_len, extra_size) 1522725bebb2SAl Viro < EXT4_DIR_REC_LEN(1)) 152365d165d9STao Ma break; 152465d165d9STao Ma i += ext4_rec_len_from_disk(de->rec_len, 1525c4d8b023STao Ma extra_size); 152665d165d9STao Ma } 152765d165d9STao Ma offset = i; 1528725bebb2SAl Viro ctx->pos = offset; 1529725bebb2SAl Viro file->f_version = inode->i_version; 153065d165d9STao Ma } 153165d165d9STao Ma 1532725bebb2SAl Viro while (ctx->pos < extra_size) { 1533725bebb2SAl Viro if (ctx->pos == 0) { 1534725bebb2SAl Viro if (!dir_emit(ctx, ".", 1, inode->i_ino, DT_DIR)) 1535725bebb2SAl Viro goto out; 1536725bebb2SAl Viro ctx->pos = dotdot_offset; 1537c4d8b023STao Ma continue; 1538c4d8b023STao Ma } 153965d165d9STao Ma 1540725bebb2SAl Viro if (ctx->pos == dotdot_offset) { 1541725bebb2SAl Viro if (!dir_emit(ctx, "..", 2, parent_ino, DT_DIR)) 1542725bebb2SAl Viro goto out; 1543725bebb2SAl Viro ctx->pos = dotdot_size; 154465d165d9STao Ma continue; 154565d165d9STao Ma } 154665d165d9STao Ma 1547c4d8b023STao Ma de = (struct ext4_dir_entry_2 *) 1548725bebb2SAl Viro (dir_buf + ctx->pos - extra_offset); 1549725bebb2SAl Viro if (ext4_check_dir_entry(inode, file, de, iloc.bh, dir_buf, 1550725bebb2SAl Viro extra_size, ctx->pos)) 1551725bebb2SAl Viro goto out; 1552725bebb2SAl Viro if (le32_to_cpu(de->inode)) { 1553725bebb2SAl Viro if (!dir_emit(ctx, de->name, de->name_len, 1554725bebb2SAl Viro le32_to_cpu(de->inode), 1555725bebb2SAl Viro get_dtype(sb, de->file_type))) 155665d165d9STao Ma goto out; 155765d165d9STao Ma } 1558725bebb2SAl Viro ctx->pos += ext4_rec_len_from_disk(de->rec_len, extra_size); 155965d165d9STao Ma } 156065d165d9STao Ma out: 156165d165d9STao Ma kfree(dir_buf); 156265d165d9STao Ma brelse(iloc.bh); 156365d165d9STao Ma return ret; 156465d165d9STao Ma } 156565d165d9STao Ma 156632f7f22cSTao Ma struct buffer_head *ext4_get_first_inline_block(struct inode *inode, 156732f7f22cSTao Ma struct ext4_dir_entry_2 **parent_de, 156832f7f22cSTao Ma int *retval) 156932f7f22cSTao Ma { 157032f7f22cSTao Ma struct ext4_iloc iloc; 157132f7f22cSTao Ma 157232f7f22cSTao Ma *retval = ext4_get_inode_loc(inode, &iloc); 157332f7f22cSTao Ma if (*retval) 157432f7f22cSTao Ma return NULL; 157532f7f22cSTao Ma 157632f7f22cSTao Ma *parent_de = (struct ext4_dir_entry_2 *)ext4_raw_inode(&iloc)->i_block; 157732f7f22cSTao Ma 157832f7f22cSTao Ma return iloc.bh; 157932f7f22cSTao Ma } 158032f7f22cSTao Ma 15813c47d541STao Ma /* 15823c47d541STao Ma * Try to create the inline data for the new dir. 15833c47d541STao Ma * If it succeeds, return 0, otherwise return the error. 15843c47d541STao Ma * In case of ENOSPC, the caller should create the normal disk layout dir. 15853c47d541STao Ma */ 15863c47d541STao Ma int ext4_try_create_inline_dir(handle_t *handle, struct inode *parent, 15873c47d541STao Ma struct inode *inode) 15883c47d541STao Ma { 15893c47d541STao Ma int ret, inline_size = EXT4_MIN_INLINE_DATA_SIZE; 15903c47d541STao Ma struct ext4_iloc iloc; 15913c47d541STao Ma struct ext4_dir_entry_2 *de; 15923c47d541STao Ma 15933c47d541STao Ma ret = ext4_get_inode_loc(inode, &iloc); 15943c47d541STao Ma if (ret) 15953c47d541STao Ma return ret; 15963c47d541STao Ma 15973c47d541STao Ma ret = ext4_prepare_inline_data(handle, inode, inline_size); 15983c47d541STao Ma if (ret) 15993c47d541STao Ma goto out; 16003c47d541STao Ma 16013c47d541STao Ma /* 16023c47d541STao Ma * For inline dir, we only save the inode information for the ".." 16033c47d541STao Ma * and create a fake dentry to cover the left space. 16043c47d541STao Ma */ 16053c47d541STao Ma de = (struct ext4_dir_entry_2 *)ext4_raw_inode(&iloc)->i_block; 16063c47d541STao Ma de->inode = cpu_to_le32(parent->i_ino); 16073c47d541STao Ma de = (struct ext4_dir_entry_2 *)((void *)de + EXT4_INLINE_DOTDOT_SIZE); 16083c47d541STao Ma de->inode = 0; 16093c47d541STao Ma de->rec_len = ext4_rec_len_to_disk( 16103c47d541STao Ma inline_size - EXT4_INLINE_DOTDOT_SIZE, 16113c47d541STao Ma inline_size); 16123c47d541STao Ma set_nlink(inode, 2); 16133c47d541STao Ma inode->i_size = EXT4_I(inode)->i_disksize = inline_size; 16143c47d541STao Ma out: 16153c47d541STao Ma brelse(iloc.bh); 16163c47d541STao Ma return ret; 16173c47d541STao Ma } 16183c47d541STao Ma 1619e8e948e7STao Ma struct buffer_head *ext4_find_inline_entry(struct inode *dir, 16205b643f9cSTheodore Ts'o struct ext4_filename *fname, 1621e8e948e7STao Ma const struct qstr *d_name, 1622e8e948e7STao Ma struct ext4_dir_entry_2 **res_dir, 1623e8e948e7STao Ma int *has_inline_data) 1624e8e948e7STao Ma { 1625e8e948e7STao Ma int ret; 1626e8e948e7STao Ma struct ext4_iloc iloc; 1627e8e948e7STao Ma void *inline_start; 1628e8e948e7STao Ma int inline_size; 1629e8e948e7STao Ma 1630e8e948e7STao Ma if (ext4_get_inode_loc(dir, &iloc)) 1631e8e948e7STao Ma return NULL; 1632e8e948e7STao Ma 1633e8e948e7STao Ma down_read(&EXT4_I(dir)->xattr_sem); 1634e8e948e7STao Ma if (!ext4_has_inline_data(dir)) { 1635e8e948e7STao Ma *has_inline_data = 0; 1636e8e948e7STao Ma goto out; 1637e8e948e7STao Ma } 1638e8e948e7STao Ma 1639e8e948e7STao Ma inline_start = (void *)ext4_raw_inode(&iloc)->i_block + 1640e8e948e7STao Ma EXT4_INLINE_DOTDOT_SIZE; 1641e8e948e7STao Ma inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE; 16425b643f9cSTheodore Ts'o ret = ext4_search_dir(iloc.bh, inline_start, inline_size, 16435b643f9cSTheodore Ts'o dir, fname, d_name, 0, res_dir); 1644e8e948e7STao Ma if (ret == 1) 1645e8e948e7STao Ma goto out_find; 1646e8e948e7STao Ma if (ret < 0) 1647e8e948e7STao Ma goto out; 1648e8e948e7STao Ma 1649e8e948e7STao Ma if (ext4_get_inline_size(dir) == EXT4_MIN_INLINE_DATA_SIZE) 1650e8e948e7STao Ma goto out; 1651e8e948e7STao Ma 1652e8e948e7STao Ma inline_start = ext4_get_inline_xattr_pos(dir, &iloc); 1653e8e948e7STao Ma inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE; 1654e8e948e7STao Ma 16555b643f9cSTheodore Ts'o ret = ext4_search_dir(iloc.bh, inline_start, inline_size, 16565b643f9cSTheodore Ts'o dir, fname, d_name, 0, res_dir); 1657e8e948e7STao Ma if (ret == 1) 1658e8e948e7STao Ma goto out_find; 1659e8e948e7STao Ma 1660e8e948e7STao Ma out: 1661e8e948e7STao Ma brelse(iloc.bh); 1662e8e948e7STao Ma iloc.bh = NULL; 1663e8e948e7STao Ma out_find: 1664e8e948e7STao Ma up_read(&EXT4_I(dir)->xattr_sem); 1665e8e948e7STao Ma return iloc.bh; 1666e8e948e7STao Ma } 1667e8e948e7STao Ma 16689f40fe54STao Ma int ext4_delete_inline_entry(handle_t *handle, 16699f40fe54STao Ma struct inode *dir, 16709f40fe54STao Ma struct ext4_dir_entry_2 *de_del, 16719f40fe54STao Ma struct buffer_head *bh, 16729f40fe54STao Ma int *has_inline_data) 16739f40fe54STao Ma { 1674c755e251STheodore Ts'o int err, inline_size, no_expand; 16759f40fe54STao Ma struct ext4_iloc iloc; 16769f40fe54STao Ma void *inline_start; 16779f40fe54STao Ma 16789f40fe54STao Ma err = ext4_get_inode_loc(dir, &iloc); 16799f40fe54STao Ma if (err) 16809f40fe54STao Ma return err; 16819f40fe54STao Ma 1682c755e251STheodore Ts'o ext4_write_lock_xattr(dir, &no_expand); 16839f40fe54STao Ma if (!ext4_has_inline_data(dir)) { 16849f40fe54STao Ma *has_inline_data = 0; 16859f40fe54STao Ma goto out; 16869f40fe54STao Ma } 16879f40fe54STao Ma 16889f40fe54STao Ma if ((void *)de_del - ((void *)ext4_raw_inode(&iloc)->i_block) < 16899f40fe54STao Ma EXT4_MIN_INLINE_DATA_SIZE) { 16909f40fe54STao Ma inline_start = (void *)ext4_raw_inode(&iloc)->i_block + 16919f40fe54STao Ma EXT4_INLINE_DOTDOT_SIZE; 16929f40fe54STao Ma inline_size = EXT4_MIN_INLINE_DATA_SIZE - 16939f40fe54STao Ma EXT4_INLINE_DOTDOT_SIZE; 16949f40fe54STao Ma } else { 16959f40fe54STao Ma inline_start = ext4_get_inline_xattr_pos(dir, &iloc); 16969f40fe54STao Ma inline_size = ext4_get_inline_size(dir) - 16979f40fe54STao Ma EXT4_MIN_INLINE_DATA_SIZE; 16989f40fe54STao Ma } 16999f40fe54STao Ma 17005d601255Sliang xie BUFFER_TRACE(bh, "get_write_access"); 17019f40fe54STao Ma err = ext4_journal_get_write_access(handle, bh); 17029f40fe54STao Ma if (err) 17039f40fe54STao Ma goto out; 17049f40fe54STao Ma 17059f40fe54STao Ma err = ext4_generic_delete_entry(handle, dir, de_del, bh, 17069f40fe54STao Ma inline_start, inline_size, 0); 17079f40fe54STao Ma if (err) 17089f40fe54STao Ma goto out; 17099f40fe54STao Ma 17109f40fe54STao Ma ext4_show_inline_dir(dir, iloc.bh, inline_start, inline_size); 17119f40fe54STao Ma out: 1712c755e251STheodore Ts'o ext4_write_unlock_xattr(dir, &no_expand); 1713*b907f2d5STheodore Ts'o if (likely(err == 0)) 1714*b907f2d5STheodore Ts'o err = ext4_mark_inode_dirty(handle, dir); 17159f40fe54STao Ma brelse(iloc.bh); 17169f40fe54STao Ma if (err != -ENOENT) 17179f40fe54STao Ma ext4_std_error(dir->i_sb, err); 17189f40fe54STao Ma return err; 17199f40fe54STao Ma } 17209f40fe54STao Ma 172161f86638STao Ma /* 172261f86638STao Ma * Get the inline dentry at offset. 172361f86638STao Ma */ 172461f86638STao Ma static inline struct ext4_dir_entry_2 * 172561f86638STao Ma ext4_get_inline_entry(struct inode *inode, 172661f86638STao Ma struct ext4_iloc *iloc, 172761f86638STao Ma unsigned int offset, 172861f86638STao Ma void **inline_start, 172961f86638STao Ma int *inline_size) 173061f86638STao Ma { 173161f86638STao Ma void *inline_pos; 173261f86638STao Ma 173361f86638STao Ma BUG_ON(offset > ext4_get_inline_size(inode)); 173461f86638STao Ma 173561f86638STao Ma if (offset < EXT4_MIN_INLINE_DATA_SIZE) { 173661f86638STao Ma inline_pos = (void *)ext4_raw_inode(iloc)->i_block; 173761f86638STao Ma *inline_size = EXT4_MIN_INLINE_DATA_SIZE; 173861f86638STao Ma } else { 173961f86638STao Ma inline_pos = ext4_get_inline_xattr_pos(inode, iloc); 174061f86638STao Ma offset -= EXT4_MIN_INLINE_DATA_SIZE; 174161f86638STao Ma *inline_size = ext4_get_inline_size(inode) - 174261f86638STao Ma EXT4_MIN_INLINE_DATA_SIZE; 174361f86638STao Ma } 174461f86638STao Ma 174561f86638STao Ma if (inline_start) 174661f86638STao Ma *inline_start = inline_pos; 174761f86638STao Ma return (struct ext4_dir_entry_2 *)(inline_pos + offset); 174861f86638STao Ma } 174961f86638STao Ma 1750a7550b30SJaegeuk Kim bool empty_inline_dir(struct inode *dir, int *has_inline_data) 175161f86638STao Ma { 175261f86638STao Ma int err, inline_size; 175361f86638STao Ma struct ext4_iloc iloc; 175461f86638STao Ma void *inline_pos; 175561f86638STao Ma unsigned int offset; 175661f86638STao Ma struct ext4_dir_entry_2 *de; 1757a7550b30SJaegeuk Kim bool ret = true; 175861f86638STao Ma 175961f86638STao Ma err = ext4_get_inode_loc(dir, &iloc); 176061f86638STao Ma if (err) { 176161f86638STao Ma EXT4_ERROR_INODE(dir, "error %d getting inode %lu block", 176261f86638STao Ma err, dir->i_ino); 1763a7550b30SJaegeuk Kim return true; 176461f86638STao Ma } 176561f86638STao Ma 176661f86638STao Ma down_read(&EXT4_I(dir)->xattr_sem); 176761f86638STao Ma if (!ext4_has_inline_data(dir)) { 176861f86638STao Ma *has_inline_data = 0; 176961f86638STao Ma goto out; 177061f86638STao Ma } 177161f86638STao Ma 177261f86638STao Ma de = (struct ext4_dir_entry_2 *)ext4_raw_inode(&iloc)->i_block; 177361f86638STao Ma if (!le32_to_cpu(de->inode)) { 177461f86638STao Ma ext4_warning(dir->i_sb, 177561f86638STao Ma "bad inline directory (dir #%lu) - no `..'", 177661f86638STao Ma dir->i_ino); 1777a7550b30SJaegeuk Kim ret = true; 177861f86638STao Ma goto out; 177961f86638STao Ma } 178061f86638STao Ma 178161f86638STao Ma offset = EXT4_INLINE_DOTDOT_SIZE; 178261f86638STao Ma while (offset < dir->i_size) { 178361f86638STao Ma de = ext4_get_inline_entry(dir, &iloc, offset, 178461f86638STao Ma &inline_pos, &inline_size); 178561f86638STao Ma if (ext4_check_dir_entry(dir, NULL, de, 178661f86638STao Ma iloc.bh, inline_pos, 178761f86638STao Ma inline_size, offset)) { 178861f86638STao Ma ext4_warning(dir->i_sb, 178961f86638STao Ma "bad inline directory (dir #%lu) - " 179061f86638STao Ma "inode %u, rec_len %u, name_len %d" 17918d2ae1cbSJakub Wilk "inline size %d", 179261f86638STao Ma dir->i_ino, le32_to_cpu(de->inode), 179361f86638STao Ma le16_to_cpu(de->rec_len), de->name_len, 179461f86638STao Ma inline_size); 1795a7550b30SJaegeuk Kim ret = true; 179661f86638STao Ma goto out; 179761f86638STao Ma } 179861f86638STao Ma if (le32_to_cpu(de->inode)) { 1799a7550b30SJaegeuk Kim ret = false; 180061f86638STao Ma goto out; 180161f86638STao Ma } 180261f86638STao Ma offset += ext4_rec_len_from_disk(de->rec_len, inline_size); 180361f86638STao Ma } 180461f86638STao Ma 180561f86638STao Ma out: 180661f86638STao Ma up_read(&EXT4_I(dir)->xattr_sem); 180761f86638STao Ma brelse(iloc.bh); 180861f86638STao Ma return ret; 180961f86638STao Ma } 181061f86638STao Ma 181167cf5b09STao Ma int ext4_destroy_inline_data(handle_t *handle, struct inode *inode) 181267cf5b09STao Ma { 1813c755e251STheodore Ts'o int ret, no_expand; 181467cf5b09STao Ma 1815c755e251STheodore Ts'o ext4_write_lock_xattr(inode, &no_expand); 181667cf5b09STao Ma ret = ext4_destroy_inline_data_nolock(handle, inode); 1817c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 181867cf5b09STao Ma 181967cf5b09STao Ma return ret; 182067cf5b09STao Ma } 182194191985STao Ma 182294191985STao Ma int ext4_inline_data_fiemap(struct inode *inode, 182394191985STao Ma struct fiemap_extent_info *fieinfo, 1824d952d69eSDmitry Monakhov int *has_inline, __u64 start, __u64 len) 182594191985STao Ma { 182694191985STao Ma __u64 physical = 0; 1827d952d69eSDmitry Monakhov __u64 inline_len; 1828d952d69eSDmitry Monakhov __u32 flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED | 1829d952d69eSDmitry Monakhov FIEMAP_EXTENT_LAST; 183094191985STao Ma int error = 0; 183194191985STao Ma struct ext4_iloc iloc; 183294191985STao Ma 183394191985STao Ma down_read(&EXT4_I(inode)->xattr_sem); 183494191985STao Ma if (!ext4_has_inline_data(inode)) { 183594191985STao Ma *has_inline = 0; 183694191985STao Ma goto out; 183794191985STao Ma } 1838d952d69eSDmitry Monakhov inline_len = min_t(size_t, ext4_get_inline_size(inode), 1839d952d69eSDmitry Monakhov i_size_read(inode)); 1840d952d69eSDmitry Monakhov if (start >= inline_len) 1841d952d69eSDmitry Monakhov goto out; 1842d952d69eSDmitry Monakhov if (start + len < inline_len) 1843d952d69eSDmitry Monakhov inline_len = start + len; 1844d952d69eSDmitry Monakhov inline_len -= start; 184594191985STao Ma 184694191985STao Ma error = ext4_get_inode_loc(inode, &iloc); 184794191985STao Ma if (error) 184894191985STao Ma goto out; 184994191985STao Ma 1850eaf37937SJan Kara physical = (__u64)iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits; 185194191985STao Ma physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data; 185294191985STao Ma physical += offsetof(struct ext4_inode, i_block); 185394191985STao Ma 185494191985STao Ma if (physical) 1855d952d69eSDmitry Monakhov error = fiemap_fill_next_extent(fieinfo, start, physical, 1856d952d69eSDmitry Monakhov inline_len, flags); 185794191985STao Ma brelse(iloc.bh); 185894191985STao Ma out: 185994191985STao Ma up_read(&EXT4_I(inode)->xattr_sem); 186094191985STao Ma return (error < 0 ? error : 0); 186194191985STao Ma } 18620d812f77STao Ma 18630d812f77STao Ma /* 18640d812f77STao Ma * Called during xattr set, and if we can sparse space 'needed', 18650d812f77STao Ma * just create the extent tree evict the data to the outer block. 18660d812f77STao Ma * 18670d812f77STao Ma * We use jbd2 instead of page cache to move data to the 1st block 18680d812f77STao Ma * so that the whole transaction can be committed as a whole and 18690d812f77STao Ma * the data isn't lost because of the delayed page cache write. 18700d812f77STao Ma */ 18710d812f77STao Ma int ext4_try_to_evict_inline_data(handle_t *handle, 18720d812f77STao Ma struct inode *inode, 18730d812f77STao Ma int needed) 18740d812f77STao Ma { 18750d812f77STao Ma int error; 18760d812f77STao Ma struct ext4_xattr_entry *entry; 18770d812f77STao Ma struct ext4_inode *raw_inode; 18780d812f77STao Ma struct ext4_iloc iloc; 18790d812f77STao Ma 18800d812f77STao Ma error = ext4_get_inode_loc(inode, &iloc); 18810d812f77STao Ma if (error) 18820d812f77STao Ma return error; 18830d812f77STao Ma 18840d812f77STao Ma raw_inode = ext4_raw_inode(&iloc); 18850d812f77STao Ma entry = (struct ext4_xattr_entry *)((void *)raw_inode + 18860d812f77STao Ma EXT4_I(inode)->i_inline_off); 18870d812f77STao Ma if (EXT4_XATTR_LEN(entry->e_name_len) + 18880d812f77STao Ma EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)) < needed) { 18890d812f77STao Ma error = -ENOSPC; 18900d812f77STao Ma goto out; 18910d812f77STao Ma } 18920d812f77STao Ma 18930d812f77STao Ma error = ext4_convert_inline_data_nolock(handle, inode, &iloc); 18940d812f77STao Ma out: 18950d812f77STao Ma brelse(iloc.bh); 18960d812f77STao Ma return error; 18970d812f77STao Ma } 1898aef1c851STao Ma 1899aef1c851STao Ma void ext4_inline_data_truncate(struct inode *inode, int *has_inline) 1900aef1c851STao Ma { 1901aef1c851STao Ma handle_t *handle; 1902c755e251STheodore Ts'o int inline_size, value_len, needed_blocks, no_expand; 1903aef1c851STao Ma size_t i_size; 1904aef1c851STao Ma void *value = NULL; 1905aef1c851STao Ma struct ext4_xattr_ibody_find is = { 1906aef1c851STao Ma .s = { .not_found = -ENODATA, }, 1907aef1c851STao Ma }; 1908aef1c851STao Ma struct ext4_xattr_info i = { 1909aef1c851STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 1910aef1c851STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 1911aef1c851STao Ma }; 1912aef1c851STao Ma 1913aef1c851STao Ma 1914aef1c851STao Ma needed_blocks = ext4_writepage_trans_blocks(inode); 19159924a92aSTheodore Ts'o handle = ext4_journal_start(inode, EXT4_HT_INODE, needed_blocks); 1916aef1c851STao Ma if (IS_ERR(handle)) 1917aef1c851STao Ma return; 1918aef1c851STao Ma 1919c755e251STheodore Ts'o ext4_write_lock_xattr(inode, &no_expand); 1920aef1c851STao Ma if (!ext4_has_inline_data(inode)) { 1921aef1c851STao Ma *has_inline = 0; 1922aef1c851STao Ma ext4_journal_stop(handle); 1923aef1c851STao Ma return; 1924aef1c851STao Ma } 1925aef1c851STao Ma 1926aef1c851STao Ma if (ext4_orphan_add(handle, inode)) 1927aef1c851STao Ma goto out; 1928aef1c851STao Ma 1929aef1c851STao Ma if (ext4_get_inode_loc(inode, &is.iloc)) 1930aef1c851STao Ma goto out; 1931aef1c851STao Ma 1932aef1c851STao Ma down_write(&EXT4_I(inode)->i_data_sem); 1933aef1c851STao Ma i_size = inode->i_size; 1934aef1c851STao Ma inline_size = ext4_get_inline_size(inode); 1935aef1c851STao Ma EXT4_I(inode)->i_disksize = i_size; 1936aef1c851STao Ma 1937aef1c851STao Ma if (i_size < inline_size) { 1938aef1c851STao Ma /* Clear the content in the xattr space. */ 1939aef1c851STao Ma if (inline_size > EXT4_MIN_INLINE_DATA_SIZE) { 1940aef1c851STao Ma if (ext4_xattr_ibody_find(inode, &i, &is)) 1941aef1c851STao Ma goto out_error; 1942aef1c851STao Ma 1943aef1c851STao Ma BUG_ON(is.s.not_found); 1944aef1c851STao Ma 1945aef1c851STao Ma value_len = le32_to_cpu(is.s.here->e_value_size); 1946aef1c851STao Ma value = kmalloc(value_len, GFP_NOFS); 1947aef1c851STao Ma if (!value) 1948aef1c851STao Ma goto out_error; 1949aef1c851STao Ma 1950aef1c851STao Ma if (ext4_xattr_ibody_get(inode, i.name_index, i.name, 1951aef1c851STao Ma value, value_len)) 1952aef1c851STao Ma goto out_error; 1953aef1c851STao Ma 1954aef1c851STao Ma i.value = value; 1955aef1c851STao Ma i.value_len = i_size > EXT4_MIN_INLINE_DATA_SIZE ? 1956aef1c851STao Ma i_size - EXT4_MIN_INLINE_DATA_SIZE : 0; 1957aef1c851STao Ma if (ext4_xattr_ibody_inline_set(handle, inode, &i, &is)) 1958aef1c851STao Ma goto out_error; 1959aef1c851STao Ma } 1960aef1c851STao Ma 1961aef1c851STao Ma /* Clear the content within i_blocks. */ 196209c455aaSTheodore Ts'o if (i_size < EXT4_MIN_INLINE_DATA_SIZE) { 196309c455aaSTheodore Ts'o void *p = (void *) ext4_raw_inode(&is.iloc)->i_block; 196409c455aaSTheodore Ts'o memset(p + i_size, 0, 1965aef1c851STao Ma EXT4_MIN_INLINE_DATA_SIZE - i_size); 196609c455aaSTheodore Ts'o } 1967aef1c851STao Ma 1968aef1c851STao Ma EXT4_I(inode)->i_inline_size = i_size < 1969aef1c851STao Ma EXT4_MIN_INLINE_DATA_SIZE ? 1970aef1c851STao Ma EXT4_MIN_INLINE_DATA_SIZE : i_size; 1971aef1c851STao Ma } 1972aef1c851STao Ma 1973aef1c851STao Ma out_error: 1974aef1c851STao Ma up_write(&EXT4_I(inode)->i_data_sem); 1975aef1c851STao Ma out: 1976aef1c851STao Ma brelse(is.iloc.bh); 1977c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 1978aef1c851STao Ma kfree(value); 1979aef1c851STao Ma if (inode->i_nlink) 1980aef1c851STao Ma ext4_orphan_del(handle, inode); 1981aef1c851STao Ma 1982eeca7ea1SDeepa Dinamani inode->i_mtime = inode->i_ctime = current_time(inode); 1983aef1c851STao Ma ext4_mark_inode_dirty(handle, inode); 1984aef1c851STao Ma if (IS_SYNC(inode)) 1985aef1c851STao Ma ext4_handle_sync(handle); 1986aef1c851STao Ma 1987aef1c851STao Ma ext4_journal_stop(handle); 1988aef1c851STao Ma return; 1989aef1c851STao Ma } 19900c8d414fSTao Ma 19910c8d414fSTao Ma int ext4_convert_inline_data(struct inode *inode) 19920c8d414fSTao Ma { 1993c755e251STheodore Ts'o int error, needed_blocks, no_expand; 19940c8d414fSTao Ma handle_t *handle; 19950c8d414fSTao Ma struct ext4_iloc iloc; 19960c8d414fSTao Ma 19970c8d414fSTao Ma if (!ext4_has_inline_data(inode)) { 19980c8d414fSTao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 19990c8d414fSTao Ma return 0; 20000c8d414fSTao Ma } 20010c8d414fSTao Ma 20020c8d414fSTao Ma needed_blocks = ext4_writepage_trans_blocks(inode); 20030c8d414fSTao Ma 20040c8d414fSTao Ma iloc.bh = NULL; 20050c8d414fSTao Ma error = ext4_get_inode_loc(inode, &iloc); 20060c8d414fSTao Ma if (error) 20070c8d414fSTao Ma return error; 20080c8d414fSTao Ma 20099924a92aSTheodore Ts'o handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, needed_blocks); 20100c8d414fSTao Ma if (IS_ERR(handle)) { 20110c8d414fSTao Ma error = PTR_ERR(handle); 20120c8d414fSTao Ma goto out_free; 20130c8d414fSTao Ma } 20140c8d414fSTao Ma 2015c755e251STheodore Ts'o ext4_write_lock_xattr(inode, &no_expand); 2016c755e251STheodore Ts'o if (ext4_has_inline_data(inode)) 20170c8d414fSTao Ma error = ext4_convert_inline_data_nolock(handle, inode, &iloc); 2018c755e251STheodore Ts'o ext4_write_unlock_xattr(inode, &no_expand); 20190c8d414fSTao Ma ext4_journal_stop(handle); 20200c8d414fSTao Ma out_free: 20210c8d414fSTao Ma brelse(iloc.bh); 20220c8d414fSTao Ma return error; 20230c8d414fSTao Ma } 2024