Commit 1a0507d8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull gfs2 updates from Andreas Gruenbacher:

 - Don't update inode timestamps for direct writes (performance
   regression fix)

 - Skip no-op quota records instead of panicing

 - Fix a RCU race in gfs2_permission()

 - Various other smaller fixes and cleanups all over the place

* tag 'gfs2-v6.6-rc2-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: (24 commits)
  gfs2: don't withdraw if init_threads() got interrupted
  gfs2: remove dead code in add_to_queue
  gfs2: Fix slab-use-after-free in gfs2_qd_dealloc
  gfs2: Silence "suspicious RCU usage in gfs2_permission" warning
  gfs2: fs: derive f_fsid from s_uuid
  gfs2: No longer use 'extern' in function declarations
  gfs2: Rename gfs2_lookup_{ simple => meta }
  gfs2: Convert gfs2_internal_read to folios
  gfs2: Convert stuffed_readpage to folios
  gfs2: Minor gfs2_write_jdata_batch PAGE_SIZE cleanup
  gfs2: Get rid of gfs2_alloc_blocks generation parameter
  gfs2: Add metapath_dibh helper
  gfs2: Clean up quota.c:print_message
  gfs2: Clean up gfs2_alloc_parms initializers
  gfs2: Two quota=account mode fixes
  gfs2: Stop using GFS2_BASIC_BLOCK and GFS2_BASIC_BLOCK_SHIFT
  gfs2: setattr_chown: Add missing initialization
  gfs2: fix an oops in gfs2_permission
  gfs2: ignore negated quota changes
  gfs2: Don't update inode timestamps for direct writes
  ...
parents 7f851936 0cdc6f44
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -11,9 +11,9 @@

#define GFS2_ACL_MAX_ENTRIES(sdp) ((300 << (sdp)->sd_sb.sb_bsize_shift) >> 12)

extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type, bool rcu);
extern int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type);
extern int gfs2_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
struct posix_acl *gfs2_get_acl(struct inode *inode, int type, bool rcu);
int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type);
int gfs2_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
		 struct posix_acl *acl, int type);

#endif /* __ACL_DOT_H__ */
+34 −38
Original line number Diff line number Diff line
@@ -155,7 +155,7 @@ static int gfs2_jdata_writepage(struct page *page, struct writeback_control *wbc
	struct gfs2_inode *ip = GFS2_I(inode);
	struct gfs2_sbd *sdp = GFS2_SB(inode);

	if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl)))
	if (gfs2_assert_withdraw(sdp, ip->i_gl->gl_state == LM_ST_EXCLUSIVE))
		goto out;
	if (folio_test_checked(folio) || current->journal_info)
		goto out_ignore;
@@ -214,12 +214,12 @@ static int gfs2_write_jdata_batch(struct address_space *mapping,
	unsigned nrblocks;
	int i;
	int ret;
	int nr_pages = 0;
	size_t size = 0;
	int nr_folios = folio_batch_count(fbatch);

	for (i = 0; i < nr_folios; i++)
		nr_pages += folio_nr_pages(fbatch->folios[i]);
	nrblocks = nr_pages * (PAGE_SIZE >> inode->i_blkbits);
		size += folio_size(fbatch->folios[i]);
	nrblocks = size >> inode->i_blkbits;

	ret = gfs2_trans_begin(sdp, nrblocks, nrblocks);
	if (ret < 0)
@@ -403,27 +403,27 @@ static int gfs2_jdata_writepages(struct address_space *mapping,
}

/**
 * stuffed_readpage - Fill in a Linux page with stuffed file data
 * stuffed_readpage - Fill in a Linux folio with stuffed file data
 * @ip: the inode
 * @page: the page
 * @folio: the folio
 *
 * Returns: errno
 */
static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
static int stuffed_readpage(struct gfs2_inode *ip, struct folio *folio)
{
	struct buffer_head *dibh;
	u64 dsize = i_size_read(&ip->i_inode);
	void *kaddr;
	size_t i_size = i_size_read(&ip->i_inode);
	void *data;
	int error;

	/*
	 * Due to the order of unstuffing files and ->fault(), we can be
	 * asked for a zero page in the case of a stuffed file being extended,
	 * asked for a zero folio in the case of a stuffed file being extended,
	 * so we need to supply one here. It doesn't happen often.
	 */
	if (unlikely(page->index)) {
		zero_user(page, 0, PAGE_SIZE);
		SetPageUptodate(page);
	if (unlikely(folio->index)) {
		folio_zero_range(folio, 0, folio_size(folio));
		folio_mark_uptodate(folio);
		return 0;
	}

@@ -431,13 +431,11 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
	if (error)
		return error;

	kaddr = kmap_local_page(page);
	memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), dsize);
	memset(kaddr + dsize, 0, PAGE_SIZE - dsize);
	kunmap_local(kaddr);
	flush_dcache_page(page);
	data = dibh->b_data + sizeof(struct gfs2_dinode);
	memcpy_to_folio(folio, 0, data, i_size);
	folio_zero_range(folio, i_size, folio_size(folio) - i_size);
	brelse(dibh);
	SetPageUptodate(page);
	folio_mark_uptodate(folio);

	return 0;
}
@@ -458,7 +456,7 @@ static int gfs2_read_folio(struct file *file, struct folio *folio)
	    (i_blocksize(inode) == PAGE_SIZE && !folio_buffers(folio))) {
		error = iomap_read_folio(folio, &gfs2_iomap_ops);
	} else if (gfs2_is_stuffed(ip)) {
		error = stuffed_readpage(ip, &folio->page);
		error = stuffed_readpage(ip, folio);
		folio_unlock(folio);
	} else {
		error = mpage_read_folio(folio, gfs2_block_map);
@@ -479,31 +477,29 @@ static int gfs2_read_folio(struct file *file, struct folio *folio)
 *
 */

int gfs2_internal_read(struct gfs2_inode *ip, char *buf, loff_t *pos,
                       unsigned size)
ssize_t gfs2_internal_read(struct gfs2_inode *ip, char *buf, loff_t *pos,
			   size_t size)
{
	struct address_space *mapping = ip->i_inode.i_mapping;
	unsigned long index = *pos >> PAGE_SHIFT;
	unsigned offset = *pos & (PAGE_SIZE - 1);
	unsigned copied = 0;
	unsigned amt;
	struct page *page;
	size_t copied = 0;

	do {
		page = read_cache_page(mapping, index, gfs2_read_folio, NULL);
		if (IS_ERR(page)) {
			if (PTR_ERR(page) == -EINTR)
		size_t offset, chunk;
		struct folio *folio;

		folio = read_cache_folio(mapping, index, gfs2_read_folio, NULL);
		if (IS_ERR(folio)) {
			if (PTR_ERR(folio) == -EINTR)
				continue;
			return PTR_ERR(page);
		}
		amt = size - copied;
		if (offset + size > PAGE_SIZE)
			amt = PAGE_SIZE - offset;
		memcpy_from_page(buf + copied, page, offset, amt);
		put_page(page);
		copied += amt;
		index++;
		offset = 0;
			return PTR_ERR(folio);
		}
		offset = *pos + copied - folio_pos(folio);
		chunk = min(size - copied, folio_size(folio) - offset);
		memcpy_from_folio(buf + copied, folio, offset, chunk);
		index = folio_next_index(folio);
		folio_put(folio);
		copied += chunk;
	} while(copied < size);
	(*pos) += size;
	return size;
+3 −3
Original line number Diff line number Diff line
@@ -8,8 +8,8 @@

#include "incore.h"

extern void adjust_fs_space(struct inode *inode);
extern void gfs2_trans_add_databufs(struct gfs2_inode *ip, struct folio *folio,
void adjust_fs_space(struct inode *inode);
void gfs2_trans_add_databufs(struct gfs2_inode *ip, struct folio *folio,
			     size_t from, size_t len);

#endif /* __AOPS_DOT_H__ */
+11 −6
Original line number Diff line number Diff line
@@ -104,7 +104,7 @@ static int __gfs2_unstuff_inode(struct gfs2_inode *ip, struct folio *folio)
		   and write it out to disk */

		unsigned int n = 1;
		error = gfs2_alloc_blocks(ip, &block, &n, 0, NULL);
		error = gfs2_alloc_blocks(ip, &block, &n, 0);
		if (error)
			goto out_brelse;
		if (isdir) {
@@ -315,6 +315,12 @@ static void gfs2_metapath_ra(struct gfs2_glock *gl, __be64 *start, __be64 *end)
	}
}

static inline struct buffer_head *
metapath_dibh(struct metapath *mp)
{
	return mp->mp_bh[0];
}

static int __fillup_metapath(struct gfs2_inode *ip, struct metapath *mp,
			     unsigned int x, unsigned int h)
{
@@ -413,13 +419,12 @@ static void release_metapath(struct metapath *mp)
 * gfs2_extent_length - Returns length of an extent of blocks
 * @bh: The metadata block
 * @ptr: Current position in @bh
 * @limit: Max extent length to return
 * @eob: Set to 1 if we hit "end of block"
 *
 * Returns: The length of the extent (minimum of one block)
 */

static inline unsigned int gfs2_extent_length(struct buffer_head *bh, __be64 *ptr, size_t limit, int *eob)
static inline unsigned int gfs2_extent_length(struct buffer_head *bh, __be64 *ptr, int *eob)
{
	const __be64 *end = (__be64 *)(bh->b_data + bh->b_size);
	const __be64 *first = ptr;
@@ -658,7 +663,7 @@ static int __gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
{
	struct gfs2_inode *ip = GFS2_I(inode);
	struct gfs2_sbd *sdp = GFS2_SB(inode);
	struct buffer_head *dibh = mp->mp_bh[0];
	struct buffer_head *dibh = metapath_dibh(mp);
	u64 bn;
	unsigned n, i, blks, alloced = 0, iblks = 0, branch_start = 0;
	size_t dblks = iomap->length >> inode->i_blkbits;
@@ -700,7 +705,7 @@ static int __gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
	i = mp->mp_aheight;
	do {
		n = blks - alloced;
		ret = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL);
		ret = gfs2_alloc_blocks(ip, &bn, &n, 0);
		if (ret)
			goto out;
		alloced += n;
@@ -911,7 +916,7 @@ static int __gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
		goto do_alloc;

	bh = mp->mp_bh[ip->i_height - 1];
	len = gfs2_extent_length(bh, ptr, len, &eob);
	len = gfs2_extent_length(bh, ptr, &eob);

	iomap->addr = be64_to_cpu(*ptr) << inode->i_blkbits;
	iomap->length = len << inode->i_blkbits;
+19 −19
Original line number Diff line number Diff line
@@ -46,24 +46,24 @@ static inline void gfs2_write_calc_reserv(const struct gfs2_inode *ip,
extern const struct iomap_ops gfs2_iomap_ops;
extern const struct iomap_writeback_ops gfs2_writeback_ops;

extern int gfs2_unstuff_dinode(struct gfs2_inode *ip);
extern int gfs2_block_map(struct inode *inode, sector_t lblock,
int gfs2_unstuff_dinode(struct gfs2_inode *ip);
int gfs2_block_map(struct inode *inode, sector_t lblock,
		   struct buffer_head *bh, int create);
extern int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
		   struct iomap *iomap);
extern int gfs2_iomap_alloc(struct inode *inode, loff_t pos, loff_t length,
int gfs2_iomap_alloc(struct inode *inode, loff_t pos, loff_t length,
		     struct iomap *iomap);
extern int gfs2_get_extent(struct inode *inode, u64 lblock, u64 *dblock,
int gfs2_get_extent(struct inode *inode, u64 lblock, u64 *dblock,
		    unsigned int *extlen);
extern int gfs2_alloc_extent(struct inode *inode, u64 lblock, u64 *dblock,
int gfs2_alloc_extent(struct inode *inode, u64 lblock, u64 *dblock,
		      unsigned *extlen, bool *new);
extern int gfs2_setattr_size(struct inode *inode, u64 size);
extern int gfs2_truncatei_resume(struct gfs2_inode *ip);
extern int gfs2_file_dealloc(struct gfs2_inode *ip);
extern int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
int gfs2_setattr_size(struct inode *inode, u64 size);
int gfs2_truncatei_resume(struct gfs2_inode *ip);
int gfs2_file_dealloc(struct gfs2_inode *ip);
int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
			      unsigned int len);
extern int gfs2_map_journal_extents(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd);
extern void gfs2_free_journal_extents(struct gfs2_jdesc *jd);
extern int __gfs2_punch_hole(struct file *file, loff_t offset, loff_t length);
int gfs2_map_journal_extents(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd);
void gfs2_free_journal_extents(struct gfs2_jdesc *jd);
int __gfs2_punch_hole(struct file *file, loff_t offset, loff_t length);

#endif /* __BMAP_DOT_H__ */
Loading