+ if (pos + len > lli->lli_maxbytes)
+ RETURN(-ERANGE);
+
+ lustre_build_lock_params(session->lis_cmd, lli->lli_open_flags,
+ lli->lli_sbi->ll_lco.lco_flags,
+ pos, len, &p);
+
+ iogroup = get_io_group(inode, max_io_pages(len, iovlen), &p);
+ if (IS_ERR(iogroup))
+ RETURN(PTR_ERR(iogroup));
+
+ local_lock = p.lrp_lock_mode != LCK_NL;
+
+ err = llu_extent_lock(fd, inode, lsm, p.lrp_lock_mode, &p.lrp_policy,
+ &lockh, p.lrp_ast_flags);
+ if (err != ELDLM_OK)
+ GOTO(err_put, err);
+
+ is_read = (session->lis_cmd == OBD_BRW_READ);
+ if (is_read) {
+ /*
+ * If OST-side locking is used, KMS can be completely out of
+ * date, and, hence, cannot be used for short-read
+ * detection. Rely in OST to handle short reads in that case.
+ */
+ inode_init_lvb(inode, &lvb);
+ obd_merge_lvb(exp, lsm, &lvb, 1);
+ kms = lvb.lvb_size;
+ /* extent.end is last byte of the range */
+ if (p.lrp_policy.l_extent.end >= kms) {
+ /* A glimpse is necessary to determine whether
+ * we return a short read or some zeroes at
+ * the end of the buffer
+ *
+ * In the case of OST-side locking KMS can be
+ * completely out of date and short-reads maybe
+ * mishandled. See llu_queue_pio() for more detailed
+ * comment.
+ */
+ if ((err = llu_glimpse_size(inode))) {
+ GOTO(err_unlock, err);
+ }
+ } else {
+ st->st_size = kms;
+ }
+ } else if (lli->lli_open_flags & O_APPEND) {
+ pos = st->st_size;
+ }