2006-01-16 16:50:04 +00:00
/*
* Copyright ( C ) Sistina Software , Inc . 1997 - 2003 All rights reserved .
2006-05-18 15:09:15 -04:00
* Copyright ( C ) 2004 - 2006 Red Hat , Inc . All rights reserved .
2006-01-16 16:50:04 +00:00
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
2006-09-01 11:05:15 -04:00
* of the GNU General Public License version 2.
2006-01-16 16:50:04 +00:00
*/
# include <linux/sched.h>
# include <linux/slab.h>
# include <linux/spinlock.h>
# include <linux/completion.h>
# include <linux/buffer_head.h>
# include <linux/kthread.h>
# include <linux/delay.h>
2006-02-27 17:23:27 -05:00
# include <linux/gfs2_ondisk.h>
2006-09-19 07:56:29 +02:00
# include <linux/lm_interface.h>
2007-06-27 11:06:19 -05:00
# include <linux/freezer.h>
2006-01-16 16:50:04 +00:00
# include "gfs2.h"
2006-02-27 17:23:27 -05:00
# include "incore.h"
2006-01-16 16:50:04 +00:00
# include "daemon.h"
# include "glock.h"
# include "log.h"
# include "quota.h"
# include "recovery.h"
# include "super.h"
2006-02-27 17:23:27 -05:00
# include "util.h"
2006-01-16 16:50:04 +00:00
/* This uses schedule_timeout() instead of msleep() because it's good for
the daemons to wake up more often than the timeout when unmounting so
the user ' s unmount doesn ' t sit there forever .
2006-09-25 09:26:04 -04:00
2006-01-16 16:50:04 +00:00
The kthread functions used to start these daemons block and flush signals . */
/**
* gfs2_glockd - Reclaim unused glock structures
* @ sdp : Pointer to GFS2 superblock
*
* One or more of these daemons run , reclaiming glocks on sd_reclaim_list .
* Number of daemons can be set by user , with num_glockd mount option .
*/
int gfs2_glockd ( void * data )
{
2006-04-24 13:13:56 -04:00
struct gfs2_sbd * sdp = data ;
2006-01-16 16:50:04 +00:00
while ( ! kthread_should_stop ( ) ) {
while ( atomic_read ( & sdp - > sd_reclaim_count ) )
gfs2_reclaim_glock ( sdp ) ;
2006-04-24 13:13:56 -04:00
wait_event_interruptible ( sdp - > sd_reclaim_wq ,
( atomic_read ( & sdp - > sd_reclaim_count ) | |
kthread_should_stop ( ) ) ) ;
2007-06-27 11:06:19 -05:00
if ( freezing ( current ) )
refrigerator ( ) ;
2006-01-16 16:50:04 +00:00
}
return 0 ;
}
/**
* gfs2_recoverd - Recover dead machine ' s journals
* @ sdp : Pointer to GFS2 superblock
*
*/
int gfs2_recoverd ( void * data )
{
2006-04-24 13:13:56 -04:00
struct gfs2_sbd * sdp = data ;
2006-01-16 16:50:04 +00:00
unsigned long t ;
while ( ! kthread_should_stop ( ) ) {
gfs2_check_journals ( sdp ) ;
t = gfs2_tune_get ( sdp , gt_recoverd_secs ) * HZ ;
2007-06-27 11:06:19 -05:00
if ( freezing ( current ) )
refrigerator ( ) ;
2006-01-16 16:50:04 +00:00
schedule_timeout_interruptible ( t ) ;
}
return 0 ;
}
/**
* gfs2_quotad - Write cached quota changes into the quota file
* @ sdp : Pointer to GFS2 superblock
*
*/
int gfs2_quotad ( void * data )
{
2006-04-24 13:13:56 -04:00
struct gfs2_sbd * sdp = data ;
2006-01-16 16:50:04 +00:00
unsigned long t ;
int error ;
while ( ! kthread_should_stop ( ) ) {
/* Update the master statfs file */
t = sdp - > sd_statfs_sync_time +
gfs2_tune_get ( sdp , gt_statfs_quantum ) * HZ ;
if ( time_after_eq ( jiffies , t ) ) {
error = gfs2_statfs_sync ( sdp ) ;
if ( error & &
error ! = - EROFS & &
! test_bit ( SDF_SHUTDOWN , & sdp - > sd_flags ) )
fs_err ( sdp , " quotad: (1) error=%d \n " , error ) ;
sdp - > sd_statfs_sync_time = jiffies ;
}
/* Update quota file */
t = sdp - > sd_quota_sync_time +
gfs2_tune_get ( sdp , gt_quota_quantum ) * HZ ;
if ( time_after_eq ( jiffies , t ) ) {
error = gfs2_quota_sync ( sdp ) ;
if ( error & &
error ! = - EROFS & &
! test_bit ( SDF_SHUTDOWN , & sdp - > sd_flags ) )
fs_err ( sdp , " quotad: (2) error=%d \n " , error ) ;
sdp - > sd_quota_sync_time = jiffies ;
}
gfs2_quota_scan ( sdp ) ;
t = gfs2_tune_get ( sdp , gt_quotad_secs ) * HZ ;
2007-06-27 11:06:19 -05:00
if ( freezing ( current ) )
refrigerator ( ) ;
2006-01-16 16:50:04 +00:00
schedule_timeout_interruptible ( t ) ;
}
return 0 ;
}