brintos

brintos / linux-shallow public Read only

0
0
Text · 50.8 KiB · 3536ca7 Raw
2068 lines · c
1// SPDX-License-Identifier: LGPL-2.12/*3 * Copyright (c) 2012 Taobao.4 * Written by Tao Ma <boyu.mt@taobao.com>5 */6 7#include <linux/iomap.h>8#include <linux/fiemap.h>9#include <linux/namei.h>10#include <linux/iversion.h>11#include <linux/sched/mm.h>12 13#include "ext4_jbd2.h"14#include "ext4.h"15#include "xattr.h"16#include "truncate.h"17 18#define EXT4_XATTR_SYSTEM_DATA	"data"19#define EXT4_MIN_INLINE_DATA_SIZE	((sizeof(__le32) * EXT4_N_BLOCKS))20#define EXT4_INLINE_DOTDOT_OFFSET	221#define EXT4_INLINE_DOTDOT_SIZE		422 23static int ext4_get_inline_size(struct inode *inode)24{25	if (EXT4_I(inode)->i_inline_off)26		return EXT4_I(inode)->i_inline_size;27 28	return 0;29}30 31static int get_max_inline_xattr_value_size(struct inode *inode,32					   struct ext4_iloc *iloc)33{34	struct ext4_xattr_ibody_header *header;35	struct ext4_xattr_entry *entry;36	struct ext4_inode *raw_inode;37	void *end;38	int free, min_offs;39 40	if (!EXT4_INODE_HAS_XATTR_SPACE(inode))41		return 0;42 43	min_offs = EXT4_SB(inode->i_sb)->s_inode_size -44			EXT4_GOOD_OLD_INODE_SIZE -45			EXT4_I(inode)->i_extra_isize -46			sizeof(struct ext4_xattr_ibody_header);47 48	/*49	 * We need to subtract another sizeof(__u32) since an in-inode xattr50	 * needs an empty 4 bytes to indicate the gap between the xattr entry51	 * and the name/value pair.52	 */53	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))54		return EXT4_XATTR_SIZE(min_offs -55			EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA)) -56			EXT4_XATTR_ROUND - sizeof(__u32));57 58	raw_inode = ext4_raw_inode(iloc);59	header = IHDR(inode, raw_inode);60	entry = IFIRST(header);61	end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;62 63	/* Compute min_offs. */64	while (!IS_LAST_ENTRY(entry)) {65		void *next = EXT4_XATTR_NEXT(entry);66 67		if (next >= end) {68			EXT4_ERROR_INODE(inode,69					 "corrupt xattr in inline inode");70			return 0;71		}72		if (!entry->e_value_inum && entry->e_value_size) {73			size_t offs = le16_to_cpu(entry->e_value_offs);74			if (offs < min_offs)75				min_offs = offs;76		}77		entry = next;78	}79	free = min_offs -80		((void *)entry - (void *)IFIRST(header)) - sizeof(__u32);81 82	if (EXT4_I(inode)->i_inline_off) {83		entry = (struct ext4_xattr_entry *)84			((void *)raw_inode + EXT4_I(inode)->i_inline_off);85 86		free += EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size));87		goto out;88	}89 90	free -= EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA));91 92	if (free > EXT4_XATTR_ROUND)93		free = EXT4_XATTR_SIZE(free - EXT4_XATTR_ROUND);94	else95		free = 0;96 97out:98	return free;99}100 101/*102 * Get the maximum size we now can store in an inode.103 * If we can't find the space for a xattr entry, don't use the space104 * of the extents since we have no space to indicate the inline data.105 */106int ext4_get_max_inline_size(struct inode *inode)107{108	int error, max_inline_size;109	struct ext4_iloc iloc;110 111	if (EXT4_I(inode)->i_extra_isize == 0)112		return 0;113 114	error = ext4_get_inode_loc(inode, &iloc);115	if (error) {116		ext4_error_inode_err(inode, __func__, __LINE__, 0, -error,117				     "can't get inode location %lu",118				     inode->i_ino);119		return 0;120	}121 122	down_read(&EXT4_I(inode)->xattr_sem);123	max_inline_size = get_max_inline_xattr_value_size(inode, &iloc);124	up_read(&EXT4_I(inode)->xattr_sem);125 126	brelse(iloc.bh);127 128	if (!max_inline_size)129		return 0;130 131	return max_inline_size + EXT4_MIN_INLINE_DATA_SIZE;132}133 134/*135 * this function does not take xattr_sem, which is OK because it is136 * currently only used in a code path coming form ext4_iget, before137 * the new inode has been unlocked138 */139int ext4_find_inline_data_nolock(struct inode *inode)140{141	struct ext4_xattr_ibody_find is = {142		.s = { .not_found = -ENODATA, },143	};144	struct ext4_xattr_info i = {145		.name_index = EXT4_XATTR_INDEX_SYSTEM,146		.name = EXT4_XATTR_SYSTEM_DATA,147	};148	int error;149 150	if (EXT4_I(inode)->i_extra_isize == 0)151		return 0;152 153	error = ext4_get_inode_loc(inode, &is.iloc);154	if (error)155		return error;156 157	error = ext4_xattr_ibody_find(inode, &i, &is);158	if (error)159		goto out;160 161	if (!is.s.not_found) {162		if (is.s.here->e_value_inum) {163			EXT4_ERROR_INODE(inode, "inline data xattr refers "164					 "to an external xattr inode");165			error = -EFSCORRUPTED;166			goto out;167		}168		EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here -169					(void *)ext4_raw_inode(&is.iloc));170		EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE +171				le32_to_cpu(is.s.here->e_value_size);172	}173out:174	brelse(is.iloc.bh);175	return error;176}177 178static int ext4_read_inline_data(struct inode *inode, void *buffer,179				 unsigned int len,180				 struct ext4_iloc *iloc)181{182	struct ext4_xattr_entry *entry;183	struct ext4_xattr_ibody_header *header;184	int cp_len = 0;185	struct ext4_inode *raw_inode;186 187	if (!len)188		return 0;189 190	BUG_ON(len > EXT4_I(inode)->i_inline_size);191 192	cp_len = min_t(unsigned int, len, EXT4_MIN_INLINE_DATA_SIZE);193 194	raw_inode = ext4_raw_inode(iloc);195	memcpy(buffer, (void *)(raw_inode->i_block), cp_len);196 197	len -= cp_len;198	buffer += cp_len;199 200	if (!len)201		goto out;202 203	header = IHDR(inode, raw_inode);204	entry = (struct ext4_xattr_entry *)((void *)raw_inode +205					    EXT4_I(inode)->i_inline_off);206	len = min_t(unsigned int, len,207		    (unsigned int)le32_to_cpu(entry->e_value_size));208 209	memcpy(buffer,210	       (void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs), len);211	cp_len += len;212 213out:214	return cp_len;215}216 217/*218 * write the buffer to the inline inode.219 * If 'create' is set, we don't need to do the extra copy in the xattr220 * value since it is already handled by ext4_xattr_ibody_set.221 * That saves us one memcpy.222 */223static void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc,224				   void *buffer, loff_t pos, unsigned int len)225{226	struct ext4_xattr_entry *entry;227	struct ext4_xattr_ibody_header *header;228	struct ext4_inode *raw_inode;229	int cp_len = 0;230 231	if (unlikely(ext4_forced_shutdown(inode->i_sb)))232		return;233 234	BUG_ON(!EXT4_I(inode)->i_inline_off);235	BUG_ON(pos + len > EXT4_I(inode)->i_inline_size);236 237	raw_inode = ext4_raw_inode(iloc);238	buffer += pos;239 240	if (pos < EXT4_MIN_INLINE_DATA_SIZE) {241		cp_len = pos + len > EXT4_MIN_INLINE_DATA_SIZE ?242			 EXT4_MIN_INLINE_DATA_SIZE - pos : len;243		memcpy((void *)raw_inode->i_block + pos, buffer, cp_len);244 245		len -= cp_len;246		buffer += cp_len;247		pos += cp_len;248	}249 250	if (!len)251		return;252 253	pos -= EXT4_MIN_INLINE_DATA_SIZE;254	header = IHDR(inode, raw_inode);255	entry = (struct ext4_xattr_entry *)((void *)raw_inode +256					    EXT4_I(inode)->i_inline_off);257 258	memcpy((void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs) + pos,259	       buffer, len);260}261 262static int ext4_create_inline_data(handle_t *handle,263				   struct inode *inode, unsigned len)264{265	int error;266	void *value = NULL;267	struct ext4_xattr_ibody_find is = {268		.s = { .not_found = -ENODATA, },269	};270	struct ext4_xattr_info i = {271		.name_index = EXT4_XATTR_INDEX_SYSTEM,272		.name = EXT4_XATTR_SYSTEM_DATA,273	};274 275	error = ext4_get_inode_loc(inode, &is.iloc);276	if (error)277		return error;278 279	BUFFER_TRACE(is.iloc.bh, "get_write_access");280	error = ext4_journal_get_write_access(handle, inode->i_sb, is.iloc.bh,281					      EXT4_JTR_NONE);282	if (error)283		goto out;284 285	if (len > EXT4_MIN_INLINE_DATA_SIZE) {286		value = EXT4_ZERO_XATTR_VALUE;287		len -= EXT4_MIN_INLINE_DATA_SIZE;288	} else {289		value = "";290		len = 0;291	}292 293	/* Insert the xttr entry. */294	i.value = value;295	i.value_len = len;296 297	error = ext4_xattr_ibody_find(inode, &i, &is);298	if (error)299		goto out;300 301	BUG_ON(!is.s.not_found);302 303	error = ext4_xattr_ibody_set(handle, inode, &i, &is);304	if (error) {305		if (error == -ENOSPC)306			ext4_clear_inode_state(inode,307					       EXT4_STATE_MAY_INLINE_DATA);308		goto out;309	}310 311	memset((void *)ext4_raw_inode(&is.iloc)->i_block,312		0, EXT4_MIN_INLINE_DATA_SIZE);313 314	EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here -315				      (void *)ext4_raw_inode(&is.iloc));316	EXT4_I(inode)->i_inline_size = len + EXT4_MIN_INLINE_DATA_SIZE;317	ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS);318	ext4_set_inode_flag(inode, EXT4_INODE_INLINE_DATA);319	get_bh(is.iloc.bh);320	error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);321 322out:323	brelse(is.iloc.bh);324	return error;325}326 327static int ext4_update_inline_data(handle_t *handle, struct inode *inode,328				   unsigned int len)329{330	int error;331	void *value = NULL;332	struct ext4_xattr_ibody_find is = {333		.s = { .not_found = -ENODATA, },334	};335	struct ext4_xattr_info i = {336		.name_index = EXT4_XATTR_INDEX_SYSTEM,337		.name = EXT4_XATTR_SYSTEM_DATA,338	};339 340	/* If the old space is ok, write the data directly. */341	if (len <= EXT4_I(inode)->i_inline_size)342		return 0;343 344	error = ext4_get_inode_loc(inode, &is.iloc);345	if (error)346		return error;347 348	error = ext4_xattr_ibody_find(inode, &i, &is);349	if (error)350		goto out;351 352	BUG_ON(is.s.not_found);353 354	len -= EXT4_MIN_INLINE_DATA_SIZE;355	value = kzalloc(len, GFP_NOFS);356	if (!value) {357		error = -ENOMEM;358		goto out;359	}360 361	error = ext4_xattr_ibody_get(inode, i.name_index, i.name,362				     value, len);363	if (error < 0)364		goto out;365 366	BUFFER_TRACE(is.iloc.bh, "get_write_access");367	error = ext4_journal_get_write_access(handle, inode->i_sb, is.iloc.bh,368					      EXT4_JTR_NONE);369	if (error)370		goto out;371 372	/* Update the xattr entry. */373	i.value = value;374	i.value_len = len;375 376	error = ext4_xattr_ibody_set(handle, inode, &i, &is);377	if (error)378		goto out;379 380	EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here -381				      (void *)ext4_raw_inode(&is.iloc));382	EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE +383				le32_to_cpu(is.s.here->e_value_size);384	ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);385	get_bh(is.iloc.bh);386	error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);387 388out:389	kfree(value);390	brelse(is.iloc.bh);391	return error;392}393 394static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,395				    unsigned int len)396{397	int ret, size, no_expand;398	struct ext4_inode_info *ei = EXT4_I(inode);399 400	if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA))401		return -ENOSPC;402 403	size = ext4_get_max_inline_size(inode);404	if (size < len)405		return -ENOSPC;406 407	ext4_write_lock_xattr(inode, &no_expand);408 409	if (ei->i_inline_off)410		ret = ext4_update_inline_data(handle, inode, len);411	else412		ret = ext4_create_inline_data(handle, inode, len);413 414	ext4_write_unlock_xattr(inode, &no_expand);415	return ret;416}417 418static int ext4_destroy_inline_data_nolock(handle_t *handle,419					   struct inode *inode)420{421	struct ext4_inode_info *ei = EXT4_I(inode);422	struct ext4_xattr_ibody_find is = {423		.s = { .not_found = 0, },424	};425	struct ext4_xattr_info i = {426		.name_index = EXT4_XATTR_INDEX_SYSTEM,427		.name = EXT4_XATTR_SYSTEM_DATA,428		.value = NULL,429		.value_len = 0,430	};431	int error;432 433	if (!ei->i_inline_off)434		return 0;435 436	error = ext4_get_inode_loc(inode, &is.iloc);437	if (error)438		return error;439 440	error = ext4_xattr_ibody_find(inode, &i, &is);441	if (error)442		goto out;443 444	BUFFER_TRACE(is.iloc.bh, "get_write_access");445	error = ext4_journal_get_write_access(handle, inode->i_sb, is.iloc.bh,446					      EXT4_JTR_NONE);447	if (error)448		goto out;449 450	error = ext4_xattr_ibody_set(handle, inode, &i, &is);451	if (error)452		goto out;453 454	memset((void *)ext4_raw_inode(&is.iloc)->i_block,455		0, EXT4_MIN_INLINE_DATA_SIZE);456	memset(ei->i_data, 0, EXT4_MIN_INLINE_DATA_SIZE);457 458	if (ext4_has_feature_extents(inode->i_sb)) {459		if (S_ISDIR(inode->i_mode) ||460		    S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) {461			ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS);462			ext4_ext_tree_init(handle, inode);463		}464	}465	ext4_clear_inode_flag(inode, EXT4_INODE_INLINE_DATA);466 467	get_bh(is.iloc.bh);468	error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);469 470	EXT4_I(inode)->i_inline_off = 0;471	EXT4_I(inode)->i_inline_size = 0;472	ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);473out:474	brelse(is.iloc.bh);475	if (error == -ENODATA)476		error = 0;477	return error;478}479 480static int ext4_read_inline_folio(struct inode *inode, struct folio *folio)481{482	void *kaddr;483	int ret = 0;484	size_t len;485	struct ext4_iloc iloc;486 487	BUG_ON(!folio_test_locked(folio));488	BUG_ON(!ext4_has_inline_data(inode));489	BUG_ON(folio->index);490 491	if (!EXT4_I(inode)->i_inline_off) {492		ext4_warning(inode->i_sb, "inode %lu doesn't have inline data.",493			     inode->i_ino);494		goto out;495	}496 497	ret = ext4_get_inode_loc(inode, &iloc);498	if (ret)499		goto out;500 501	len = min_t(size_t, ext4_get_inline_size(inode), i_size_read(inode));502	BUG_ON(len > PAGE_SIZE);503	kaddr = kmap_local_folio(folio, 0);504	ret = ext4_read_inline_data(inode, kaddr, len, &iloc);505	kaddr = folio_zero_tail(folio, len, kaddr + len);506	kunmap_local(kaddr);507	folio_mark_uptodate(folio);508	brelse(iloc.bh);509 510out:511	return ret;512}513 514int ext4_readpage_inline(struct inode *inode, struct folio *folio)515{516	int ret = 0;517 518	down_read(&EXT4_I(inode)->xattr_sem);519	if (!ext4_has_inline_data(inode)) {520		up_read(&EXT4_I(inode)->xattr_sem);521		return -EAGAIN;522	}523 524	/*525	 * Current inline data can only exist in the 1st page,526	 * So for all the other pages, just set them uptodate.527	 */528	if (!folio->index)529		ret = ext4_read_inline_folio(inode, folio);530	else if (!folio_test_uptodate(folio)) {531		folio_zero_segment(folio, 0, folio_size(folio));532		folio_mark_uptodate(folio);533	}534 535	up_read(&EXT4_I(inode)->xattr_sem);536 537	folio_unlock(folio);538	return ret >= 0 ? 0 : ret;539}540 541static int ext4_convert_inline_data_to_extent(struct address_space *mapping,542					      struct inode *inode)543{544	int ret, needed_blocks, no_expand;545	handle_t *handle = NULL;546	int retries = 0, sem_held = 0;547	struct folio *folio = NULL;548	unsigned from, to;549	struct ext4_iloc iloc;550 551	if (!ext4_has_inline_data(inode)) {552		/*553		 * clear the flag so that no new write554		 * will trap here again.555		 */556		ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);557		return 0;558	}559 560	needed_blocks = ext4_writepage_trans_blocks(inode);561 562	ret = ext4_get_inode_loc(inode, &iloc);563	if (ret)564		return ret;565 566retry:567	handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, needed_blocks);568	if (IS_ERR(handle)) {569		ret = PTR_ERR(handle);570		handle = NULL;571		goto out;572	}573 574	/* We cannot recurse into the filesystem as the transaction is already575	 * started */576	folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN | FGP_NOFS,577			mapping_gfp_mask(mapping));578	if (IS_ERR(folio)) {579		ret = PTR_ERR(folio);580		goto out_nofolio;581	}582 583	ext4_write_lock_xattr(inode, &no_expand);584	sem_held = 1;585	/* If some one has already done this for us, just exit. */586	if (!ext4_has_inline_data(inode)) {587		ret = 0;588		goto out;589	}590 591	from = 0;592	to = ext4_get_inline_size(inode);593	if (!folio_test_uptodate(folio)) {594		ret = ext4_read_inline_folio(inode, folio);595		if (ret < 0)596			goto out;597	}598 599	ret = ext4_destroy_inline_data_nolock(handle, inode);600	if (ret)601		goto out;602 603	if (ext4_should_dioread_nolock(inode)) {604		ret = ext4_block_write_begin(handle, folio, from, to,605					     ext4_get_block_unwritten);606	} else607		ret = ext4_block_write_begin(handle, folio, from, to,608					     ext4_get_block);609 610	if (!ret && ext4_should_journal_data(inode)) {611		ret = ext4_walk_page_buffers(handle, inode,612					     folio_buffers(folio), from, to,613					     NULL, do_journal_get_write_access);614	}615 616	if (ret) {617		folio_unlock(folio);618		folio_put(folio);619		folio = NULL;620		ext4_orphan_add(handle, inode);621		ext4_write_unlock_xattr(inode, &no_expand);622		sem_held = 0;623		ext4_journal_stop(handle);624		handle = NULL;625		ext4_truncate_failed_write(inode);626		/*627		 * If truncate failed early the inode might628		 * still be on the orphan list; we need to629		 * make sure the inode is removed from the630		 * orphan list in that case.631		 */632		if (inode->i_nlink)633			ext4_orphan_del(NULL, inode);634	}635 636	if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))637		goto retry;638 639	if (folio)640		block_commit_write(&folio->page, from, to);641out:642	if (folio) {643		folio_unlock(folio);644		folio_put(folio);645	}646out_nofolio:647	if (sem_held)648		ext4_write_unlock_xattr(inode, &no_expand);649	if (handle)650		ext4_journal_stop(handle);651	brelse(iloc.bh);652	return ret;653}654 655/*656 * Try to write data in the inode.657 * If the inode has inline data, check whether the new write can be658 * in the inode also. If not, create the page the handle, move the data659 * to the page make it update and let the later codes create extent for it.660 */661int ext4_try_to_write_inline_data(struct address_space *mapping,662				  struct inode *inode,663				  loff_t pos, unsigned len,664				  struct folio **foliop)665{666	int ret;667	handle_t *handle;668	struct folio *folio;669	struct ext4_iloc iloc;670 671	if (pos + len > ext4_get_max_inline_size(inode))672		goto convert;673 674	ret = ext4_get_inode_loc(inode, &iloc);675	if (ret)676		return ret;677 678	/*679	 * The possible write could happen in the inode,680	 * so try to reserve the space in inode first.681	 */682	handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);683	if (IS_ERR(handle)) {684		ret = PTR_ERR(handle);685		handle = NULL;686		goto out;687	}688 689	ret = ext4_prepare_inline_data(handle, inode, pos + len);690	if (ret && ret != -ENOSPC)691		goto out;692 693	/* We don't have space in inline inode, so convert it to extent. */694	if (ret == -ENOSPC) {695		ext4_journal_stop(handle);696		brelse(iloc.bh);697		goto convert;698	}699 700	ret = ext4_journal_get_write_access(handle, inode->i_sb, iloc.bh,701					    EXT4_JTR_NONE);702	if (ret)703		goto out;704 705	folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN | FGP_NOFS,706					mapping_gfp_mask(mapping));707	if (IS_ERR(folio)) {708		ret = PTR_ERR(folio);709		goto out;710	}711 712	*foliop = folio;713	down_read(&EXT4_I(inode)->xattr_sem);714	if (!ext4_has_inline_data(inode)) {715		ret = 0;716		folio_unlock(folio);717		folio_put(folio);718		goto out_up_read;719	}720 721	if (!folio_test_uptodate(folio)) {722		ret = ext4_read_inline_folio(inode, folio);723		if (ret < 0) {724			folio_unlock(folio);725			folio_put(folio);726			goto out_up_read;727		}728	}729 730	ret = 1;731	handle = NULL;732out_up_read:733	up_read(&EXT4_I(inode)->xattr_sem);734out:735	if (handle && (ret != 1))736		ext4_journal_stop(handle);737	brelse(iloc.bh);738	return ret;739convert:740	return ext4_convert_inline_data_to_extent(mapping, inode);741}742 743int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,744			       unsigned copied, struct folio *folio)745{746	handle_t *handle = ext4_journal_current_handle();747	int no_expand;748	void *kaddr;749	struct ext4_iloc iloc;750	int ret = 0, ret2;751 752	if (unlikely(copied < len) && !folio_test_uptodate(folio))753		copied = 0;754 755	if (likely(copied)) {756		ret = ext4_get_inode_loc(inode, &iloc);757		if (ret) {758			folio_unlock(folio);759			folio_put(folio);760			ext4_std_error(inode->i_sb, ret);761			goto out;762		}763		ext4_write_lock_xattr(inode, &no_expand);764		BUG_ON(!ext4_has_inline_data(inode));765 766		/*767		 * ei->i_inline_off may have changed since768		 * ext4_write_begin() called769		 * ext4_try_to_write_inline_data()770		 */771		(void) ext4_find_inline_data_nolock(inode);772 773		kaddr = kmap_local_folio(folio, 0);774		ext4_write_inline_data(inode, &iloc, kaddr, pos, copied);775		kunmap_local(kaddr);776		folio_mark_uptodate(folio);777		/* clear dirty flag so that writepages wouldn't work for us. */778		folio_clear_dirty(folio);779 780		ext4_write_unlock_xattr(inode, &no_expand);781		brelse(iloc.bh);782 783		/*784		 * It's important to update i_size while still holding folio785		 * lock: page writeout could otherwise come in and zero786		 * beyond i_size.787		 */788		ext4_update_inode_size(inode, pos + copied);789	}790	folio_unlock(folio);791	folio_put(folio);792 793	/*794	 * Don't mark the inode dirty under folio lock. First, it unnecessarily795	 * makes the holding time of folio lock longer. Second, it forces lock796	 * ordering of folio lock and transaction start for journaling797	 * filesystems.798	 */799	if (likely(copied))800		mark_inode_dirty(inode);801out:802	/*803	 * If we didn't copy as much data as expected, we need to trim back804	 * size of xattr containing inline data.805	 */806	if (pos + len > inode->i_size && ext4_can_truncate(inode))807		ext4_orphan_add(handle, inode);808 809	ret2 = ext4_journal_stop(handle);810	if (!ret)811		ret = ret2;812	if (pos + len > inode->i_size) {813		ext4_truncate_failed_write(inode);814		/*815		 * If truncate failed early the inode might still be816		 * on the orphan list; we need to make sure the inode817		 * is removed from the orphan list in that case.818		 */819		if (inode->i_nlink)820			ext4_orphan_del(NULL, inode);821	}822	return ret ? ret : copied;823}824 825/*826 * Try to make the page cache and handle ready for the inline data case.827 * We can call this function in 2 cases:828 * 1. The inode is created and the first write exceeds inline size. We can829 *    clear the inode state safely.830 * 2. The inode has inline data, then we need to read the data, make it831 *    update and dirty so that ext4_da_writepages can handle it. We don't832 *    need to start the journal since the file's metadata isn't changed now.833 */834static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping,835						 struct inode *inode,836						 void **fsdata)837{838	int ret = 0, inline_size;839	struct folio *folio;840 841	folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN,842					mapping_gfp_mask(mapping));843	if (IS_ERR(folio))844		return PTR_ERR(folio);845 846	down_read(&EXT4_I(inode)->xattr_sem);847	if (!ext4_has_inline_data(inode)) {848		ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);849		goto out;850	}851 852	inline_size = ext4_get_inline_size(inode);853 854	if (!folio_test_uptodate(folio)) {855		ret = ext4_read_inline_folio(inode, folio);856		if (ret < 0)857			goto out;858	}859 860	ret = ext4_block_write_begin(NULL, folio, 0, inline_size,861				     ext4_da_get_block_prep);862	if (ret) {863		up_read(&EXT4_I(inode)->xattr_sem);864		folio_unlock(folio);865		folio_put(folio);866		ext4_truncate_failed_write(inode);867		return ret;868	}869 870	folio_mark_dirty(folio);871	folio_mark_uptodate(folio);872	ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);873	*fsdata = (void *)CONVERT_INLINE_DATA;874 875out:876	up_read(&EXT4_I(inode)->xattr_sem);877	if (folio) {878		folio_unlock(folio);879		folio_put(folio);880	}881	return ret;882}883 884/*885 * Prepare the write for the inline data.886 * If the data can be written into the inode, we just read887 * the page and make it uptodate, and start the journal.888 * Otherwise read the page, makes it dirty so that it can be889 * handle in writepages(the i_disksize update is left to the890 * normal ext4_da_write_end).891 */892int ext4_da_write_inline_data_begin(struct address_space *mapping,893				    struct inode *inode,894				    loff_t pos, unsigned len,895				    struct folio **foliop,896				    void **fsdata)897{898	int ret;899	handle_t *handle;900	struct folio *folio;901	struct ext4_iloc iloc;902	int retries = 0;903 904	ret = ext4_get_inode_loc(inode, &iloc);905	if (ret)906		return ret;907 908retry_journal:909	handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);910	if (IS_ERR(handle)) {911		ret = PTR_ERR(handle);912		goto out;913	}914 915	ret = ext4_prepare_inline_data(handle, inode, pos + len);916	if (ret && ret != -ENOSPC)917		goto out_journal;918 919	if (ret == -ENOSPC) {920		ext4_journal_stop(handle);921		ret = ext4_da_convert_inline_data_to_extent(mapping,922							    inode,923							    fsdata);924		if (ret == -ENOSPC &&925		    ext4_should_retry_alloc(inode->i_sb, &retries))926			goto retry_journal;927		goto out;928	}929 930	/*931	 * We cannot recurse into the filesystem as the transaction932	 * is already started.933	 */934	folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN | FGP_NOFS,935					mapping_gfp_mask(mapping));936	if (IS_ERR(folio)) {937		ret = PTR_ERR(folio);938		goto out_journal;939	}940 941	down_read(&EXT4_I(inode)->xattr_sem);942	if (!ext4_has_inline_data(inode)) {943		ret = 0;944		goto out_release_page;945	}946 947	if (!folio_test_uptodate(folio)) {948		ret = ext4_read_inline_folio(inode, folio);949		if (ret < 0)950			goto out_release_page;951	}952	ret = ext4_journal_get_write_access(handle, inode->i_sb, iloc.bh,953					    EXT4_JTR_NONE);954	if (ret)955		goto out_release_page;956 957	up_read(&EXT4_I(inode)->xattr_sem);958	*foliop = folio;959	brelse(iloc.bh);960	return 1;961out_release_page:962	up_read(&EXT4_I(inode)->xattr_sem);963	folio_unlock(folio);964	folio_put(folio);965out_journal:966	ext4_journal_stop(handle);967out:968	brelse(iloc.bh);969	return ret;970}971 972#ifdef INLINE_DIR_DEBUG973void ext4_show_inline_dir(struct inode *dir, struct buffer_head *bh,974			  void *inline_start, int inline_size)975{976	int offset;977	unsigned short de_len;978	struct ext4_dir_entry_2 *de = inline_start;979	void *dlimit = inline_start + inline_size;980 981	trace_printk("inode %lu\n", dir->i_ino);982	offset = 0;983	while ((void *)de < dlimit) {984		de_len = ext4_rec_len_from_disk(de->rec_len, inline_size);985		trace_printk("de: off %u rlen %u name %.*s nlen %u ino %u\n",986			     offset, de_len, de->name_len, de->name,987			     de->name_len, le32_to_cpu(de->inode));988		if (ext4_check_dir_entry(dir, NULL, de, bh,989					 inline_start, inline_size, offset))990			BUG();991 992		offset += de_len;993		de = (struct ext4_dir_entry_2 *) ((char *) de + de_len);994	}995}996#else997#define ext4_show_inline_dir(dir, bh, inline_start, inline_size)998#endif999 1000/*1001 * Add a new entry into a inline dir.1002 * It will return -ENOSPC if no space is available, and -EIO1003 * and -EEXIST if directory entry already exists.1004 */1005static int ext4_add_dirent_to_inline(handle_t *handle,1006				     struct ext4_filename *fname,1007				     struct inode *dir,1008				     struct inode *inode,1009				     struct ext4_iloc *iloc,1010				     void *inline_start, int inline_size)1011{1012	int		err;1013	struct ext4_dir_entry_2 *de;1014 1015	err = ext4_find_dest_de(dir, inode, iloc->bh, inline_start,1016				inline_size, fname, &de);1017	if (err)1018		return err;1019 1020	BUFFER_TRACE(iloc->bh, "get_write_access");1021	err = ext4_journal_get_write_access(handle, dir->i_sb, iloc->bh,1022					    EXT4_JTR_NONE);1023	if (err)1024		return err;1025	ext4_insert_dentry(dir, inode, de, inline_size, fname);1026 1027	ext4_show_inline_dir(dir, iloc->bh, inline_start, inline_size);1028 1029	/*1030	 * XXX shouldn't update any times until successful1031	 * completion of syscall, but too many callers depend1032	 * on this.1033	 *1034	 * XXX similarly, too many callers depend on1035	 * ext4_new_inode() setting the times, but error1036	 * recovery deletes the inode, so the worst that can1037	 * happen is that the times are slightly out of date1038	 * and/or different from the directory change time.1039	 */1040	inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));1041	ext4_update_dx_flag(dir);1042	inode_inc_iversion(dir);1043	return 1;1044}1045 1046static void *ext4_get_inline_xattr_pos(struct inode *inode,1047				       struct ext4_iloc *iloc)1048{1049	struct ext4_xattr_entry *entry;1050	struct ext4_xattr_ibody_header *header;1051 1052	BUG_ON(!EXT4_I(inode)->i_inline_off);1053 1054	header = IHDR(inode, ext4_raw_inode(iloc));1055	entry = (struct ext4_xattr_entry *)((void *)ext4_raw_inode(iloc) +1056					    EXT4_I(inode)->i_inline_off);1057 1058	return (void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs);1059}1060 1061/* Set the final de to cover the whole block. */1062static void ext4_update_final_de(void *de_buf, int old_size, int new_size)1063{1064	struct ext4_dir_entry_2 *de, *prev_de;1065	void *limit;1066	int de_len;1067 1068	de = de_buf;1069	if (old_size) {1070		limit = de_buf + old_size;1071		do {1072			prev_de = de;1073			de_len = ext4_rec_len_from_disk(de->rec_len, old_size);1074			de_buf += de_len;1075			de = de_buf;1076		} while (de_buf < limit);1077 1078		prev_de->rec_len = ext4_rec_len_to_disk(de_len + new_size -1079							old_size, new_size);1080	} else {1081		/* this is just created, so create an empty entry. */1082		de->inode = 0;1083		de->rec_len = ext4_rec_len_to_disk(new_size, new_size);1084	}1085}1086 1087static int ext4_update_inline_dir(handle_t *handle, struct inode *dir,1088				  struct ext4_iloc *iloc)1089{1090	int ret;1091	int old_size = EXT4_I(dir)->i_inline_size - EXT4_MIN_INLINE_DATA_SIZE;1092	int new_size = get_max_inline_xattr_value_size(dir, iloc);1093 1094	if (new_size - old_size <= ext4_dir_rec_len(1, NULL))1095		return -ENOSPC;1096 1097	ret = ext4_update_inline_data(handle, dir,1098				      new_size + EXT4_MIN_INLINE_DATA_SIZE);1099	if (ret)1100		return ret;1101 1102	ext4_update_final_de(ext4_get_inline_xattr_pos(dir, iloc), old_size,1103			     EXT4_I(dir)->i_inline_size -1104						EXT4_MIN_INLINE_DATA_SIZE);1105	dir->i_size = EXT4_I(dir)->i_disksize = EXT4_I(dir)->i_inline_size;1106	return 0;1107}1108 1109static void ext4_restore_inline_data(handle_t *handle, struct inode *inode,1110				     struct ext4_iloc *iloc,1111				     void *buf, int inline_size)1112{1113	int ret;1114 1115	ret = ext4_create_inline_data(handle, inode, inline_size);1116	if (ret) {1117		ext4_msg(inode->i_sb, KERN_EMERG,1118			"error restoring inline_data for inode -- potential data loss! (inode %lu, error %d)",1119			inode->i_ino, ret);1120		return;1121	}1122	ext4_write_inline_data(inode, iloc, buf, 0, inline_size);1123	ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);1124}1125 1126static int ext4_finish_convert_inline_dir(handle_t *handle,1127					  struct inode *inode,1128					  struct buffer_head *dir_block,1129					  void *buf,1130					  int inline_size)1131{1132	int err, csum_size = 0, header_size = 0;1133	struct ext4_dir_entry_2 *de;1134	void *target = dir_block->b_data;1135 1136	/*1137	 * First create "." and ".." and then copy the dir information1138	 * back to the block.1139	 */1140	de = target;1141	de = ext4_init_dot_dotdot(inode, de,1142		inode->i_sb->s_blocksize, csum_size,1143		le32_to_cpu(((struct ext4_dir_entry_2 *)buf)->inode), 1);1144	header_size = (void *)de - target;1145 1146	memcpy((void *)de, buf + EXT4_INLINE_DOTDOT_SIZE,1147		inline_size - EXT4_INLINE_DOTDOT_SIZE);1148 1149	if (ext4_has_metadata_csum(inode->i_sb))1150		csum_size = sizeof(struct ext4_dir_entry_tail);1151 1152	inode->i_size = inode->i_sb->s_blocksize;1153	i_size_write(inode, inode->i_sb->s_blocksize);1154	EXT4_I(inode)->i_disksize = inode->i_sb->s_blocksize;1155	ext4_update_final_de(dir_block->b_data,1156			inline_size - EXT4_INLINE_DOTDOT_SIZE + header_size,1157			inode->i_sb->s_blocksize - csum_size);1158 1159	if (csum_size)1160		ext4_initialize_dirent_tail(dir_block,1161					    inode->i_sb->s_blocksize);1162	set_buffer_uptodate(dir_block);1163	unlock_buffer(dir_block);1164	err = ext4_handle_dirty_dirblock(handle, inode, dir_block);1165	if (err)1166		return err;1167	set_buffer_verified(dir_block);1168	return ext4_mark_inode_dirty(handle, inode);1169}1170 1171static int ext4_convert_inline_data_nolock(handle_t *handle,1172					   struct inode *inode,1173					   struct ext4_iloc *iloc)1174{1175	int error;1176	void *buf = NULL;1177	struct buffer_head *data_bh = NULL;1178	struct ext4_map_blocks map;1179	int inline_size;1180 1181	inline_size = ext4_get_inline_size(inode);1182	buf = kmalloc(inline_size, GFP_NOFS);1183	if (!buf) {1184		error = -ENOMEM;1185		goto out;1186	}1187 1188	error = ext4_read_inline_data(inode, buf, inline_size, iloc);1189	if (error < 0)1190		goto out;1191 1192	/*1193	 * Make sure the inline directory entries pass checks before we try to1194	 * convert them, so that we avoid touching stuff that needs fsck.1195	 */1196	if (S_ISDIR(inode->i_mode)) {1197		error = ext4_check_all_de(inode, iloc->bh,1198					buf + EXT4_INLINE_DOTDOT_SIZE,1199					inline_size - EXT4_INLINE_DOTDOT_SIZE);1200		if (error)1201			goto out;1202	}1203 1204	error = ext4_destroy_inline_data_nolock(handle, inode);1205	if (error)1206		goto out;1207 1208	map.m_lblk = 0;1209	map.m_len = 1;1210	map.m_flags = 0;1211	error = ext4_map_blocks(handle, inode, &map, EXT4_GET_BLOCKS_CREATE);1212	if (error < 0)1213		goto out_restore;1214	if (!(map.m_flags & EXT4_MAP_MAPPED)) {1215		error = -EIO;1216		goto out_restore;1217	}1218 1219	data_bh = sb_getblk(inode->i_sb, map.m_pblk);1220	if (!data_bh) {1221		error = -ENOMEM;1222		goto out_restore;1223	}1224 1225	lock_buffer(data_bh);1226	error = ext4_journal_get_create_access(handle, inode->i_sb, data_bh,1227					       EXT4_JTR_NONE);1228	if (error) {1229		unlock_buffer(data_bh);1230		error = -EIO;1231		goto out_restore;1232	}1233	memset(data_bh->b_data, 0, inode->i_sb->s_blocksize);1234 1235	if (!S_ISDIR(inode->i_mode)) {1236		memcpy(data_bh->b_data, buf, inline_size);1237		set_buffer_uptodate(data_bh);1238		unlock_buffer(data_bh);1239		error = ext4_handle_dirty_metadata(handle,1240						   inode, data_bh);1241	} else {1242		error = ext4_finish_convert_inline_dir(handle, inode, data_bh,1243						       buf, inline_size);1244	}1245 1246out_restore:1247	if (error)1248		ext4_restore_inline_data(handle, inode, iloc, buf, inline_size);1249 1250out:1251	brelse(data_bh);1252	kfree(buf);1253	return error;1254}1255 1256/*1257 * Try to add the new entry to the inline data.1258 * If succeeds, return 0. If not, extended the inline dir and copied data to1259 * the new created block.1260 */1261int ext4_try_add_inline_entry(handle_t *handle, struct ext4_filename *fname,1262			      struct inode *dir, struct inode *inode)1263{1264	int ret, ret2, inline_size, no_expand;1265	void *inline_start;1266	struct ext4_iloc iloc;1267 1268	ret = ext4_get_inode_loc(dir, &iloc);1269	if (ret)1270		return ret;1271 1272	ext4_write_lock_xattr(dir, &no_expand);1273	if (!ext4_has_inline_data(dir))1274		goto out;1275 1276	inline_start = (void *)ext4_raw_inode(&iloc)->i_block +1277						 EXT4_INLINE_DOTDOT_SIZE;1278	inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE;1279 1280	ret = ext4_add_dirent_to_inline(handle, fname, dir, inode, &iloc,1281					inline_start, inline_size);1282	if (ret != -ENOSPC)1283		goto out;1284 1285	/* check whether it can be inserted to inline xattr space. */1286	inline_size = EXT4_I(dir)->i_inline_size -1287			EXT4_MIN_INLINE_DATA_SIZE;1288	if (!inline_size) {1289		/* Try to use the xattr space.*/1290		ret = ext4_update_inline_dir(handle, dir, &iloc);1291		if (ret && ret != -ENOSPC)1292			goto out;1293 1294		inline_size = EXT4_I(dir)->i_inline_size -1295				EXT4_MIN_INLINE_DATA_SIZE;1296	}1297 1298	if (inline_size) {1299		inline_start = ext4_get_inline_xattr_pos(dir, &iloc);1300 1301		ret = ext4_add_dirent_to_inline(handle, fname, dir,1302						inode, &iloc, inline_start,1303						inline_size);1304 1305		if (ret != -ENOSPC)1306			goto out;1307	}1308 1309	/*1310	 * The inline space is filled up, so create a new block for it.1311	 * As the extent tree will be created, we have to save the inline1312	 * dir first.1313	 */1314	ret = ext4_convert_inline_data_nolock(handle, dir, &iloc);1315 1316out:1317	ext4_write_unlock_xattr(dir, &no_expand);1318	ret2 = ext4_mark_inode_dirty(handle, dir);1319	if (unlikely(ret2 && !ret))1320		ret = ret2;1321	brelse(iloc.bh);1322	return ret;1323}1324 1325/*1326 * This function fills a red-black tree with information from an1327 * inlined dir.  It returns the number directory entries loaded1328 * into the tree.  If there is an error it is returned in err.1329 */1330int ext4_inlinedir_to_tree(struct file *dir_file,1331			   struct inode *dir, ext4_lblk_t block,1332			   struct dx_hash_info *hinfo,1333			   __u32 start_hash, __u32 start_minor_hash,1334			   int *has_inline_data)1335{1336	int err = 0, count = 0;1337	unsigned int parent_ino;1338	int pos;1339	struct ext4_dir_entry_2 *de;1340	struct inode *inode = file_inode(dir_file);1341	int ret, inline_size = 0;1342	struct ext4_iloc iloc;1343	void *dir_buf = NULL;1344	struct ext4_dir_entry_2 fake;1345	struct fscrypt_str tmp_str;1346 1347	ret = ext4_get_inode_loc(inode, &iloc);1348	if (ret)1349		return ret;1350 1351	down_read(&EXT4_I(inode)->xattr_sem);1352	if (!ext4_has_inline_data(inode)) {1353		up_read(&EXT4_I(inode)->xattr_sem);1354		*has_inline_data = 0;1355		goto out;1356	}1357 1358	inline_size = ext4_get_inline_size(inode);1359	dir_buf = kmalloc(inline_size, GFP_NOFS);1360	if (!dir_buf) {1361		ret = -ENOMEM;1362		up_read(&EXT4_I(inode)->xattr_sem);1363		goto out;1364	}1365 1366	ret = ext4_read_inline_data(inode, dir_buf, inline_size, &iloc);1367	up_read(&EXT4_I(inode)->xattr_sem);1368	if (ret < 0)1369		goto out;1370 1371	pos = 0;1372	parent_ino = le32_to_cpu(((struct ext4_dir_entry_2 *)dir_buf)->inode);1373	while (pos < inline_size) {1374		/*1375		 * As inlined dir doesn't store any information about '.' and1376		 * only the inode number of '..' is stored, we have to handle1377		 * them differently.1378		 */1379		if (pos == 0) {1380			fake.inode = cpu_to_le32(inode->i_ino);1381			fake.name_len = 1;1382			strcpy(fake.name, ".");1383			fake.rec_len = ext4_rec_len_to_disk(1384					  ext4_dir_rec_len(fake.name_len, NULL),1385					  inline_size);1386			ext4_set_de_type(inode->i_sb, &fake, S_IFDIR);1387			de = &fake;1388			pos = EXT4_INLINE_DOTDOT_OFFSET;1389		} else if (pos == EXT4_INLINE_DOTDOT_OFFSET) {1390			fake.inode = cpu_to_le32(parent_ino);1391			fake.name_len = 2;1392			strcpy(fake.name, "..");1393			fake.rec_len = ext4_rec_len_to_disk(1394					  ext4_dir_rec_len(fake.name_len, NULL),1395					  inline_size);1396			ext4_set_de_type(inode->i_sb, &fake, S_IFDIR);1397			de = &fake;1398			pos = EXT4_INLINE_DOTDOT_SIZE;1399		} else {1400			de = (struct ext4_dir_entry_2 *)(dir_buf + pos);1401			pos += ext4_rec_len_from_disk(de->rec_len, inline_size);1402			if (ext4_check_dir_entry(inode, dir_file, de,1403					 iloc.bh, dir_buf,1404					 inline_size, pos)) {1405				ret = count;1406				goto out;1407			}1408		}1409 1410		if (ext4_hash_in_dirent(dir)) {1411			hinfo->hash = EXT4_DIRENT_HASH(de);1412			hinfo->minor_hash = EXT4_DIRENT_MINOR_HASH(de);1413		} else {1414			err = ext4fs_dirhash(dir, de->name, de->name_len, hinfo);1415			if (err) {1416				ret = err;1417				goto out;1418			}1419		}1420		if ((hinfo->hash < start_hash) ||1421		    ((hinfo->hash == start_hash) &&1422		     (hinfo->minor_hash < start_minor_hash)))1423			continue;1424		if (de->inode == 0)1425			continue;1426		tmp_str.name = de->name;1427		tmp_str.len = de->name_len;1428		err = ext4_htree_store_dirent(dir_file, hinfo->hash,1429					      hinfo->minor_hash, de, &tmp_str);1430		if (err) {1431			ret = err;1432			goto out;1433		}1434		count++;1435	}1436	ret = count;1437out:1438	kfree(dir_buf);1439	brelse(iloc.bh);1440	return ret;1441}1442 1443/*1444 * So this function is called when the volume is mkfsed with1445 * dir_index disabled. In order to keep f_pos persistent1446 * after we convert from an inlined dir to a blocked based,1447 * we just pretend that we are a normal dir and return the1448 * offset as if '.' and '..' really take place.1449 *1450 */1451int ext4_read_inline_dir(struct file *file,1452			 struct dir_context *ctx,1453			 int *has_inline_data)1454{1455	unsigned int offset, parent_ino;1456	int i;1457	struct ext4_dir_entry_2 *de;1458	struct super_block *sb;1459	struct inode *inode = file_inode(file);1460	int ret, inline_size = 0;1461	struct ext4_iloc iloc;1462	void *dir_buf = NULL;1463	int dotdot_offset, dotdot_size, extra_offset, extra_size;1464	struct dir_private_info *info = file->private_data;1465 1466	ret = ext4_get_inode_loc(inode, &iloc);1467	if (ret)1468		return ret;1469 1470	down_read(&EXT4_I(inode)->xattr_sem);1471	if (!ext4_has_inline_data(inode)) {1472		up_read(&EXT4_I(inode)->xattr_sem);1473		*has_inline_data = 0;1474		goto out;1475	}1476 1477	inline_size = ext4_get_inline_size(inode);1478	dir_buf = kmalloc(inline_size, GFP_NOFS);1479	if (!dir_buf) {1480		ret = -ENOMEM;1481		up_read(&EXT4_I(inode)->xattr_sem);1482		goto out;1483	}1484 1485	ret = ext4_read_inline_data(inode, dir_buf, inline_size, &iloc);1486	up_read(&EXT4_I(inode)->xattr_sem);1487	if (ret < 0)1488		goto out;1489 1490	ret = 0;1491	sb = inode->i_sb;1492	parent_ino = le32_to_cpu(((struct ext4_dir_entry_2 *)dir_buf)->inode);1493	offset = ctx->pos;1494 1495	/*1496	 * dotdot_offset and dotdot_size is the real offset and1497	 * size for ".." and "." if the dir is block based while1498	 * the real size for them are only EXT4_INLINE_DOTDOT_SIZE.1499	 * So we will use extra_offset and extra_size to indicate them1500	 * during the inline dir iteration.1501	 */1502	dotdot_offset = ext4_dir_rec_len(1, NULL);1503	dotdot_size = dotdot_offset + ext4_dir_rec_len(2, NULL);1504	extra_offset = dotdot_size - EXT4_INLINE_DOTDOT_SIZE;1505	extra_size = extra_offset + inline_size;1506 1507	/*1508	 * If the cookie has changed since the last call to1509	 * readdir(2), then we might be pointing to an invalid1510	 * dirent right now.  Scan from the start of the inline1511	 * dir to make sure.1512	 */1513	if (!inode_eq_iversion(inode, info->cookie)) {1514		for (i = 0; i < extra_size && i < offset;) {1515			/*1516			 * "." is with offset 0 and1517			 * ".." is dotdot_offset.1518			 */1519			if (!i) {1520				i = dotdot_offset;1521				continue;1522			} else if (i == dotdot_offset) {1523				i = dotdot_size;1524				continue;1525			}1526			/* for other entry, the real offset in1527			 * the buf has to be tuned accordingly.1528			 */1529			de = (struct ext4_dir_entry_2 *)1530				(dir_buf + i - extra_offset);1531			/* It's too expensive to do a full1532			 * dirent test each time round this1533			 * loop, but we do have to test at1534			 * least that it is non-zero.  A1535			 * failure will be detected in the1536			 * dirent test below. */1537			if (ext4_rec_len_from_disk(de->rec_len, extra_size)1538				< ext4_dir_rec_len(1, NULL))1539				break;1540			i += ext4_rec_len_from_disk(de->rec_len,1541						    extra_size);1542		}1543		offset = i;1544		ctx->pos = offset;1545		info->cookie = inode_query_iversion(inode);1546	}1547 1548	while (ctx->pos < extra_size) {1549		if (ctx->pos == 0) {1550			if (!dir_emit(ctx, ".", 1, inode->i_ino, DT_DIR))1551				goto out;1552			ctx->pos = dotdot_offset;1553			continue;1554		}1555 1556		if (ctx->pos == dotdot_offset) {1557			if (!dir_emit(ctx, "..", 2, parent_ino, DT_DIR))1558				goto out;1559			ctx->pos = dotdot_size;1560			continue;1561		}1562 1563		de = (struct ext4_dir_entry_2 *)1564			(dir_buf + ctx->pos - extra_offset);1565		if (ext4_check_dir_entry(inode, file, de, iloc.bh, dir_buf,1566					 extra_size, ctx->pos))1567			goto out;1568		if (le32_to_cpu(de->inode)) {1569			if (!dir_emit(ctx, de->name, de->name_len,1570				      le32_to_cpu(de->inode),1571				      get_dtype(sb, de->file_type)))1572				goto out;1573		}1574		ctx->pos += ext4_rec_len_from_disk(de->rec_len, extra_size);1575	}1576out:1577	kfree(dir_buf);1578	brelse(iloc.bh);1579	return ret;1580}1581 1582void *ext4_read_inline_link(struct inode *inode)1583{1584	struct ext4_iloc iloc;1585	int ret, inline_size;1586	void *link;1587 1588	ret = ext4_get_inode_loc(inode, &iloc);1589	if (ret)1590		return ERR_PTR(ret);1591 1592	ret = -ENOMEM;1593	inline_size = ext4_get_inline_size(inode);1594	link = kmalloc(inline_size + 1, GFP_NOFS);1595	if (!link)1596		goto out;1597 1598	ret = ext4_read_inline_data(inode, link, inline_size, &iloc);1599	if (ret < 0) {1600		kfree(link);1601		goto out;1602	}1603	nd_terminate_link(link, inode->i_size, ret);1604out:1605	if (ret < 0)1606		link = ERR_PTR(ret);1607	brelse(iloc.bh);1608	return link;1609}1610 1611struct buffer_head *ext4_get_first_inline_block(struct inode *inode,1612					struct ext4_dir_entry_2 **parent_de,1613					int *retval)1614{1615	struct ext4_iloc iloc;1616 1617	*retval = ext4_get_inode_loc(inode, &iloc);1618	if (*retval)1619		return NULL;1620 1621	*parent_de = (struct ext4_dir_entry_2 *)ext4_raw_inode(&iloc)->i_block;1622 1623	return iloc.bh;1624}1625 1626/*1627 * Try to create the inline data for the new dir.1628 * If it succeeds, return 0, otherwise return the error.1629 * In case of ENOSPC, the caller should create the normal disk layout dir.1630 */1631int ext4_try_create_inline_dir(handle_t *handle, struct inode *parent,1632			       struct inode *inode)1633{1634	int ret, inline_size = EXT4_MIN_INLINE_DATA_SIZE;1635	struct ext4_iloc iloc;1636	struct ext4_dir_entry_2 *de;1637 1638	ret = ext4_get_inode_loc(inode, &iloc);1639	if (ret)1640		return ret;1641 1642	ret = ext4_prepare_inline_data(handle, inode, inline_size);1643	if (ret)1644		goto out;1645 1646	/*1647	 * For inline dir, we only save the inode information for the ".."1648	 * and create a fake dentry to cover the left space.1649	 */1650	de = (struct ext4_dir_entry_2 *)ext4_raw_inode(&iloc)->i_block;1651	de->inode = cpu_to_le32(parent->i_ino);1652	de = (struct ext4_dir_entry_2 *)((void *)de + EXT4_INLINE_DOTDOT_SIZE);1653	de->inode = 0;1654	de->rec_len = ext4_rec_len_to_disk(1655				inline_size - EXT4_INLINE_DOTDOT_SIZE,1656				inline_size);1657	set_nlink(inode, 2);1658	inode->i_size = EXT4_I(inode)->i_disksize = inline_size;1659out:1660	brelse(iloc.bh);1661	return ret;1662}1663 1664struct buffer_head *ext4_find_inline_entry(struct inode *dir,1665					struct ext4_filename *fname,1666					struct ext4_dir_entry_2 **res_dir,1667					int *has_inline_data)1668{1669	struct ext4_xattr_ibody_find is = {1670		.s = { .not_found = -ENODATA, },1671	};1672	struct ext4_xattr_info i = {1673		.name_index = EXT4_XATTR_INDEX_SYSTEM,1674		.name = EXT4_XATTR_SYSTEM_DATA,1675	};1676	int ret;1677	void *inline_start;1678	int inline_size;1679 1680	ret = ext4_get_inode_loc(dir, &is.iloc);1681	if (ret)1682		return ERR_PTR(ret);1683 1684	down_read(&EXT4_I(dir)->xattr_sem);1685 1686	ret = ext4_xattr_ibody_find(dir, &i, &is);1687	if (ret)1688		goto out;1689 1690	if (!ext4_has_inline_data(dir)) {1691		*has_inline_data = 0;1692		goto out;1693	}1694 1695	inline_start = (void *)ext4_raw_inode(&is.iloc)->i_block +1696						EXT4_INLINE_DOTDOT_SIZE;1697	inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE;1698	ret = ext4_search_dir(is.iloc.bh, inline_start, inline_size,1699			      dir, fname, 0, res_dir);1700	if (ret == 1)1701		goto out_find;1702	if (ret < 0)1703		goto out;1704 1705	if (ext4_get_inline_size(dir) == EXT4_MIN_INLINE_DATA_SIZE)1706		goto out;1707 1708	inline_start = ext4_get_inline_xattr_pos(dir, &is.iloc);1709	inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE;1710 1711	ret = ext4_search_dir(is.iloc.bh, inline_start, inline_size,1712			      dir, fname, 0, res_dir);1713	if (ret == 1)1714		goto out_find;1715 1716out:1717	brelse(is.iloc.bh);1718	if (ret < 0)1719		is.iloc.bh = ERR_PTR(ret);1720	else1721		is.iloc.bh = NULL;1722out_find:1723	up_read(&EXT4_I(dir)->xattr_sem);1724	return is.iloc.bh;1725}1726 1727int ext4_delete_inline_entry(handle_t *handle,1728			     struct inode *dir,1729			     struct ext4_dir_entry_2 *de_del,1730			     struct buffer_head *bh,1731			     int *has_inline_data)1732{1733	int err, inline_size, no_expand;1734	struct ext4_iloc iloc;1735	void *inline_start;1736 1737	err = ext4_get_inode_loc(dir, &iloc);1738	if (err)1739		return err;1740 1741	ext4_write_lock_xattr(dir, &no_expand);1742	if (!ext4_has_inline_data(dir)) {1743		*has_inline_data = 0;1744		goto out;1745	}1746 1747	if ((void *)de_del - ((void *)ext4_raw_inode(&iloc)->i_block) <1748		EXT4_MIN_INLINE_DATA_SIZE) {1749		inline_start = (void *)ext4_raw_inode(&iloc)->i_block +1750					EXT4_INLINE_DOTDOT_SIZE;1751		inline_size = EXT4_MIN_INLINE_DATA_SIZE -1752				EXT4_INLINE_DOTDOT_SIZE;1753	} else {1754		inline_start = ext4_get_inline_xattr_pos(dir, &iloc);1755		inline_size = ext4_get_inline_size(dir) -1756				EXT4_MIN_INLINE_DATA_SIZE;1757	}1758 1759	BUFFER_TRACE(bh, "get_write_access");1760	err = ext4_journal_get_write_access(handle, dir->i_sb, bh,1761					    EXT4_JTR_NONE);1762	if (err)1763		goto out;1764 1765	err = ext4_generic_delete_entry(dir, de_del, bh,1766					inline_start, inline_size, 0);1767	if (err)1768		goto out;1769 1770	ext4_show_inline_dir(dir, iloc.bh, inline_start, inline_size);1771out:1772	ext4_write_unlock_xattr(dir, &no_expand);1773	if (likely(err == 0))1774		err = ext4_mark_inode_dirty(handle, dir);1775	brelse(iloc.bh);1776	if (err != -ENOENT)1777		ext4_std_error(dir->i_sb, err);1778	return err;1779}1780 1781/*1782 * Get the inline dentry at offset.1783 */1784static inline struct ext4_dir_entry_2 *1785ext4_get_inline_entry(struct inode *inode,1786		      struct ext4_iloc *iloc,1787		      unsigned int offset,1788		      void **inline_start,1789		      int *inline_size)1790{1791	void *inline_pos;1792 1793	BUG_ON(offset > ext4_get_inline_size(inode));1794 1795	if (offset < EXT4_MIN_INLINE_DATA_SIZE) {1796		inline_pos = (void *)ext4_raw_inode(iloc)->i_block;1797		*inline_size = EXT4_MIN_INLINE_DATA_SIZE;1798	} else {1799		inline_pos = ext4_get_inline_xattr_pos(inode, iloc);1800		offset -= EXT4_MIN_INLINE_DATA_SIZE;1801		*inline_size = ext4_get_inline_size(inode) -1802				EXT4_MIN_INLINE_DATA_SIZE;1803	}1804 1805	if (inline_start)1806		*inline_start = inline_pos;1807	return (struct ext4_dir_entry_2 *)(inline_pos + offset);1808}1809 1810bool empty_inline_dir(struct inode *dir, int *has_inline_data)1811{1812	int err, inline_size;1813	struct ext4_iloc iloc;1814	size_t inline_len;1815	void *inline_pos;1816	unsigned int offset;1817	struct ext4_dir_entry_2 *de;1818	bool ret = false;1819 1820	err = ext4_get_inode_loc(dir, &iloc);1821	if (err) {1822		EXT4_ERROR_INODE_ERR(dir, -err,1823				     "error %d getting inode %lu block",1824				     err, dir->i_ino);1825		return false;1826	}1827 1828	down_read(&EXT4_I(dir)->xattr_sem);1829	if (!ext4_has_inline_data(dir)) {1830		*has_inline_data = 0;1831		ret = true;1832		goto out;1833	}1834 1835	de = (struct ext4_dir_entry_2 *)ext4_raw_inode(&iloc)->i_block;1836	if (!le32_to_cpu(de->inode)) {1837		ext4_warning(dir->i_sb,1838			     "bad inline directory (dir #%lu) - no `..'",1839			     dir->i_ino);1840		goto out;1841	}1842 1843	inline_len = ext4_get_inline_size(dir);1844	offset = EXT4_INLINE_DOTDOT_SIZE;1845	while (offset < inline_len) {1846		de = ext4_get_inline_entry(dir, &iloc, offset,1847					   &inline_pos, &inline_size);1848		if (ext4_check_dir_entry(dir, NULL, de,1849					 iloc.bh, inline_pos,1850					 inline_size, offset)) {1851			ext4_warning(dir->i_sb,1852				     "bad inline directory (dir #%lu) - "1853				     "inode %u, rec_len %u, name_len %d"1854				     "inline size %d",1855				     dir->i_ino, le32_to_cpu(de->inode),1856				     le16_to_cpu(de->rec_len), de->name_len,1857				     inline_size);1858			goto out;1859		}1860		if (le32_to_cpu(de->inode)) {1861			goto out;1862		}1863		offset += ext4_rec_len_from_disk(de->rec_len, inline_size);1864	}1865 1866	ret = true;1867out:1868	up_read(&EXT4_I(dir)->xattr_sem);1869	brelse(iloc.bh);1870	return ret;1871}1872 1873int ext4_destroy_inline_data(handle_t *handle, struct inode *inode)1874{1875	int ret, no_expand;1876 1877	ext4_write_lock_xattr(inode, &no_expand);1878	ret = ext4_destroy_inline_data_nolock(handle, inode);1879	ext4_write_unlock_xattr(inode, &no_expand);1880 1881	return ret;1882}1883 1884int ext4_inline_data_iomap(struct inode *inode, struct iomap *iomap)1885{1886	__u64 addr;1887	int error = -EAGAIN;1888	struct ext4_iloc iloc;1889 1890	down_read(&EXT4_I(inode)->xattr_sem);1891	if (!ext4_has_inline_data(inode))1892		goto out;1893 1894	error = ext4_get_inode_loc(inode, &iloc);1895	if (error)1896		goto out;1897 1898	addr = (__u64)iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits;1899	addr += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data;1900	addr += offsetof(struct ext4_inode, i_block);1901 1902	brelse(iloc.bh);1903 1904	iomap->addr = addr;1905	iomap->offset = 0;1906	iomap->length = min_t(loff_t, ext4_get_inline_size(inode),1907			      i_size_read(inode));1908	iomap->type = IOMAP_INLINE;1909	iomap->flags = 0;1910 1911out:1912	up_read(&EXT4_I(inode)->xattr_sem);1913	return error;1914}1915 1916int ext4_inline_data_truncate(struct inode *inode, int *has_inline)1917{1918	handle_t *handle;1919	int inline_size, value_len, needed_blocks, no_expand, err = 0;1920	size_t i_size;1921	void *value = NULL;1922	struct ext4_xattr_ibody_find is = {1923		.s = { .not_found = -ENODATA, },1924	};1925	struct ext4_xattr_info i = {1926		.name_index = EXT4_XATTR_INDEX_SYSTEM,1927		.name = EXT4_XATTR_SYSTEM_DATA,1928	};1929 1930 1931	needed_blocks = ext4_writepage_trans_blocks(inode);1932	handle = ext4_journal_start(inode, EXT4_HT_INODE, needed_blocks);1933	if (IS_ERR(handle))1934		return PTR_ERR(handle);1935 1936	ext4_write_lock_xattr(inode, &no_expand);1937	if (!ext4_has_inline_data(inode)) {1938		ext4_write_unlock_xattr(inode, &no_expand);1939		*has_inline = 0;1940		ext4_journal_stop(handle);1941		return 0;1942	}1943 1944	if ((err = ext4_orphan_add(handle, inode)) != 0)1945		goto out;1946 1947	if ((err = ext4_get_inode_loc(inode, &is.iloc)) != 0)1948		goto out;1949 1950	down_write(&EXT4_I(inode)->i_data_sem);1951	i_size = inode->i_size;1952	inline_size = ext4_get_inline_size(inode);1953	EXT4_I(inode)->i_disksize = i_size;1954 1955	if (i_size < inline_size) {1956		/*1957		 * if there's inline data to truncate and this file was1958		 * converted to extents after that inline data was written,1959		 * the extent status cache must be cleared to avoid leaving1960		 * behind stale delayed allocated extent entries1961		 */1962		if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA))1963			ext4_es_remove_extent(inode, 0, EXT_MAX_BLOCKS);1964 1965		/* Clear the content in the xattr space. */1966		if (inline_size > EXT4_MIN_INLINE_DATA_SIZE) {1967			if ((err = ext4_xattr_ibody_find(inode, &i, &is)) != 0)1968				goto out_error;1969 1970			BUG_ON(is.s.not_found);1971 1972			value_len = le32_to_cpu(is.s.here->e_value_size);1973			value = kmalloc(value_len, GFP_NOFS);1974			if (!value) {1975				err = -ENOMEM;1976				goto out_error;1977			}1978 1979			err = ext4_xattr_ibody_get(inode, i.name_index,1980						   i.name, value, value_len);1981			if (err <= 0)1982				goto out_error;1983 1984			i.value = value;1985			i.value_len = i_size > EXT4_MIN_INLINE_DATA_SIZE ?1986					i_size - EXT4_MIN_INLINE_DATA_SIZE : 0;1987			err = ext4_xattr_ibody_set(handle, inode, &i, &is);1988			if (err)1989				goto out_error;1990		}1991 1992		/* Clear the content within i_blocks. */1993		if (i_size < EXT4_MIN_INLINE_DATA_SIZE) {1994			void *p = (void *) ext4_raw_inode(&is.iloc)->i_block;1995			memset(p + i_size, 0,1996			       EXT4_MIN_INLINE_DATA_SIZE - i_size);1997		}1998 1999		EXT4_I(inode)->i_inline_size = i_size <2000					EXT4_MIN_INLINE_DATA_SIZE ?2001					EXT4_MIN_INLINE_DATA_SIZE : i_size;2002	}2003 2004out_error:2005	up_write(&EXT4_I(inode)->i_data_sem);2006out:2007	brelse(is.iloc.bh);2008	ext4_write_unlock_xattr(inode, &no_expand);2009	kfree(value);2010	if (inode->i_nlink)2011		ext4_orphan_del(handle, inode);2012 2013	if (err == 0) {2014		inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));2015		err = ext4_mark_inode_dirty(handle, inode);2016		if (IS_SYNC(inode))2017			ext4_handle_sync(handle);2018	}2019	ext4_journal_stop(handle);2020	return err;2021}2022 2023int ext4_convert_inline_data(struct inode *inode)2024{2025	int error, needed_blocks, no_expand;2026	handle_t *handle;2027	struct ext4_iloc iloc;2028 2029	if (!ext4_has_inline_data(inode)) {2030		ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);2031		return 0;2032	} else if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {2033		/*2034		 * Inode has inline data but EXT4_STATE_MAY_INLINE_DATA is2035		 * cleared. This means we are in the middle of moving of2036		 * inline data to delay allocated block. Just force writeout2037		 * here to finish conversion.2038		 */2039		error = filemap_flush(inode->i_mapping);2040		if (error)2041			return error;2042		if (!ext4_has_inline_data(inode))2043			return 0;2044	}2045 2046	needed_blocks = ext4_writepage_trans_blocks(inode);2047 2048	iloc.bh = NULL;2049	error = ext4_get_inode_loc(inode, &iloc);2050	if (error)2051		return error;2052 2053	handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, needed_blocks);2054	if (IS_ERR(handle)) {2055		error = PTR_ERR(handle);2056		goto out_free;2057	}2058 2059	ext4_write_lock_xattr(inode, &no_expand);2060	if (ext4_has_inline_data(inode))2061		error = ext4_convert_inline_data_nolock(handle, inode, &iloc);2062	ext4_write_unlock_xattr(inode, &no_expand);2063	ext4_journal_stop(handle);2064out_free:2065	brelse(iloc.bh);2066	return error;2067}2068