*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
*
* GPL HEADER END
*/
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2011, 2012, Whamcloud, Inc.
+ * Copyright (c) 2011, 2017, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
#include <obd_class.h>
#include <lprocfs_status.h>
#include <lustre_mds.h>
+#include <lustre_barrier.h>
#include "mdd_internal.h"
struct thandle *mdd_trans_create(const struct lu_env *env,
struct mdd_device *mdd)
{
- return mdd_child_ops(mdd)->dt_trans_create(env, mdd->mdd_child);
+ struct thandle *th;
+ struct lu_ucred *uc = lu_ucred_check(env);
+
+ /* If blocked by the write barrier, then return "-EINPROGRESS"
+ * to the caller. Usually, such error will be forwarded to the
+ * client, and the expected behaviour is to re-try such modify
+ * RPC some time later until the barrier is thawed or expired. */
+ if (unlikely(!barrier_entry(mdd->mdd_bottom)))
+ return ERR_PTR(-EINPROGRESS);
+
+ th = mdd_child_ops(mdd)->dt_trans_create(env, mdd->mdd_child);
+ if (!IS_ERR(th) && uc)
+ th->th_ignore_quota = !!md_capable(uc, CFS_CAP_SYS_RESOURCE);
+
+ return th;
}
int mdd_trans_start(const struct lu_env *env, struct mdd_device *mdd,
return mdd_child_ops(mdd)->dt_trans_start(env, mdd->mdd_child, th);
}
-void mdd_trans_stop(const struct lu_env *env, struct mdd_device *mdd,
- int result, struct thandle *handle)
+int mdd_trans_stop(const struct lu_env *env, struct mdd_device *mdd,
+ int result, struct thandle *handle)
{
- handle->th_result = result;
- mdd_child_ops(mdd)->dt_trans_stop(env, handle);
+ int rc;
+
+ handle->th_result = result;
+ rc = mdd_child_ops(mdd)->dt_trans_stop(env, mdd->mdd_child, handle);
+ barrier_exit(mdd->mdd_bottom);
+
+ /* if operation failed, return \a result, otherwise return status of
+ * dt_trans_stop */
+ return result ?: rc;
}