Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
232c2f5c
Commit
232c2f5c
authored
May 15, 2014
by
Dave Chinner
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'xfs-filestreams-lookup' into for-next
parents
fdd3a2ae
b94acd47
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
403 additions
and
806 deletions
+403
-806
fs/xfs/xfs_bmap.c
fs/xfs/xfs_bmap.c
+117
-85
fs/xfs/xfs_filestream.c
fs/xfs/xfs_filestream.c
+147
-537
fs/xfs/xfs_filestream.h
fs/xfs/xfs_filestream.h
+2
-32
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.c
+1
-34
fs/xfs/xfs_inode.h
fs/xfs/xfs_inode.h
+1
-3
fs/xfs/xfs_mru_cache.c
fs/xfs/xfs_mru_cache.c
+63
-88
fs/xfs/xfs_mru_cache.h
fs/xfs/xfs_mru_cache.h
+12
-19
fs/xfs/xfs_super.c
fs/xfs/xfs_super.c
+1
-8
fs/xfs/xfs_trace.c
fs/xfs/xfs_trace.c
+1
-0
fs/xfs/xfs_trace.h
fs/xfs/xfs_trace.h
+58
-0
No files found.
fs/xfs/xfs_bmap.c
View file @
232c2f5c
...
...
@@ -3515,6 +3515,67 @@ xfs_bmap_adjacent(
#undef ISVALID
}
static
int
xfs_bmap_longest_free_extent
(
struct
xfs_trans
*
tp
,
xfs_agnumber_t
ag
,
xfs_extlen_t
*
blen
,
int
*
notinit
)
{
struct
xfs_mount
*
mp
=
tp
->
t_mountp
;
struct
xfs_perag
*
pag
;
xfs_extlen_t
longest
;
int
error
=
0
;
pag
=
xfs_perag_get
(
mp
,
ag
);
if
(
!
pag
->
pagf_init
)
{
error
=
xfs_alloc_pagf_init
(
mp
,
tp
,
ag
,
XFS_ALLOC_FLAG_TRYLOCK
);
if
(
error
)
goto
out
;
if
(
!
pag
->
pagf_init
)
{
*
notinit
=
1
;
goto
out
;
}
}
longest
=
xfs_alloc_longest_free_extent
(
mp
,
pag
);
if
(
*
blen
<
longest
)
*
blen
=
longest
;
out:
xfs_perag_put
(
pag
);
return
error
;
}
static
void
xfs_bmap_select_minlen
(
struct
xfs_bmalloca
*
ap
,
struct
xfs_alloc_arg
*
args
,
xfs_extlen_t
*
blen
,
int
notinit
)
{
if
(
notinit
||
*
blen
<
ap
->
minlen
)
{
/*
* Since we did a BUF_TRYLOCK above, it is possible that
* there is space for this request.
*/
args
->
minlen
=
ap
->
minlen
;
}
else
if
(
*
blen
<
args
->
maxlen
)
{
/*
* If the best seen length is less than the request length,
* use the best as the minimum.
*/
args
->
minlen
=
*
blen
;
}
else
{
/*
* Otherwise we've seen an extent as big as maxlen, use that
* as the minimum.
*/
args
->
minlen
=
args
->
maxlen
;
}
}
STATIC
int
xfs_bmap_btalloc_nullfb
(
struct
xfs_bmalloca
*
ap
,
...
...
@@ -3522,111 +3583,74 @@ xfs_bmap_btalloc_nullfb(
xfs_extlen_t
*
blen
)
{
struct
xfs_mount
*
mp
=
ap
->
ip
->
i_mount
;
struct
xfs_perag
*
pag
;
xfs_agnumber_t
ag
,
startag
;
int
notinit
=
0
;
int
error
;
if
(
ap
->
userdata
&&
xfs_inode_is_filestream
(
ap
->
ip
))
args
->
type
=
XFS_ALLOCTYPE_NEAR_BNO
;
else
args
->
type
=
XFS_ALLOCTYPE_START_BNO
;
args
->
type
=
XFS_ALLOCTYPE_START_BNO
;
args
->
total
=
ap
->
total
;
/*
* Search for an allocation group with a single extent large enough
* for the request. If one isn't found, then adjust the minimum
* allocation size to the largest space found.
*/
startag
=
ag
=
XFS_FSB_TO_AGNO
(
mp
,
args
->
fsbno
);
if
(
startag
==
NULLAGNUMBER
)
startag
=
ag
=
0
;
pag
=
xfs_perag_get
(
mp
,
ag
);
while
(
*
blen
<
args
->
maxlen
)
{
if
(
!
pag
->
pagf_init
)
{
error
=
xfs_alloc_pagf_init
(
mp
,
args
->
tp
,
ag
,
XFS_ALLOC_FLAG_TRYLOCK
);
if
(
error
)
{
xfs_perag_put
(
pag
);
return
error
;
}
}
/*
* See xfs_alloc_fix_freelist...
*/
if
(
pag
->
pagf_init
)
{
xfs_extlen_t
longest
;
longest
=
xfs_alloc_longest_free_extent
(
mp
,
pag
);
if
(
*
blen
<
longest
)
*
blen
=
longest
;
}
else
notinit
=
1
;
if
(
xfs_inode_is_filestream
(
ap
->
ip
))
{
if
(
*
blen
>=
args
->
maxlen
)
break
;
if
(
ap
->
userdata
)
{
/*
* If startag is an invalid AG, we've
* come here once before and
* xfs_filestream_new_ag picked the
* best currently available.
*
* Don't continue looping, since we
* could loop forever.
*/
if
(
startag
==
NULLAGNUMBER
)
break
;
error
=
xfs_filestream_new_ag
(
ap
,
&
ag
);
xfs_perag_put
(
pag
);
if
(
error
)
return
error
;
error
=
xfs_bmap_longest_free_extent
(
args
->
tp
,
ag
,
blen
,
&
notinit
);
if
(
error
)
return
error
;
/* loop again to set 'blen'*/
startag
=
NULLAGNUMBER
;
pag
=
xfs_perag_get
(
mp
,
ag
);
continue
;
}
}
if
(
++
ag
==
mp
->
m_sb
.
sb_agcount
)
ag
=
0
;
if
(
ag
==
startag
)
break
;
xfs_perag_put
(
pag
);
pag
=
xfs_perag_get
(
mp
,
ag
);
}
xfs_perag_put
(
pag
);
/*
* Since the above loop did a BUF_TRYLOCK, it is
* possible that there is space for this request.
*/
if
(
notinit
||
*
blen
<
ap
->
minlen
)
args
->
minlen
=
ap
->
minlen
;
/*
* If the best seen length is less than the request
* length, use the best as the minimum.
*/
else
if
(
*
blen
<
args
->
maxlen
)
args
->
minlen
=
*
blen
;
/*
* Otherwise we've seen an extent as big as maxlen,
* use that as the minimum.
*/
else
args
->
minlen
=
args
->
maxlen
;
xfs_bmap_select_minlen
(
ap
,
args
,
blen
,
notinit
);
return
0
;
}
STATIC
int
xfs_bmap_btalloc_filestreams
(
struct
xfs_bmalloca
*
ap
,
struct
xfs_alloc_arg
*
args
,
xfs_extlen_t
*
blen
)
{
struct
xfs_mount
*
mp
=
ap
->
ip
->
i_mount
;
xfs_agnumber_t
ag
;
int
notinit
=
0
;
int
error
;
args
->
type
=
XFS_ALLOCTYPE_NEAR_BNO
;
args
->
total
=
ap
->
total
;
ag
=
XFS_FSB_TO_AGNO
(
mp
,
args
->
fsbno
);
if
(
ag
==
NULLAGNUMBER
)
ag
=
0
;
error
=
xfs_bmap_longest_free_extent
(
args
->
tp
,
ag
,
blen
,
&
notinit
);
if
(
error
)
return
error
;
if
(
*
blen
<
args
->
maxlen
)
{
error
=
xfs_filestream_new_ag
(
ap
,
&
ag
);
if
(
error
)
return
error
;
error
=
xfs_bmap_longest_free_extent
(
args
->
tp
,
ag
,
blen
,
&
notinit
);
if
(
error
)
return
error
;
}
xfs_bmap_select_minlen
(
ap
,
args
,
blen
,
notinit
);
/*
*
set the failure fallback case to look in the selected
*
AG as the stream
may have moved.
*
Set the failure fallback case to look in the selected AG as stream
* may have moved.
*/
if
(
xfs_inode_is_filestream
(
ap
->
ip
))
ap
->
blkno
=
args
->
fsbno
=
XFS_AGB_TO_FSB
(
mp
,
ag
,
0
);
ap
->
blkno
=
args
->
fsbno
=
XFS_AGB_TO_FSB
(
mp
,
ag
,
0
);
return
0
;
}
...
...
@@ -3706,7 +3730,15 @@ xfs_bmap_btalloc(
args
.
firstblock
=
*
ap
->
firstblock
;
blen
=
0
;
if
(
nullfb
)
{
error
=
xfs_bmap_btalloc_nullfb
(
ap
,
&
args
,
&
blen
);
/*
* Search for an allocation group with a single extent large
* enough for the request. If one isn't found, then adjust
* the minimum allocation size to the largest space found.
*/
if
(
ap
->
userdata
&&
xfs_inode_is_filestream
(
ap
->
ip
))
error
=
xfs_bmap_btalloc_filestreams
(
ap
,
&
args
,
&
blen
);
else
error
=
xfs_bmap_btalloc_nullfb
(
ap
,
&
args
,
&
blen
);
if
(
error
)
return
error
;
}
else
if
(
ap
->
flist
->
xbf_low
)
{
...
...
fs/xfs/xfs_filestream.c
View file @
232c2f5c
This diff is collapsed.
Click to expand it.
fs/xfs/xfs_filestream.h
View file @
232c2f5c
...
...
@@ -20,50 +20,20 @@
struct
xfs_mount
;
struct
xfs_inode
;
struct
xfs_perag
;
struct
xfs_bmalloca
;
#ifdef XFS_FILESTREAMS_TRACE
#define XFS_FSTRM_KTRACE_INFO 1
#define XFS_FSTRM_KTRACE_AGSCAN 2
#define XFS_FSTRM_KTRACE_AGPICK1 3
#define XFS_FSTRM_KTRACE_AGPICK2 4
#define XFS_FSTRM_KTRACE_UPDATE 5
#define XFS_FSTRM_KTRACE_FREE 6
#define XFS_FSTRM_KTRACE_ITEM_LOOKUP 7
#define XFS_FSTRM_KTRACE_ASSOCIATE 8
#define XFS_FSTRM_KTRACE_MOVEAG 9
#define XFS_FSTRM_KTRACE_ORPHAN 10
#define XFS_FSTRM_KTRACE_SIZE 16384
extern
ktrace_t
*
xfs_filestreams_trace_buf
;
#endif
/* allocation selection flags */
typedef
enum
xfs_fstrm_alloc
{
XFS_PICK_USERDATA
=
1
,
XFS_PICK_LOWSPACE
=
2
,
}
xfs_fstrm_alloc_t
;
/* prototypes for filestream.c */
int
xfs_filestream_init
(
void
);
void
xfs_filestream_uninit
(
void
);
int
xfs_filestream_mount
(
struct
xfs_mount
*
mp
);
void
xfs_filestream_unmount
(
struct
xfs_mount
*
mp
);
xfs_agnumber_t
xfs_filestream_lookup_ag
(
struct
xfs_inode
*
ip
);
int
xfs_filestream_associate
(
struct
xfs_inode
*
dip
,
struct
xfs_inode
*
ip
);
void
xfs_filestream_deassociate
(
struct
xfs_inode
*
ip
);
xfs_agnumber_t
xfs_filestream_lookup_ag
(
struct
xfs_inode
*
ip
);
int
xfs_filestream_new_ag
(
struct
xfs_bmalloca
*
ap
,
xfs_agnumber_t
*
agp
);
int
xfs_filestream_peek_ag
(
struct
xfs_mount
*
mp
,
xfs_agnumber_t
agno
);
/* filestreams for the inode? */
static
inline
int
xfs_inode_is_filestream
(
struct
xfs_inode
*
ip
)
{
return
(
ip
->
i_mount
->
m_flags
&
XFS_MOUNT_FILESTREAMS
)
||
xfs_iflags_test
(
ip
,
XFS_IFILESTREAM
)
||
(
ip
->
i_d
.
di_flags
&
XFS_DIFLAG_FILESTREAM
);
}
...
...
fs/xfs/xfs_inode.c
View file @
232c2f5c
...
...
@@ -655,7 +655,6 @@ xfs_ialloc(
uint
flags
;
int
error
;
timespec_t
tv
;
int
filestreams
=
0
;
/*
* Call the space management code to pick
...
...
@@ -772,13 +771,6 @@ xfs_ialloc(
flags
|=
XFS_ILOG_DEV
;
break
;
case
S_IFREG
:
/*
* we can't set up filestreams until after the VFS inode
* is set up properly.
*/
if
(
pip
&&
xfs_inode_is_filestream
(
pip
))
filestreams
=
1
;
/* fall through */
case
S_IFDIR
:
if
(
pip
&&
(
pip
->
i_d
.
di_flags
&
XFS_DIFLAG_ANY
))
{
uint
di_flags
=
0
;
...
...
@@ -844,15 +836,6 @@ xfs_ialloc(
/* now that we have an i_mode we can setup inode ops and unlock */
xfs_setup_inode
(
ip
);
/* now we have set up the vfs inode we can associate the filestream */
if
(
filestreams
)
{
error
=
xfs_filestream_associate
(
pip
,
ip
);
if
(
error
<
0
)
return
-
error
;
if
(
!
error
)
xfs_iflags_set
(
ip
,
XFS_IFILESTREAM
);
}
*
ipp
=
ip
;
return
0
;
}
...
...
@@ -1698,16 +1681,6 @@ xfs_release(
if
(
!
XFS_FORCED_SHUTDOWN
(
mp
))
{
int
truncated
;
/*
* If we are using filestreams, and we have an unlinked
* file that we are processing the last close on, then nothing
* will be able to reopen and write to this file. Purge this
* inode from the filestreams cache so that it doesn't delay
* teardown of the inode.
*/
if
((
ip
->
i_d
.
di_nlink
==
0
)
&&
xfs_inode_is_filestream
(
ip
))
xfs_filestream_deassociate
(
ip
);
/*
* If we previously truncated this file and removed old data
* in the process, we want to initiate "early" writeout on
...
...
@@ -2664,13 +2637,7 @@ xfs_remove(
if
(
error
)
goto
std_return
;
/*
* If we are using filestreams, kill the stream association.
* If the file is still open it may get a new one but that
* will get killed on last close in xfs_close() so we don't
* have to worry about that.
*/
if
(
!
is_dir
&&
link_zero
&&
xfs_inode_is_filestream
(
ip
))
if
(
is_dir
&&
xfs_inode_is_filestream
(
ip
))
xfs_filestream_deassociate
(
ip
);
return
0
;
...
...
fs/xfs/xfs_inode.h
View file @
232c2f5c
...
...
@@ -209,7 +209,6 @@ xfs_get_initial_prid(struct xfs_inode *dp)
#define XFS_ISTALE (1 << 1)
/* inode has been staled */
#define XFS_IRECLAIMABLE (1 << 2)
/* inode can be reclaimed */
#define XFS_INEW (1 << 3)
/* inode has just been allocated */
#define XFS_IFILESTREAM (1 << 4)
/* inode is in a filestream dir. */
#define XFS_ITRUNCATED (1 << 5)
/* truncated down so flush-on-close */
#define XFS_IDIRTY_RELEASE (1 << 6)
/* dirty release already seen */
#define __XFS_IFLOCK_BIT 7
/* inode is being flushed right now */
...
...
@@ -225,8 +224,7 @@ xfs_get_initial_prid(struct xfs_inode *dp)
*/
#define XFS_IRECLAIM_RESET_FLAGS \
(XFS_IRECLAIMABLE | XFS_IRECLAIM | \
XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | \
XFS_IFILESTREAM);
XFS_IDIRTY_RELEASE | XFS_ITRUNCATED)
/*
* Synchronize processes attempting to flush the in-core inode back to disk.
...
...
fs/xfs/xfs_mru_cache.c
View file @
232c2f5c
...
...
@@ -100,14 +100,20 @@
* likely result in a loop in one of the lists. That's a sure-fire recipe for
* an infinite loop in the code.
*/
typedef
struct
xfs_mru_cache_elem
{
struct
list_head
list_node
;
unsigned
long
key
;
void
*
value
;
}
xfs_mru_cache_elem_t
;
struct
xfs_mru_cache
{
struct
radix_tree_root
store
;
/* Core storage data structure. */
struct
list_head
*
lists
;
/* Array of lists, one per grp. */
struct
list_head
reap_list
;
/* Elements overdue for reaping. */
spinlock_t
lock
;
/* Lock to protect this struct. */
unsigned
int
grp_count
;
/* Number of discrete groups. */
unsigned
int
grp_time
;
/* Time period spanned by grps. */
unsigned
int
lru_grp
;
/* Group containing time zero. */
unsigned
long
time_zero
;
/* Time first element was added. */
xfs_mru_cache_free_func_t
free_func
;
/* Function pointer for freeing. */
struct
delayed_work
work
;
/* Workqueue data for reaping. */
unsigned
int
queued
;
/* work has been queued */
};
static
kmem_zone_t
*
xfs_mru_elem_zone
;
static
struct
workqueue_struct
*
xfs_mru_reap_wq
;
/*
...
...
@@ -129,12 +135,12 @@ static struct workqueue_struct *xfs_mru_reap_wq;
*/
STATIC
unsigned
long
_xfs_mru_cache_migrate
(
xfs_mru_cache_t
*
mru
,
unsigned
long
now
)
struct
xfs_mru_cache
*
mru
,
unsigned
long
now
)
{
unsigned
int
grp
;
unsigned
int
migrated
=
0
;
struct
list_head
*
lru_list
;
unsigned
int
grp
;
unsigned
int
migrated
=
0
;
struct
list_head
*
lru_list
;
/* Nothing to do if the data store is empty. */
if
(
!
mru
->
time_zero
)
...
...
@@ -193,11 +199,11 @@ _xfs_mru_cache_migrate(
*/
STATIC
void
_xfs_mru_cache_list_insert
(
xfs_mru_cache_t
*
mru
,
xfs_mru_cache_elem_t
*
elem
)
struct
xfs_mru_cache
*
mru
,
struct
xfs_mru_cache_elem
*
elem
)
{
unsigned
int
grp
=
0
;
unsigned
long
now
=
jiffies
;
unsigned
int
grp
=
0
;
unsigned
long
now
=
jiffies
;
/*
* If the data store is empty, initialise time zero, leave grp set to
...
...
@@ -231,10 +237,10 @@ _xfs_mru_cache_list_insert(
*/
STATIC
void
_xfs_mru_cache_clear_reap_list
(
xfs_mru_cache_t
*
mru
)
__releases
(
mru
->
lock
)
__acquires
(
mru
->
lock
)
struct
xfs_mru_cache
*
mru
)
__releases
(
mru
->
lock
)
__acquires
(
mru
->
lock
)
{
xfs_mru_cache_elem_t
*
elem
,
*
next
;
struct
xfs_mru_cache_elem
*
elem
,
*
next
;
struct
list_head
tmp
;
INIT_LIST_HEAD
(
&
tmp
);
...
...
@@ -252,15 +258,8 @@ _xfs_mru_cache_clear_reap_list(
spin_unlock
(
&
mru
->
lock
);
list_for_each_entry_safe
(
elem
,
next
,
&
tmp
,
list_node
)
{
/* Remove the element from the reap list. */
list_del_init
(
&
elem
->
list_node
);
/* Call the client's free function with the key and value pointer. */
mru
->
free_func
(
elem
->
key
,
elem
->
value
);
/* Free the element structure. */
kmem_zone_free
(
xfs_mru_elem_zone
,
elem
);
mru
->
free_func
(
elem
);
}
spin_lock
(
&
mru
->
lock
);
...
...
@@ -277,7 +276,8 @@ STATIC void
_xfs_mru_cache_reap
(
struct
work_struct
*
work
)
{
xfs_mru_cache_t
*
mru
=
container_of
(
work
,
xfs_mru_cache_t
,
work
.
work
);
struct
xfs_mru_cache
*
mru
=
container_of
(
work
,
struct
xfs_mru_cache
,
work
.
work
);
unsigned
long
now
,
next
;
ASSERT
(
mru
&&
mru
->
lists
);
...
...
@@ -304,28 +304,16 @@ _xfs_mru_cache_reap(
int
xfs_mru_cache_init
(
void
)
{
xfs_mru_elem_zone
=
kmem_zone_init
(
sizeof
(
xfs_mru_cache_elem_t
),
"xfs_mru_cache_elem"
);
if
(
!
xfs_mru_elem_zone
)
goto
out
;
xfs_mru_reap_wq
=
alloc_workqueue
(
"xfs_mru_cache"
,
WQ_MEM_RECLAIM
,
1
);
if
(
!
xfs_mru_reap_wq
)
goto
out_destroy_mru_elem_zone
;
return
-
ENOMEM
;
return
0
;
out_destroy_mru_elem_zone:
kmem_zone_destroy
(
xfs_mru_elem_zone
);
out:
return
-
ENOMEM
;
}
void
xfs_mru_cache_uninit
(
void
)
{
destroy_workqueue
(
xfs_mru_reap_wq
);
kmem_zone_destroy
(
xfs_mru_elem_zone
);
}
/*
...
...
@@ -336,14 +324,14 @@ xfs_mru_cache_uninit(void)
*/
int
xfs_mru_cache_create
(
xfs_mru_cache_t
**
mrup
,
struct
xfs_mru_cache
**
mrup
,
unsigned
int
lifetime_ms
,
unsigned
int
grp_count
,
xfs_mru_cache_free_func_t
free_func
)
{
xfs_mru_cache_t
*
mru
=
NULL
;
int
err
=
0
,
grp
;
unsigned
int
grp_time
;
struct
xfs_mru_cache
*
mru
=
NULL
;
int
err
=
0
,
grp
;
unsigned
int
grp_time
;
if
(
mrup
)
*
mrup
=
NULL
;
...
...
@@ -400,7 +388,7 @@ xfs_mru_cache_create(
*/
static
void
xfs_mru_cache_flush
(
xfs_mru_cache_t
*
mru
)
struct
xfs_mru_cache
*
mru
)
{
if
(
!
mru
||
!
mru
->
lists
)
return
;
...
...
@@ -420,7 +408,7 @@ xfs_mru_cache_flush(
void
xfs_mru_cache_destroy
(
xfs_mru_cache_t
*
mru
)
struct
xfs_mru_cache
*
mru
)
{
if
(
!
mru
||
!
mru
->
lists
)
return
;
...
...
@@ -438,38 +426,30 @@ xfs_mru_cache_destroy(
*/
int
xfs_mru_cache_insert
(
xfs_mru_cache_t
*
mru
,
unsigned
long
key
,
void
*
value
)
struct
xfs_mru_cache
*
mru
,
unsigned
long
key
,
struct
xfs_mru_cache_elem
*
elem
)
{
xfs_mru_cache_elem_t
*
elem
;
int
error
;
ASSERT
(
mru
&&
mru
->
lists
);
if
(
!
mru
||
!
mru
->
lists
)
return
EINVAL
;
elem
=
kmem_zone_zalloc
(
xfs_mru_elem_zone
,
KM_SLEEP
);
if
(
!
elem
)
if
(
radix_tree_preload
(
GFP_KERNEL
))
return
ENOMEM
;
if
(
radix_tree_preload
(
GFP_KERNEL
))
{
kmem_zone_free
(
xfs_mru_elem_zone
,
elem
);
return
ENOMEM
;
}
INIT_LIST_HEAD
(
&
elem
->
list_node
);
elem
->
key
=
key
;
elem
->
value
=
value
;
spin_lock
(
&
mru
->
lock
);
radix_tree_insert
(
&
mru
->
store
,
key
,
elem
);
error
=
-
radix_tree_insert
(
&
mru
->
store
,
key
,
elem
);
radix_tree_preload_end
();
_xfs_mru_cache_list_insert
(
mru
,
elem
);
if
(
!
error
)
_xfs_mru_cache_list_insert
(
mru
,
elem
);
spin_unlock
(
&
mru
->
lock
);
return
0
;
return
error
;
}
/*
...
...
@@ -478,13 +458,12 @@ xfs_mru_cache_insert(
* the client data pointer for the removed element is returned, otherwise this
* function will return a NULL pointer.
*/
void
*
struct
xfs_mru_cache_elem
*
xfs_mru_cache_remove
(
xfs_mru_cache_t
*
mru
,
unsigned
long
key
)
struct
xfs_mru_cache
*
mru
,
unsigned
long
key
)
{
xfs_mru_cache_elem_t
*
elem
;
void
*
value
=
NULL
;
struct
xfs_mru_cache_elem
*
elem
;
ASSERT
(
mru
&&
mru
->
lists
);
if
(
!
mru
||
!
mru
->
lists
)
...
...
@@ -492,17 +471,11 @@ xfs_mru_cache_remove(
spin_lock
(
&
mru
->
lock
);
elem
=
radix_tree_delete
(
&
mru
->
store
,
key
);
if
(
elem
)
{
value
=
elem
->
value
;
if
(
elem
)
list_del
(
&
elem
->
list_node
);
}
spin_unlock
(
&
mru
->
lock
);
if
(
elem
)
kmem_zone_free
(
xfs_mru_elem_zone
,
elem
);
return
value
;
return
elem
;
}
/*
...
...
@@ -511,13 +484,14 @@ xfs_mru_cache_remove(
*/
void
xfs_mru_cache_delete
(
xfs_mru_cache_t
*
mru
,
unsigned
long
key
)
struct
xfs_mru_cache
*
mru
,
unsigned
long
key
)
{
void
*
value
=
xfs_mru_cache_remove
(
mru
,
key
)
;
struct
xfs_mru_cache_elem
*
elem
;
if
(
value
)
mru
->
free_func
(
key
,
value
);
elem
=
xfs_mru_cache_remove
(
mru
,
key
);
if
(
elem
)
mru
->
free_func
(
elem
);
}
/*
...
...
@@ -540,12 +514,12 @@ xfs_mru_cache_delete(
* status, we need to help it get it right by annotating the path that does
* not release the lock.
*/
void
*
struct
xfs_mru_cache_elem
*
xfs_mru_cache_lookup
(
xfs_mru_cache_t
*
mru
,
unsigned
long
key
)
struct
xfs_mru_cache
*
mru
,
unsigned
long
key
)
{
xfs_mru_cache_elem_t
*
elem
;
struct
xfs_mru_cache_elem
*
elem
;
ASSERT
(
mru
&&
mru
->
lists
);
if
(
!
mru
||
!
mru
->
lists
)
...
...
@@ -560,7 +534,7 @@ xfs_mru_cache_lookup(
}
else
spin_unlock
(
&
mru
->
lock
);
return
elem
?
elem
->
value
:
NULL
;
return
elem
;
}
/*
...
...
@@ -570,7 +544,8 @@ xfs_mru_cache_lookup(
*/
void
xfs_mru_cache_done
(
xfs_mru_cache_t
*
mru
)
__releases
(
mru
->
lock
)
struct
xfs_mru_cache
*
mru
)
__releases
(
mru
->
lock
)
{
spin_unlock
(
&
mru
->
lock
);
}
fs/xfs/xfs_mru_cache.h
View file @
232c2f5c
...
...
@@ -18,24 +18,15 @@
#ifndef __XFS_MRU_CACHE_H__
#define __XFS_MRU_CACHE_H__
struct
xfs_mru_cache
;
/* Function pointer type for callback to free a client's data pointer. */
typedef
void
(
*
xfs_mru_cache_free_func_t
)(
unsigned
long
,
void
*
);
struct
xfs_mru_cache_elem
{
struct
list_head
list_node
;
unsigned
long
key
;
};
typedef
struct
xfs_mru_cache
{
struct
radix_tree_root
store
;
/* Core storage data structure. */
struct
list_head
*
lists
;
/* Array of lists, one per grp. */
struct
list_head
reap_list
;
/* Elements overdue for reaping. */
spinlock_t
lock
;
/* Lock to protect this struct. */
unsigned
int
grp_count
;
/* Number of discrete groups. */
unsigned
int
grp_time
;
/* Time period spanned by grps. */
unsigned
int
lru_grp
;
/* Group containing time zero. */
unsigned
long
time_zero
;
/* Time first element was added. */
xfs_mru_cache_free_func_t
free_func
;
/* Function pointer for freeing. */
struct
delayed_work
work
;
/* Workqueue data for reaping. */
unsigned
int
queued
;
/* work has been queued */
}
xfs_mru_cache_t
;
/* Function pointer type for callback to free a client's data pointer. */
typedef
void
(
*
xfs_mru_cache_free_func_t
)(
struct
xfs_mru_cache_elem
*
elem
);
int
xfs_mru_cache_init
(
void
);
void
xfs_mru_cache_uninit
(
void
);
...
...
@@ -44,10 +35,12 @@ int xfs_mru_cache_create(struct xfs_mru_cache **mrup, unsigned int lifetime_ms,
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
,
void
*
value
);
void
*
xfs_mru_cache_remove
(
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
);
void
*
xfs_mru_cache_lookup
(
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__ */
fs/xfs/xfs_super.c
View file @
232c2f5c
...
...
@@ -1749,13 +1749,9 @@ init_xfs_fs(void)
if
(
error
)
goto
out_destroy_wq
;
error
=
xfs_filestream_init
();
if
(
error
)
goto
out_mru_cache_uninit
;
error
=
xfs_buf_init
();
if
(
error
)
goto
out_
filestream
_uninit
;
goto
out_
mru_cache
_uninit
;
error
=
xfs_init_procfs
();
if
(
error
)
...
...
@@ -1782,8 +1778,6 @@ init_xfs_fs(void)
xfs_cleanup_procfs
();
out_buf_terminate:
xfs_buf_terminate
();
out_filestream_uninit:
xfs_filestream_uninit
();
out_mru_cache_uninit:
xfs_mru_cache_uninit
();
out_destroy_wq:
...
...
@@ -1802,7 +1796,6 @@ exit_xfs_fs(void)
xfs_sysctl_unregister
();
xfs_cleanup_procfs
();
xfs_buf_terminate
();
xfs_filestream_uninit
();
xfs_mru_cache_uninit
();
xfs_destroy_workqueues
();
xfs_destroy_zones
();
...
...
fs/xfs/xfs_trace.c
View file @
232c2f5c
...
...
@@ -46,6 +46,7 @@
#include "xfs_log_recover.h"
#include "xfs_inode_item.h"
#include "xfs_bmap_btree.h"
#include "xfs_filestream.h"
/*
* We include this last to have the helpers above available for the trace
...
...
fs/xfs/xfs_trace.h
View file @
232c2f5c
...
...
@@ -538,6 +538,64 @@ DEFINE_BUF_ITEM_EVENT(xfs_trans_bhold_release);
DEFINE_BUF_ITEM_EVENT
(
xfs_trans_binval
);
DEFINE_BUF_ITEM_EVENT
(
xfs_trans_buf_ordered
);
DECLARE_EVENT_CLASS
(
xfs_filestream_class
,
TP_PROTO
(
struct
xfs_inode
*
ip
,
xfs_agnumber_t
agno
),
TP_ARGS
(
ip
,
agno
),
TP_STRUCT__entry
(
__field
(
dev_t
,
dev
)
__field
(
xfs_ino_t
,
ino
)
__field
(
xfs_agnumber_t
,
agno
)
__field
(
int
,
streams
)
),
TP_fast_assign
(
__entry
->
dev
=
VFS_I
(
ip
)
->
i_sb
->
s_dev
;
__entry
->
ino
=
ip
->
i_ino
;
__entry
->
agno
=
agno
;
__entry
->
streams
=
xfs_filestream_peek_ag
(
ip
->
i_mount
,
agno
);
),
TP_printk
(
"dev %d:%d ino 0x%llx agno %u streams %d"
,
MAJOR
(
__entry
->
dev
),
MINOR
(
__entry
->
dev
),
__entry
->
ino
,
__entry
->
agno
,
__entry
->
streams
)
)
#define DEFINE_FILESTREAM_EVENT(name) \
DEFINE_EVENT(xfs_filestream_class, name, \
TP_PROTO(struct xfs_inode *ip, xfs_agnumber_t agno), \
TP_ARGS(ip, agno))
DEFINE_FILESTREAM_EVENT
(
xfs_filestream_free
);
DEFINE_FILESTREAM_EVENT
(
xfs_filestream_lookup
);
DEFINE_FILESTREAM_EVENT
(
xfs_filestream_scan
);
TRACE_EVENT
(
xfs_filestream_pick
,
TP_PROTO
(
struct
xfs_inode
*
ip
,
xfs_agnumber_t
agno
,
xfs_extlen_t
free
,
int
nscan
),
TP_ARGS
(
ip
,
agno
,
free
,
nscan
),
TP_STRUCT__entry
(
__field
(
dev_t
,
dev
)
__field
(
xfs_ino_t
,
ino
)
__field
(
xfs_agnumber_t
,
agno
)
__field
(
int
,
streams
)
__field
(
xfs_extlen_t
,
free
)
__field
(
int
,
nscan
)
),
TP_fast_assign
(
__entry
->
dev
=
VFS_I
(
ip
)
->
i_sb
->
s_dev
;
__entry
->
ino
=
ip
->
i_ino
;
__entry
->
agno
=
agno
;
__entry
->
streams
=
xfs_filestream_peek_ag
(
ip
->
i_mount
,
agno
);
__entry
->
free
=
free
;
__entry
->
nscan
=
nscan
;
),
TP_printk
(
"dev %d:%d ino 0x%llx agno %u streams %d free %d nscan %d"
,
MAJOR
(
__entry
->
dev
),
MINOR
(
__entry
->
dev
),
__entry
->
ino
,
__entry
->
agno
,
__entry
->
streams
,
__entry
->
free
,
__entry
->
nscan
)
);
DECLARE_EVENT_CLASS
(
xfs_lock_class
,
TP_PROTO
(
struct
xfs_inode
*
ip
,
unsigned
lock_flags
,
unsigned
long
caller_ip
),
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment