+int osc_fsync_ost(const struct lu_env *env, struct osc_object *obj,
+ struct cl_fsync_io *fio)
+{
+ struct osc_io *oio = osc_env_io(env);
+ struct obdo *oa = &oio->oi_oa;
+ struct lov_oinfo *loi = obj->oo_oinfo;
+ struct osc_async_cbargs *cbargs = &oio->oi_cbarg;
+ int rc = 0;
+ ENTRY;
+
+ memset(oa, 0, sizeof(*oa));
+ oa->o_oi = loi->loi_oi;
+ oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;
+
+ /* reload size abd blocks for start and end of sync range */
+ oa->o_size = fio->fi_start;
+ oa->o_blocks = fio->fi_end;
+ oa->o_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
+
+ obdo_set_parent_fid(oa, fio->fi_fid);
+
+ init_completion(&cbargs->opc_sync);
+
+ rc = osc_sync_base(obj, oa, osc_async_upcall, cbargs, PTLRPCD_SET);
+ RETURN(rc);
+}
+EXPORT_SYMBOL(osc_fsync_ost);
+
+int osc_io_fsync_start(const struct lu_env *env,
+ const struct cl_io_slice *slice)
+{
+ struct cl_io *io = slice->cis_io;
+ struct cl_fsync_io *fio = &io->u.ci_fsync;
+ struct cl_object *obj = slice->cis_obj;
+ struct osc_object *osc = cl2osc(obj);
+ pgoff_t start = cl_index(obj, fio->fi_start);
+ pgoff_t end = cl_index(obj, fio->fi_end);
+ int result = 0;
+ ENTRY;
+
+ if (fio->fi_end == OBD_OBJECT_EOF)
+ end = CL_PAGE_EOF;
+
+ result = osc_cache_writeback_range(env, osc, start, end, 0,
+ fio->fi_mode == CL_FSYNC_DISCARD);
+ if (result > 0) {
+ fio->fi_nr_written += result;
+ result = 0;
+ }
+ if (fio->fi_mode == CL_FSYNC_ALL) {
+ int rc;
+
+ /* we have to wait for writeback to finish before we can
+ * send OST_SYNC RPC. This is bad because it causes extents
+ * to be written osc by osc. However, we usually start
+ * writeback before CL_FSYNC_ALL so this won't have any real
+ * problem. */
+ rc = osc_cache_wait_range(env, osc, start, end);
+ if (result == 0)
+ result = rc;
+ rc = osc_fsync_ost(env, osc, fio);
+ if (result == 0)
+ result = rc;
+ }
+
+ RETURN(result);
+}
+
+void osc_io_fsync_end(const struct lu_env *env,
+ const struct cl_io_slice *slice)
+{
+ struct cl_fsync_io *fio = &slice->cis_io->u.ci_fsync;
+ struct cl_object *obj = slice->cis_obj;
+ pgoff_t start = cl_index(obj, fio->fi_start);
+ pgoff_t end = cl_index(obj, fio->fi_end);
+ int result = 0;
+
+ if (fio->fi_mode == CL_FSYNC_LOCAL) {
+ result = osc_cache_wait_range(env, cl2osc(obj), start, end);
+ } else if (fio->fi_mode == CL_FSYNC_ALL) {
+ struct osc_io *oio = cl2osc_io(env, slice);
+ struct osc_async_cbargs *cbargs = &oio->oi_cbarg;
+
+ wait_for_completion(&cbargs->opc_sync);
+ if (result == 0)
+ result = cbargs->opc_rc;
+ }
+ slice->cis_io->ci_result = result;
+}
+EXPORT_SYMBOL(osc_io_fsync_end);
+
+static int osc_io_ladvise_start(const struct lu_env *env,
+ const struct cl_io_slice *slice)
+{
+ int result = 0;
+ struct cl_io *io = slice->cis_io;
+ struct osc_io *oio = cl2osc_io(env, slice);
+ struct cl_object *obj = slice->cis_obj;
+ struct lov_oinfo *loi = cl2osc(obj)->oo_oinfo;
+ struct cl_ladvise_io *lio = &io->u.ci_ladvise;
+ struct obdo *oa = &oio->oi_oa;
+ struct osc_async_cbargs *cbargs = &oio->oi_cbarg;
+ struct lu_ladvise *ladvise;
+ struct ladvise_hdr *ladvise_hdr;
+ int buf_size;
+ int num_advise = 1;
+ ENTRY;
+
+ /* TODO: add multiple ladvise support in CLIO */
+ buf_size = offsetof(typeof(*ladvise_hdr), lah_advise[num_advise]);
+ if (osc_env_info(env)->oti_ladvise_buf.lb_len < buf_size)
+ lu_buf_realloc(&osc_env_info(env)->oti_ladvise_buf, buf_size);
+
+ ladvise_hdr = osc_env_info(env)->oti_ladvise_buf.lb_buf;
+ if (ladvise_hdr == NULL)
+ RETURN(-ENOMEM);
+
+ memset(ladvise_hdr, 0, buf_size);
+ ladvise_hdr->lah_magic = LADVISE_MAGIC;
+ ladvise_hdr->lah_count = num_advise;
+ ladvise_hdr->lah_flags = lio->li_flags;
+
+ memset(oa, 0, sizeof(*oa));
+ oa->o_oi = loi->loi_oi;
+ oa->o_valid = OBD_MD_FLID;
+ obdo_set_parent_fid(oa, lio->li_fid);
+
+ ladvise = ladvise_hdr->lah_advise;
+ ladvise->lla_start = lio->li_start;
+ ladvise->lla_end = lio->li_end;
+ ladvise->lla_advice = lio->li_advice;
+
+ if (lio->li_flags & LF_ASYNC) {
+ result = osc_ladvise_base(osc_export(cl2osc(obj)), oa,
+ ladvise_hdr, NULL, NULL, NULL);
+ } else {
+ init_completion(&cbargs->opc_sync);
+ result = osc_ladvise_base(osc_export(cl2osc(obj)), oa,
+ ladvise_hdr, osc_async_upcall,
+ cbargs, PTLRPCD_SET);
+ cbargs->opc_rpc_sent = result == 0;
+ }
+ RETURN(result);