struct osc_extent *oi_trunc;
/** write osc_lock for this IO, used by osc_extent_find(). */
struct osc_lock *oi_write_osclock;
+ struct osc_lock *oi_read_osclock;
struct obdo oi_oa;
struct osc_async_cbargs {
bool opc_rpc_sent;
struct osc_lock *oscl);
void osc_lock_set_writer(const struct lu_env *env, const struct cl_io *io,
struct cl_object *obj, struct osc_lock *oscl);
+void osc_lock_set_reader(const struct lu_env *env, const struct cl_io *io,
+ struct cl_object *obj, struct osc_lock *oscl);
int osc_lock_print(const struct lu_env *env, void *cookie,
lu_printer_t p, const struct cl_lock_slice *slice);
void osc_lock_cancel(const struct lu_env *env,
if (io->ci_type == CIT_WRITE || cl_io_is_mkwrite(io))
osc_lock_set_writer(env, io, obj, ols);
+ else if (io->ci_type == CIT_READ ||
+ (io->ci_type == CIT_FAULT && !io->u.ci_fault.ft_mkwrite))
+ osc_lock_set_reader(env, io, obj, ols);
LDLM_DEBUG_NOLOCK("lock %p, mdc lock %p, flags %llx\n",
lock, ols, ols->ols_flags);
struct osc_object *obj, struct list_head *list,
int brw_flags)
{
+ struct osc_io *oio = osc_env_io(env);
struct client_obd *cli = osc_cli(obj);
struct osc_extent *ext;
struct osc_async_page *oap;
bool can_merge = true;
pgoff_t start = CL_PAGE_EOF;
pgoff_t end = 0;
+ struct osc_lock *oscl;
ENTRY;
list_for_each_entry(oap, list, oap_pending_item) {
ext->oe_srvlock = !!(brw_flags & OBD_BRW_SRVLOCK);
ext->oe_ndelay = !!(brw_flags & OBD_BRW_NDELAY);
ext->oe_dio = !!(brw_flags & OBD_BRW_NOCACHE);
+ oscl = oio->oi_write_osclock ? : oio->oi_read_osclock;
+ if (oscl && oscl->ols_dlmlock != NULL) {
+ ext->oe_dlmlock = LDLM_LOCK_GET(oscl->ols_dlmlock);
+ lu_ref_add(&ext->oe_dlmlock->l_reference, "osc_extent", ext);
+ }
if (ext->oe_dio && !ext->oe_rw) { /* direct io write */
int grants;
int ppc;
oio->oi_lru_reserved = 0;
}
oio->oi_write_osclock = NULL;
+ oio->oi_read_osclock = NULL;
osc_io_iter_fini(env, ios);
}
}
EXPORT_SYMBOL(osc_lock_set_writer);
+void osc_lock_set_reader(const struct lu_env *env, const struct cl_io *io,
+ struct cl_object *obj, struct osc_lock *oscl)
+{
+ struct osc_io *oio = osc_env_io(env);
+
+ if (!cl_object_same(io->ci_obj, obj))
+ return;
+
+ if (oscl->ols_glimpse || osc_lock_is_lockless(oscl))
+ return;
+
+ if (oio->oi_read_osclock == NULL)
+ oio->oi_read_osclock = oscl;
+}
+EXPORT_SYMBOL(osc_lock_set_reader);
+
int osc_lock_init(const struct lu_env *env,
struct cl_object *obj, struct cl_lock *lock,
const struct cl_io *io)
if (io->ci_type == CIT_WRITE || cl_io_is_mkwrite(io))
osc_lock_set_writer(env, io, obj, oscl);
+ else if (io->ci_type == CIT_READ ||
+ (io->ci_type == CIT_FAULT && !io->u.ci_fault.ft_mkwrite))
+ osc_lock_set_reader(env, io, obj, oscl);
LDLM_DEBUG_NOLOCK("lock %p, osc lock %p, flags %#llx",
lock, oscl, oscl->ols_flags);
}
run_test 16f "rw sequential consistency vs drop_caches"
+test_16h() {
+ local tf=$DIR/$tdir/$tfile
+ local tf2=$DIR2/$tdir/$tfile
+ local cmd="$MMAP_CAT $tf | od -x | tail -q -n4"
+ local cmd2="$MMAP_CAT $tf2 | od -x | tail -q -n4"
+
+ test_mkdir $DIR/$tdir
+
+ # create file and populate data
+ cp /etc/passwd $tf || error "cp failed"
+
+ local size=$(stat -c %s $tf)
+ c1=$(eval $cmd)
+ c2=$(eval $cmd2)
+ if [[ "$c1" != "$c2" ]]; then
+ echo " ------- mount 1 read --------"
+ echo $c1
+ echo " ------- mount 2 read --------"
+ echo $c2
+ error "content mismatch"
+ fi
+
+ echo " ------- before truncate --------"
+ echo $c1
+
+ # truncate file
+ $TRUNCATE $tf $((size / 2)) || error "truncate file"
+
+ #cancel_lru_locks
+ echo " ------- after truncate --------"
+
+ # repeat the comparison
+ c1=$(eval $cmd)
+ c2=$(eval $cmd2)
+ if [[ "$c1" != "$c2" ]]; then
+ echo " ------- mount 1 read --------"
+ echo $c1
+ echo " ------- mount 2 read --------"
+ echo $c2
+ error "content mismatch after truncate"
+ fi
+ echo $c2
+}
+run_test 16h "mmap read after truncate file"
+
test_17() { # bug 3513, 3667
remote_ost_nodsh && skip "remote OST with nodsh" && return