loff_t start, loff_t end);
void ccc_io_end(const struct lu_env *env, const struct cl_io_slice *ios);
int ccc_prep_size(const struct lu_env *env, struct cl_object *obj,
- struct cl_io *io, loff_t pos, int vfslock);
+ struct cl_io *io, loff_t start, size_t count, int vfslock,
+ int *exceed);
void ccc_req_completion(const struct lu_env *env,
const struct cl_req_slice *slice, int ioret);
void ccc_req_attr_set(const struct lu_env *env,const struct cl_req_slice *slice,
* the resulting races.
*/
int ccc_prep_size(const struct lu_env *env, struct cl_object *obj,
- struct cl_io *io, loff_t pos, int vfslock)
+ struct cl_io *io, loff_t start, size_t count, int vfslock,
+ int *exceed)
{
struct cl_attr *attr = &ccc_env_info(env)->cti_attr;
struct inode *inode = ccc_object_inode(obj);
+ loff_t pos = start + count - 1;
loff_t kms;
int result;
* of the buffer (C)
*/
ccc_object_size_unlock(obj, vfslock);
- return cl_glimpse_lock(env, io, inode, obj);
+ result = cl_glimpse_lock(env, io, inode, obj);
+ if (result == 0 && exceed != NULL) {
+ /* If objective page index exceed end-of-file
+ * page index, return directly. Do not expect
+ * kernel will check such case correctly.
+ * linux-2.6.18-128.1.1 miss to do that.
+ * --bug 17336 */
+ size_t size = cl_isize_read(inode);
+ unsigned long cur_index = start >> CFS_PAGE_SHIFT;
+
+ if ((size == 0 && cur_index != 0) ||
+ (((size - 1) >> CFS_PAGE_SHIFT) < cur_index))
+ *exceed = 1;
+ }
+ return result;
} else {
/*
* region is within kms and, hence, within real file
struct llu_inode_info *lli = llu_i2info(inode);
struct llu_io_session *session = cl2slp_io(env, ios)->sio_session;
int write = io->ci_type == CIT_WRITE;
+ int exceed = 0;
CLOBINVRNT(env, obj, ccc_object_invariant(obj));
if (IS_ERR(iogroup))
RETURN(PTR_ERR(iogroup));
- err = ccc_prep_size(env, obj, io, pos + cnt - 1, 0);
- if (err != 0)
+ err = ccc_prep_size(env, obj, io, pos, cnt, 0, &exceed);
+ if (err != 0 || (write == 0 && exceed != 0))
GOTO(out, err);
CDEBUG(D_INODE,
loff_t pos = io->u.ci_rd.rd.crw_pos;
size_t cnt = io->u.ci_rd.rd.crw_count;
size_t tot = cio->cui_tot_count;
+ int exceed = 0;
CLOBINVRNT(env, obj, ccc_object_invariant(obj));
LASSERT(vio->cui_oneshot == 0);
CDEBUG(D_VFSTRACE, "read: -> [%lli, %lli)\n", pos, pos + cnt);
- result = ccc_prep_size(env, obj, io, pos + tot - 1, 1);
+ result = ccc_prep_size(env, obj, io, pos, tot, 1, &exceed);
if (result != 0)
return result;
+ else if (exceed != 0)
+ goto out;
LU_OBJECT_HEADER(D_INODE, env, &obj->co_lu,
"Read ino %lu, "LPSZ" bytes, offset %lld, size %llu\n",
result = lustre_generic_file_read(file, cio, &pos);
}
+out:
if (result >= 0) {
if (result < cnt)
io->ci_continue = 0;
/* offset of the last byte on the page */
offset = cl_offset(obj, fio->ft_index + 1) - 1;
LASSERT(cl_index(obj, offset) == fio->ft_index);
- result = ccc_prep_size(env, obj, io, offset, 0);
+ result = ccc_prep_size(env, obj, io, 0, offset + 1, 0, NULL);
if (result != 0)
return result;