summaryrefslogtreecommitdiff
path: root/drivers/staging/lustre
diff options
context:
space:
mode:
authorArtem Blagodarenko <artem_blagodarenko@xyratex.com>2013-06-03 17:40:53 +0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-06-03 22:26:36 +0400
commit9d8654397d0dcb1885457a2188b59995f2219676 (patch)
treedd0cfb6e65179877f78f47603be0935a18cec1d9 /drivers/staging/lustre
parente377988ed83ebbd871cea36ef5cf47f2360b7bfc (diff)
downloadlinux-9d8654397d0dcb1885457a2188b59995f2219676.tar.xz
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/6127 Signed-off-by: Artem Blagodarenko <artem_blagodarenko@xyratex.com> Signed-off-by: Niu Yawei <yawei.niu@intel.com> Reviewed-by: Nathaniel Clark <nathaniel.l.clark@intel.com> Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: Peng Tao <tao.peng@emc.com> Signed-off-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/lustre')
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_request.c59
1 files changed, 49 insertions, 10 deletions
diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c
index 7422215a2606..53d6a35c80b9 100644
--- a/drivers/staging/lustre/lustre/osc/osc_request.c
+++ b/drivers/staging/lustre/lustre/osc/osc_request.c
@@ -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);
}