diff options
Diffstat (limited to 'fs/ext4/inode.c')
| -rw-r--r-- | fs/ext4/inode.c | 135 | 
1 files changed, 69 insertions, 66 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 9d9f414f99fe..bf0b7dea4900 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -786,11 +786,10 @@ static void ext4_update_bh_state(struct buffer_head *bh, unsigned long flags)  	 * once we get rid of using bh as a container for mapping information  	 * to pass to / from get_block functions, this can go away.  	 */ +	old_state = READ_ONCE(bh->b_state);  	do { -		old_state = READ_ONCE(bh->b_state);  		new_state = (old_state & ~EXT4_MAP_FLAGS) | flags; -	} while (unlikely( -		 cmpxchg(&bh->b_state, old_state, new_state) != old_state)); +	} while (unlikely(!try_cmpxchg(&bh->b_state, &old_state, new_state)));  }  static int _ext4_get_block(struct inode *inode, sector_t iblock, @@ -1136,7 +1135,8 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len,  		for (i = 0; i < nr_wait; i++) {  			int err2; -			err2 = fscrypt_decrypt_pagecache_blocks(page, blocksize, +			err2 = fscrypt_decrypt_pagecache_blocks(page_folio(page), +								blocksize,  								bh_offset(wait[i]));  			if (err2) {  				clear_buffer_uptodate(wait[i]); @@ -2595,8 +2595,8 @@ static bool ext4_page_nomap_can_writeout(struct page *page)  static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd)  {  	struct address_space *mapping = mpd->inode->i_mapping; -	struct pagevec pvec; -	unsigned int nr_pages; +	struct folio_batch fbatch; +	unsigned int nr_folios;  	long left = mpd->wbc->nr_to_write;  	pgoff_t index = mpd->first_page;  	pgoff_t end = mpd->last_page; @@ -2610,18 +2610,17 @@ static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd)  		tag = PAGECACHE_TAG_TOWRITE;  	else  		tag = PAGECACHE_TAG_DIRTY; - -	pagevec_init(&pvec); +	folio_batch_init(&fbatch);  	mpd->map.m_len = 0;  	mpd->next_page = index;  	while (index <= end) { -		nr_pages = pagevec_lookup_range_tag(&pvec, mapping, &index, end, -				tag); -		if (nr_pages == 0) +		nr_folios = filemap_get_folios_tag(mapping, &index, end, +				tag, &fbatch); +		if (nr_folios == 0)  			break; -		for (i = 0; i < nr_pages; i++) { -			struct page *page = pvec.pages[i]; +		for (i = 0; i < nr_folios; i++) { +			struct folio *folio = fbatch.folios[i];  			/*  			 * Accumulated enough dirty pages? This doesn't apply @@ -2635,10 +2634,10 @@ static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd)  				goto out;  			/* If we can't merge this page, we are done. */ -			if (mpd->map.m_len > 0 && mpd->next_page != page->index) +			if (mpd->map.m_len > 0 && mpd->next_page != folio->index)  				goto out; -			lock_page(page); +			folio_lock(folio);  			/*  			 * If the page is no longer dirty, or its mapping no  			 * longer corresponds to inode we are writing (which @@ -2646,16 +2645,16 @@ static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd)  			 * page is already under writeback and we are not doing  			 * a data integrity writeback, skip the page  			 */ -			if (!PageDirty(page) || -			    (PageWriteback(page) && +			if (!folio_test_dirty(folio) || +			    (folio_test_writeback(folio) &&  			     (mpd->wbc->sync_mode == WB_SYNC_NONE)) || -			    unlikely(page->mapping != mapping)) { -				unlock_page(page); +			    unlikely(folio->mapping != mapping)) { +				folio_unlock(folio);  				continue;  			} -			wait_on_page_writeback(page); -			BUG_ON(PageWriteback(page)); +			folio_wait_writeback(folio); +			BUG_ON(folio_test_writeback(folio));  			/*  			 * Should never happen but for buggy code in @@ -2666,56 +2665,56 @@ static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd)  			 *  			 * [1] https://lore.kernel.org/linux-mm/[email protected]  			 */ -			if (!page_has_buffers(page)) { -				ext4_warning_inode(mpd->inode, "page %lu does not have buffers attached", page->index); -				ClearPageDirty(page); -				unlock_page(page); +			if (!folio_buffers(folio)) { +				ext4_warning_inode(mpd->inode, "page %lu does not have buffers attached", folio->index); +				folio_clear_dirty(folio); +				folio_unlock(folio);  				continue;  			}  			if (mpd->map.m_len == 0) -				mpd->first_page = page->index; -			mpd->next_page = page->index + 1; +				mpd->first_page = folio->index; +			mpd->next_page = folio->index + folio_nr_pages(folio);  			/*  			 * Writeout for transaction commit where we cannot  			 * modify metadata is simple. Just submit the page.  			 */  			if (!mpd->can_map) { -				if (ext4_page_nomap_can_writeout(page)) { -					err = mpage_submit_page(mpd, page); +				if (ext4_page_nomap_can_writeout(&folio->page)) { +					err = mpage_submit_page(mpd, &folio->page);  					if (err < 0)  						goto out;  				} else { -					unlock_page(page); -					mpd->first_page++; +					folio_unlock(folio); +					mpd->first_page += folio_nr_pages(folio);  				}  			} else {  				/* Add all dirty buffers to mpd */ -				lblk = ((ext4_lblk_t)page->index) << +				lblk = ((ext4_lblk_t)folio->index) <<  					(PAGE_SHIFT - blkbits); -				head = page_buffers(page); +				head = folio_buffers(folio);  				err = mpage_process_page_bufs(mpd, head, head, -							      lblk); +						lblk);  				if (err <= 0)  					goto out;  				err = 0;  			} -			left--; +			left -= folio_nr_pages(folio);  		} -		pagevec_release(&pvec); +		folio_batch_release(&fbatch);  		cond_resched();  	}  	mpd->scanned_until_end = 1;  	return 0;  out: -	pagevec_release(&pvec); +	folio_batch_release(&fbatch);  	return err;  } -static int ext4_writepage_cb(struct page *page, struct writeback_control *wbc, +static int ext4_writepage_cb(struct folio *folio, struct writeback_control *wbc,  			     void *data)  { -	return ext4_writepage(page, wbc); +	return ext4_writepage(&folio->page, wbc);  }  static int ext4_do_writepages(struct mpage_da_data *mpd) @@ -3858,7 +3857,8 @@ static int __ext4_block_zero_page_range(handle_t *handle,  		if (fscrypt_inode_uses_fs_layer_crypto(inode)) {  			/* We expect the key to be set. */  			BUG_ON(!fscrypt_has_encryption_key(inode)); -			err = fscrypt_decrypt_pagecache_blocks(page, blocksize, +			err = fscrypt_decrypt_pagecache_blocks(page_folio(page), +							       blocksize,  							       bh_offset(bh));  			if (err) {  				clear_buffer_uptodate(bh); @@ -4797,8 +4797,13 @@ static inline int ext4_iget_extra_inode(struct inode *inode,  	if (EXT4_INODE_HAS_XATTR_SPACE(inode)  &&  	    *magic == cpu_to_le32(EXT4_XATTR_MAGIC)) { +		int err; +  		ext4_set_inode_state(inode, EXT4_STATE_XATTR); -		return ext4_find_inline_data_nolock(inode); +		err = ext4_find_inline_data_nolock(inode); +		if (!err && ext4_has_inline_data(inode)) +			ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); +		return err;  	} else  		EXT4_I(inode)->i_inline_off = 0;  	return 0; @@ -4872,13 +4877,6 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,  		goto bad_inode;  	raw_inode = ext4_raw_inode(&iloc); -	if ((ino == EXT4_ROOT_INO) && (raw_inode->i_links_count == 0)) { -		ext4_error_inode(inode, function, line, 0, -				 "iget: root inode unallocated"); -		ret = -EFSCORRUPTED; -		goto bad_inode; -	} -  	if ((flags & EXT4_IGET_HANDLE) &&  	    (raw_inode->i_links_count == 0) && (raw_inode->i_mode == 0)) {  		ret = -ESTALE; @@ -4951,11 +4949,16 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,  	 * NeilBrown 1999oct15  	 */  	if (inode->i_nlink == 0) { -		if ((inode->i_mode == 0 || +		if ((inode->i_mode == 0 || flags & EXT4_IGET_SPECIAL ||  		     !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) &&  		    ino != EXT4_BOOT_LOADER_INO) { -			/* this inode is deleted */ -			ret = -ESTALE; +			/* this inode is deleted or unallocated */ +			if (flags & EXT4_IGET_SPECIAL) { +				ext4_error_inode(inode, function, line, 0, +						 "iget: special inode unallocated"); +				ret = -EFSCORRUPTED; +			} else +				ret = -ESTALE;  			goto bad_inode;  		}  		/* The only unlinked inodes we let through here have @@ -5434,7 +5437,7 @@ static void ext4_wait_for_tail_page_commit(struct inode *inode)   *   * Called with inode->i_rwsem down.   */ -int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, +int ext4_setattr(struct mnt_idmap *idmap, struct dentry *dentry,  		 struct iattr *attr)  {  	struct inode *inode = d_inode(dentry); @@ -5454,7 +5457,7 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,  				  ATTR_GID | ATTR_TIMES_SET))))  		return -EPERM; -	error = setattr_prepare(mnt_userns, dentry, attr); +	error = setattr_prepare(idmap, dentry, attr);  	if (error)  		return error; @@ -5466,14 +5469,14 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,  	if (error)  		return error; -	if (is_quota_modification(mnt_userns, inode, attr)) { +	if (is_quota_modification(idmap, inode, attr)) {  		error = dquot_initialize(inode);  		if (error)  			return error;  	} -	if (i_uid_needs_update(mnt_userns, attr, inode) || -	    i_gid_needs_update(mnt_userns, attr, inode)) { +	if (i_uid_needs_update(idmap, attr, inode) || +	    i_gid_needs_update(idmap, attr, inode)) {  		handle_t *handle;  		/* (user+group)*(old+new) structure, inode write (sb, @@ -5490,7 +5493,7 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,  		 * counts xattr inode references.  		 */  		down_read(&EXT4_I(inode)->xattr_sem); -		error = dquot_transfer(mnt_userns, inode, attr); +		error = dquot_transfer(idmap, inode, attr);  		up_read(&EXT4_I(inode)->xattr_sem);  		if (error) { @@ -5499,8 +5502,8 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,  		}  		/* Update corresponding info in inode so that everything is in  		 * one transaction */ -		i_uid_update(mnt_userns, attr, inode); -		i_gid_update(mnt_userns, attr, inode); +		i_uid_update(idmap, attr, inode); +		i_gid_update(idmap, attr, inode);  		error = ext4_mark_inode_dirty(handle, inode);  		ext4_journal_stop(handle);  		if (unlikely(error)) { @@ -5630,7 +5633,7 @@ out_mmap_sem:  	if (!error) {  		if (inc_ivers)  			inode_inc_iversion(inode); -		setattr_copy(mnt_userns, inode, attr); +		setattr_copy(idmap, inode, attr);  		mark_inode_dirty(inode);  	} @@ -5642,7 +5645,7 @@ out_mmap_sem:  		ext4_orphan_del(NULL, inode);  	if (!error && (ia_valid & ATTR_MODE)) -		rc = posix_acl_chmod(mnt_userns, dentry, inode->i_mode); +		rc = posix_acl_chmod(idmap, dentry, inode->i_mode);  err_out:  	if  (error) @@ -5668,7 +5671,7 @@ u32 ext4_dio_alignment(struct inode *inode)  	return 1; /* use the iomap defaults */  } -int ext4_getattr(struct user_namespace *mnt_userns, const struct path *path, +int ext4_getattr(struct mnt_idmap *idmap, const struct path *path,  		 struct kstat *stat, u32 request_mask, unsigned int query_flags)  {  	struct inode *inode = d_inode(path->dentry); @@ -5725,18 +5728,18 @@ int ext4_getattr(struct user_namespace *mnt_userns, const struct path *path,  				  STATX_ATTR_NODUMP |  				  STATX_ATTR_VERITY); -	generic_fillattr(mnt_userns, inode, stat); +	generic_fillattr(idmap, inode, stat);  	return 0;  } -int ext4_file_getattr(struct user_namespace *mnt_userns, +int ext4_file_getattr(struct mnt_idmap *idmap,  		      const struct path *path, struct kstat *stat,  		      u32 request_mask, unsigned int query_flags)  {  	struct inode *inode = d_inode(path->dentry);  	u64 delalloc_blocks; -	ext4_getattr(mnt_userns, path, stat, request_mask, query_flags); +	ext4_getattr(idmap, path, stat, request_mask, query_flags);  	/*  	 * If there is inline data in the inode, the inode will normally not @@ -5788,7 +5791,7 @@ static int ext4_meta_trans_blocks(struct inode *inode, int lblocks,  	ext4_group_t groups, ngroups = ext4_get_groups_count(inode->i_sb);  	int gdpblocks;  	int idxblocks; -	int ret = 0; +	int ret;  	/*  	 * How many index blocks need to touch to map @lblocks logical blocks  |