2019-05-27 09:55:01 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2009-04-03 19:42:36 +04:00
/* General filesystem local caching manager
*
* Copyright ( C ) 2004 - 2007 Red Hat , Inc . All Rights Reserved .
* Written by David Howells ( dhowells @ redhat . com )
*/
# define FSCACHE_DEBUG_LEVEL CACHE
# include <linux/module.h>
# include <linux/init.h>
# include <linux/sched.h>
# include <linux/completion.h>
# include <linux/slab.h>
2010-07-21 00:09:01 +04:00
# include <linux/seq_file.h>
2018-04-04 15:41:27 +03:00
# define CREATE_TRACE_POINTS
2009-04-03 19:42:36 +04:00
# include "internal.h"
MODULE_DESCRIPTION ( " FS Cache Manager " ) ;
MODULE_AUTHOR ( " Red Hat, Inc. " ) ;
MODULE_LICENSE ( " GPL " ) ;
unsigned fscache_defer_lookup = 1 ;
module_param_named ( defer_lookup , fscache_defer_lookup , uint ,
S_IWUSR | S_IRUGO ) ;
MODULE_PARM_DESC ( fscache_defer_lookup ,
" Defer cookie lookup to background thread " ) ;
unsigned fscache_defer_create = 1 ;
module_param_named ( defer_create , fscache_defer_create , uint ,
S_IWUSR | S_IRUGO ) ;
MODULE_PARM_DESC ( fscache_defer_create ,
" Defer cookie creation to background thread " ) ;
unsigned fscache_debug ;
module_param_named ( debug , fscache_debug , uint ,
S_IWUSR | S_IRUGO ) ;
MODULE_PARM_DESC ( fscache_debug ,
" FS-Cache debugging mask " ) ;
struct kobject * fscache_root ;
2010-07-21 00:09:01 +04:00
struct workqueue_struct * fscache_object_wq ;
2010-07-21 00:09:01 +04:00
struct workqueue_struct * fscache_op_wq ;
2010-07-21 00:09:01 +04:00
DEFINE_PER_CPU ( wait_queue_head_t , fscache_object_cong_wait ) ;
/* these values serve as lower bounds, will be adjusted in fscache_init() */
static unsigned fscache_object_max_active = 4 ;
2010-07-21 00:09:01 +04:00
static unsigned fscache_op_max_active = 2 ;
2010-07-21 00:09:01 +04:00
# ifdef CONFIG_SYSCTL
static struct ctl_table_header * fscache_sysctl_header ;
static int fscache_max_active_sysctl ( struct ctl_table * table , int write ,
void __user * buffer ,
size_t * lenp , loff_t * ppos )
{
struct workqueue_struct * * wqp = table - > extra1 ;
unsigned int * datap = table - > data ;
int ret ;
ret = proc_dointvec ( table , write , buffer , lenp , ppos ) ;
if ( ret = = 0 )
workqueue_set_max_active ( * wqp , * datap ) ;
return ret ;
}
2014-08-07 03:03:24 +04:00
static struct ctl_table fscache_sysctls [ ] = {
2010-07-21 00:09:01 +04:00
{
. procname = " object_max_active " ,
. data = & fscache_object_max_active ,
. maxlen = sizeof ( unsigned ) ,
. mode = 0644 ,
. proc_handler = fscache_max_active_sysctl ,
. extra1 = & fscache_object_wq ,
} ,
2010-07-21 00:09:01 +04:00
{
. procname = " operation_max_active " ,
. data = & fscache_op_max_active ,
. maxlen = sizeof ( unsigned ) ,
. mode = 0644 ,
. proc_handler = fscache_max_active_sysctl ,
. extra1 = & fscache_op_wq ,
} ,
2010-07-21 00:09:01 +04:00
{ }
} ;
2014-08-07 03:03:24 +04:00
static struct ctl_table fscache_sysctls_root [ ] = {
2010-07-21 00:09:01 +04:00
{
. procname = " fscache " ,
. mode = 0555 ,
. child = fscache_sysctls ,
} ,
{ }
} ;
# endif
2009-04-03 19:42:36 +04:00
/*
* initialise the fs caching module
*/
static int __init fscache_init ( void )
{
2010-07-21 00:09:01 +04:00
unsigned int nr_cpus = num_possible_cpus ( ) ;
unsigned int cpu ;
2009-04-03 19:42:36 +04:00
int ret ;
2010-07-21 00:09:01 +04:00
fscache_object_max_active =
clamp_val ( nr_cpus ,
fscache_object_max_active , WQ_UNBOUND_MAX_ACTIVE ) ;
ret = - ENOMEM ;
fscache_object_wq = alloc_workqueue ( " fscache_object " , WQ_UNBOUND ,
fscache_object_max_active ) ;
if ( ! fscache_object_wq )
goto error_object_wq ;
2010-07-21 00:09:01 +04:00
fscache_op_max_active =
clamp_val ( fscache_object_max_active / 2 ,
fscache_op_max_active , WQ_UNBOUND_MAX_ACTIVE ) ;
ret = - ENOMEM ;
fscache_op_wq = alloc_workqueue ( " fscache_operation " , WQ_UNBOUND ,
fscache_op_max_active ) ;
if ( ! fscache_op_wq )
goto error_op_wq ;
2010-07-21 00:09:01 +04:00
for_each_possible_cpu ( cpu )
init_waitqueue_head ( & per_cpu ( fscache_object_cong_wait , cpu ) ) ;
2009-04-03 19:42:37 +04:00
ret = fscache_proc_init ( ) ;
if ( ret < 0 )
goto error_proc ;
2010-07-21 00:09:01 +04:00
# ifdef CONFIG_SYSCTL
ret = - ENOMEM ;
fscache_sysctl_header = register_sysctl_table ( fscache_sysctls_root ) ;
if ( ! fscache_sysctl_header )
goto error_sysctl ;
# endif
2009-04-03 19:42:38 +04:00
fscache_cookie_jar = kmem_cache_create ( " fscache_cookie_jar " ,
sizeof ( struct fscache_cookie ) ,
2018-10-17 17:23:45 +03:00
0 , 0 , NULL ) ;
2009-04-03 19:42:38 +04:00
if ( ! fscache_cookie_jar ) {
2014-06-05 03:05:38 +04:00
pr_notice ( " Failed to allocate a cookie jar \n " ) ;
2009-04-03 19:42:38 +04:00
ret = - ENOMEM ;
goto error_cookie_jar ;
}
2009-04-03 19:42:37 +04:00
fscache_root = kobject_create_and_add ( " fscache " , kernel_kobj ) ;
if ( ! fscache_root )
goto error_kobj ;
2014-06-05 03:05:38 +04:00
pr_notice ( " Loaded \n " ) ;
2009-04-03 19:42:36 +04:00
return 0 ;
2009-04-03 19:42:37 +04:00
error_kobj :
2009-04-03 19:42:38 +04:00
kmem_cache_destroy ( fscache_cookie_jar ) ;
error_cookie_jar :
2010-07-21 00:09:01 +04:00
# ifdef CONFIG_SYSCTL
unregister_sysctl_table ( fscache_sysctl_header ) ;
error_sysctl :
# endif
2009-04-03 19:42:37 +04:00
fscache_proc_cleanup ( ) ;
2009-04-03 19:42:37 +04:00
error_proc :
2010-07-21 00:09:01 +04:00
destroy_workqueue ( fscache_op_wq ) ;
error_op_wq :
2010-07-21 00:09:01 +04:00
destroy_workqueue ( fscache_object_wq ) ;
error_object_wq :
2009-04-03 19:42:36 +04:00
return ret ;
}
fs_initcall ( fscache_init ) ;
/*
* clean up on module removal
*/
static void __exit fscache_exit ( void )
{
_enter ( " " ) ;
2009-04-03 19:42:37 +04:00
kobject_put ( fscache_root ) ;
2009-04-03 19:42:38 +04:00
kmem_cache_destroy ( fscache_cookie_jar ) ;
2010-07-24 13:10:09 +04:00
# ifdef CONFIG_SYSCTL
2010-07-21 00:09:01 +04:00
unregister_sysctl_table ( fscache_sysctl_header ) ;
2010-07-24 13:10:09 +04:00
# endif
2009-04-03 19:42:37 +04:00
fscache_proc_cleanup ( ) ;
2010-07-21 00:09:01 +04:00
destroy_workqueue ( fscache_op_wq ) ;
2010-07-21 00:09:01 +04:00
destroy_workqueue ( fscache_object_wq ) ;
2014-06-05 03:05:38 +04:00
pr_notice ( " Unloaded \n " ) ;
2009-04-03 19:42:36 +04:00
}
module_exit ( fscache_exit ) ;