/*
 * GPL HEADER START
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 only,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License version 2 for more details (a copy is included
 * in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU General Public License
 * version 2 along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 021110-1307, USA
 *
 * GPL HEADER END
 */
/*
 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
 *
 * Copyright (c) 2011, 2012, Intel Corporation.
 *
 * Code originally extracted from quota directory
 */

#include "../include/obd_class.h"
#include "osc_internal.h"

static inline struct osc_quota_info *osc_oqi_alloc(u32 id)
{
	struct osc_quota_info *oqi;

	OBD_SLAB_ALLOC_PTR(oqi, osc_quota_kmem);
	if (oqi != NULL)
		oqi->oqi_id = id;

	return oqi;
}

int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
{
	int type;

	for (type = 0; type < MAXQUOTAS; type++) {
		struct osc_quota_info *oqi;

		oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
		if (oqi) {
			/* do not try to access oqi here, it could have been
			 * freed by osc_quota_setdq() */

			/* the slot is busy, the user is about to run out of
			 * quota space on this OST */
			CDEBUG(D_QUOTA, "chkdq found noquota for %s %d\n",
			       type == USRQUOTA ? "user" : "grout", qid[type]);
			return NO_QUOTA;
		}
	}

	return QUOTA_OK;
}

#define MD_QUOTA_FLAG(type) ((type == USRQUOTA) ? OBD_MD_FLUSRQUOTA \
						: OBD_MD_FLGRPQUOTA)
#define FL_QUOTA_FLAG(type) ((type == USRQUOTA) ? OBD_FL_NO_USRQUOTA \
						: OBD_FL_NO_GRPQUOTA)

int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
		    u32 valid, u32 flags)
{
	int type;
	int rc = 0;

	if ((valid & (OBD_MD_FLUSRQUOTA | OBD_MD_FLGRPQUOTA)) == 0)
		return 0;

	for (type = 0; type < MAXQUOTAS; type++) {
		struct osc_quota_info *oqi;

		if ((valid & MD_QUOTA_FLAG(type)) == 0)
			continue;

		/* lookup the ID in the per-type hash table */
		oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
		if ((flags & FL_QUOTA_FLAG(type)) != 0) {
			/* This ID is getting close to its quota limit, let's
			 * switch to sync I/O */
			if (oqi != NULL)
				continue;

			oqi = osc_oqi_alloc(qid[type]);
			if (oqi == NULL) {
				rc = -ENOMEM;
				break;
			}

			rc = cfs_hash_add_unique(cli->cl_quota_hash[type],
						 &qid[type], &oqi->oqi_hash);
			/* race with others? */
			if (rc == -EALREADY) {
				rc = 0;
				OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
			}

			CDEBUG(D_QUOTA, "%s: setdq to insert for %s %d (%d)\n",
			       cli->cl_import->imp_obd->obd_name,
			       type == USRQUOTA ? "user" : "group",
			       qid[type], rc);
		} else {
			/* This ID is now off the hook, let's remove it from
			 * the hash table */
			if (oqi == NULL)
				continue;

			oqi = cfs_hash_del_key(cli->cl_quota_hash[type],
					       &qid[type]);
			if (oqi)
				OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);

			CDEBUG(D_QUOTA, "%s: setdq to remove for %s %d (%p)\n",
			       cli->cl_import->imp_obd->obd_name,
			       type == USRQUOTA ? "user" : "group",
			       qid[type], oqi);
		}
	}

	return rc;
}

/*
 * Hash operations for uid/gid <-> osc_quota_info
 */
static unsigned
oqi_hashfn(struct cfs_hash *hs, const void *key, unsigned mask)
{
	return cfs_hash_u32_hash(*((__u32 *)key), mask);
}

static int
oqi_keycmp(const void *key, struct hlist_node *hnode)
{
	struct osc_quota_info *oqi;
	u32 uid;

	LASSERT(key != NULL);
	uid = *((u32 *)key);
	oqi = hlist_entry(hnode, struct osc_quota_info, oqi_hash);

	return uid == oqi->oqi_id;
}

static void *
oqi_key(struct hlist_node *hnode)
{
	struct osc_quota_info *oqi;
	oqi = hlist_entry(hnode, struct osc_quota_info, oqi_hash);
	return &oqi->oqi_id;
}

static void *
oqi_object(struct hlist_node *hnode)
{
	return hlist_entry(hnode, struct osc_quota_info, oqi_hash);
}

static void
oqi_get(struct cfs_hash *hs, struct hlist_node *hnode)
{
}

static void
oqi_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
{
}

static void
oqi_exit(struct cfs_hash *hs, struct hlist_node *hnode)
{
	struct osc_quota_info *oqi;

	oqi = hlist_entry(hnode, struct osc_quota_info, oqi_hash);

	OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
}

#define HASH_QUOTA_BKT_BITS 5
#define HASH_QUOTA_CUR_BITS 5
#define HASH_QUOTA_MAX_BITS 15

static cfs_hash_ops_t quota_hash_ops = {
	.hs_hash	= oqi_hashfn,
	.hs_keycmp	= oqi_keycmp,
	.hs_key		= oqi_key,
	.hs_object	= oqi_object,
	.hs_get		= oqi_get,
	.hs_put_locked	= oqi_put_locked,
	.hs_exit	= oqi_exit,
};

int osc_quota_setup(struct obd_device *obd)
{
	struct client_obd *cli = &obd->u.cli;
	int i, type;

	for (type = 0; type < MAXQUOTAS; type++) {
		cli->cl_quota_hash[type] = cfs_hash_create("QUOTA_HASH",
							   HASH_QUOTA_CUR_BITS,
							   HASH_QUOTA_MAX_BITS,
							   HASH_QUOTA_BKT_BITS,
							   0,
							   CFS_HASH_MIN_THETA,
							   CFS_HASH_MAX_THETA,
							   &quota_hash_ops,
							   CFS_HASH_DEFAULT);
		if (cli->cl_quota_hash[type] == NULL)
			break;
	}

	if (type == MAXQUOTAS)
		return 0;

	for (i = 0; i < type; i++)
		cfs_hash_putref(cli->cl_quota_hash[i]);

	return -ENOMEM;
}

int osc_quota_cleanup(struct obd_device *obd)
{
	struct client_obd     *cli = &obd->u.cli;
	int type;

	for (type = 0; type < MAXQUOTAS; type++)
		cfs_hash_putref(cli->cl_quota_hash[type]);

	return 0;
}

int osc_quotactl(struct obd_device *unused, struct obd_export *exp,
		 struct obd_quotactl *oqctl)
{
	struct ptlrpc_request *req;
	struct obd_quotactl   *oqc;
	int		    rc;

	req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
					&RQF_OST_QUOTACTL, LUSTRE_OST_VERSION,
					OST_QUOTACTL);
	if (req == NULL)
		return -ENOMEM;

	oqc = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
	*oqc = *oqctl;

	ptlrpc_request_set_replen(req);
	ptlrpc_at_set_req_timeout(req);
	req->rq_no_resend = 1;

	rc = ptlrpc_queue_wait(req);
	if (rc)
		CERROR("ptlrpc_queue_wait failed, rc: %d\n", rc);

	if (req->rq_repmsg) {
		oqc = req_capsule_server_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
		if (oqc) {
			*oqctl = *oqc;
		} else if (!rc) {
			CERROR("Can't unpack obd_quotactl\n");
			rc = -EPROTO;
		}
	} else if (!rc) {
		CERROR("Can't unpack obd_quotactl\n");
		rc = -EPROTO;
	}
	ptlrpc_req_finished(req);

	return rc;
}

int osc_quotacheck(struct obd_device *unused, struct obd_export *exp,
		   struct obd_quotactl *oqctl)
{
	struct client_obd       *cli = &exp->exp_obd->u.cli;
	struct ptlrpc_request   *req;
	struct obd_quotactl     *body;
	int		      rc;

	req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
					&RQF_OST_QUOTACHECK, LUSTRE_OST_VERSION,
					OST_QUOTACHECK);
	if (req == NULL)
		return -ENOMEM;

	body = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
	*body = *oqctl;

	ptlrpc_request_set_replen(req);

	/* the next poll will find -ENODATA, that means quotacheck is
	 * going on */
	cli->cl_qchk_stat = -ENODATA;
	rc = ptlrpc_queue_wait(req);
	if (rc)
		cli->cl_qchk_stat = rc;
	ptlrpc_req_finished(req);
	return rc;
}

int osc_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk)
{
	struct client_obd *cli = &exp->exp_obd->u.cli;
	int rc;

	qchk->obd_uuid = cli->cl_target_uuid;
	memcpy(qchk->obd_type, LUSTRE_OST_NAME, strlen(LUSTRE_OST_NAME));

	rc = cli->cl_qchk_stat;
	/* the client is not the previous one */
	if (rc == CL_NOT_QUOTACHECKED)
		rc = -EINTR;
	return rc;
}
