Commit 9d865439 authored by Artem Blagodarenko's avatar Artem Blagodarenko Committed by Greg Kroah-Hartman

staging/lustre/ost: Ensure dirty flushed on fiemap ioctl

Data corruption is possible if cp(coreutils) uses FIEMAP to obtain
data holes in shared file, since there could be dirty cache on
other clients which hasn't been flushed back.

To ensure all the dirty on remote clients being flushed back on
fiemap ioctl, we'd acquire ldlm lock on server side for fiemap,
unless the local client (which invoke fiemap) has cached lock.

[picked osc part for upstream kernel submission]
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3219
Xyratex-bug-id: MRP-1001
Lustre-change: http://review.whamcloud.com/6127Signed-off-by: default avatarArtem Blagodarenko <artem_blagodarenko@xyratex.com>
Signed-off-by: default avatarNiu Yawei <yawei.niu@intel.com>
Reviewed-by: default avatarNathaniel Clark <nathaniel.l.clark@intel.com>
Reviewed-by: default avatarJinshan Xiong <jinshan.xiong@intel.com>
Reviewed-by: default avatarAndreas Dilger <andreas.dilger@intel.com>
Signed-off-by: default avatarPeng Tao <tao.peng@emc.com>
Signed-off-by: default avatarAndreas Dilger <andreas.dilger@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e377988e
......@@ -3062,15 +3062,52 @@ static int osc_get_info(const struct lu_env *env, struct obd_export *exp,
ptlrpc_req_finished(req);
RETURN(rc);
} else if (KEY_IS(KEY_FIEMAP)) {
struct ptlrpc_request *req;
struct ll_user_fiemap *reply;
char *tmp;
int rc;
struct ll_fiemap_info_key *fm_key =
(struct ll_fiemap_info_key *)key;
struct ldlm_res_id res_id;
ldlm_policy_data_t policy;
struct lustre_handle lockh;
ldlm_mode_t mode = 0;
struct ptlrpc_request *req;
struct ll_user_fiemap *reply;
char *tmp;
int rc;
if (!(fm_key->fiemap.fm_flags & FIEMAP_FLAG_SYNC))
goto skip_locking;
policy.l_extent.start = fm_key->fiemap.fm_start &
CFS_PAGE_MASK;
if (OBD_OBJECT_EOF - fm_key->fiemap.fm_length <=
fm_key->fiemap.fm_start + PAGE_CACHE_SIZE - 1)
policy.l_extent.end = OBD_OBJECT_EOF;
else
policy.l_extent.end = (fm_key->fiemap.fm_start +
fm_key->fiemap.fm_length +
PAGE_CACHE_SIZE - 1) & CFS_PAGE_MASK;
ostid_build_res_name(&fm_key->oa.o_oi, &res_id);
mode = ldlm_lock_match(exp->exp_obd->obd_namespace,
LDLM_FL_BLOCK_GRANTED |
LDLM_FL_LVB_READY,
&res_id, LDLM_EXTENT, &policy,
LCK_PR | LCK_PW, &lockh, 0);
if (mode) { /* lock is cached on client */
if (mode != LCK_PR) {
ldlm_lock_addref(&lockh, LCK_PR);
ldlm_lock_decref(&lockh, LCK_PW);
}
} else { /* no cached lock, needs acquire lock on server side */
fm_key->oa.o_valid |= OBD_MD_FLFLAGS;
fm_key->oa.o_flags |= OBD_FL_SRVLOCK;
}
skip_locking:
req = ptlrpc_request_alloc(class_exp2cliimp(exp),
&RQF_OST_GET_INFO_FIEMAP);
if (req == NULL)
RETURN(-ENOMEM);
GOTO(drop_lock, rc = -ENOMEM);
req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_KEY,
RCL_CLIENT, keylen);
......@@ -3082,7 +3119,7 @@ static int osc_get_info(const struct lu_env *env, struct obd_export *exp,
rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_GET_INFO);
if (rc) {
ptlrpc_request_free(req);
RETURN(rc);
GOTO(drop_lock, rc);
}
tmp = req_capsule_client_get(&req->rq_pill, &RMF_FIEMAP_KEY);
......@@ -3093,16 +3130,18 @@ static int osc_get_info(const struct lu_env *env, struct obd_export *exp,
ptlrpc_request_set_replen(req);
rc = ptlrpc_queue_wait(req);
if (rc)
GOTO(out1, rc);
GOTO(fini_req, rc);
reply = req_capsule_server_get(&req->rq_pill, &RMF_FIEMAP_VAL);
if (reply == NULL)
GOTO(out1, rc = -EPROTO);
GOTO(fini_req, rc = -EPROTO);
memcpy(val, reply, *vallen);
out1:
fini_req:
ptlrpc_req_finished(req);
drop_lock:
if (mode)
ldlm_lock_decref(&lockh, LCK_PR);
RETURN(rc);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment