- OBD_ALLOC(lsca, sizeof(*lsca));
- if (!lsca)
- RETURN(ERR_PTR(-ENOMEM));
-
- for (iovidx = 0; iovidx < iovlen; iovidx++) {
- char *buf = iovec[iovidx].iov_base;
- size_t count = iovec[iovidx].iov_len;
-
- /* "If nbyte is 0, read() will return 0 and have no other results."
- * -- Single Unix Spec */
- if (count == 0)
- continue;
-
- policy.l_extent.start = pos;
- policy.l_extent.end = pos + count - 1;
-
- err = llu_extent_lock(fd, inode, lsm, LCK_PR, &policy,
- &lockh, astflag);
- if (err != ELDLM_OK)
- GOTO(err_out, err = -ENOLCK);
-
- kms = lov_merge_size(lsm, 1);
- if (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 */
- struct ost_lvb lvb;
- if (llu_glimpse_size(inode, &lvb)) {
- llu_extent_unlock(fd, inode, lsm, LCK_PR, &lockh);
- GOTO(err_out, err = -ENOLCK);
- }
- lli->lli_st_size = lvb.lvb_size;
- } else {
- lli->lli_st_size = kms;
- }
-
- CDEBUG(D_INFO, "Reading inode %lu, "LPSZ" bytes, offset %Ld, "
- "i_size "LPU64"\n", lli->lli_st_ino, count, pos,
- lli->lli_st_size);
-
- if (pos >= lli->lli_st_size) {
- llu_extent_unlock(fd, inode, lsm, LCK_PR, &lockh);
- break;
- }
-
- cookie = llu_rw(OBD_BRW_READ, inode, buf, count, pos);
- if (!IS_ERR(cookie)) {
- /* save cookie */
- lsca->cookies[lsca->ncookies++] = cookie;
- pos += count;
- } else {
- llu_extent_unlock(fd, inode, lsm, LCK_PR, &lockh);
- GOTO(err_out, err = PTR_ERR(cookie));
- }
-
- /* XXX errors? */
- err = llu_extent_unlock(fd, inode, lsm, LCK_PR, &lockh);
- if (err)
- CERROR("extent_unlock fail: %d\n", err);
- }
-#if 0
- if (readed > 0)
- llu_update_atime(inode);
-#endif
- RETURN(lsca);
-
-err_out:
- /* teardown all async stuff */
- while (lsca->ncookies--) {
- put_sysio_cookie(lsca->cookies[lsca->ncookies]);
- }
- OBD_FREE(lsca, sizeof(*lsca));
-
- RETURN(ERR_PTR(err));