Commit 44ecac68 authored by Fan Yong's avatar Fan Yong Committed by Greg Kroah-Hartman
Browse files

staging/lustre/llite: cleanup open handle for client open failure



For open case, the client side open handling thread may hit error
after the MDT grant the open. Under such case, the client should
send close RPC to the MDT as cleanup; otherwise, the open handle
on the MDT will be leaked there until the client umount or evicted.

If the LFSCK marks LU_OBJECT_HEARD_BANSHEE on the MDT-object that is
opened by others for repairing some inconsistency, such as repairing
multiple-referenced OST-object, because the leaked open handle still
references the MDT-object, then it will block the subsequent threads
that want to locate such object via FID.

Signed-off-by: default avatarFan Yong <fan.yong@intel.com>
Reviewed-on: http://review.whamcloud.com/13709
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6301


Reviewed-by: default avatarAndreas Dilger <andreas.dilger@intel.com>
Reviewed-by: default avatarLai Siyao <lai.siyao@intel.com>
Reviewed-by: default avatarAlex Zhuravlev <alexey.zhuravlev@intel.com>
Signed-off-by: default avatarOleg Drokin <oleg.drokin@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6e580ab5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -801,6 +801,7 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data,
void ll_finish_md_op_data(struct md_op_data *op_data);
int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg);
char *ll_get_fsname(struct super_block *sb, char *buf, int buflen);
void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req);

/* llite/llite_nfs.c */
extern struct export_operations lustre_export_operations;
+47 −1
Original line number Diff line number Diff line
@@ -1973,6 +1973,47 @@ int ll_remount_fs(struct super_block *sb, int *flags, char *data)
	return 0;
}

/**
 * Cleanup the open handle that is cached on MDT-side.
 *
 * For open case, the client side open handling thread may hit error
 * after the MDT grant the open. Under such case, the client should
 * send close RPC to the MDT as cleanup; otherwise, the open handle
 * on the MDT will be leaked there until the client umount or evicted.
 *
 * In further, if someone unlinked the file, because the open handle
 * holds the reference on such file/object, then it will block the
 * subsequent threads that want to locate such object via FID.
 *
 * \param[in] sb	super block for this file-system
 * \param[in] open_req	pointer to the original open request
 */
void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req)
{
	struct mdt_body			*body;
	struct md_op_data		*op_data;
	struct ptlrpc_request		*close_req = NULL;
	struct obd_export		*exp	   = ll_s2sbi(sb)->ll_md_exp;

	body = req_capsule_server_get(&open_req->rq_pill, &RMF_MDT_BODY);
	OBD_ALLOC_PTR(op_data);
	if (!op_data) {
		CWARN("%s: cannot allocate op_data to release open handle for "
		      DFID "\n",
		      ll_get_fsname(sb, NULL, 0), PFID(&body->fid1));

		return;
	}

	op_data->op_fid1 = body->fid1;
	op_data->op_ioepoch = body->ioepoch;
	op_data->op_handle = body->handle;
	op_data->op_mod_time = get_seconds();
	md_close(exp, op_data, NULL, &close_req);
	ptlrpc_req_finished(close_req);
	ll_finish_md_op_data(op_data);
}

int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req,
		  struct super_block *sb, struct lookup_intent *it)
{
@@ -1985,7 +2026,7 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req,
	rc = md_get_lustre_md(sbi->ll_md_exp, req, sbi->ll_dt_exp,
			      sbi->ll_md_exp, &md);
	if (rc)
		return rc;
		goto cleanup;

	if (*inode) {
		ll_update_inode(*inode, &md);
@@ -2047,6 +2088,11 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req,
	if (md.lsm != NULL)
		obd_free_memmd(sbi->ll_dt_exp, &md.lsm);
	md_free_lustre_md(sbi->ll_md_exp, &md);

cleanup:
	if (rc != 0 && it && it->it_op & IT_OPEN)
		ll_open_cleanup(sb ? sb : (*inode)->i_sb, req);

	return rc;
}

+10 −4
Original line number Diff line number Diff line
@@ -409,7 +409,7 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request,
{
	struct inode *inode = NULL;
	__u64 bits = 0;
	int rc;
	int rc = 0;

	/* NB 1 request reference will be taken away by ll_intent_lock()
	 * when I return */
@@ -439,8 +439,10 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request,
		struct dentry *alias;

		alias = ll_splice_alias(inode, *de);
		if (IS_ERR(alias))
			return PTR_ERR(alias);
		if (IS_ERR(alias)) {
			rc = PTR_ERR(alias);
			goto out;
		}
		*de = alias;
	} else if (!it_disposition(it, DISP_LOOKUP_NEG)  &&
		   !it_disposition(it, DISP_OPEN_CREATE)) {
@@ -471,7 +473,11 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request,
		}
	}

	return 0;
out:
	if (rc != 0 && it->it_op & IT_OPEN)
		ll_open_cleanup((*de)->d_sb, request);

	return rc;
}

static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,