167cf5b09STao Ma /* 267cf5b09STao Ma * Copyright (c) 2012 Taobao. 367cf5b09STao Ma * Written by Tao Ma <boyu.mt@taobao.com> 467cf5b09STao Ma * 567cf5b09STao Ma * This program is free software; you can redistribute it and/or modify it 667cf5b09STao Ma * under the terms of version 2.1 of the GNU Lesser General Public License 767cf5b09STao Ma * as published by the Free Software Foundation. 867cf5b09STao Ma * 967cf5b09STao Ma * This program is distributed in the hope that it will be useful, 1067cf5b09STao Ma * but WITHOUT ANY WARRANTY; without even the implied warranty of 1167cf5b09STao Ma * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1267cf5b09STao Ma * GNU General Public License for more details. 1367cf5b09STao Ma */ 1467cf5b09STao Ma #include "ext4_jbd2.h" 1567cf5b09STao Ma #include "ext4.h" 1667cf5b09STao Ma #include "xattr.h" 17f19d5870STao Ma #include "truncate.h" 1894191985STao Ma #include <linux/fiemap.h> 1967cf5b09STao Ma 2067cf5b09STao Ma #define EXT4_XATTR_SYSTEM_DATA "data" 2167cf5b09STao Ma #define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS)) 228af0f082STao Ma #define EXT4_INLINE_DOTDOT_OFFSET 2 233c47d541STao Ma #define EXT4_INLINE_DOTDOT_SIZE 4 2467cf5b09STao Ma 2567cf5b09STao Ma int ext4_get_inline_size(struct inode *inode) 2667cf5b09STao Ma { 2767cf5b09STao Ma if (EXT4_I(inode)->i_inline_off) 2867cf5b09STao Ma return EXT4_I(inode)->i_inline_size; 2967cf5b09STao Ma 3067cf5b09STao Ma return 0; 3167cf5b09STao Ma } 3267cf5b09STao Ma 3367cf5b09STao Ma static int get_max_inline_xattr_value_size(struct inode *inode, 3467cf5b09STao Ma struct ext4_iloc *iloc) 3567cf5b09STao Ma { 3667cf5b09STao Ma struct ext4_xattr_ibody_header *header; 3767cf5b09STao Ma struct ext4_xattr_entry *entry; 3867cf5b09STao Ma struct ext4_inode *raw_inode; 3967cf5b09STao Ma int free, min_offs; 4067cf5b09STao Ma 4167cf5b09STao Ma min_offs = EXT4_SB(inode->i_sb)->s_inode_size - 4267cf5b09STao Ma EXT4_GOOD_OLD_INODE_SIZE - 4367cf5b09STao Ma EXT4_I(inode)->i_extra_isize - 4467cf5b09STao Ma sizeof(struct ext4_xattr_ibody_header); 4567cf5b09STao Ma 4667cf5b09STao Ma /* 4767cf5b09STao Ma * We need to subtract another sizeof(__u32) since an in-inode xattr 4867cf5b09STao Ma * needs an empty 4 bytes to indicate the gap between the xattr entry 4967cf5b09STao Ma * and the name/value pair. 5067cf5b09STao Ma */ 5167cf5b09STao Ma if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR)) 5267cf5b09STao Ma return EXT4_XATTR_SIZE(min_offs - 5367cf5b09STao Ma EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA)) - 5467cf5b09STao Ma EXT4_XATTR_ROUND - sizeof(__u32)); 5567cf5b09STao Ma 5667cf5b09STao Ma raw_inode = ext4_raw_inode(iloc); 5767cf5b09STao Ma header = IHDR(inode, raw_inode); 5867cf5b09STao Ma entry = IFIRST(header); 5967cf5b09STao Ma 6067cf5b09STao Ma /* Compute min_offs. */ 6167cf5b09STao Ma for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { 6267cf5b09STao Ma if (!entry->e_value_block && entry->e_value_size) { 6367cf5b09STao Ma size_t offs = le16_to_cpu(entry->e_value_offs); 6467cf5b09STao Ma if (offs < min_offs) 6567cf5b09STao Ma min_offs = offs; 6667cf5b09STao Ma } 6767cf5b09STao Ma } 6867cf5b09STao Ma free = min_offs - 6967cf5b09STao Ma ((void *)entry - (void *)IFIRST(header)) - sizeof(__u32); 7067cf5b09STao Ma 7167cf5b09STao Ma if (EXT4_I(inode)->i_inline_off) { 7267cf5b09STao Ma entry = (struct ext4_xattr_entry *) 7367cf5b09STao Ma ((void *)raw_inode + EXT4_I(inode)->i_inline_off); 7467cf5b09STao Ma 75*c4932dbeSboxi liu free += EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)); 7667cf5b09STao Ma goto out; 7767cf5b09STao Ma } 7867cf5b09STao Ma 7967cf5b09STao Ma free -= EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA)); 8067cf5b09STao Ma 8167cf5b09STao Ma if (free > EXT4_XATTR_ROUND) 8267cf5b09STao Ma free = EXT4_XATTR_SIZE(free - EXT4_XATTR_ROUND); 8367cf5b09STao Ma else 8467cf5b09STao Ma free = 0; 8567cf5b09STao Ma 8667cf5b09STao Ma out: 8767cf5b09STao Ma return free; 8867cf5b09STao Ma } 8967cf5b09STao Ma 9067cf5b09STao Ma /* 9167cf5b09STao Ma * Get the maximum size we now can store in an inode. 9267cf5b09STao Ma * If we can't find the space for a xattr entry, don't use the space 9367cf5b09STao Ma * of the extents since we have no space to indicate the inline data. 9467cf5b09STao Ma */ 9567cf5b09STao Ma int ext4_get_max_inline_size(struct inode *inode) 9667cf5b09STao Ma { 9767cf5b09STao Ma int error, max_inline_size; 9867cf5b09STao Ma struct ext4_iloc iloc; 9967cf5b09STao Ma 10067cf5b09STao Ma if (EXT4_I(inode)->i_extra_isize == 0) 10167cf5b09STao Ma return 0; 10267cf5b09STao Ma 10367cf5b09STao Ma error = ext4_get_inode_loc(inode, &iloc); 10467cf5b09STao Ma if (error) { 10567cf5b09STao Ma ext4_error_inode(inode, __func__, __LINE__, 0, 10667cf5b09STao Ma "can't get inode location %lu", 10767cf5b09STao Ma inode->i_ino); 10867cf5b09STao Ma return 0; 10967cf5b09STao Ma } 11067cf5b09STao Ma 11167cf5b09STao Ma down_read(&EXT4_I(inode)->xattr_sem); 11267cf5b09STao Ma max_inline_size = get_max_inline_xattr_value_size(inode, &iloc); 11367cf5b09STao Ma up_read(&EXT4_I(inode)->xattr_sem); 11467cf5b09STao Ma 11567cf5b09STao Ma brelse(iloc.bh); 11667cf5b09STao Ma 11767cf5b09STao Ma if (!max_inline_size) 11867cf5b09STao Ma return 0; 11967cf5b09STao Ma 12067cf5b09STao Ma return max_inline_size + EXT4_MIN_INLINE_DATA_SIZE; 12167cf5b09STao Ma } 12267cf5b09STao Ma 12367cf5b09STao Ma int ext4_has_inline_data(struct inode *inode) 12467cf5b09STao Ma { 12567cf5b09STao Ma return ext4_test_inode_flag(inode, EXT4_INODE_INLINE_DATA) && 12667cf5b09STao Ma EXT4_I(inode)->i_inline_off; 12767cf5b09STao Ma } 12867cf5b09STao Ma 12967cf5b09STao Ma /* 13067cf5b09STao Ma * this function does not take xattr_sem, which is OK because it is 13167cf5b09STao Ma * currently only used in a code path coming form ext4_iget, before 13267cf5b09STao Ma * the new inode has been unlocked 13367cf5b09STao Ma */ 13467cf5b09STao Ma int ext4_find_inline_data_nolock(struct inode *inode) 13567cf5b09STao Ma { 13667cf5b09STao Ma struct ext4_xattr_ibody_find is = { 13767cf5b09STao Ma .s = { .not_found = -ENODATA, }, 13867cf5b09STao Ma }; 13967cf5b09STao Ma struct ext4_xattr_info i = { 14067cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 14167cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 14267cf5b09STao Ma }; 14367cf5b09STao Ma int error; 14467cf5b09STao Ma 14567cf5b09STao Ma if (EXT4_I(inode)->i_extra_isize == 0) 14667cf5b09STao Ma return 0; 14767cf5b09STao Ma 14867cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 14967cf5b09STao Ma if (error) 15067cf5b09STao Ma return error; 15167cf5b09STao Ma 15267cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 15367cf5b09STao Ma if (error) 15467cf5b09STao Ma goto out; 15567cf5b09STao Ma 15667cf5b09STao Ma if (!is.s.not_found) { 15767cf5b09STao Ma EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here - 15867cf5b09STao Ma (void *)ext4_raw_inode(&is.iloc)); 15967cf5b09STao Ma EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE + 16067cf5b09STao Ma le32_to_cpu(is.s.here->e_value_size); 16167cf5b09STao Ma ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 16267cf5b09STao Ma } 16367cf5b09STao Ma out: 16467cf5b09STao Ma brelse(is.iloc.bh); 16567cf5b09STao Ma return error; 16667cf5b09STao Ma } 16767cf5b09STao Ma 16867cf5b09STao Ma static int ext4_read_inline_data(struct inode *inode, void *buffer, 16967cf5b09STao Ma unsigned int len, 17067cf5b09STao Ma struct ext4_iloc *iloc) 17167cf5b09STao Ma { 17267cf5b09STao Ma struct ext4_xattr_entry *entry; 17367cf5b09STao Ma struct ext4_xattr_ibody_header *header; 17467cf5b09STao Ma int cp_len = 0; 17567cf5b09STao Ma struct ext4_inode *raw_inode; 17667cf5b09STao Ma 17767cf5b09STao Ma if (!len) 17867cf5b09STao Ma return 0; 17967cf5b09STao Ma 18067cf5b09STao Ma BUG_ON(len > EXT4_I(inode)->i_inline_size); 18167cf5b09STao Ma 18267cf5b09STao Ma cp_len = len < EXT4_MIN_INLINE_DATA_SIZE ? 18367cf5b09STao Ma len : EXT4_MIN_INLINE_DATA_SIZE; 18467cf5b09STao Ma 18567cf5b09STao Ma raw_inode = ext4_raw_inode(iloc); 18667cf5b09STao Ma memcpy(buffer, (void *)(raw_inode->i_block), cp_len); 18767cf5b09STao Ma 18867cf5b09STao Ma len -= cp_len; 18967cf5b09STao Ma buffer += cp_len; 19067cf5b09STao Ma 19167cf5b09STao Ma if (!len) 19267cf5b09STao Ma goto out; 19367cf5b09STao Ma 19467cf5b09STao Ma header = IHDR(inode, raw_inode); 19567cf5b09STao Ma entry = (struct ext4_xattr_entry *)((void *)raw_inode + 19667cf5b09STao Ma EXT4_I(inode)->i_inline_off); 19767cf5b09STao Ma len = min_t(unsigned int, len, 19867cf5b09STao Ma (unsigned int)le32_to_cpu(entry->e_value_size)); 19967cf5b09STao Ma 20067cf5b09STao Ma memcpy(buffer, 20167cf5b09STao Ma (void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs), len); 20267cf5b09STao Ma cp_len += len; 20367cf5b09STao Ma 20467cf5b09STao Ma out: 20567cf5b09STao Ma return cp_len; 20667cf5b09STao Ma } 20767cf5b09STao Ma 20867cf5b09STao Ma /* 20967cf5b09STao Ma * write the buffer to the inline inode. 21067cf5b09STao Ma * If 'create' is set, we don't need to do the extra copy in the xattr 2110d812f77STao Ma * value since it is already handled by ext4_xattr_ibody_inline_set. 2120d812f77STao Ma * That saves us one memcpy. 21367cf5b09STao Ma */ 21467cf5b09STao Ma void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc, 21567cf5b09STao Ma void *buffer, loff_t pos, unsigned int len) 21667cf5b09STao Ma { 21767cf5b09STao Ma struct ext4_xattr_entry *entry; 21867cf5b09STao Ma struct ext4_xattr_ibody_header *header; 21967cf5b09STao Ma struct ext4_inode *raw_inode; 22067cf5b09STao Ma int cp_len = 0; 22167cf5b09STao Ma 22267cf5b09STao Ma BUG_ON(!EXT4_I(inode)->i_inline_off); 22367cf5b09STao Ma BUG_ON(pos + len > EXT4_I(inode)->i_inline_size); 22467cf5b09STao Ma 22567cf5b09STao Ma raw_inode = ext4_raw_inode(iloc); 22667cf5b09STao Ma buffer += pos; 22767cf5b09STao Ma 22867cf5b09STao Ma if (pos < EXT4_MIN_INLINE_DATA_SIZE) { 22967cf5b09STao Ma cp_len = pos + len > EXT4_MIN_INLINE_DATA_SIZE ? 23067cf5b09STao Ma EXT4_MIN_INLINE_DATA_SIZE - pos : len; 23167cf5b09STao Ma memcpy((void *)raw_inode->i_block + pos, buffer, cp_len); 23267cf5b09STao Ma 23367cf5b09STao Ma len -= cp_len; 23467cf5b09STao Ma buffer += cp_len; 23567cf5b09STao Ma pos += cp_len; 23667cf5b09STao Ma } 23767cf5b09STao Ma 23867cf5b09STao Ma if (!len) 23967cf5b09STao Ma return; 24067cf5b09STao Ma 24167cf5b09STao Ma pos -= EXT4_MIN_INLINE_DATA_SIZE; 24267cf5b09STao Ma header = IHDR(inode, raw_inode); 24367cf5b09STao Ma entry = (struct ext4_xattr_entry *)((void *)raw_inode + 24467cf5b09STao Ma EXT4_I(inode)->i_inline_off); 24567cf5b09STao Ma 24667cf5b09STao Ma memcpy((void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs) + pos, 24767cf5b09STao Ma buffer, len); 24867cf5b09STao Ma } 24967cf5b09STao Ma 25067cf5b09STao Ma static int ext4_create_inline_data(handle_t *handle, 25167cf5b09STao Ma struct inode *inode, unsigned len) 25267cf5b09STao Ma { 25367cf5b09STao Ma int error; 25467cf5b09STao Ma void *value = NULL; 25567cf5b09STao Ma struct ext4_xattr_ibody_find is = { 25667cf5b09STao Ma .s = { .not_found = -ENODATA, }, 25767cf5b09STao Ma }; 25867cf5b09STao Ma struct ext4_xattr_info i = { 25967cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 26067cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 26167cf5b09STao Ma }; 26267cf5b09STao Ma 26367cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 26467cf5b09STao Ma if (error) 26567cf5b09STao Ma return error; 26667cf5b09STao Ma 26767cf5b09STao Ma error = ext4_journal_get_write_access(handle, is.iloc.bh); 26867cf5b09STao Ma if (error) 26967cf5b09STao Ma goto out; 27067cf5b09STao Ma 27167cf5b09STao Ma if (len > EXT4_MIN_INLINE_DATA_SIZE) { 272bd9926e8STheodore Ts'o value = EXT4_ZERO_XATTR_VALUE; 27367cf5b09STao Ma len -= EXT4_MIN_INLINE_DATA_SIZE; 27467cf5b09STao Ma } else { 27567cf5b09STao Ma value = ""; 27667cf5b09STao Ma len = 0; 27767cf5b09STao Ma } 27867cf5b09STao Ma 27967cf5b09STao Ma /* Insert the the xttr entry. */ 28067cf5b09STao Ma i.value = value; 28167cf5b09STao Ma i.value_len = len; 28267cf5b09STao Ma 28367cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 28467cf5b09STao Ma if (error) 28567cf5b09STao Ma goto out; 28667cf5b09STao Ma 28767cf5b09STao Ma BUG_ON(!is.s.not_found); 28867cf5b09STao Ma 2890d812f77STao Ma error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); 29067cf5b09STao Ma if (error) { 29167cf5b09STao Ma if (error == -ENOSPC) 29267cf5b09STao Ma ext4_clear_inode_state(inode, 29367cf5b09STao Ma EXT4_STATE_MAY_INLINE_DATA); 29467cf5b09STao Ma goto out; 29567cf5b09STao Ma } 29667cf5b09STao Ma 29767cf5b09STao Ma memset((void *)ext4_raw_inode(&is.iloc)->i_block, 29867cf5b09STao Ma 0, EXT4_MIN_INLINE_DATA_SIZE); 29967cf5b09STao Ma 30067cf5b09STao Ma EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here - 30167cf5b09STao Ma (void *)ext4_raw_inode(&is.iloc)); 30267cf5b09STao Ma EXT4_I(inode)->i_inline_size = len + EXT4_MIN_INLINE_DATA_SIZE; 30367cf5b09STao Ma ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS); 30467cf5b09STao Ma ext4_set_inode_flag(inode, EXT4_INODE_INLINE_DATA); 30567cf5b09STao Ma get_bh(is.iloc.bh); 30667cf5b09STao Ma error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); 30767cf5b09STao Ma 30867cf5b09STao Ma out: 30967cf5b09STao Ma brelse(is.iloc.bh); 31067cf5b09STao Ma return error; 31167cf5b09STao Ma } 31267cf5b09STao Ma 31367cf5b09STao Ma static int ext4_update_inline_data(handle_t *handle, struct inode *inode, 31467cf5b09STao Ma unsigned int len) 31567cf5b09STao Ma { 31667cf5b09STao Ma int error; 31767cf5b09STao Ma void *value = NULL; 31867cf5b09STao Ma struct ext4_xattr_ibody_find is = { 31967cf5b09STao Ma .s = { .not_found = -ENODATA, }, 32067cf5b09STao Ma }; 32167cf5b09STao Ma struct ext4_xattr_info i = { 32267cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 32367cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 32467cf5b09STao Ma }; 32567cf5b09STao Ma 32667cf5b09STao Ma /* If the old space is ok, write the data directly. */ 32767cf5b09STao Ma if (len <= EXT4_I(inode)->i_inline_size) 32867cf5b09STao Ma return 0; 32967cf5b09STao Ma 33067cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 33167cf5b09STao Ma if (error) 33267cf5b09STao Ma return error; 33367cf5b09STao Ma 33467cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 33567cf5b09STao Ma if (error) 33667cf5b09STao Ma goto out; 33767cf5b09STao Ma 33867cf5b09STao Ma BUG_ON(is.s.not_found); 33967cf5b09STao Ma 34067cf5b09STao Ma len -= EXT4_MIN_INLINE_DATA_SIZE; 34167cf5b09STao Ma value = kzalloc(len, GFP_NOFS); 34267cf5b09STao Ma if (!value) 34367cf5b09STao Ma goto out; 34467cf5b09STao Ma 34567cf5b09STao Ma error = ext4_xattr_ibody_get(inode, i.name_index, i.name, 34667cf5b09STao Ma value, len); 34767cf5b09STao Ma if (error == -ENODATA) 34867cf5b09STao Ma goto out; 34967cf5b09STao Ma 35067cf5b09STao Ma error = ext4_journal_get_write_access(handle, is.iloc.bh); 35167cf5b09STao Ma if (error) 35267cf5b09STao Ma goto out; 35367cf5b09STao Ma 35467cf5b09STao Ma /* Update the xttr entry. */ 35567cf5b09STao Ma i.value = value; 35667cf5b09STao Ma i.value_len = len; 35767cf5b09STao Ma 3580d812f77STao Ma error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); 35967cf5b09STao Ma if (error) 36067cf5b09STao Ma goto out; 36167cf5b09STao Ma 36267cf5b09STao Ma EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here - 36367cf5b09STao Ma (void *)ext4_raw_inode(&is.iloc)); 36467cf5b09STao Ma EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE + 36567cf5b09STao Ma le32_to_cpu(is.s.here->e_value_size); 36667cf5b09STao Ma ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 36767cf5b09STao Ma get_bh(is.iloc.bh); 36867cf5b09STao Ma error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); 36967cf5b09STao Ma 37067cf5b09STao Ma out: 37167cf5b09STao Ma kfree(value); 37267cf5b09STao Ma brelse(is.iloc.bh); 37367cf5b09STao Ma return error; 37467cf5b09STao Ma } 37567cf5b09STao Ma 37667cf5b09STao Ma int ext4_prepare_inline_data(handle_t *handle, struct inode *inode, 37767cf5b09STao Ma unsigned int len) 37867cf5b09STao Ma { 37967cf5b09STao Ma int ret, size; 38067cf5b09STao Ma struct ext4_inode_info *ei = EXT4_I(inode); 38167cf5b09STao Ma 38267cf5b09STao Ma if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) 38367cf5b09STao Ma return -ENOSPC; 38467cf5b09STao Ma 38567cf5b09STao Ma size = ext4_get_max_inline_size(inode); 38667cf5b09STao Ma if (size < len) 38767cf5b09STao Ma return -ENOSPC; 38867cf5b09STao Ma 38967cf5b09STao Ma down_write(&EXT4_I(inode)->xattr_sem); 39067cf5b09STao Ma 39167cf5b09STao Ma if (ei->i_inline_off) 39267cf5b09STao Ma ret = ext4_update_inline_data(handle, inode, len); 39367cf5b09STao Ma else 39467cf5b09STao Ma ret = ext4_create_inline_data(handle, inode, len); 39567cf5b09STao Ma 39667cf5b09STao Ma up_write(&EXT4_I(inode)->xattr_sem); 39767cf5b09STao Ma 39867cf5b09STao Ma return ret; 39967cf5b09STao Ma } 40067cf5b09STao Ma 40167cf5b09STao Ma static int ext4_destroy_inline_data_nolock(handle_t *handle, 40267cf5b09STao Ma struct inode *inode) 40367cf5b09STao Ma { 40467cf5b09STao Ma struct ext4_inode_info *ei = EXT4_I(inode); 40567cf5b09STao Ma struct ext4_xattr_ibody_find is = { 40667cf5b09STao Ma .s = { .not_found = 0, }, 40767cf5b09STao Ma }; 40867cf5b09STao Ma struct ext4_xattr_info i = { 40967cf5b09STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 41067cf5b09STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 41167cf5b09STao Ma .value = NULL, 41267cf5b09STao Ma .value_len = 0, 41367cf5b09STao Ma }; 41467cf5b09STao Ma int error; 41567cf5b09STao Ma 41667cf5b09STao Ma if (!ei->i_inline_off) 41767cf5b09STao Ma return 0; 41867cf5b09STao Ma 41967cf5b09STao Ma error = ext4_get_inode_loc(inode, &is.iloc); 42067cf5b09STao Ma if (error) 42167cf5b09STao Ma return error; 42267cf5b09STao Ma 42367cf5b09STao Ma error = ext4_xattr_ibody_find(inode, &i, &is); 42467cf5b09STao Ma if (error) 42567cf5b09STao Ma goto out; 42667cf5b09STao Ma 42767cf5b09STao Ma error = ext4_journal_get_write_access(handle, is.iloc.bh); 42867cf5b09STao Ma if (error) 42967cf5b09STao Ma goto out; 43067cf5b09STao Ma 4310d812f77STao Ma error = ext4_xattr_ibody_inline_set(handle, inode, &i, &is); 43267cf5b09STao Ma if (error) 43367cf5b09STao Ma goto out; 43467cf5b09STao Ma 43567cf5b09STao Ma memset((void *)ext4_raw_inode(&is.iloc)->i_block, 43667cf5b09STao Ma 0, EXT4_MIN_INLINE_DATA_SIZE); 43767cf5b09STao Ma 43867cf5b09STao Ma if (EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb, 43967cf5b09STao Ma EXT4_FEATURE_INCOMPAT_EXTENTS)) { 44067cf5b09STao Ma if (S_ISDIR(inode->i_mode) || 44167cf5b09STao Ma S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) { 44267cf5b09STao Ma ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS); 44367cf5b09STao Ma ext4_ext_tree_init(handle, inode); 44467cf5b09STao Ma } 44567cf5b09STao Ma } 44667cf5b09STao Ma ext4_clear_inode_flag(inode, EXT4_INODE_INLINE_DATA); 44767cf5b09STao Ma 44867cf5b09STao Ma get_bh(is.iloc.bh); 44967cf5b09STao Ma error = ext4_mark_iloc_dirty(handle, inode, &is.iloc); 45067cf5b09STao Ma 45167cf5b09STao Ma EXT4_I(inode)->i_inline_off = 0; 45267cf5b09STao Ma EXT4_I(inode)->i_inline_size = 0; 45367cf5b09STao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 45467cf5b09STao Ma out: 45567cf5b09STao Ma brelse(is.iloc.bh); 45667cf5b09STao Ma if (error == -ENODATA) 45767cf5b09STao Ma error = 0; 45867cf5b09STao Ma return error; 45967cf5b09STao Ma } 46067cf5b09STao Ma 46146c7f254STao Ma static int ext4_read_inline_page(struct inode *inode, struct page *page) 46246c7f254STao Ma { 46346c7f254STao Ma void *kaddr; 46446c7f254STao Ma int ret = 0; 46546c7f254STao Ma size_t len; 46646c7f254STao Ma struct ext4_iloc iloc; 46746c7f254STao Ma 46846c7f254STao Ma BUG_ON(!PageLocked(page)); 46946c7f254STao Ma BUG_ON(!ext4_has_inline_data(inode)); 47046c7f254STao Ma BUG_ON(page->index); 47146c7f254STao Ma 47246c7f254STao Ma if (!EXT4_I(inode)->i_inline_off) { 47346c7f254STao Ma ext4_warning(inode->i_sb, "inode %lu doesn't have inline data.", 47446c7f254STao Ma inode->i_ino); 47546c7f254STao Ma goto out; 47646c7f254STao Ma } 47746c7f254STao Ma 47846c7f254STao Ma ret = ext4_get_inode_loc(inode, &iloc); 47946c7f254STao Ma if (ret) 48046c7f254STao Ma goto out; 48146c7f254STao Ma 48246c7f254STao Ma len = min_t(size_t, ext4_get_inline_size(inode), i_size_read(inode)); 48346c7f254STao Ma kaddr = kmap_atomic(page); 48446c7f254STao Ma ret = ext4_read_inline_data(inode, kaddr, len, &iloc); 48546c7f254STao Ma flush_dcache_page(page); 48646c7f254STao Ma kunmap_atomic(kaddr); 48746c7f254STao Ma zero_user_segment(page, len, PAGE_CACHE_SIZE); 48846c7f254STao Ma SetPageUptodate(page); 48946c7f254STao Ma brelse(iloc.bh); 49046c7f254STao Ma 49146c7f254STao Ma out: 49246c7f254STao Ma return ret; 49346c7f254STao Ma } 49446c7f254STao Ma 49546c7f254STao Ma int ext4_readpage_inline(struct inode *inode, struct page *page) 49646c7f254STao Ma { 49746c7f254STao Ma int ret = 0; 49846c7f254STao Ma 49946c7f254STao Ma down_read(&EXT4_I(inode)->xattr_sem); 50046c7f254STao Ma if (!ext4_has_inline_data(inode)) { 50146c7f254STao Ma up_read(&EXT4_I(inode)->xattr_sem); 50246c7f254STao Ma return -EAGAIN; 50346c7f254STao Ma } 50446c7f254STao Ma 50546c7f254STao Ma /* 50646c7f254STao Ma * Current inline data can only exist in the 1st page, 50746c7f254STao Ma * So for all the other pages, just set them uptodate. 50846c7f254STao Ma */ 50946c7f254STao Ma if (!page->index) 51046c7f254STao Ma ret = ext4_read_inline_page(inode, page); 51146c7f254STao Ma else if (!PageUptodate(page)) { 51246c7f254STao Ma zero_user_segment(page, 0, PAGE_CACHE_SIZE); 51346c7f254STao Ma SetPageUptodate(page); 51446c7f254STao Ma } 51546c7f254STao Ma 51646c7f254STao Ma up_read(&EXT4_I(inode)->xattr_sem); 51746c7f254STao Ma 51846c7f254STao Ma unlock_page(page); 51946c7f254STao Ma return ret >= 0 ? 0 : ret; 52046c7f254STao Ma } 52146c7f254STao Ma 522f19d5870STao Ma static int ext4_convert_inline_data_to_extent(struct address_space *mapping, 523f19d5870STao Ma struct inode *inode, 524f19d5870STao Ma unsigned flags) 525f19d5870STao Ma { 526f19d5870STao Ma int ret, needed_blocks; 527f19d5870STao Ma handle_t *handle = NULL; 528f19d5870STao Ma int retries = 0, sem_held = 0; 529f19d5870STao Ma struct page *page = NULL; 530f19d5870STao Ma unsigned from, to; 531f19d5870STao Ma struct ext4_iloc iloc; 532f19d5870STao Ma 533f19d5870STao Ma if (!ext4_has_inline_data(inode)) { 534f19d5870STao Ma /* 535f19d5870STao Ma * clear the flag so that no new write 536f19d5870STao Ma * will trap here again. 537f19d5870STao Ma */ 538f19d5870STao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 539f19d5870STao Ma return 0; 540f19d5870STao Ma } 541f19d5870STao Ma 542f19d5870STao Ma needed_blocks = ext4_writepage_trans_blocks(inode); 543f19d5870STao Ma 544f19d5870STao Ma ret = ext4_get_inode_loc(inode, &iloc); 545f19d5870STao Ma if (ret) 546f19d5870STao Ma return ret; 547f19d5870STao Ma 548f19d5870STao Ma retry: 5499924a92aSTheodore Ts'o handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, needed_blocks); 550f19d5870STao Ma if (IS_ERR(handle)) { 551f19d5870STao Ma ret = PTR_ERR(handle); 552f19d5870STao Ma handle = NULL; 553f19d5870STao Ma goto out; 554f19d5870STao Ma } 555f19d5870STao Ma 556f19d5870STao Ma /* We cannot recurse into the filesystem as the transaction is already 557f19d5870STao Ma * started */ 558f19d5870STao Ma flags |= AOP_FLAG_NOFS; 559f19d5870STao Ma 560f19d5870STao Ma page = grab_cache_page_write_begin(mapping, 0, flags); 561f19d5870STao Ma if (!page) { 562f19d5870STao Ma ret = -ENOMEM; 563f19d5870STao Ma goto out; 564f19d5870STao Ma } 565f19d5870STao Ma 566f19d5870STao Ma down_write(&EXT4_I(inode)->xattr_sem); 567f19d5870STao Ma sem_held = 1; 568f19d5870STao Ma /* If some one has already done this for us, just exit. */ 569f19d5870STao Ma if (!ext4_has_inline_data(inode)) { 570f19d5870STao Ma ret = 0; 571f19d5870STao Ma goto out; 572f19d5870STao Ma } 573f19d5870STao Ma 574f19d5870STao Ma from = 0; 575f19d5870STao Ma to = ext4_get_inline_size(inode); 576f19d5870STao Ma if (!PageUptodate(page)) { 577f19d5870STao Ma ret = ext4_read_inline_page(inode, page); 578f19d5870STao Ma if (ret < 0) 579f19d5870STao Ma goto out; 580f19d5870STao Ma } 581f19d5870STao Ma 582f19d5870STao Ma ret = ext4_destroy_inline_data_nolock(handle, inode); 583f19d5870STao Ma if (ret) 584f19d5870STao Ma goto out; 585f19d5870STao Ma 586f19d5870STao Ma if (ext4_should_dioread_nolock(inode)) 587f19d5870STao Ma ret = __block_write_begin(page, from, to, ext4_get_block_write); 588f19d5870STao Ma else 589f19d5870STao Ma ret = __block_write_begin(page, from, to, ext4_get_block); 590f19d5870STao Ma 591f19d5870STao Ma if (!ret && ext4_should_journal_data(inode)) { 592f19d5870STao Ma ret = ext4_walk_page_buffers(handle, page_buffers(page), 593f19d5870STao Ma from, to, NULL, 594f19d5870STao Ma do_journal_get_write_access); 595f19d5870STao Ma } 596f19d5870STao Ma 597f19d5870STao Ma if (ret) { 598f19d5870STao Ma unlock_page(page); 599f19d5870STao Ma page_cache_release(page); 600f19d5870STao Ma ext4_orphan_add(handle, inode); 601f19d5870STao Ma up_write(&EXT4_I(inode)->xattr_sem); 602f19d5870STao Ma sem_held = 0; 603f19d5870STao Ma ext4_journal_stop(handle); 604f19d5870STao Ma handle = NULL; 605f19d5870STao Ma ext4_truncate_failed_write(inode); 606f19d5870STao Ma /* 607f19d5870STao Ma * If truncate failed early the inode might 608f19d5870STao Ma * still be on the orphan list; we need to 609f19d5870STao Ma * make sure the inode is removed from the 610f19d5870STao Ma * orphan list in that case. 611f19d5870STao Ma */ 612f19d5870STao Ma if (inode->i_nlink) 613f19d5870STao Ma ext4_orphan_del(NULL, inode); 614f19d5870STao Ma } 615f19d5870STao Ma 616f19d5870STao Ma if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) 617f19d5870STao Ma goto retry; 618f19d5870STao Ma 619f19d5870STao Ma block_commit_write(page, from, to); 620f19d5870STao Ma out: 621f19d5870STao Ma if (page) { 622f19d5870STao Ma unlock_page(page); 623f19d5870STao Ma page_cache_release(page); 624f19d5870STao Ma } 625f19d5870STao Ma if (sem_held) 626f19d5870STao Ma up_write(&EXT4_I(inode)->xattr_sem); 627f19d5870STao Ma if (handle) 628f19d5870STao Ma ext4_journal_stop(handle); 629f19d5870STao Ma brelse(iloc.bh); 630f19d5870STao Ma return ret; 631f19d5870STao Ma } 632f19d5870STao Ma 633f19d5870STao Ma /* 634f19d5870STao Ma * Try to write data in the inode. 635f19d5870STao Ma * If the inode has inline data, check whether the new write can be 636f19d5870STao Ma * in the inode also. If not, create the page the handle, move the data 637f19d5870STao Ma * to the page make it update and let the later codes create extent for it. 638f19d5870STao Ma */ 639f19d5870STao Ma int ext4_try_to_write_inline_data(struct address_space *mapping, 640f19d5870STao Ma struct inode *inode, 641f19d5870STao Ma loff_t pos, unsigned len, 642f19d5870STao Ma unsigned flags, 643f19d5870STao Ma struct page **pagep) 644f19d5870STao Ma { 645f19d5870STao Ma int ret; 646f19d5870STao Ma handle_t *handle; 647f19d5870STao Ma struct page *page; 648f19d5870STao Ma struct ext4_iloc iloc; 649f19d5870STao Ma 650f19d5870STao Ma if (pos + len > ext4_get_max_inline_size(inode)) 651f19d5870STao Ma goto convert; 652f19d5870STao Ma 653f19d5870STao Ma ret = ext4_get_inode_loc(inode, &iloc); 654f19d5870STao Ma if (ret) 655f19d5870STao Ma return ret; 656f19d5870STao Ma 657f19d5870STao Ma /* 658f19d5870STao Ma * The possible write could happen in the inode, 659f19d5870STao Ma * so try to reserve the space in inode first. 660f19d5870STao Ma */ 6619924a92aSTheodore Ts'o handle = ext4_journal_start(inode, EXT4_HT_INODE, 1); 662f19d5870STao Ma if (IS_ERR(handle)) { 663f19d5870STao Ma ret = PTR_ERR(handle); 664f19d5870STao Ma handle = NULL; 665f19d5870STao Ma goto out; 666f19d5870STao Ma } 667f19d5870STao Ma 668f19d5870STao Ma ret = ext4_prepare_inline_data(handle, inode, pos + len); 669f19d5870STao Ma if (ret && ret != -ENOSPC) 670f19d5870STao Ma goto out; 671f19d5870STao Ma 672f19d5870STao Ma /* We don't have space in inline inode, so convert it to extent. */ 673f19d5870STao Ma if (ret == -ENOSPC) { 674f19d5870STao Ma ext4_journal_stop(handle); 675f19d5870STao Ma brelse(iloc.bh); 676f19d5870STao Ma goto convert; 677f19d5870STao Ma } 678f19d5870STao Ma 679f19d5870STao Ma flags |= AOP_FLAG_NOFS; 680f19d5870STao Ma 681f19d5870STao Ma page = grab_cache_page_write_begin(mapping, 0, flags); 682f19d5870STao Ma if (!page) { 683f19d5870STao Ma ret = -ENOMEM; 684f19d5870STao Ma goto out; 685f19d5870STao Ma } 686f19d5870STao Ma 687f19d5870STao Ma *pagep = page; 688f19d5870STao Ma down_read(&EXT4_I(inode)->xattr_sem); 689f19d5870STao Ma if (!ext4_has_inline_data(inode)) { 690f19d5870STao Ma ret = 0; 691f19d5870STao Ma unlock_page(page); 692f19d5870STao Ma page_cache_release(page); 693f19d5870STao Ma goto out_up_read; 694f19d5870STao Ma } 695f19d5870STao Ma 696f19d5870STao Ma if (!PageUptodate(page)) { 697f19d5870STao Ma ret = ext4_read_inline_page(inode, page); 698f19d5870STao Ma if (ret < 0) 699f19d5870STao Ma goto out_up_read; 700f19d5870STao Ma } 701f19d5870STao Ma 702f19d5870STao Ma ret = 1; 703f19d5870STao Ma handle = NULL; 704f19d5870STao Ma out_up_read: 705f19d5870STao Ma up_read(&EXT4_I(inode)->xattr_sem); 706f19d5870STao Ma out: 707f19d5870STao Ma if (handle) 708f19d5870STao Ma ext4_journal_stop(handle); 709f19d5870STao Ma brelse(iloc.bh); 710f19d5870STao Ma return ret; 711f19d5870STao Ma convert: 712f19d5870STao Ma return ext4_convert_inline_data_to_extent(mapping, 713f19d5870STao Ma inode, flags); 714f19d5870STao Ma } 715f19d5870STao Ma 716f19d5870STao Ma int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len, 717f19d5870STao Ma unsigned copied, struct page *page) 718f19d5870STao Ma { 719f19d5870STao Ma int ret; 720f19d5870STao Ma void *kaddr; 721f19d5870STao Ma struct ext4_iloc iloc; 722f19d5870STao Ma 723f19d5870STao Ma if (unlikely(copied < len)) { 724f19d5870STao Ma if (!PageUptodate(page)) { 725f19d5870STao Ma copied = 0; 726f19d5870STao Ma goto out; 727f19d5870STao Ma } 728f19d5870STao Ma } 729f19d5870STao Ma 730f19d5870STao Ma ret = ext4_get_inode_loc(inode, &iloc); 731f19d5870STao Ma if (ret) { 732f19d5870STao Ma ext4_std_error(inode->i_sb, ret); 733f19d5870STao Ma copied = 0; 734f19d5870STao Ma goto out; 735f19d5870STao Ma } 736f19d5870STao Ma 737f19d5870STao Ma down_write(&EXT4_I(inode)->xattr_sem); 738f19d5870STao Ma BUG_ON(!ext4_has_inline_data(inode)); 739f19d5870STao Ma 740f19d5870STao Ma kaddr = kmap_atomic(page); 741f19d5870STao Ma ext4_write_inline_data(inode, &iloc, kaddr, pos, len); 742f19d5870STao Ma kunmap_atomic(kaddr); 743f19d5870STao Ma SetPageUptodate(page); 744f19d5870STao Ma /* clear page dirty so that writepages wouldn't work for us. */ 745f19d5870STao Ma ClearPageDirty(page); 746f19d5870STao Ma 747f19d5870STao Ma up_write(&EXT4_I(inode)->xattr_sem); 748f19d5870STao Ma brelse(iloc.bh); 749f19d5870STao Ma out: 750f19d5870STao Ma return copied; 751f19d5870STao Ma } 752f19d5870STao Ma 7533fdcfb66STao Ma struct buffer_head * 7543fdcfb66STao Ma ext4_journalled_write_inline_data(struct inode *inode, 7553fdcfb66STao Ma unsigned len, 7563fdcfb66STao Ma struct page *page) 7573fdcfb66STao Ma { 7583fdcfb66STao Ma int ret; 7593fdcfb66STao Ma void *kaddr; 7603fdcfb66STao Ma struct ext4_iloc iloc; 7613fdcfb66STao Ma 7623fdcfb66STao Ma ret = ext4_get_inode_loc(inode, &iloc); 7633fdcfb66STao Ma if (ret) { 7643fdcfb66STao Ma ext4_std_error(inode->i_sb, ret); 7653fdcfb66STao Ma return NULL; 7663fdcfb66STao Ma } 7673fdcfb66STao Ma 7683fdcfb66STao Ma down_write(&EXT4_I(inode)->xattr_sem); 7693fdcfb66STao Ma kaddr = kmap_atomic(page); 7703fdcfb66STao Ma ext4_write_inline_data(inode, &iloc, kaddr, 0, len); 7713fdcfb66STao Ma kunmap_atomic(kaddr); 7723fdcfb66STao Ma up_write(&EXT4_I(inode)->xattr_sem); 7733fdcfb66STao Ma 7743fdcfb66STao Ma return iloc.bh; 7753fdcfb66STao Ma } 7763fdcfb66STao Ma 7779c3569b5STao Ma /* 7789c3569b5STao Ma * Try to make the page cache and handle ready for the inline data case. 7799c3569b5STao Ma * We can call this function in 2 cases: 7809c3569b5STao Ma * 1. The inode is created and the first write exceeds inline size. We can 7819c3569b5STao Ma * clear the inode state safely. 7829c3569b5STao Ma * 2. The inode has inline data, then we need to read the data, make it 7839c3569b5STao Ma * update and dirty so that ext4_da_writepages can handle it. We don't 7849c3569b5STao Ma * need to start the journal since the file's metatdata isn't changed now. 7859c3569b5STao Ma */ 7869c3569b5STao Ma static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping, 7879c3569b5STao Ma struct inode *inode, 7889c3569b5STao Ma unsigned flags, 7899c3569b5STao Ma void **fsdata) 7909c3569b5STao Ma { 7919c3569b5STao Ma int ret = 0, inline_size; 7929c3569b5STao Ma struct page *page; 7939c3569b5STao Ma 7949c3569b5STao Ma page = grab_cache_page_write_begin(mapping, 0, flags); 7959c3569b5STao Ma if (!page) 7969c3569b5STao Ma return -ENOMEM; 7979c3569b5STao Ma 7989c3569b5STao Ma down_read(&EXT4_I(inode)->xattr_sem); 7999c3569b5STao Ma if (!ext4_has_inline_data(inode)) { 8009c3569b5STao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 8019c3569b5STao Ma goto out; 8029c3569b5STao Ma } 8039c3569b5STao Ma 8049c3569b5STao Ma inline_size = ext4_get_inline_size(inode); 8059c3569b5STao Ma 8069c3569b5STao Ma if (!PageUptodate(page)) { 8079c3569b5STao Ma ret = ext4_read_inline_page(inode, page); 8089c3569b5STao Ma if (ret < 0) 8099c3569b5STao Ma goto out; 8109c3569b5STao Ma } 8119c3569b5STao Ma 8129c3569b5STao Ma ret = __block_write_begin(page, 0, inline_size, 8139c3569b5STao Ma ext4_da_get_block_prep); 8149c3569b5STao Ma if (ret) { 8159c3569b5STao Ma ext4_truncate_failed_write(inode); 8169c3569b5STao Ma goto out; 8179c3569b5STao Ma } 8189c3569b5STao Ma 8199c3569b5STao Ma SetPageDirty(page); 8209c3569b5STao Ma SetPageUptodate(page); 8219c3569b5STao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 8229c3569b5STao Ma *fsdata = (void *)CONVERT_INLINE_DATA; 8239c3569b5STao Ma 8249c3569b5STao Ma out: 8259c3569b5STao Ma up_read(&EXT4_I(inode)->xattr_sem); 8269c3569b5STao Ma if (page) { 8279c3569b5STao Ma unlock_page(page); 8289c3569b5STao Ma page_cache_release(page); 8299c3569b5STao Ma } 8309c3569b5STao Ma return ret; 8319c3569b5STao Ma } 8329c3569b5STao Ma 8339c3569b5STao Ma /* 8349c3569b5STao Ma * Prepare the write for the inline data. 8359c3569b5STao Ma * If the the data can be written into the inode, we just read 8369c3569b5STao Ma * the page and make it uptodate, and start the journal. 8379c3569b5STao Ma * Otherwise read the page, makes it dirty so that it can be 8389c3569b5STao Ma * handle in writepages(the i_disksize update is left to the 8399c3569b5STao Ma * normal ext4_da_write_end). 8409c3569b5STao Ma */ 8419c3569b5STao Ma int ext4_da_write_inline_data_begin(struct address_space *mapping, 8429c3569b5STao Ma struct inode *inode, 8439c3569b5STao Ma loff_t pos, unsigned len, 8449c3569b5STao Ma unsigned flags, 8459c3569b5STao Ma struct page **pagep, 8469c3569b5STao Ma void **fsdata) 8479c3569b5STao Ma { 8489c3569b5STao Ma int ret, inline_size; 8499c3569b5STao Ma handle_t *handle; 8509c3569b5STao Ma struct page *page; 8519c3569b5STao Ma struct ext4_iloc iloc; 8529c3569b5STao Ma 8539c3569b5STao Ma ret = ext4_get_inode_loc(inode, &iloc); 8549c3569b5STao Ma if (ret) 8559c3569b5STao Ma return ret; 8569c3569b5STao Ma 8579924a92aSTheodore Ts'o handle = ext4_journal_start(inode, EXT4_HT_INODE, 1); 8589c3569b5STao Ma if (IS_ERR(handle)) { 8599c3569b5STao Ma ret = PTR_ERR(handle); 8609c3569b5STao Ma handle = NULL; 8619c3569b5STao Ma goto out; 8629c3569b5STao Ma } 8639c3569b5STao Ma 8649c3569b5STao Ma inline_size = ext4_get_max_inline_size(inode); 8659c3569b5STao Ma 8669c3569b5STao Ma ret = -ENOSPC; 8679c3569b5STao Ma if (inline_size >= pos + len) { 8689c3569b5STao Ma ret = ext4_prepare_inline_data(handle, inode, pos + len); 8699c3569b5STao Ma if (ret && ret != -ENOSPC) 8709c3569b5STao Ma goto out; 8719c3569b5STao Ma } 8729c3569b5STao Ma 8739c3569b5STao Ma if (ret == -ENOSPC) { 8749c3569b5STao Ma ret = ext4_da_convert_inline_data_to_extent(mapping, 8759c3569b5STao Ma inode, 8769c3569b5STao Ma flags, 8779c3569b5STao Ma fsdata); 8789c3569b5STao Ma goto out; 8799c3569b5STao Ma } 8809c3569b5STao Ma 8819c3569b5STao Ma /* 8829c3569b5STao Ma * We cannot recurse into the filesystem as the transaction 8839c3569b5STao Ma * is already started. 8849c3569b5STao Ma */ 8859c3569b5STao Ma flags |= AOP_FLAG_NOFS; 8869c3569b5STao Ma 8879c3569b5STao Ma page = grab_cache_page_write_begin(mapping, 0, flags); 8889c3569b5STao Ma if (!page) { 8899c3569b5STao Ma ret = -ENOMEM; 8909c3569b5STao Ma goto out; 8919c3569b5STao Ma } 8929c3569b5STao Ma 8939c3569b5STao Ma down_read(&EXT4_I(inode)->xattr_sem); 8949c3569b5STao Ma if (!ext4_has_inline_data(inode)) { 8959c3569b5STao Ma ret = 0; 8969c3569b5STao Ma goto out_release_page; 8979c3569b5STao Ma } 8989c3569b5STao Ma 8999c3569b5STao Ma if (!PageUptodate(page)) { 9009c3569b5STao Ma ret = ext4_read_inline_page(inode, page); 9019c3569b5STao Ma if (ret < 0) 9029c3569b5STao Ma goto out_release_page; 9039c3569b5STao Ma } 9049c3569b5STao Ma 9059c3569b5STao Ma up_read(&EXT4_I(inode)->xattr_sem); 9069c3569b5STao Ma *pagep = page; 9079c3569b5STao Ma handle = NULL; 9089c3569b5STao Ma brelse(iloc.bh); 9099c3569b5STao Ma return 1; 9109c3569b5STao Ma out_release_page: 9119c3569b5STao Ma up_read(&EXT4_I(inode)->xattr_sem); 9129c3569b5STao Ma unlock_page(page); 9139c3569b5STao Ma page_cache_release(page); 9149c3569b5STao Ma out: 9159c3569b5STao Ma if (handle) 9169c3569b5STao Ma ext4_journal_stop(handle); 9179c3569b5STao Ma brelse(iloc.bh); 9189c3569b5STao Ma return ret; 9199c3569b5STao Ma } 9209c3569b5STao Ma 9219c3569b5STao Ma int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos, 9229c3569b5STao Ma unsigned len, unsigned copied, 9239c3569b5STao Ma struct page *page) 9249c3569b5STao Ma { 9259c3569b5STao Ma int i_size_changed = 0; 9269c3569b5STao Ma 9279c3569b5STao Ma copied = ext4_write_inline_data_end(inode, pos, len, copied, page); 9289c3569b5STao Ma 9299c3569b5STao Ma /* 9309c3569b5STao Ma * No need to use i_size_read() here, the i_size 9319c3569b5STao Ma * cannot change under us because we hold i_mutex. 9329c3569b5STao Ma * 9339c3569b5STao Ma * But it's important to update i_size while still holding page lock: 9349c3569b5STao Ma * page writeout could otherwise come in and zero beyond i_size. 9359c3569b5STao Ma */ 9369c3569b5STao Ma if (pos+copied > inode->i_size) { 9379c3569b5STao Ma i_size_write(inode, pos+copied); 9389c3569b5STao Ma i_size_changed = 1; 9399c3569b5STao Ma } 9409c3569b5STao Ma unlock_page(page); 9419c3569b5STao Ma page_cache_release(page); 9429c3569b5STao Ma 9439c3569b5STao Ma /* 9449c3569b5STao Ma * Don't mark the inode dirty under page lock. First, it unnecessarily 9459c3569b5STao Ma * makes the holding time of page lock longer. Second, it forces lock 9469c3569b5STao Ma * ordering of page lock and transaction start for journaling 9479c3569b5STao Ma * filesystems. 9489c3569b5STao Ma */ 9499c3569b5STao Ma if (i_size_changed) 9509c3569b5STao Ma mark_inode_dirty(inode); 9519c3569b5STao Ma 9529c3569b5STao Ma return copied; 9539c3569b5STao Ma } 954f19d5870STao Ma 9553c47d541STao Ma #ifdef INLINE_DIR_DEBUG 9563c47d541STao Ma void ext4_show_inline_dir(struct inode *dir, struct buffer_head *bh, 9573c47d541STao Ma void *inline_start, int inline_size) 9583c47d541STao Ma { 9593c47d541STao Ma int offset; 9603c47d541STao Ma unsigned short de_len; 9613c47d541STao Ma struct ext4_dir_entry_2 *de = inline_start; 9623c47d541STao Ma void *dlimit = inline_start + inline_size; 9633c47d541STao Ma 9643c47d541STao Ma trace_printk("inode %lu\n", dir->i_ino); 9653c47d541STao Ma offset = 0; 9663c47d541STao Ma while ((void *)de < dlimit) { 9673c47d541STao Ma de_len = ext4_rec_len_from_disk(de->rec_len, inline_size); 9683c47d541STao Ma trace_printk("de: off %u rlen %u name %*.s nlen %u ino %u\n", 9693c47d541STao Ma offset, de_len, de->name_len, de->name, 9703c47d541STao Ma de->name_len, le32_to_cpu(de->inode)); 9713c47d541STao Ma if (ext4_check_dir_entry(dir, NULL, de, bh, 9723c47d541STao Ma inline_start, inline_size, offset)) 9733c47d541STao Ma BUG(); 9743c47d541STao Ma 9753c47d541STao Ma offset += de_len; 9763c47d541STao Ma de = (struct ext4_dir_entry_2 *) ((char *) de + de_len); 9773c47d541STao Ma } 9783c47d541STao Ma } 9793c47d541STao Ma #else 9803c47d541STao Ma #define ext4_show_inline_dir(dir, bh, inline_start, inline_size) 9813c47d541STao Ma #endif 9823c47d541STao Ma 9833c47d541STao Ma /* 9843c47d541STao Ma * Add a new entry into a inline dir. 9853c47d541STao Ma * It will return -ENOSPC if no space is available, and -EIO 9863c47d541STao Ma * and -EEXIST if directory entry already exists. 9873c47d541STao Ma */ 9883c47d541STao Ma static int ext4_add_dirent_to_inline(handle_t *handle, 9893c47d541STao Ma struct dentry *dentry, 9903c47d541STao Ma struct inode *inode, 9913c47d541STao Ma struct ext4_iloc *iloc, 9923c47d541STao Ma void *inline_start, int inline_size) 9933c47d541STao Ma { 9943c47d541STao Ma struct inode *dir = dentry->d_parent->d_inode; 9953c47d541STao Ma const char *name = dentry->d_name.name; 9963c47d541STao Ma int namelen = dentry->d_name.len; 9973c47d541STao Ma unsigned short reclen; 9983c47d541STao Ma int err; 9993c47d541STao Ma struct ext4_dir_entry_2 *de; 10003c47d541STao Ma 10013c47d541STao Ma reclen = EXT4_DIR_REC_LEN(namelen); 10023c47d541STao Ma err = ext4_find_dest_de(dir, inode, iloc->bh, 10033c47d541STao Ma inline_start, inline_size, 10043c47d541STao Ma name, namelen, &de); 10053c47d541STao Ma if (err) 10063c47d541STao Ma return err; 10073c47d541STao Ma 10083c47d541STao Ma err = ext4_journal_get_write_access(handle, iloc->bh); 10093c47d541STao Ma if (err) 10103c47d541STao Ma return err; 10113c47d541STao Ma ext4_insert_dentry(inode, de, inline_size, name, namelen); 10123c47d541STao Ma 10133c47d541STao Ma ext4_show_inline_dir(dir, iloc->bh, inline_start, inline_size); 10143c47d541STao Ma 10153c47d541STao Ma /* 10163c47d541STao Ma * XXX shouldn't update any times until successful 10173c47d541STao Ma * completion of syscall, but too many callers depend 10183c47d541STao Ma * on this. 10193c47d541STao Ma * 10203c47d541STao Ma * XXX similarly, too many callers depend on 10213c47d541STao Ma * ext4_new_inode() setting the times, but error 10223c47d541STao Ma * recovery deletes the inode, so the worst that can 10233c47d541STao Ma * happen is that the times are slightly out of date 10243c47d541STao Ma * and/or different from the directory change time. 10253c47d541STao Ma */ 10263c47d541STao Ma dir->i_mtime = dir->i_ctime = ext4_current_time(dir); 10273c47d541STao Ma ext4_update_dx_flag(dir); 10283c47d541STao Ma dir->i_version++; 10293c47d541STao Ma ext4_mark_inode_dirty(handle, dir); 10303c47d541STao Ma return 1; 10313c47d541STao Ma } 10323c47d541STao Ma 10333c47d541STao Ma static void *ext4_get_inline_xattr_pos(struct inode *inode, 10343c47d541STao Ma struct ext4_iloc *iloc) 10353c47d541STao Ma { 10363c47d541STao Ma struct ext4_xattr_entry *entry; 10373c47d541STao Ma struct ext4_xattr_ibody_header *header; 10383c47d541STao Ma 10393c47d541STao Ma BUG_ON(!EXT4_I(inode)->i_inline_off); 10403c47d541STao Ma 10413c47d541STao Ma header = IHDR(inode, ext4_raw_inode(iloc)); 10423c47d541STao Ma entry = (struct ext4_xattr_entry *)((void *)ext4_raw_inode(iloc) + 10433c47d541STao Ma EXT4_I(inode)->i_inline_off); 10443c47d541STao Ma 10453c47d541STao Ma return (void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs); 10463c47d541STao Ma } 10473c47d541STao Ma 10483c47d541STao Ma /* Set the final de to cover the whole block. */ 10493c47d541STao Ma static void ext4_update_final_de(void *de_buf, int old_size, int new_size) 10503c47d541STao Ma { 10513c47d541STao Ma struct ext4_dir_entry_2 *de, *prev_de; 10523c47d541STao Ma void *limit; 10533c47d541STao Ma int de_len; 10543c47d541STao Ma 10553c47d541STao Ma de = (struct ext4_dir_entry_2 *)de_buf; 10563c47d541STao Ma if (old_size) { 10573c47d541STao Ma limit = de_buf + old_size; 10583c47d541STao Ma do { 10593c47d541STao Ma prev_de = de; 10603c47d541STao Ma de_len = ext4_rec_len_from_disk(de->rec_len, old_size); 10613c47d541STao Ma de_buf += de_len; 10623c47d541STao Ma de = (struct ext4_dir_entry_2 *)de_buf; 10633c47d541STao Ma } while (de_buf < limit); 10643c47d541STao Ma 10653c47d541STao Ma prev_de->rec_len = ext4_rec_len_to_disk(de_len + new_size - 10663c47d541STao Ma old_size, new_size); 10673c47d541STao Ma } else { 10683c47d541STao Ma /* this is just created, so create an empty entry. */ 10693c47d541STao Ma de->inode = 0; 10703c47d541STao Ma de->rec_len = ext4_rec_len_to_disk(new_size, new_size); 10713c47d541STao Ma } 10723c47d541STao Ma } 10733c47d541STao Ma 10743c47d541STao Ma static int ext4_update_inline_dir(handle_t *handle, struct inode *dir, 10753c47d541STao Ma struct ext4_iloc *iloc) 10763c47d541STao Ma { 10773c47d541STao Ma int ret; 10783c47d541STao Ma int old_size = EXT4_I(dir)->i_inline_size - EXT4_MIN_INLINE_DATA_SIZE; 10793c47d541STao Ma int new_size = get_max_inline_xattr_value_size(dir, iloc); 10803c47d541STao Ma 10813c47d541STao Ma if (new_size - old_size <= EXT4_DIR_REC_LEN(1)) 10823c47d541STao Ma return -ENOSPC; 10833c47d541STao Ma 10843c47d541STao Ma ret = ext4_update_inline_data(handle, dir, 10853c47d541STao Ma new_size + EXT4_MIN_INLINE_DATA_SIZE); 10863c47d541STao Ma if (ret) 10873c47d541STao Ma return ret; 10883c47d541STao Ma 10893c47d541STao Ma ext4_update_final_de(ext4_get_inline_xattr_pos(dir, iloc), old_size, 10903c47d541STao Ma EXT4_I(dir)->i_inline_size - 10913c47d541STao Ma EXT4_MIN_INLINE_DATA_SIZE); 10923c47d541STao Ma dir->i_size = EXT4_I(dir)->i_disksize = EXT4_I(dir)->i_inline_size; 10933c47d541STao Ma return 0; 10943c47d541STao Ma } 10953c47d541STao Ma 10963c47d541STao Ma static void ext4_restore_inline_data(handle_t *handle, struct inode *inode, 10973c47d541STao Ma struct ext4_iloc *iloc, 10983c47d541STao Ma void *buf, int inline_size) 10993c47d541STao Ma { 11003c47d541STao Ma ext4_create_inline_data(handle, inode, inline_size); 11013c47d541STao Ma ext4_write_inline_data(inode, iloc, buf, 0, inline_size); 11023c47d541STao Ma ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 11033c47d541STao Ma } 11043c47d541STao Ma 11053c47d541STao Ma static int ext4_finish_convert_inline_dir(handle_t *handle, 11063c47d541STao Ma struct inode *inode, 11073c47d541STao Ma struct buffer_head *dir_block, 11083c47d541STao Ma void *buf, 11093c47d541STao Ma int inline_size) 11103c47d541STao Ma { 11113c47d541STao Ma int err, csum_size = 0, header_size = 0; 11123c47d541STao Ma struct ext4_dir_entry_2 *de; 11133c47d541STao Ma struct ext4_dir_entry_tail *t; 11143c47d541STao Ma void *target = dir_block->b_data; 11153c47d541STao Ma 11163c47d541STao Ma /* 11173c47d541STao Ma * First create "." and ".." and then copy the dir information 11183c47d541STao Ma * back to the block. 11193c47d541STao Ma */ 11203c47d541STao Ma de = (struct ext4_dir_entry_2 *)target; 11213c47d541STao Ma de = ext4_init_dot_dotdot(inode, de, 11223c47d541STao Ma inode->i_sb->s_blocksize, csum_size, 11233c47d541STao Ma le32_to_cpu(((struct ext4_dir_entry_2 *)buf)->inode), 1); 11243c47d541STao Ma header_size = (void *)de - target; 11253c47d541STao Ma 11263c47d541STao Ma memcpy((void *)de, buf + EXT4_INLINE_DOTDOT_SIZE, 11273c47d541STao Ma inline_size - EXT4_INLINE_DOTDOT_SIZE); 11283c47d541STao Ma 11293c47d541STao Ma if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, 11303c47d541STao Ma EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) 11313c47d541STao Ma csum_size = sizeof(struct ext4_dir_entry_tail); 11323c47d541STao Ma 11333c47d541STao Ma inode->i_size = inode->i_sb->s_blocksize; 11343c47d541STao Ma i_size_write(inode, inode->i_sb->s_blocksize); 11353c47d541STao Ma EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize; 11363c47d541STao Ma ext4_update_final_de(dir_block->b_data, 11373c47d541STao Ma inline_size - EXT4_INLINE_DOTDOT_SIZE + header_size, 11383c47d541STao Ma inode->i_sb->s_blocksize - csum_size); 11393c47d541STao Ma 11403c47d541STao Ma if (csum_size) { 11413c47d541STao Ma t = EXT4_DIRENT_TAIL(dir_block->b_data, 11423c47d541STao Ma inode->i_sb->s_blocksize); 11433c47d541STao Ma initialize_dirent_tail(t, inode->i_sb->s_blocksize); 11443c47d541STao Ma } 11453c47d541STao Ma set_buffer_uptodate(dir_block); 11463c47d541STao Ma err = ext4_handle_dirty_dirent_node(handle, inode, dir_block); 11473c47d541STao Ma if (err) 11483c47d541STao Ma goto out; 11493c47d541STao Ma set_buffer_verified(dir_block); 11503c47d541STao Ma out: 11513c47d541STao Ma return err; 11523c47d541STao Ma } 11533c47d541STao Ma 11543c47d541STao Ma static int ext4_convert_inline_data_nolock(handle_t *handle, 11553c47d541STao Ma struct inode *inode, 11563c47d541STao Ma struct ext4_iloc *iloc) 11573c47d541STao Ma { 11583c47d541STao Ma int error; 11593c47d541STao Ma void *buf = NULL; 11603c47d541STao Ma struct buffer_head *data_bh = NULL; 11613c47d541STao Ma struct ext4_map_blocks map; 11623c47d541STao Ma int inline_size; 11633c47d541STao Ma 11643c47d541STao Ma inline_size = ext4_get_inline_size(inode); 11653c47d541STao Ma buf = kmalloc(inline_size, GFP_NOFS); 11663c47d541STao Ma if (!buf) { 11673c47d541STao Ma error = -ENOMEM; 11683c47d541STao Ma goto out; 11693c47d541STao Ma } 11703c47d541STao Ma 11713c47d541STao Ma error = ext4_read_inline_data(inode, buf, inline_size, iloc); 11723c47d541STao Ma if (error < 0) 11733c47d541STao Ma goto out; 11743c47d541STao Ma 11753c47d541STao Ma error = ext4_destroy_inline_data_nolock(handle, inode); 11763c47d541STao Ma if (error) 11773c47d541STao Ma goto out; 11783c47d541STao Ma 11793c47d541STao Ma map.m_lblk = 0; 11803c47d541STao Ma map.m_len = 1; 11813c47d541STao Ma map.m_flags = 0; 11823c47d541STao Ma error = ext4_map_blocks(handle, inode, &map, EXT4_GET_BLOCKS_CREATE); 11833c47d541STao Ma if (error < 0) 11843c47d541STao Ma goto out_restore; 11853c47d541STao Ma if (!(map.m_flags & EXT4_MAP_MAPPED)) { 11863c47d541STao Ma error = -EIO; 11873c47d541STao Ma goto out_restore; 11883c47d541STao Ma } 11893c47d541STao Ma 11903c47d541STao Ma data_bh = sb_getblk(inode->i_sb, map.m_pblk); 11913c47d541STao Ma if (!data_bh) { 1192860d21e2STheodore Ts'o error = -ENOMEM; 11933c47d541STao Ma goto out_restore; 11943c47d541STao Ma } 11953c47d541STao Ma 11963c47d541STao Ma lock_buffer(data_bh); 11973c47d541STao Ma error = ext4_journal_get_create_access(handle, data_bh); 11983c47d541STao Ma if (error) { 11993c47d541STao Ma unlock_buffer(data_bh); 12003c47d541STao Ma error = -EIO; 12013c47d541STao Ma goto out_restore; 12023c47d541STao Ma } 12033c47d541STao Ma memset(data_bh->b_data, 0, inode->i_sb->s_blocksize); 12043c47d541STao Ma 12053c47d541STao Ma if (!S_ISDIR(inode->i_mode)) { 12063c47d541STao Ma memcpy(data_bh->b_data, buf, inline_size); 12073c47d541STao Ma set_buffer_uptodate(data_bh); 12083c47d541STao Ma error = ext4_handle_dirty_metadata(handle, 12093c47d541STao Ma inode, data_bh); 12103c47d541STao Ma } else { 12113c47d541STao Ma error = ext4_finish_convert_inline_dir(handle, inode, data_bh, 12123c47d541STao Ma buf, inline_size); 12133c47d541STao Ma } 12143c47d541STao Ma 12153c47d541STao Ma unlock_buffer(data_bh); 12163c47d541STao Ma out_restore: 12173c47d541STao Ma if (error) 12183c47d541STao Ma ext4_restore_inline_data(handle, inode, iloc, buf, inline_size); 12193c47d541STao Ma 12203c47d541STao Ma out: 12213c47d541STao Ma brelse(data_bh); 12223c47d541STao Ma kfree(buf); 12233c47d541STao Ma return error; 12243c47d541STao Ma } 12253c47d541STao Ma 12263c47d541STao Ma /* 12273c47d541STao Ma * Try to add the new entry to the inline data. 12283c47d541STao Ma * If succeeds, return 0. If not, extended the inline dir and copied data to 12293c47d541STao Ma * the new created block. 12303c47d541STao Ma */ 12313c47d541STao Ma int ext4_try_add_inline_entry(handle_t *handle, struct dentry *dentry, 12323c47d541STao Ma struct inode *inode) 12333c47d541STao Ma { 12343c47d541STao Ma int ret, inline_size; 12353c47d541STao Ma void *inline_start; 12363c47d541STao Ma struct ext4_iloc iloc; 12373c47d541STao Ma struct inode *dir = dentry->d_parent->d_inode; 12383c47d541STao Ma 12393c47d541STao Ma ret = ext4_get_inode_loc(dir, &iloc); 12403c47d541STao Ma if (ret) 12413c47d541STao Ma return ret; 12423c47d541STao Ma 12433c47d541STao Ma down_write(&EXT4_I(dir)->xattr_sem); 12443c47d541STao Ma if (!ext4_has_inline_data(dir)) 12453c47d541STao Ma goto out; 12463c47d541STao Ma 12473c47d541STao Ma inline_start = (void *)ext4_raw_inode(&iloc)->i_block + 12483c47d541STao Ma EXT4_INLINE_DOTDOT_SIZE; 12493c47d541STao Ma inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE; 12503c47d541STao Ma 12513c47d541STao Ma ret = ext4_add_dirent_to_inline(handle, dentry, inode, &iloc, 12523c47d541STao Ma inline_start, inline_size); 12533c47d541STao Ma if (ret != -ENOSPC) 12543c47d541STao Ma goto out; 12553c47d541STao Ma 12563c47d541STao Ma /* check whether it can be inserted to inline xattr space. */ 12573c47d541STao Ma inline_size = EXT4_I(dir)->i_inline_size - 12583c47d541STao Ma EXT4_MIN_INLINE_DATA_SIZE; 12593c47d541STao Ma if (!inline_size) { 12603c47d541STao Ma /* Try to use the xattr space.*/ 12613c47d541STao Ma ret = ext4_update_inline_dir(handle, dir, &iloc); 12623c47d541STao Ma if (ret && ret != -ENOSPC) 12633c47d541STao Ma goto out; 12643c47d541STao Ma 12653c47d541STao Ma inline_size = EXT4_I(dir)->i_inline_size - 12663c47d541STao Ma EXT4_MIN_INLINE_DATA_SIZE; 12673c47d541STao Ma } 12683c47d541STao Ma 12693c47d541STao Ma if (inline_size) { 12703c47d541STao Ma inline_start = ext4_get_inline_xattr_pos(dir, &iloc); 12713c47d541STao Ma 12723c47d541STao Ma ret = ext4_add_dirent_to_inline(handle, dentry, inode, &iloc, 12733c47d541STao Ma inline_start, inline_size); 12743c47d541STao Ma 12753c47d541STao Ma if (ret != -ENOSPC) 12763c47d541STao Ma goto out; 12773c47d541STao Ma } 12783c47d541STao Ma 12793c47d541STao Ma /* 12803c47d541STao Ma * The inline space is filled up, so create a new block for it. 12813c47d541STao Ma * As the extent tree will be created, we have to save the inline 12823c47d541STao Ma * dir first. 12833c47d541STao Ma */ 12843c47d541STao Ma ret = ext4_convert_inline_data_nolock(handle, dir, &iloc); 12853c47d541STao Ma 12863c47d541STao Ma out: 12873c47d541STao Ma ext4_mark_inode_dirty(handle, dir); 12883c47d541STao Ma up_write(&EXT4_I(dir)->xattr_sem); 12893c47d541STao Ma brelse(iloc.bh); 12903c47d541STao Ma return ret; 12913c47d541STao Ma } 12923c47d541STao Ma 12938af0f082STao Ma /* 12948af0f082STao Ma * This function fills a red-black tree with information from an 12958af0f082STao Ma * inlined dir. It returns the number directory entries loaded 12968af0f082STao Ma * into the tree. If there is an error it is returned in err. 12978af0f082STao Ma */ 12988af0f082STao Ma int htree_inlinedir_to_tree(struct file *dir_file, 12998af0f082STao Ma struct inode *dir, ext4_lblk_t block, 13008af0f082STao Ma struct dx_hash_info *hinfo, 13018af0f082STao Ma __u32 start_hash, __u32 start_minor_hash, 13028af0f082STao Ma int *has_inline_data) 13038af0f082STao Ma { 13048af0f082STao Ma int err = 0, count = 0; 13058af0f082STao Ma unsigned int parent_ino; 13068af0f082STao Ma int pos; 13078af0f082STao Ma struct ext4_dir_entry_2 *de; 13088af0f082STao Ma struct inode *inode = file_inode(dir_file); 13098af0f082STao Ma int ret, inline_size = 0; 13108af0f082STao Ma struct ext4_iloc iloc; 13118af0f082STao Ma void *dir_buf = NULL; 13128af0f082STao Ma struct ext4_dir_entry_2 fake; 13138af0f082STao Ma 13148af0f082STao Ma ret = ext4_get_inode_loc(inode, &iloc); 13158af0f082STao Ma if (ret) 13168af0f082STao Ma return ret; 13178af0f082STao Ma 13188af0f082STao Ma down_read(&EXT4_I(inode)->xattr_sem); 13198af0f082STao Ma if (!ext4_has_inline_data(inode)) { 13208af0f082STao Ma up_read(&EXT4_I(inode)->xattr_sem); 13218af0f082STao Ma *has_inline_data = 0; 13228af0f082STao Ma goto out; 13238af0f082STao Ma } 13248af0f082STao Ma 13258af0f082STao Ma inline_size = ext4_get_inline_size(inode); 13268af0f082STao Ma dir_buf = kmalloc(inline_size, GFP_NOFS); 13278af0f082STao Ma if (!dir_buf) { 13288af0f082STao Ma ret = -ENOMEM; 13298af0f082STao Ma up_read(&EXT4_I(inode)->xattr_sem); 13308af0f082STao Ma goto out; 13318af0f082STao Ma } 13328af0f082STao Ma 13338af0f082STao Ma ret = ext4_read_inline_data(inode, dir_buf, inline_size, &iloc); 13348af0f082STao Ma up_read(&EXT4_I(inode)->xattr_sem); 13358af0f082STao Ma if (ret < 0) 13368af0f082STao Ma goto out; 13378af0f082STao Ma 13388af0f082STao Ma pos = 0; 13398af0f082STao Ma parent_ino = le32_to_cpu(((struct ext4_dir_entry_2 *)dir_buf)->inode); 13408af0f082STao Ma while (pos < inline_size) { 13418af0f082STao Ma /* 13428af0f082STao Ma * As inlined dir doesn't store any information about '.' and 13438af0f082STao Ma * only the inode number of '..' is stored, we have to handle 13448af0f082STao Ma * them differently. 13458af0f082STao Ma */ 13468af0f082STao Ma if (pos == 0) { 13478af0f082STao Ma fake.inode = cpu_to_le32(inode->i_ino); 13488af0f082STao Ma fake.name_len = 1; 13498af0f082STao Ma strcpy(fake.name, "."); 13508af0f082STao Ma fake.rec_len = ext4_rec_len_to_disk( 13518af0f082STao Ma EXT4_DIR_REC_LEN(fake.name_len), 13528af0f082STao Ma inline_size); 13538af0f082STao Ma ext4_set_de_type(inode->i_sb, &fake, S_IFDIR); 13548af0f082STao Ma de = &fake; 13558af0f082STao Ma pos = EXT4_INLINE_DOTDOT_OFFSET; 13568af0f082STao Ma } else if (pos == EXT4_INLINE_DOTDOT_OFFSET) { 13578af0f082STao Ma fake.inode = cpu_to_le32(parent_ino); 13588af0f082STao Ma fake.name_len = 2; 13598af0f082STao Ma strcpy(fake.name, ".."); 13608af0f082STao Ma fake.rec_len = ext4_rec_len_to_disk( 13618af0f082STao Ma EXT4_DIR_REC_LEN(fake.name_len), 13628af0f082STao Ma inline_size); 13638af0f082STao Ma ext4_set_de_type(inode->i_sb, &fake, S_IFDIR); 13648af0f082STao Ma de = &fake; 13658af0f082STao Ma pos = EXT4_INLINE_DOTDOT_SIZE; 13668af0f082STao Ma } else { 13678af0f082STao Ma de = (struct ext4_dir_entry_2 *)(dir_buf + pos); 13688af0f082STao Ma pos += ext4_rec_len_from_disk(de->rec_len, inline_size); 13698af0f082STao Ma if (ext4_check_dir_entry(inode, dir_file, de, 13708af0f082STao Ma iloc.bh, dir_buf, 13718af0f082STao Ma inline_size, pos)) { 13728af0f082STao Ma ret = count; 13738af0f082STao Ma goto out; 13748af0f082STao Ma } 13758af0f082STao Ma } 13768af0f082STao Ma 13778af0f082STao Ma ext4fs_dirhash(de->name, de->name_len, hinfo); 13788af0f082STao Ma if ((hinfo->hash < start_hash) || 13798af0f082STao Ma ((hinfo->hash == start_hash) && 13808af0f082STao Ma (hinfo->minor_hash < start_minor_hash))) 13818af0f082STao Ma continue; 13828af0f082STao Ma if (de->inode == 0) 13838af0f082STao Ma continue; 13848af0f082STao Ma err = ext4_htree_store_dirent(dir_file, 13858af0f082STao Ma hinfo->hash, hinfo->minor_hash, de); 13868af0f082STao Ma if (err) { 13878af0f082STao Ma count = err; 13888af0f082STao Ma goto out; 13898af0f082STao Ma } 13908af0f082STao Ma count++; 13918af0f082STao Ma } 13928af0f082STao Ma ret = count; 13938af0f082STao Ma out: 13948af0f082STao Ma kfree(dir_buf); 13958af0f082STao Ma brelse(iloc.bh); 13968af0f082STao Ma return ret; 13978af0f082STao Ma } 13988af0f082STao Ma 1399c4d8b023STao Ma /* 1400c4d8b023STao Ma * So this function is called when the volume is mkfsed with 1401c4d8b023STao Ma * dir_index disabled. In order to keep f_pos persistent 1402c4d8b023STao Ma * after we convert from an inlined dir to a blocked based, 1403c4d8b023STao Ma * we just pretend that we are a normal dir and return the 1404c4d8b023STao Ma * offset as if '.' and '..' really take place. 1405c4d8b023STao Ma * 1406c4d8b023STao Ma */ 140765d165d9STao Ma int ext4_read_inline_dir(struct file *filp, 140865d165d9STao Ma void *dirent, filldir_t filldir, 140965d165d9STao Ma int *has_inline_data) 141065d165d9STao Ma { 141165d165d9STao Ma int error = 0; 141265d165d9STao Ma unsigned int offset, parent_ino; 141365d165d9STao Ma int i, stored; 141465d165d9STao Ma struct ext4_dir_entry_2 *de; 141565d165d9STao Ma struct super_block *sb; 1416496ad9aaSAl Viro struct inode *inode = file_inode(filp); 141765d165d9STao Ma int ret, inline_size = 0; 141865d165d9STao Ma struct ext4_iloc iloc; 141965d165d9STao Ma void *dir_buf = NULL; 1420c4d8b023STao Ma int dotdot_offset, dotdot_size, extra_offset, extra_size; 142165d165d9STao Ma 142265d165d9STao Ma ret = ext4_get_inode_loc(inode, &iloc); 142365d165d9STao Ma if (ret) 142465d165d9STao Ma return ret; 142565d165d9STao Ma 142665d165d9STao Ma down_read(&EXT4_I(inode)->xattr_sem); 142765d165d9STao Ma if (!ext4_has_inline_data(inode)) { 142865d165d9STao Ma up_read(&EXT4_I(inode)->xattr_sem); 142965d165d9STao Ma *has_inline_data = 0; 143065d165d9STao Ma goto out; 143165d165d9STao Ma } 143265d165d9STao Ma 143365d165d9STao Ma inline_size = ext4_get_inline_size(inode); 143465d165d9STao Ma dir_buf = kmalloc(inline_size, GFP_NOFS); 143565d165d9STao Ma if (!dir_buf) { 143665d165d9STao Ma ret = -ENOMEM; 143765d165d9STao Ma up_read(&EXT4_I(inode)->xattr_sem); 143865d165d9STao Ma goto out; 143965d165d9STao Ma } 144065d165d9STao Ma 144165d165d9STao Ma ret = ext4_read_inline_data(inode, dir_buf, inline_size, &iloc); 144265d165d9STao Ma up_read(&EXT4_I(inode)->xattr_sem); 144365d165d9STao Ma if (ret < 0) 144465d165d9STao Ma goto out; 144565d165d9STao Ma 144665d165d9STao Ma sb = inode->i_sb; 144765d165d9STao Ma stored = 0; 144865d165d9STao Ma parent_ino = le32_to_cpu(((struct ext4_dir_entry_2 *)dir_buf)->inode); 1449c4d8b023STao Ma offset = filp->f_pos; 145065d165d9STao Ma 1451c4d8b023STao Ma /* 1452c4d8b023STao Ma * dotdot_offset and dotdot_size is the real offset and 1453c4d8b023STao Ma * size for ".." and "." if the dir is block based while 1454c4d8b023STao Ma * the real size for them are only EXT4_INLINE_DOTDOT_SIZE. 1455c4d8b023STao Ma * So we will use extra_offset and extra_size to indicate them 1456c4d8b023STao Ma * during the inline dir iteration. 1457c4d8b023STao Ma */ 1458c4d8b023STao Ma dotdot_offset = EXT4_DIR_REC_LEN(1); 1459c4d8b023STao Ma dotdot_size = dotdot_offset + EXT4_DIR_REC_LEN(2); 1460c4d8b023STao Ma extra_offset = dotdot_size - EXT4_INLINE_DOTDOT_SIZE; 1461c4d8b023STao Ma extra_size = extra_offset + inline_size; 1462c4d8b023STao Ma 1463c4d8b023STao Ma while (!error && !stored && filp->f_pos < extra_size) { 146465d165d9STao Ma revalidate: 146565d165d9STao Ma /* 146665d165d9STao Ma * If the version has changed since the last call to 146765d165d9STao Ma * readdir(2), then we might be pointing to an invalid 146865d165d9STao Ma * dirent right now. Scan from the start of the inline 146965d165d9STao Ma * dir to make sure. 147065d165d9STao Ma */ 147165d165d9STao Ma if (filp->f_version != inode->i_version) { 1472c4d8b023STao Ma for (i = 0; i < extra_size && i < offset;) { 1473c4d8b023STao Ma /* 1474c4d8b023STao Ma * "." is with offset 0 and 1475c4d8b023STao Ma * ".." is dotdot_offset. 1476c4d8b023STao Ma */ 147765d165d9STao Ma if (!i) { 1478c4d8b023STao Ma i = dotdot_offset; 1479c4d8b023STao Ma continue; 1480c4d8b023STao Ma } else if (i == dotdot_offset) { 1481c4d8b023STao Ma i = dotdot_size; 148265d165d9STao Ma continue; 148365d165d9STao Ma } 1484c4d8b023STao Ma /* for other entry, the real offset in 1485c4d8b023STao Ma * the buf has to be tuned accordingly. 1486c4d8b023STao Ma */ 148765d165d9STao Ma de = (struct ext4_dir_entry_2 *) 1488c4d8b023STao Ma (dir_buf + i - extra_offset); 148965d165d9STao Ma /* It's too expensive to do a full 149065d165d9STao Ma * dirent test each time round this 149165d165d9STao Ma * loop, but we do have to test at 149265d165d9STao Ma * least that it is non-zero. A 149365d165d9STao Ma * failure will be detected in the 149465d165d9STao Ma * dirent test below. */ 149565d165d9STao Ma if (ext4_rec_len_from_disk(de->rec_len, 1496c4d8b023STao Ma extra_size) < EXT4_DIR_REC_LEN(1)) 149765d165d9STao Ma break; 149865d165d9STao Ma i += ext4_rec_len_from_disk(de->rec_len, 1499c4d8b023STao Ma extra_size); 150065d165d9STao Ma } 150165d165d9STao Ma offset = i; 150265d165d9STao Ma filp->f_pos = offset; 150365d165d9STao Ma filp->f_version = inode->i_version; 150465d165d9STao Ma } 150565d165d9STao Ma 1506c4d8b023STao Ma while (!error && filp->f_pos < extra_size) { 150765d165d9STao Ma if (filp->f_pos == 0) { 150865d165d9STao Ma error = filldir(dirent, ".", 1, 0, inode->i_ino, 150965d165d9STao Ma DT_DIR); 151065d165d9STao Ma if (error) 151165d165d9STao Ma break; 151265d165d9STao Ma stored++; 1513c4d8b023STao Ma filp->f_pos = dotdot_offset; 1514c4d8b023STao Ma continue; 1515c4d8b023STao Ma } 151665d165d9STao Ma 1517c4d8b023STao Ma if (filp->f_pos == dotdot_offset) { 1518c4d8b023STao Ma error = filldir(dirent, "..", 2, 1519c4d8b023STao Ma dotdot_offset, 1520c4d8b023STao Ma parent_ino, DT_DIR); 152165d165d9STao Ma if (error) 152265d165d9STao Ma break; 152365d165d9STao Ma stored++; 152465d165d9STao Ma 1525c4d8b023STao Ma filp->f_pos = dotdot_size; 152665d165d9STao Ma continue; 152765d165d9STao Ma } 152865d165d9STao Ma 1529c4d8b023STao Ma de = (struct ext4_dir_entry_2 *) 1530c4d8b023STao Ma (dir_buf + filp->f_pos - extra_offset); 153165d165d9STao Ma if (ext4_check_dir_entry(inode, filp, de, 153265d165d9STao Ma iloc.bh, dir_buf, 1533c4d8b023STao Ma extra_size, filp->f_pos)) { 153465d165d9STao Ma ret = stored; 153565d165d9STao Ma goto out; 153665d165d9STao Ma } 153765d165d9STao Ma if (le32_to_cpu(de->inode)) { 153865d165d9STao Ma /* We might block in the next section 153965d165d9STao Ma * if the data destination is 154065d165d9STao Ma * currently swapped out. So, use a 154165d165d9STao Ma * version stamp to detect whether or 154265d165d9STao Ma * not the directory has been modified 154365d165d9STao Ma * during the copy operation. 154465d165d9STao Ma */ 154565d165d9STao Ma u64 version = filp->f_version; 154665d165d9STao Ma 154765d165d9STao Ma error = filldir(dirent, de->name, 154865d165d9STao Ma de->name_len, 154965d165d9STao Ma filp->f_pos, 155065d165d9STao Ma le32_to_cpu(de->inode), 155165d165d9STao Ma get_dtype(sb, de->file_type)); 155265d165d9STao Ma if (error) 155365d165d9STao Ma break; 155465d165d9STao Ma if (version != filp->f_version) 155565d165d9STao Ma goto revalidate; 155665d165d9STao Ma stored++; 155765d165d9STao Ma } 155865d165d9STao Ma filp->f_pos += ext4_rec_len_from_disk(de->rec_len, 1559c4d8b023STao Ma extra_size); 156065d165d9STao Ma } 156165d165d9STao Ma } 156265d165d9STao Ma out: 156365d165d9STao Ma kfree(dir_buf); 156465d165d9STao Ma brelse(iloc.bh); 156565d165d9STao Ma return ret; 156665d165d9STao Ma } 156765d165d9STao Ma 156832f7f22cSTao Ma struct buffer_head *ext4_get_first_inline_block(struct inode *inode, 156932f7f22cSTao Ma struct ext4_dir_entry_2 **parent_de, 157032f7f22cSTao Ma int *retval) 157132f7f22cSTao Ma { 157232f7f22cSTao Ma struct ext4_iloc iloc; 157332f7f22cSTao Ma 157432f7f22cSTao Ma *retval = ext4_get_inode_loc(inode, &iloc); 157532f7f22cSTao Ma if (*retval) 157632f7f22cSTao Ma return NULL; 157732f7f22cSTao Ma 157832f7f22cSTao Ma *parent_de = (struct ext4_dir_entry_2 *)ext4_raw_inode(&iloc)->i_block; 157932f7f22cSTao Ma 158032f7f22cSTao Ma return iloc.bh; 158132f7f22cSTao Ma } 158232f7f22cSTao Ma 15833c47d541STao Ma /* 15843c47d541STao Ma * Try to create the inline data for the new dir. 15853c47d541STao Ma * If it succeeds, return 0, otherwise return the error. 15863c47d541STao Ma * In case of ENOSPC, the caller should create the normal disk layout dir. 15873c47d541STao Ma */ 15883c47d541STao Ma int ext4_try_create_inline_dir(handle_t *handle, struct inode *parent, 15893c47d541STao Ma struct inode *inode) 15903c47d541STao Ma { 15913c47d541STao Ma int ret, inline_size = EXT4_MIN_INLINE_DATA_SIZE; 15923c47d541STao Ma struct ext4_iloc iloc; 15933c47d541STao Ma struct ext4_dir_entry_2 *de; 15943c47d541STao Ma 15953c47d541STao Ma ret = ext4_get_inode_loc(inode, &iloc); 15963c47d541STao Ma if (ret) 15973c47d541STao Ma return ret; 15983c47d541STao Ma 15993c47d541STao Ma ret = ext4_prepare_inline_data(handle, inode, inline_size); 16003c47d541STao Ma if (ret) 16013c47d541STao Ma goto out; 16023c47d541STao Ma 16033c47d541STao Ma /* 16043c47d541STao Ma * For inline dir, we only save the inode information for the ".." 16053c47d541STao Ma * and create a fake dentry to cover the left space. 16063c47d541STao Ma */ 16073c47d541STao Ma de = (struct ext4_dir_entry_2 *)ext4_raw_inode(&iloc)->i_block; 16083c47d541STao Ma de->inode = cpu_to_le32(parent->i_ino); 16093c47d541STao Ma de = (struct ext4_dir_entry_2 *)((void *)de + EXT4_INLINE_DOTDOT_SIZE); 16103c47d541STao Ma de->inode = 0; 16113c47d541STao Ma de->rec_len = ext4_rec_len_to_disk( 16123c47d541STao Ma inline_size - EXT4_INLINE_DOTDOT_SIZE, 16133c47d541STao Ma inline_size); 16143c47d541STao Ma set_nlink(inode, 2); 16153c47d541STao Ma inode->i_size = EXT4_I(inode)->i_disksize = inline_size; 16163c47d541STao Ma out: 16173c47d541STao Ma brelse(iloc.bh); 16183c47d541STao Ma return ret; 16193c47d541STao Ma } 16203c47d541STao Ma 1621e8e948e7STao Ma struct buffer_head *ext4_find_inline_entry(struct inode *dir, 1622e8e948e7STao Ma const struct qstr *d_name, 1623e8e948e7STao Ma struct ext4_dir_entry_2 **res_dir, 1624e8e948e7STao Ma int *has_inline_data) 1625e8e948e7STao Ma { 1626e8e948e7STao Ma int ret; 1627e8e948e7STao Ma struct ext4_iloc iloc; 1628e8e948e7STao Ma void *inline_start; 1629e8e948e7STao Ma int inline_size; 1630e8e948e7STao Ma 1631e8e948e7STao Ma if (ext4_get_inode_loc(dir, &iloc)) 1632e8e948e7STao Ma return NULL; 1633e8e948e7STao Ma 1634e8e948e7STao Ma down_read(&EXT4_I(dir)->xattr_sem); 1635e8e948e7STao Ma if (!ext4_has_inline_data(dir)) { 1636e8e948e7STao Ma *has_inline_data = 0; 1637e8e948e7STao Ma goto out; 1638e8e948e7STao Ma } 1639e8e948e7STao Ma 1640e8e948e7STao Ma inline_start = (void *)ext4_raw_inode(&iloc)->i_block + 1641e8e948e7STao Ma EXT4_INLINE_DOTDOT_SIZE; 1642e8e948e7STao Ma inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE; 1643e8e948e7STao Ma ret = search_dir(iloc.bh, inline_start, inline_size, 1644e8e948e7STao Ma dir, d_name, 0, res_dir); 1645e8e948e7STao Ma if (ret == 1) 1646e8e948e7STao Ma goto out_find; 1647e8e948e7STao Ma if (ret < 0) 1648e8e948e7STao Ma goto out; 1649e8e948e7STao Ma 1650e8e948e7STao Ma if (ext4_get_inline_size(dir) == EXT4_MIN_INLINE_DATA_SIZE) 1651e8e948e7STao Ma goto out; 1652e8e948e7STao Ma 1653e8e948e7STao Ma inline_start = ext4_get_inline_xattr_pos(dir, &iloc); 1654e8e948e7STao Ma inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE; 1655e8e948e7STao Ma 1656e8e948e7STao Ma ret = search_dir(iloc.bh, inline_start, inline_size, 1657e8e948e7STao Ma dir, d_name, 0, res_dir); 1658e8e948e7STao Ma if (ret == 1) 1659e8e948e7STao Ma goto out_find; 1660e8e948e7STao Ma 1661e8e948e7STao Ma out: 1662e8e948e7STao Ma brelse(iloc.bh); 1663e8e948e7STao Ma iloc.bh = NULL; 1664e8e948e7STao Ma out_find: 1665e8e948e7STao Ma up_read(&EXT4_I(dir)->xattr_sem); 1666e8e948e7STao Ma return iloc.bh; 1667e8e948e7STao Ma } 1668e8e948e7STao Ma 16699f40fe54STao Ma int ext4_delete_inline_entry(handle_t *handle, 16709f40fe54STao Ma struct inode *dir, 16719f40fe54STao Ma struct ext4_dir_entry_2 *de_del, 16729f40fe54STao Ma struct buffer_head *bh, 16739f40fe54STao Ma int *has_inline_data) 16749f40fe54STao Ma { 16759f40fe54STao Ma int err, inline_size; 16769f40fe54STao Ma struct ext4_iloc iloc; 16779f40fe54STao Ma void *inline_start; 16789f40fe54STao Ma 16799f40fe54STao Ma err = ext4_get_inode_loc(dir, &iloc); 16809f40fe54STao Ma if (err) 16819f40fe54STao Ma return err; 16829f40fe54STao Ma 16839f40fe54STao Ma down_write(&EXT4_I(dir)->xattr_sem); 16849f40fe54STao Ma if (!ext4_has_inline_data(dir)) { 16859f40fe54STao Ma *has_inline_data = 0; 16869f40fe54STao Ma goto out; 16879f40fe54STao Ma } 16889f40fe54STao Ma 16899f40fe54STao Ma if ((void *)de_del - ((void *)ext4_raw_inode(&iloc)->i_block) < 16909f40fe54STao Ma EXT4_MIN_INLINE_DATA_SIZE) { 16919f40fe54STao Ma inline_start = (void *)ext4_raw_inode(&iloc)->i_block + 16929f40fe54STao Ma EXT4_INLINE_DOTDOT_SIZE; 16939f40fe54STao Ma inline_size = EXT4_MIN_INLINE_DATA_SIZE - 16949f40fe54STao Ma EXT4_INLINE_DOTDOT_SIZE; 16959f40fe54STao Ma } else { 16969f40fe54STao Ma inline_start = ext4_get_inline_xattr_pos(dir, &iloc); 16979f40fe54STao Ma inline_size = ext4_get_inline_size(dir) - 16989f40fe54STao Ma EXT4_MIN_INLINE_DATA_SIZE; 16999f40fe54STao Ma } 17009f40fe54STao Ma 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 BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); 17119f40fe54STao Ma err = ext4_mark_inode_dirty(handle, dir); 17129f40fe54STao Ma if (unlikely(err)) 17139f40fe54STao Ma goto out; 17149f40fe54STao Ma 17159f40fe54STao Ma ext4_show_inline_dir(dir, iloc.bh, inline_start, inline_size); 17169f40fe54STao Ma out: 17179f40fe54STao Ma up_write(&EXT4_I(dir)->xattr_sem); 17189f40fe54STao Ma brelse(iloc.bh); 17199f40fe54STao Ma if (err != -ENOENT) 17209f40fe54STao Ma ext4_std_error(dir->i_sb, err); 17219f40fe54STao Ma return err; 17229f40fe54STao Ma } 17239f40fe54STao Ma 172461f86638STao Ma /* 172561f86638STao Ma * Get the inline dentry at offset. 172661f86638STao Ma */ 172761f86638STao Ma static inline struct ext4_dir_entry_2 * 172861f86638STao Ma ext4_get_inline_entry(struct inode *inode, 172961f86638STao Ma struct ext4_iloc *iloc, 173061f86638STao Ma unsigned int offset, 173161f86638STao Ma void **inline_start, 173261f86638STao Ma int *inline_size) 173361f86638STao Ma { 173461f86638STao Ma void *inline_pos; 173561f86638STao Ma 173661f86638STao Ma BUG_ON(offset > ext4_get_inline_size(inode)); 173761f86638STao Ma 173861f86638STao Ma if (offset < EXT4_MIN_INLINE_DATA_SIZE) { 173961f86638STao Ma inline_pos = (void *)ext4_raw_inode(iloc)->i_block; 174061f86638STao Ma *inline_size = EXT4_MIN_INLINE_DATA_SIZE; 174161f86638STao Ma } else { 174261f86638STao Ma inline_pos = ext4_get_inline_xattr_pos(inode, iloc); 174361f86638STao Ma offset -= EXT4_MIN_INLINE_DATA_SIZE; 174461f86638STao Ma *inline_size = ext4_get_inline_size(inode) - 174561f86638STao Ma EXT4_MIN_INLINE_DATA_SIZE; 174661f86638STao Ma } 174761f86638STao Ma 174861f86638STao Ma if (inline_start) 174961f86638STao Ma *inline_start = inline_pos; 175061f86638STao Ma return (struct ext4_dir_entry_2 *)(inline_pos + offset); 175161f86638STao Ma } 175261f86638STao Ma 175361f86638STao Ma int empty_inline_dir(struct inode *dir, int *has_inline_data) 175461f86638STao Ma { 175561f86638STao Ma int err, inline_size; 175661f86638STao Ma struct ext4_iloc iloc; 175761f86638STao Ma void *inline_pos; 175861f86638STao Ma unsigned int offset; 175961f86638STao Ma struct ext4_dir_entry_2 *de; 176061f86638STao Ma int ret = 1; 176161f86638STao Ma 176261f86638STao Ma err = ext4_get_inode_loc(dir, &iloc); 176361f86638STao Ma if (err) { 176461f86638STao Ma EXT4_ERROR_INODE(dir, "error %d getting inode %lu block", 176561f86638STao Ma err, dir->i_ino); 176661f86638STao Ma return 1; 176761f86638STao Ma } 176861f86638STao Ma 176961f86638STao Ma down_read(&EXT4_I(dir)->xattr_sem); 177061f86638STao Ma if (!ext4_has_inline_data(dir)) { 177161f86638STao Ma *has_inline_data = 0; 177261f86638STao Ma goto out; 177361f86638STao Ma } 177461f86638STao Ma 177561f86638STao Ma de = (struct ext4_dir_entry_2 *)ext4_raw_inode(&iloc)->i_block; 177661f86638STao Ma if (!le32_to_cpu(de->inode)) { 177761f86638STao Ma ext4_warning(dir->i_sb, 177861f86638STao Ma "bad inline directory (dir #%lu) - no `..'", 177961f86638STao Ma dir->i_ino); 178061f86638STao Ma ret = 1; 178161f86638STao Ma goto out; 178261f86638STao Ma } 178361f86638STao Ma 178461f86638STao Ma offset = EXT4_INLINE_DOTDOT_SIZE; 178561f86638STao Ma while (offset < dir->i_size) { 178661f86638STao Ma de = ext4_get_inline_entry(dir, &iloc, offset, 178761f86638STao Ma &inline_pos, &inline_size); 178861f86638STao Ma if (ext4_check_dir_entry(dir, NULL, de, 178961f86638STao Ma iloc.bh, inline_pos, 179061f86638STao Ma inline_size, offset)) { 179161f86638STao Ma ext4_warning(dir->i_sb, 179261f86638STao Ma "bad inline directory (dir #%lu) - " 179361f86638STao Ma "inode %u, rec_len %u, name_len %d" 179461f86638STao Ma "inline size %d\n", 179561f86638STao Ma dir->i_ino, le32_to_cpu(de->inode), 179661f86638STao Ma le16_to_cpu(de->rec_len), de->name_len, 179761f86638STao Ma inline_size); 179861f86638STao Ma ret = 1; 179961f86638STao Ma goto out; 180061f86638STao Ma } 180161f86638STao Ma if (le32_to_cpu(de->inode)) { 180261f86638STao Ma ret = 0; 180361f86638STao Ma goto out; 180461f86638STao Ma } 180561f86638STao Ma offset += ext4_rec_len_from_disk(de->rec_len, inline_size); 180661f86638STao Ma } 180761f86638STao Ma 180861f86638STao Ma out: 180961f86638STao Ma up_read(&EXT4_I(dir)->xattr_sem); 181061f86638STao Ma brelse(iloc.bh); 181161f86638STao Ma return ret; 181261f86638STao Ma } 181361f86638STao Ma 181467cf5b09STao Ma int ext4_destroy_inline_data(handle_t *handle, struct inode *inode) 181567cf5b09STao Ma { 181667cf5b09STao Ma int ret; 181767cf5b09STao Ma 181867cf5b09STao Ma down_write(&EXT4_I(inode)->xattr_sem); 181967cf5b09STao Ma ret = ext4_destroy_inline_data_nolock(handle, inode); 182067cf5b09STao Ma up_write(&EXT4_I(inode)->xattr_sem); 182167cf5b09STao Ma 182267cf5b09STao Ma return ret; 182367cf5b09STao Ma } 182494191985STao Ma 182594191985STao Ma int ext4_inline_data_fiemap(struct inode *inode, 182694191985STao Ma struct fiemap_extent_info *fieinfo, 182794191985STao Ma int *has_inline) 182894191985STao Ma { 182994191985STao Ma __u64 physical = 0; 183094191985STao Ma __u64 length; 183194191985STao Ma __u32 flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_LAST; 183294191985STao Ma int error = 0; 183394191985STao Ma struct ext4_iloc iloc; 183494191985STao Ma 183594191985STao Ma down_read(&EXT4_I(inode)->xattr_sem); 183694191985STao Ma if (!ext4_has_inline_data(inode)) { 183794191985STao Ma *has_inline = 0; 183894191985STao Ma goto out; 183994191985STao Ma } 184094191985STao Ma 184194191985STao Ma error = ext4_get_inode_loc(inode, &iloc); 184294191985STao Ma if (error) 184394191985STao Ma goto out; 184494191985STao Ma 1845eaf37937SJan Kara physical = (__u64)iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits; 184694191985STao Ma physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data; 184794191985STao Ma physical += offsetof(struct ext4_inode, i_block); 184894191985STao Ma length = i_size_read(inode); 184994191985STao Ma 185094191985STao Ma if (physical) 185194191985STao Ma error = fiemap_fill_next_extent(fieinfo, 0, physical, 185294191985STao Ma length, flags); 185394191985STao Ma brelse(iloc.bh); 185494191985STao Ma out: 185594191985STao Ma up_read(&EXT4_I(inode)->xattr_sem); 185694191985STao Ma return (error < 0 ? error : 0); 185794191985STao Ma } 18580d812f77STao Ma 18590d812f77STao Ma /* 18600d812f77STao Ma * Called during xattr set, and if we can sparse space 'needed', 18610d812f77STao Ma * just create the extent tree evict the data to the outer block. 18620d812f77STao Ma * 18630d812f77STao Ma * We use jbd2 instead of page cache to move data to the 1st block 18640d812f77STao Ma * so that the whole transaction can be committed as a whole and 18650d812f77STao Ma * the data isn't lost because of the delayed page cache write. 18660d812f77STao Ma */ 18670d812f77STao Ma int ext4_try_to_evict_inline_data(handle_t *handle, 18680d812f77STao Ma struct inode *inode, 18690d812f77STao Ma int needed) 18700d812f77STao Ma { 18710d812f77STao Ma int error; 18720d812f77STao Ma struct ext4_xattr_entry *entry; 18730d812f77STao Ma struct ext4_xattr_ibody_header *header; 18740d812f77STao Ma struct ext4_inode *raw_inode; 18750d812f77STao Ma struct ext4_iloc iloc; 18760d812f77STao Ma 18770d812f77STao Ma error = ext4_get_inode_loc(inode, &iloc); 18780d812f77STao Ma if (error) 18790d812f77STao Ma return error; 18800d812f77STao Ma 18810d812f77STao Ma raw_inode = ext4_raw_inode(&iloc); 18820d812f77STao Ma header = IHDR(inode, raw_inode); 18830d812f77STao Ma entry = (struct ext4_xattr_entry *)((void *)raw_inode + 18840d812f77STao Ma EXT4_I(inode)->i_inline_off); 18850d812f77STao Ma if (EXT4_XATTR_LEN(entry->e_name_len) + 18860d812f77STao Ma EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)) < needed) { 18870d812f77STao Ma error = -ENOSPC; 18880d812f77STao Ma goto out; 18890d812f77STao Ma } 18900d812f77STao Ma 18910d812f77STao Ma error = ext4_convert_inline_data_nolock(handle, inode, &iloc); 18920d812f77STao Ma out: 18930d812f77STao Ma brelse(iloc.bh); 18940d812f77STao Ma return error; 18950d812f77STao Ma } 1896aef1c851STao Ma 1897aef1c851STao Ma void ext4_inline_data_truncate(struct inode *inode, int *has_inline) 1898aef1c851STao Ma { 1899aef1c851STao Ma handle_t *handle; 1900aef1c851STao Ma int inline_size, value_len, needed_blocks; 1901aef1c851STao Ma size_t i_size; 1902aef1c851STao Ma void *value = NULL; 1903aef1c851STao Ma struct ext4_xattr_ibody_find is = { 1904aef1c851STao Ma .s = { .not_found = -ENODATA, }, 1905aef1c851STao Ma }; 1906aef1c851STao Ma struct ext4_xattr_info i = { 1907aef1c851STao Ma .name_index = EXT4_XATTR_INDEX_SYSTEM, 1908aef1c851STao Ma .name = EXT4_XATTR_SYSTEM_DATA, 1909aef1c851STao Ma }; 1910aef1c851STao Ma 1911aef1c851STao Ma 1912aef1c851STao Ma needed_blocks = ext4_writepage_trans_blocks(inode); 19139924a92aSTheodore Ts'o handle = ext4_journal_start(inode, EXT4_HT_INODE, needed_blocks); 1914aef1c851STao Ma if (IS_ERR(handle)) 1915aef1c851STao Ma return; 1916aef1c851STao Ma 1917aef1c851STao Ma down_write(&EXT4_I(inode)->xattr_sem); 1918aef1c851STao Ma if (!ext4_has_inline_data(inode)) { 1919aef1c851STao Ma *has_inline = 0; 1920aef1c851STao Ma ext4_journal_stop(handle); 1921aef1c851STao Ma return; 1922aef1c851STao Ma } 1923aef1c851STao Ma 1924aef1c851STao Ma if (ext4_orphan_add(handle, inode)) 1925aef1c851STao Ma goto out; 1926aef1c851STao Ma 1927aef1c851STao Ma if (ext4_get_inode_loc(inode, &is.iloc)) 1928aef1c851STao Ma goto out; 1929aef1c851STao Ma 1930aef1c851STao Ma down_write(&EXT4_I(inode)->i_data_sem); 1931aef1c851STao Ma i_size = inode->i_size; 1932aef1c851STao Ma inline_size = ext4_get_inline_size(inode); 1933aef1c851STao Ma EXT4_I(inode)->i_disksize = i_size; 1934aef1c851STao Ma 1935aef1c851STao Ma if (i_size < inline_size) { 1936aef1c851STao Ma /* Clear the content in the xattr space. */ 1937aef1c851STao Ma if (inline_size > EXT4_MIN_INLINE_DATA_SIZE) { 1938aef1c851STao Ma if (ext4_xattr_ibody_find(inode, &i, &is)) 1939aef1c851STao Ma goto out_error; 1940aef1c851STao Ma 1941aef1c851STao Ma BUG_ON(is.s.not_found); 1942aef1c851STao Ma 1943aef1c851STao Ma value_len = le32_to_cpu(is.s.here->e_value_size); 1944aef1c851STao Ma value = kmalloc(value_len, GFP_NOFS); 1945aef1c851STao Ma if (!value) 1946aef1c851STao Ma goto out_error; 1947aef1c851STao Ma 1948aef1c851STao Ma if (ext4_xattr_ibody_get(inode, i.name_index, i.name, 1949aef1c851STao Ma value, value_len)) 1950aef1c851STao Ma goto out_error; 1951aef1c851STao Ma 1952aef1c851STao Ma i.value = value; 1953aef1c851STao Ma i.value_len = i_size > EXT4_MIN_INLINE_DATA_SIZE ? 1954aef1c851STao Ma i_size - EXT4_MIN_INLINE_DATA_SIZE : 0; 1955aef1c851STao Ma if (ext4_xattr_ibody_inline_set(handle, inode, &i, &is)) 1956aef1c851STao Ma goto out_error; 1957aef1c851STao Ma } 1958aef1c851STao Ma 1959aef1c851STao Ma /* Clear the content within i_blocks. */ 1960aef1c851STao Ma if (i_size < EXT4_MIN_INLINE_DATA_SIZE) 1961aef1c851STao Ma memset(ext4_raw_inode(&is.iloc)->i_block + i_size, 0, 1962aef1c851STao Ma EXT4_MIN_INLINE_DATA_SIZE - i_size); 1963aef1c851STao Ma 1964aef1c851STao Ma EXT4_I(inode)->i_inline_size = i_size < 1965aef1c851STao Ma EXT4_MIN_INLINE_DATA_SIZE ? 1966aef1c851STao Ma EXT4_MIN_INLINE_DATA_SIZE : i_size; 1967aef1c851STao Ma } 1968aef1c851STao Ma 1969aef1c851STao Ma out_error: 1970aef1c851STao Ma up_write(&EXT4_I(inode)->i_data_sem); 1971aef1c851STao Ma out: 1972aef1c851STao Ma brelse(is.iloc.bh); 1973aef1c851STao Ma up_write(&EXT4_I(inode)->xattr_sem); 1974aef1c851STao Ma kfree(value); 1975aef1c851STao Ma if (inode->i_nlink) 1976aef1c851STao Ma ext4_orphan_del(handle, inode); 1977aef1c851STao Ma 1978aef1c851STao Ma inode->i_mtime = inode->i_ctime = ext4_current_time(inode); 1979aef1c851STao Ma ext4_mark_inode_dirty(handle, inode); 1980aef1c851STao Ma if (IS_SYNC(inode)) 1981aef1c851STao Ma ext4_handle_sync(handle); 1982aef1c851STao Ma 1983aef1c851STao Ma ext4_journal_stop(handle); 1984aef1c851STao Ma return; 1985aef1c851STao Ma } 19860c8d414fSTao Ma 19870c8d414fSTao Ma int ext4_convert_inline_data(struct inode *inode) 19880c8d414fSTao Ma { 19890c8d414fSTao Ma int error, needed_blocks; 19900c8d414fSTao Ma handle_t *handle; 19910c8d414fSTao Ma struct ext4_iloc iloc; 19920c8d414fSTao Ma 19930c8d414fSTao Ma if (!ext4_has_inline_data(inode)) { 19940c8d414fSTao Ma ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); 19950c8d414fSTao Ma return 0; 19960c8d414fSTao Ma } 19970c8d414fSTao Ma 19980c8d414fSTao Ma needed_blocks = ext4_writepage_trans_blocks(inode); 19990c8d414fSTao Ma 20000c8d414fSTao Ma iloc.bh = NULL; 20010c8d414fSTao Ma error = ext4_get_inode_loc(inode, &iloc); 20020c8d414fSTao Ma if (error) 20030c8d414fSTao Ma return error; 20040c8d414fSTao Ma 20059924a92aSTheodore Ts'o handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, needed_blocks); 20060c8d414fSTao Ma if (IS_ERR(handle)) { 20070c8d414fSTao Ma error = PTR_ERR(handle); 20080c8d414fSTao Ma goto out_free; 20090c8d414fSTao Ma } 20100c8d414fSTao Ma 20110c8d414fSTao Ma down_write(&EXT4_I(inode)->xattr_sem); 20120c8d414fSTao Ma if (!ext4_has_inline_data(inode)) { 20130c8d414fSTao Ma up_write(&EXT4_I(inode)->xattr_sem); 20140c8d414fSTao Ma goto out; 20150c8d414fSTao Ma } 20160c8d414fSTao Ma 20170c8d414fSTao Ma error = ext4_convert_inline_data_nolock(handle, inode, &iloc); 20180c8d414fSTao Ma up_write(&EXT4_I(inode)->xattr_sem); 20190c8d414fSTao Ma out: 20200c8d414fSTao Ma ext4_journal_stop(handle); 20210c8d414fSTao Ma out_free: 20220c8d414fSTao Ma brelse(iloc.bh); 20230c8d414fSTao Ma return error; 20240c8d414fSTao Ma } 2025