/*
 * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
 * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
 *
 * 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/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/buffer_head.h>
#include <linux/gfs2_ondisk.h>
#include <linux/lm_interface.h>

#include "gfs2.h"
#include "incore.h"
#include "bmap.h"
#include "glock.h"
#include "glops.h"
#include "inode.h"
#include "log.h"
#include "meta_io.h"
#include "recovery.h"
#include "rgrp.h"
#include "util.h"


/**
 * gfs2_pte_inval - Sync and invalidate all PTEs associated with a glock
 * @gl: the glock
 *
 */

static void gfs2_pte_inval(struct gfs2_glock *gl)
{
	struct gfs2_inode *ip;
	struct inode *inode;

	ip = gl->gl_object;
	inode = &ip->i_inode;
	if (!ip || !S_ISREG(ip->i_di.di_mode))
		return;

	if (!test_bit(GIF_PAGED, &ip->i_flags))
		return;

	unmap_shared_mapping_range(inode->i_mapping, 0, 0);

	if (test_bit(GIF_SW_PAGED, &ip->i_flags))
		set_bit(GLF_DIRTY, &gl->gl_flags);

	clear_bit(GIF_SW_PAGED, &ip->i_flags);
}

/**
 * gfs2_page_inval - Invalidate all pages associated with a glock
 * @gl: the glock
 *
 */

static void gfs2_page_inval(struct gfs2_glock *gl)
{
	struct gfs2_inode *ip;
	struct inode *inode;

	ip = gl->gl_object;
	inode = &ip->i_inode;
	if (!ip || !S_ISREG(ip->i_di.di_mode))
		return;

	truncate_inode_pages(inode->i_mapping, 0);
	gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !inode->i_mapping->nrpages);
	clear_bit(GIF_PAGED, &ip->i_flags);
}

/**
 * gfs2_page_wait - Wait for writeback of data
 * @gl: the glock
 *
 * Syncs data (not metadata) for a regular file.
 * No-op for all other types.
 */

static void gfs2_page_wait(struct gfs2_glock *gl)
{
	struct gfs2_inode *ip = gl->gl_object;
	struct inode *inode = &ip->i_inode;
	struct address_space *mapping = inode->i_mapping;
	int error;

	if (!S_ISREG(ip->i_di.di_mode))
		return;

	error = filemap_fdatawait(mapping);

	/* Put back any errors cleared by filemap_fdatawait()
	   so they can be caught by someone who can pass them
	   up to user space. */

	if (error == -ENOSPC)
		set_bit(AS_ENOSPC, &mapping->flags);
	else if (error)
		set_bit(AS_EIO, &mapping->flags);

}

static void gfs2_page_writeback(struct gfs2_glock *gl)
{
	struct gfs2_inode *ip = gl->gl_object;
	struct inode *inode = &ip->i_inode;
	struct address_space *mapping = inode->i_mapping;

	if (!S_ISREG(ip->i_di.di_mode))
		return;

	filemap_fdatawrite(mapping);
}

/**
 * meta_go_sync - sync out the metadata for this glock
 * @gl: the glock
 * @flags: DIO_*
 *
 * Called when demoting or unlocking an EX glock.  We must flush
 * to disk all dirty buffers/pages relating to this glock, and must not
 * not return to caller to demote/unlock the glock until I/O is complete.
 */

static void meta_go_sync(struct gfs2_glock *gl, int flags)
{
	if (!(flags & DIO_METADATA))
		return;

	if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) {
		gfs2_log_flush(gl->gl_sbd, gl);
		gfs2_meta_sync(gl);
		if (flags & DIO_RELEASE)
			gfs2_ail_empty_gl(gl);
	}

}

/**
 * meta_go_inval - invalidate the metadata for this glock
 * @gl: the glock
 * @flags:
 *
 */

static void meta_go_inval(struct gfs2_glock *gl, int flags)
{
	if (!(flags & DIO_METADATA))
		return;

	gfs2_meta_inval(gl);
	gl->gl_vn++;
}

/**
 * inode_go_xmote_th - promote/demote a glock
 * @gl: the glock
 * @state: the requested state
 * @flags:
 *
 */

static void inode_go_xmote_th(struct gfs2_glock *gl, unsigned int state,
			      int flags)
{
	if (gl->gl_state != LM_ST_UNLOCKED)
		gfs2_pte_inval(gl);
	gfs2_glock_xmote_th(gl, state, flags);
}

/**
 * inode_go_xmote_bh - After promoting/demoting a glock
 * @gl: the glock
 *
 */

static void inode_go_xmote_bh(struct gfs2_glock *gl)
{
	struct gfs2_holder *gh = gl->gl_req_gh;
	struct buffer_head *bh;
	int error;

	if (gl->gl_state != LM_ST_UNLOCKED &&
	    (!gh || !(gh->gh_flags & GL_SKIP))) {
		error = gfs2_meta_read(gl, gl->gl_name.ln_number, 0, &bh);
		if (!error)
			brelse(bh);
	}
}

/**
 * inode_go_drop_th - unlock a glock
 * @gl: the glock
 *
 * Invoked from rq_demote().
 * Another node needs the lock in EXCLUSIVE mode, or lock (unused for too long)
 * is being purged from our node's glock cache; we're dropping lock.
 */

static void inode_go_drop_th(struct gfs2_glock *gl)
{
	gfs2_pte_inval(gl);
	gfs2_glock_drop_th(gl);
}

/**
 * inode_go_sync - Sync the dirty data and/or metadata for an inode glock
 * @gl: the glock protecting the inode
 * @flags:
 *
 */

static void inode_go_sync(struct gfs2_glock *gl, int flags)
{
	int meta = (flags & DIO_METADATA);
	int data = (flags & DIO_DATA);

	if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
		if (meta && data) {
			gfs2_page_writeback(gl);
			gfs2_log_flush(gl->gl_sbd, gl);
			gfs2_meta_sync(gl);
			gfs2_page_wait(gl);
			clear_bit(GLF_DIRTY, &gl->gl_flags);
		} else if (meta) {
			gfs2_log_flush(gl->gl_sbd, gl);
			gfs2_meta_sync(gl);
		} else if (data) {
			gfs2_page_writeback(gl);
			gfs2_page_wait(gl);
		}
		if (flags & DIO_RELEASE)
			gfs2_ail_empty_gl(gl);
	}
}

/**
 * inode_go_inval - prepare a inode glock to be released
 * @gl: the glock
 * @flags:
 *
 */

static void inode_go_inval(struct gfs2_glock *gl, int flags)
{
	int meta = (flags & DIO_METADATA);
	int data = (flags & DIO_DATA);

	if (meta) {
		gfs2_meta_inval(gl);
		gl->gl_vn++;
	}
	if (data)
		gfs2_page_inval(gl);
}

/**
 * inode_go_demote_ok - Check to see if it's ok to unlock an inode glock
 * @gl: the glock
 *
 * Returns: 1 if it's ok
 */

static int inode_go_demote_ok(struct gfs2_glock *gl)
{
	struct gfs2_sbd *sdp = gl->gl_sbd;
	int demote = 0;

	if (!gl->gl_object && !gl->gl_aspace->i_mapping->nrpages)
		demote = 1;
	else if (!sdp->sd_args.ar_localcaching &&
		 time_after_eq(jiffies, gl->gl_stamp +
			       gfs2_tune_get(sdp, gt_demote_secs) * HZ))
		demote = 1;

	return demote;
}

/**
 * inode_go_lock - operation done after an inode lock is locked by a process
 * @gl: the glock
 * @flags:
 *
 * Returns: errno
 */

static int inode_go_lock(struct gfs2_holder *gh)
{
	struct gfs2_glock *gl = gh->gh_gl;
	struct gfs2_inode *ip = gl->gl_object;
	int error = 0;

	if (!ip)
		return 0;

	if (ip->i_vn != gl->gl_vn) {
		error = gfs2_inode_refresh(ip);
		if (error)
			return error;
		gfs2_inode_attr_in(ip);
	}

	if ((ip->i_di.di_flags & GFS2_DIF_TRUNC_IN_PROG) &&
	    (gl->gl_state == LM_ST_EXCLUSIVE) &&
	    (gh->gh_flags & GL_LOCAL_EXCL))
		error = gfs2_truncatei_resume(ip);

	return error;
}

/**
 * inode_go_unlock - operation done before an inode lock is unlocked by a
 *		     process
 * @gl: the glock
 * @flags:
 *
 */

static void inode_go_unlock(struct gfs2_holder *gh)
{
	struct gfs2_glock *gl = gh->gh_gl;
	struct gfs2_inode *ip = gl->gl_object;

	if (ip == NULL)
		return;
	if (test_bit(GLF_DIRTY, &gl->gl_flags))
		gfs2_inode_attr_in(ip);
	gfs2_meta_cache_flush(ip);
}

/**
 * inode_greedy -
 * @gl: the glock
 *
 */

static void inode_greedy(struct gfs2_glock *gl)
{
	struct gfs2_sbd *sdp = gl->gl_sbd;
	struct gfs2_inode *ip = gl->gl_object;
	unsigned int quantum = gfs2_tune_get(sdp, gt_greedy_quantum);
	unsigned int max = gfs2_tune_get(sdp, gt_greedy_max);
	unsigned int new_time;

	spin_lock(&ip->i_spin);

	if (time_after(ip->i_last_pfault + quantum, jiffies)) {
		new_time = ip->i_greedy + quantum;
		if (new_time > max)
			new_time = max;
	} else {
		new_time = ip->i_greedy - quantum;
		if (!new_time || new_time > max)
			new_time = 1;
	}

	ip->i_greedy = new_time;

	spin_unlock(&ip->i_spin);

	iput(&ip->i_inode);
}

/**
 * rgrp_go_demote_ok - Check to see if it's ok to unlock a RG's glock
 * @gl: the glock
 *
 * Returns: 1 if it's ok
 */

static int rgrp_go_demote_ok(struct gfs2_glock *gl)
{
	return !gl->gl_aspace->i_mapping->nrpages;
}

/**
 * rgrp_go_lock - operation done after an rgrp lock is locked by
 *    a first holder on this node.
 * @gl: the glock
 * @flags:
 *
 * Returns: errno
 */

static int rgrp_go_lock(struct gfs2_holder *gh)
{
	return gfs2_rgrp_bh_get(gh->gh_gl->gl_object);
}

/**
 * rgrp_go_unlock - operation done before an rgrp lock is unlocked by
 *    a last holder on this node.
 * @gl: the glock
 * @flags:
 *
 */

static void rgrp_go_unlock(struct gfs2_holder *gh)
{
	gfs2_rgrp_bh_put(gh->gh_gl->gl_object);
}

/**
 * trans_go_xmote_th - promote/demote the transaction glock
 * @gl: the glock
 * @state: the requested state
 * @flags:
 *
 */

static void trans_go_xmote_th(struct gfs2_glock *gl, unsigned int state,
			      int flags)
{
	struct gfs2_sbd *sdp = gl->gl_sbd;

	if (gl->gl_state != LM_ST_UNLOCKED &&
	    test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
		gfs2_meta_syncfs(sdp);
		gfs2_log_shutdown(sdp);
	}

	gfs2_glock_xmote_th(gl, state, flags);
}

/**
 * trans_go_xmote_bh - After promoting/demoting the transaction glock
 * @gl: the glock
 *
 */

static void trans_go_xmote_bh(struct gfs2_glock *gl)
{
	struct gfs2_sbd *sdp = gl->gl_sbd;
	struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode);
	struct gfs2_glock *j_gl = ip->i_gl;
	struct gfs2_log_header head;
	int error;

	if (gl->gl_state != LM_ST_UNLOCKED &&
	    test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
		gfs2_meta_cache_flush(GFS2_I(sdp->sd_jdesc->jd_inode));
		j_gl->gl_ops->go_inval(j_gl, DIO_METADATA | DIO_DATA);

		error = gfs2_find_jhead(sdp->sd_jdesc, &head);
		if (error)
			gfs2_consist(sdp);
		if (!(head.lh_flags & GFS2_LOG_HEAD_UNMOUNT))
			gfs2_consist(sdp);

		/*  Initialize some head of the log stuff  */
		if (!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) {
			sdp->sd_log_sequence = head.lh_sequence + 1;
			gfs2_log_pointers_init(sdp, head.lh_blkno);
		}
	}
}

/**
 * trans_go_drop_th - unlock the transaction glock
 * @gl: the glock
 *
 * We want to sync the device even with localcaching.  Remember
 * that localcaching journal replay only marks buffers dirty.
 */

static void trans_go_drop_th(struct gfs2_glock *gl)
{
	struct gfs2_sbd *sdp = gl->gl_sbd;

	if (test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
		gfs2_meta_syncfs(sdp);
		gfs2_log_shutdown(sdp);
	}

	gfs2_glock_drop_th(gl);
}

/**
 * quota_go_demote_ok - Check to see if it's ok to unlock a quota glock
 * @gl: the glock
 *
 * Returns: 1 if it's ok
 */

static int quota_go_demote_ok(struct gfs2_glock *gl)
{
	return !atomic_read(&gl->gl_lvb_count);
}

const struct gfs2_glock_operations gfs2_meta_glops = {
	.go_xmote_th = gfs2_glock_xmote_th,
	.go_drop_th = gfs2_glock_drop_th,
	.go_type = LM_TYPE_META,
};

const struct gfs2_glock_operations gfs2_inode_glops = {
	.go_xmote_th = inode_go_xmote_th,
	.go_xmote_bh = inode_go_xmote_bh,
	.go_drop_th = inode_go_drop_th,
	.go_sync = inode_go_sync,
	.go_inval = inode_go_inval,
	.go_demote_ok = inode_go_demote_ok,
	.go_lock = inode_go_lock,
	.go_unlock = inode_go_unlock,
	.go_greedy = inode_greedy,
	.go_type = LM_TYPE_INODE,
};

const struct gfs2_glock_operations gfs2_rgrp_glops = {
	.go_xmote_th = gfs2_glock_xmote_th,
	.go_drop_th = gfs2_glock_drop_th,
	.go_sync = meta_go_sync,
	.go_inval = meta_go_inval,
	.go_demote_ok = rgrp_go_demote_ok,
	.go_lock = rgrp_go_lock,
	.go_unlock = rgrp_go_unlock,
	.go_type = LM_TYPE_RGRP,
};

const struct gfs2_glock_operations gfs2_trans_glops = {
	.go_xmote_th = trans_go_xmote_th,
	.go_xmote_bh = trans_go_xmote_bh,
	.go_drop_th = trans_go_drop_th,
	.go_type = LM_TYPE_NONDISK,
};

const struct gfs2_glock_operations gfs2_iopen_glops = {
	.go_xmote_th = gfs2_glock_xmote_th,
	.go_drop_th = gfs2_glock_drop_th,
	.go_type = LM_TYPE_IOPEN,
};

const struct gfs2_glock_operations gfs2_flock_glops = {
	.go_xmote_th = gfs2_glock_xmote_th,
	.go_drop_th = gfs2_glock_drop_th,
	.go_type = LM_TYPE_FLOCK,
};

const struct gfs2_glock_operations gfs2_nondisk_glops = {
	.go_xmote_th = gfs2_glock_xmote_th,
	.go_drop_th = gfs2_glock_drop_th,
	.go_type = LM_TYPE_NONDISK,
};

const struct gfs2_glock_operations gfs2_quota_glops = {
	.go_xmote_th = gfs2_glock_xmote_th,
	.go_drop_th = gfs2_glock_drop_th,
	.go_demote_ok = quota_go_demote_ok,
	.go_type = LM_TYPE_QUOTA,
};

const struct gfs2_glock_operations gfs2_journal_glops = {
	.go_xmote_th = gfs2_glock_xmote_th,
	.go_drop_th = gfs2_glock_drop_th,
	.go_type = LM_TYPE_JOURNAL,
};

