diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-03-22 11:12:21 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-03-22 11:12:21 -0700 |
commit | 6f6efce52d3a035b8332969ecf254b4dfc62e4ec (patch) | |
tree | ad078590e54b22f16e18378fb03aadd4acb6f5ed /fs | |
parent | c150b809f7de2afdd3fb5a9adff2a9a68d7331ce (diff) | |
parent | 0c6ca06aad84bac097f5c005d911db92dba3ae94 (diff) |
Merge tag 'xfs-6.9-merge-9' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs fixes from Chandan Babu:
- Fix invalid pointer dereference by initializing xmbuf before
tracepoint function is invoked
- Use memalloc_nofs_save() when inserting into quota radix tree
* tag 'xfs-6.9-merge-9' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
xfs: quota radix tree allocations need to be NOFS on insert
xfs: fix dev_t usage in xmbuf tracepoints
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/xfs_buf_mem.c | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_dquot.c | 18 | ||||
-rw-r--r-- | fs/xfs/xfs_trace.h | 9 |
3 files changed, 22 insertions, 9 deletions
diff --git a/fs/xfs/xfs_buf_mem.c b/fs/xfs/xfs_buf_mem.c index 8ad38c64708e..9bb2d24de709 100644 --- a/fs/xfs/xfs_buf_mem.c +++ b/fs/xfs/xfs_buf_mem.c @@ -81,8 +81,6 @@ xmbuf_alloc( /* ensure all writes are below EOF to avoid pagecache zeroing */ i_size_write(inode, inode->i_sb->s_maxbytes); - trace_xmbuf_create(btp); - error = xfs_buf_cache_init(btp->bt_cache); if (error) goto out_file; @@ -99,6 +97,8 @@ xmbuf_alloc( if (error) goto out_bcache; + trace_xmbuf_create(btp); + *btpp = btp; return 0; diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 30d36596a2e4..c98cb468c357 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -811,6 +811,12 @@ restart: * caller should throw away the dquot and start over. Otherwise, the dquot * is returned locked (and held by the cache) as if there had been a cache * hit. + * + * The insert needs to be done under memalloc_nofs context because the radix + * tree can do memory allocation during insert. The qi->qi_tree_lock is taken in + * memory reclaim when freeing unused dquots, so we cannot have the radix tree + * node allocation recursing into filesystem reclaim whilst we hold the + * qi_tree_lock. */ static int xfs_qm_dqget_cache_insert( @@ -820,25 +826,27 @@ xfs_qm_dqget_cache_insert( xfs_dqid_t id, struct xfs_dquot *dqp) { + unsigned int nofs_flags; int error; + nofs_flags = memalloc_nofs_save(); mutex_lock(&qi->qi_tree_lock); error = radix_tree_insert(tree, id, dqp); if (unlikely(error)) { /* Duplicate found! Caller must try again. */ - mutex_unlock(&qi->qi_tree_lock); trace_xfs_dqget_dup(dqp); - return error; + goto out_unlock; } /* Return a locked dquot to the caller, with a reference taken. */ xfs_dqlock(dqp); dqp->q_nrefs = 1; - qi->qi_dquots++; - mutex_unlock(&qi->qi_tree_lock); - return 0; +out_unlock: + mutex_unlock(&qi->qi_tree_lock); + memalloc_nofs_restore(nofs_flags); + return error; } /* Check our input parameters. */ diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 56b07d8ed431..aea97fc074f8 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -4626,6 +4626,7 @@ TRACE_EVENT(xmbuf_create, char *path; struct file *file = btp->bt_file; + __entry->dev = btp->bt_mount->m_super->s_dev; __entry->ino = file_inode(file)->i_ino; memset(pathname, 0, sizeof(pathname)); path = file_path(file, pathname, sizeof(pathname) - 1); @@ -4633,7 +4634,8 @@ TRACE_EVENT(xmbuf_create, path = "(unknown)"; strncpy(__entry->pathname, path, sizeof(__entry->pathname)); ), - TP_printk("xmino 0x%lx path '%s'", + TP_printk("dev %d:%d xmino 0x%lx path '%s'", + MAJOR(__entry->dev), MINOR(__entry->dev), __entry->ino, __entry->pathname) ); @@ -4642,6 +4644,7 @@ TRACE_EVENT(xmbuf_free, TP_PROTO(struct xfs_buftarg *btp), TP_ARGS(btp), TP_STRUCT__entry( + __field(dev_t, dev) __field(unsigned long, ino) __field(unsigned long long, bytes) __field(loff_t, size) @@ -4650,11 +4653,13 @@ TRACE_EVENT(xmbuf_free, struct file *file = btp->bt_file; struct inode *inode = file_inode(file); + __entry->dev = btp->bt_mount->m_super->s_dev; __entry->size = i_size_read(inode); __entry->bytes = (inode->i_blocks << SECTOR_SHIFT) + inode->i_bytes; __entry->ino = inode->i_ino; ), - TP_printk("xmino 0x%lx mem_bytes 0x%llx isize 0x%llx", + TP_printk("dev %d:%d xmino 0x%lx mem_bytes 0x%llx isize 0x%llx", + MAJOR(__entry->dev), MINOR(__entry->dev), __entry->ino, __entry->bytes, __entry->size) |