/*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
* Copyright 2004-2011 Red Hat, Inc.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License version 2.
*/
#include <linux/fs.h>
#include <linux/dlm.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/gfs2_ondisk.h>
#include "incore.h"
#include "glock.h"
#include "util.h"
#include "sys.h"
#include "trace_gfs2.h"
extern struct workqueue_struct *gfs2_control_wq;
/**
* gfs2_update_stats - Update time based stats
* @mv: Pointer to mean/variance structure to update
* @sample: New data to include
*
* @delta is the difference between the current rtt sample and the
* running average srtt. We add 1/8 of that to the srtt in order to
* update the current srtt estimate. The varience estimate is a bit
* more complicated. We subtract the abs value of the @delta from
* the current variance estimate and add 1/4 of that to the running
* total.
*
* Note that the index points at the array entry containing the smoothed
* mean value, and the variance is always in the following entry
*
* Reference: TCP/IP Illustrated, vol 2, p. 831,832
* All times are in units of integer nanoseconds. Unlike the TCP/IP case,
* they are not scaled fixed point.
*/
static inline void gfs2_update_stats(struct gfs2_lkstats *s, unsigned index,
s64 sample)
{
s64 delta = sample - s->stats[index];
s->stats[index] += (delta >> 3);
index++;
s->stats[index] += ((abs64(delta) - s->stats[index]) >> 2);
}
/**
* gfs2_update_reply_times - Update locking statistics
* @gl: The glock to update
*
* This assumes that gl->gl_dstamp has been set earlier.
*
* The rtt (lock round trip time) is an estimate of the time
* taken to perform a dlm lock request. We update it on each
* reply from the dlm.
*
* The blocking flag is set on the glock for all dlm requests
* which may potentially block due to lock requests from other nodes.
* DLM requests where the current lock state is exclusive, the
* requested state is null (or unlocked) or where the TRY or
* TRY_1CB flags are set are classified as non-blocking. All
* other DLM requests are counted as (potentially) blocking.
*/
static inline void gfs2_update_reply_times(struct gfs2_glock *gl)
{
struct gfs2_pcpu_lkstats *lks;
const unsigned gltype = gl->gl_name.ln_type;
unsigned index = test_bit(GLF_BLOCKING, &gl->gl_flags) ?
GFS2_LKS_SRTTB : GFS2_LKS_SRTT;
s64 rtt;
preempt_disable();
rtt = ktime_to_ns(ktime_sub(ktime_get_real(), gl->gl_dstamp));
lks = this_cpu_ptr(gl->gl_sbd->sd_lkstats);
gfs2_update_stats(&gl->gl_stats, index, rtt); /* Local */
gfs2_update_stats(&lks->lkstats[gltype], index, rtt); /* Global */
preempt_enable();
trace_gfs2_glock_lock_time(gl, rtt);
}
/**
* gfs2_update_request_times - Update locking statistics
* @gl: The glock to update
*
* The irt (lock inter-request times) measures the average time
* between requests to the dlm. It is updated immediately before
* each dlm call.
*/
static inline void<