7fcd3efa1e
The filestreams allocator stores an xfs_fstrm_item structure in the MRU to cache inode number to agno mappings for a particular length of time. Each xfs_fstrm_item contains the internal MRU structure, an inode pointer and agno value. The inode pointer stored in the xfs_fstrm_item is not referenced, however, which means the inode itself can be removed and reclaimed before the MRU item is freed. If this occurs, xfs_fstrm_free_func() can access freed or unrelated memory through xfs_fstrm_item->ip and crash. The obvious solution is to grab an inode reference for xfs_fstrm_item. The filestream mechanism only actually uses the inode pointer as a means to access the xfs_mount, however. Rather than add unnecessary complexity, simplify the implementation to store an xfs_mount pointer in struct xfs_mru_cache, and pass it to the free callback. This also requires updates to the tracepoint class to provide the associated data via parameters rather than the inode and a minor hack to peek at the MRU key to establish the inode number at free time. Based on debugging work and an earlier patch from Brian Foster, who also wrote most of this changelog. Reported-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
47 lines
1.7 KiB
C
47 lines
1.7 KiB
C
/*
|
|
* Copyright (c) 2006-2007 Silicon Graphics, Inc.
|
|
* All Rights Reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it would be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
#ifndef __XFS_MRU_CACHE_H__
|
|
#define __XFS_MRU_CACHE_H__
|
|
|
|
struct xfs_mru_cache;
|
|
|
|
struct xfs_mru_cache_elem {
|
|
struct list_head list_node;
|
|
unsigned long key;
|
|
};
|
|
|
|
/* Function pointer type for callback to free a client's data pointer. */
|
|
typedef void (*xfs_mru_cache_free_func_t)(void *, struct xfs_mru_cache_elem *);
|
|
|
|
int xfs_mru_cache_init(void);
|
|
void xfs_mru_cache_uninit(void);
|
|
int xfs_mru_cache_create(struct xfs_mru_cache **mrup, void *data,
|
|
unsigned int lifetime_ms, unsigned int grp_count,
|
|
xfs_mru_cache_free_func_t free_func);
|
|
void xfs_mru_cache_destroy(struct xfs_mru_cache *mru);
|
|
int xfs_mru_cache_insert(struct xfs_mru_cache *mru, unsigned long key,
|
|
struct xfs_mru_cache_elem *elem);
|
|
struct xfs_mru_cache_elem *
|
|
xfs_mru_cache_remove(struct xfs_mru_cache *mru, unsigned long key);
|
|
void xfs_mru_cache_delete(struct xfs_mru_cache *mru, unsigned long key);
|
|
struct xfs_mru_cache_elem *
|
|
xfs_mru_cache_lookup(struct xfs_mru_cache *mru, unsigned long key);
|
|
void xfs_mru_cache_done(struct xfs_mru_cache *mru);
|
|
|
|
#endif /* __XFS_MRU_CACHE_H__ */
|