X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fllite%2Ffile.c;h=6af68fa1ae6e5f66f74818e97ae6c22850b34900;hp=73d032b725f1a4eeab51462188ae7709e2eda501;hb=65a8ff5fbe8ca014bd01150ab102d8aa43f78cff;hpb=2d3bbce0c9f3170e16eeeeb1cd29d3372d726260 diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 73d032b..6af68fa 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -443,8 +443,26 @@ void ll_dom_finish_open(struct inode *inode, struct ptlrpc_request *req, if (rnb == NULL || rnb->rnb_len == 0) RETURN_EXIT; - CDEBUG(D_INFO, "Get data buffer along with open, len %i, i_size %llu\n", - rnb->rnb_len, i_size_read(inode)); + /* LU-11595: Server may return whole file and that is OK always or + * it may return just file tail and its offset must be aligned with + * client PAGE_SIZE to be used on that client, if server's PAGE_SIZE is + * smaller then offset may be not aligned and that data is just ignored. + */ + if (rnb->rnb_offset % PAGE_SIZE) + RETURN_EXIT; + + /* Server returns whole file or just file tail if it fills in + * reply buffer, in both cases total size should be inode size. + */ + if (rnb->rnb_offset + rnb->rnb_len < i_size_read(inode)) { + CERROR("%s: server returns off/len %llu/%u < i_size %llu\n", + ll_get_fsname(inode->i_sb, NULL, 0), rnb->rnb_offset, + rnb->rnb_len, i_size_read(inode)); + RETURN_EXIT; + } + + CDEBUG(D_INFO, "Get data along with open at %llu len %i, i_size %llu\n", + rnb->rnb_offset, rnb->rnb_len, i_size_read(inode)); data = (char *)rnb + sizeof(*rnb); @@ -1137,10 +1155,11 @@ static int ll_lease_close(struct obd_client_handle *och, struct inode *inode, * After lease is taken, send the RPC MDS_REINT_RESYNC to the MDT */ static int ll_lease_file_resync(struct obd_client_handle *och, - struct inode *inode) + struct inode *inode, unsigned long arg) { struct ll_sb_info *sbi = ll_i2sbi(inode); struct md_op_data *op_data; + struct ll_ioc_lease_id ioc; __u64 data_version_unused; int rc; ENTRY; @@ -1150,6 +1169,10 @@ static int ll_lease_file_resync(struct obd_client_handle *och, if (IS_ERR(op_data)) RETURN(PTR_ERR(op_data)); + if (copy_from_user(&ioc, (struct ll_ioc_lease_id __user *)arg, + sizeof(ioc))) + RETURN(-EFAULT); + /* before starting file resync, it's necessary to clean up page cache * in client memory, otherwise once the layout version is increased, * writing back cached data will be denied the OSTs. */ @@ -1158,6 +1181,7 @@ static int ll_lease_file_resync(struct obd_client_handle *och, GOTO(out, rc); op_data->op_lease_handle = och->och_lease_handle; + op_data->op_mirror_id = ioc.lil_mirror_id; rc = md_file_resync(sbi->ll_md_exp, op_data); if (rc) GOTO(out, rc); @@ -1192,17 +1216,19 @@ int ll_merge_attr(const struct lu_env *env, struct inode *inode) * if it's at least 'mdd.*.atime_diff' older. * All in all, the atime in Lustre does not strictly comply with * POSIX. Solving this problem needs to send an RPC to MDT for each - * read, this will hurt performance. */ - if (LTIME_S(inode->i_atime) < lli->lli_atime || lli->lli_update_atime) { - LTIME_S(inode->i_atime) = lli->lli_atime; + * read, this will hurt performance. + */ + if (inode->i_atime.tv_sec < lli->lli_atime || + lli->lli_update_atime) { + inode->i_atime.tv_sec = lli->lli_atime; lli->lli_update_atime = 0; } - LTIME_S(inode->i_mtime) = lli->lli_mtime; - LTIME_S(inode->i_ctime) = lli->lli_ctime; + inode->i_mtime.tv_sec = lli->lli_mtime; + inode->i_ctime.tv_sec = lli->lli_ctime; - atime = LTIME_S(inode->i_atime); - mtime = LTIME_S(inode->i_mtime); - ctime = LTIME_S(inode->i_ctime); + mtime = inode->i_mtime.tv_sec; + atime = inode->i_atime.tv_sec; + ctime = inode->i_ctime.tv_sec; cl_object_attr_lock(obj); if (OBD_FAIL_CHECK(OBD_FAIL_MDC_MERGE)) @@ -1229,9 +1255,9 @@ int ll_merge_attr(const struct lu_env *env, struct inode *inode) i_size_write(inode, attr->cat_size); inode->i_blocks = attr->cat_blocks; - LTIME_S(inode->i_atime) = atime; - LTIME_S(inode->i_mtime) = mtime; - LTIME_S(inode->i_ctime) = ctime; + inode->i_mtime.tv_sec = mtime; + inode->i_atime.tv_sec = atime; + inode->i_ctime.tv_sec = ctime; out_size_unlock: ll_inode_size_unlock(inode); @@ -1259,8 +1285,6 @@ void ll_io_set_mirror(struct cl_io *io, const struct file *file) io->ci_ndelay = 0; io->ci_designated_mirror = fd->fd_designated_mirror; io->ci_layout_version = fd->fd_layout_version; - io->ci_pio = 0; /* doesn't have a mechanism to pass mirror - * io to ptasks */ } CDEBUG(D_VFSTRACE, "%s: desiginated mirror: %d\n", @@ -1294,23 +1318,17 @@ static bool file_is_noatime(const struct file *file) return false; } -static int ll_file_io_ptask(struct cfs_ptask *ptask); - static void ll_io_init(struct cl_io *io, struct file *file, enum cl_io_type iot) { struct inode *inode = file_inode(file); struct ll_file_data *fd = LUSTRE_FPRIVATE(file); - memset(&io->u.ci_rw.rw_iter, 0, sizeof(io->u.ci_rw.rw_iter)); - init_sync_kiocb(&io->u.ci_rw.rw_iocb, file); - io->u.ci_rw.rw_file = file; - io->u.ci_rw.rw_ptask = ll_file_io_ptask; - io->u.ci_rw.rw_nonblock = !!(file->f_flags & O_NONBLOCK); + io->u.ci_rw.crw_nonblock = file->f_flags & O_NONBLOCK; io->ci_lock_no_expand = fd->ll_lock_no_expand; if (iot == CIT_WRITE) { - io->u.ci_rw.rw_append = !!(file->f_flags & O_APPEND); - io->u.ci_rw.rw_sync = !!(file->f_flags & O_SYNC || + io->u.ci_wr.wr_append = !!(file->f_flags & O_APPEND); + io->u.ci_wr.wr_sync = !!(file->f_flags & O_SYNC || file->f_flags & O_DIRECT || IS_SYNC(inode)); } @@ -1323,10 +1341,6 @@ static void ll_io_init(struct cl_io *io, struct file *file, enum cl_io_type iot) io->ci_lockreq = CILR_MANDATORY; } io->ci_noatime = file_is_noatime(file); - if (ll_i2sbi(inode)->ll_flags & LL_SBI_PIO) - io->ci_pio = !io->u.ci_rw.rw_append; - else - io->ci_pio = 0; /* FLR: only use non-delay I/O for read as there is only one * avaliable mirror for write. */ @@ -1335,91 +1349,17 @@ static void ll_io_init(struct cl_io *io, struct file *file, enum cl_io_type iot) ll_io_set_mirror(io, file); } -static int ll_file_io_ptask(struct cfs_ptask *ptask) -{ - struct cl_io_pt *pt = ptask->pt_cbdata; - struct file *file = pt->cip_file; - struct lu_env *env; - struct cl_io *io; - loff_t pos = pt->cip_pos; - int rc; - __u16 refcheck; - ENTRY; - - CDEBUG(D_VFSTRACE, "%s: %s range: [%llu, %llu)\n", - file_dentry(file)->d_name.name, - pt->cip_iot == CIT_READ ? "read" : "write", - pos, pos + pt->cip_count); - - env = cl_env_get(&refcheck); - if (IS_ERR(env)) - RETURN(PTR_ERR(env)); - - io = vvp_env_thread_io(env); - ll_io_init(io, file, pt->cip_iot); - io->u.ci_rw.rw_iter = pt->cip_iter; - io->u.ci_rw.rw_iocb = pt->cip_iocb; - io->ci_pio = 0; /* It's already in parallel task */ - - rc = cl_io_rw_init(env, io, pt->cip_iot, pos, - pt->cip_count - pt->cip_result); - if (!rc) { - struct vvp_io *vio = vvp_env_io(env); - - vio->vui_io_subtype = IO_NORMAL; - vio->vui_fd = LUSTRE_FPRIVATE(file); - - ll_cl_add(file, env, io, LCC_RW); - rc = cl_io_loop(env, io); - ll_cl_remove(file, env); - } else { - /* cl_io_rw_init() handled IO */ - rc = io->ci_result; - } - - if (OBD_FAIL_CHECK_RESET(OBD_FAIL_LLITE_PTASK_IO_FAIL, 0)) { - if (io->ci_nob > 0) - io->ci_nob /= 2; - rc = -EIO; - } - - if (io->ci_nob > 0) { - pt->cip_result += io->ci_nob; - iov_iter_advance(&pt->cip_iter, io->ci_nob); - pos += io->ci_nob; - pt->cip_iocb.ki_pos = pos; -#ifdef HAVE_KIOCB_KI_LEFT - pt->cip_iocb.ki_left = pt->cip_count - pt->cip_result; -#elif defined(HAVE_KI_NBYTES) - pt->cip_iocb.ki_nbytes = pt->cip_count - pt->cip_result; -#endif - } - - cl_io_fini(env, io); - cl_env_put(env, &refcheck); - - pt->cip_need_restart = io->ci_need_restart; - - CDEBUG(D_VFSTRACE, "%s: %s ret: %zd, rc: %d\n", - file_dentry(file)->d_name.name, - pt->cip_iot == CIT_READ ? "read" : "write", - pt->cip_result, rc); - - RETURN(pt->cip_result > 0 ? 0 : rc); -} - static ssize_t ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, struct file *file, enum cl_io_type iot, loff_t *ppos, size_t count) { - struct range_lock range; struct vvp_io *vio = vvp_env_io(env); struct inode *inode = file_inode(file); struct ll_inode_info *lli = ll_i2info(inode); struct ll_file_data *fd = LUSTRE_FPRIVATE(file); + struct range_lock range; struct cl_io *io; - loff_t pos = *ppos; ssize_t result = 0; int rc = 0; unsigned retried = 0; @@ -1427,34 +1367,30 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, ENTRY; - CDEBUG(D_VFSTRACE, "%s: %s range: [%llu, %llu)\n", + CDEBUG(D_VFSTRACE, "%s: %s ppos: %llu, count: %zu\n", file_dentry(file)->d_name.name, - iot == CIT_READ ? "read" : "write", pos, pos + count); + iot == CIT_READ ? "read" : "write", *ppos, count); restart: io = vvp_env_thread_io(env); ll_io_init(io, file, iot); - if (args->via_io_subtype == IO_NORMAL) { - io->u.ci_rw.rw_iter = *args->u.normal.via_iter; - io->u.ci_rw.rw_iocb = *args->u.normal.via_iocb; - } - if (args->via_io_subtype != IO_NORMAL || restarted) - io->ci_pio = 0; io->ci_ndelay_tried = retried; - if (cl_io_rw_init(env, io, iot, pos, count) == 0) { + if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) { bool range_locked = false; if (file->f_flags & O_APPEND) range_lock_init(&range, 0, LUSTRE_EOF); else - range_lock_init(&range, pos, pos + count - 1); + range_lock_init(&range, *ppos, *ppos + count - 1); vio->vui_fd = LUSTRE_FPRIVATE(file); vio->vui_io_subtype = args->via_io_subtype; switch (vio->vui_io_subtype) { case IO_NORMAL: + vio->vui_iter = args->u.normal.via_iter; + vio->vui_iocb = args->u.normal.via_iocb; /* Direct IO reads must also take range lock, * or multiple reads will try to work on the same pages * See LU-6227 for details. */ @@ -1480,16 +1416,7 @@ restart: } ll_cl_add(file, env, io, LCC_RW); - if (io->ci_pio && iot == CIT_WRITE && !IS_NOSEC(inode) && - !lli->lli_inode_locked) { - inode_lock(inode); - lli->lli_inode_locked = 1; - } rc = cl_io_loop(env, io); - if (lli->lli_inode_locked) { - lli->lli_inode_locked = 0; - inode_unlock(inode); - } ll_cl_remove(file, env); if (range_locked) { @@ -1505,26 +1432,11 @@ restart: if (io->ci_nob > 0) { result += io->ci_nob; count -= io->ci_nob; + *ppos = io->u.ci_wr.wr.crw_pos; /* for splice */ - if (args->via_io_subtype == IO_NORMAL) { - iov_iter_advance(args->u.normal.via_iter, io->ci_nob); - - /* CLIO is too complicated. See LU-11069. */ - if (cl_io_is_append(io)) - pos = io->u.ci_rw.rw_iocb.ki_pos; - else - pos += io->ci_nob; - - args->u.normal.via_iocb->ki_pos = pos; -#ifdef HAVE_KIOCB_KI_LEFT - args->u.normal.via_iocb->ki_left = count; -#elif defined(HAVE_KI_NBYTES) - args->u.normal.via_iocb->ki_nbytes = count; -#endif - } else { - /* for splice */ - pos = io->u.ci_rw.rw_range.cir_pos; - } + /* prepare IO restart */ + if (count > 0 && args->via_io_subtype == IO_NORMAL) + args->u.normal.via_iter = vio->vui_iter; } out: cl_io_fini(env, io); @@ -1536,10 +1448,10 @@ out: if ((rc == 0 || rc == -ENODATA) && count > 0 && io->ci_need_restart) { CDEBUG(D_VFSTRACE, - "%s: restart %s range: [%llu, %llu) ret: %zd, rc: %d\n", - file_dentry(file)->d_name.name, - iot == CIT_READ ? "read" : "write", - pos, pos + count, result, rc); + "%s: restart %s from %lld, count: %zu, ret: %zd, rc: %d\n", + file_dentry(file)->d_name.name, + iot == CIT_READ ? "read" : "write", + *ppos, count, result, rc); /* preserve the tried count for FLR */ retried = io->ci_ndelay_tried; restarted = true; @@ -1566,11 +1478,7 @@ out: } } - CDEBUG(D_VFSTRACE, "%s: %s *ppos: %llu, pos: %llu, ret: %zd, rc: %d\n", - file_dentry(file)->d_name.name, - iot == CIT_READ ? "read" : "write", *ppos, pos, result, rc); - - *ppos = pos; + CDEBUG(D_VFSTRACE, "iot: %d, result: %zd\n", iot, result); RETURN(result > 0 ? result : rc); } @@ -2632,8 +2540,9 @@ free: int ll_hsm_state_set(struct inode *inode, struct hsm_state_set *hss) { - struct md_op_data *op_data; - int rc; + struct obd_export *exp = ll_i2mdexp(inode); + struct md_op_data *op_data; + int rc; ENTRY; /* Detect out-of range masks */ @@ -2646,18 +2555,20 @@ int ll_hsm_state_set(struct inode *inode, struct hsm_state_set *hss) !cfs_capable(CFS_CAP_SYS_ADMIN)) RETURN(-EPERM); - /* Detect out-of range archive id */ - if ((hss->hss_valid & HSS_ARCHIVE_ID) && - (hss->hss_archive_id > LL_HSM_MAX_ARCHIVE)) - RETURN(-EINVAL); + if (!exp_connect_archive_id_array(exp)) { + /* Detect out-of range archive id */ + if ((hss->hss_valid & HSS_ARCHIVE_ID) && + (hss->hss_archive_id > LL_HSM_ORIGIN_MAX_ARCHIVE)) + RETURN(-EINVAL); + } op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, LUSTRE_OPC_ANY, hss); if (IS_ERR(op_data)) RETURN(PTR_ERR(op_data)); - rc = obd_iocontrol(LL_IOC_HSM_STATE_SET, ll_i2mdexp(inode), - sizeof(*op_data), op_data, NULL); + rc = obd_iocontrol(LL_IOC_HSM_STATE_SET, exp, sizeof(*op_data), + op_data, NULL); ll_finish_md_op_data(op_data); @@ -3274,7 +3185,7 @@ static long ll_file_set_lease(struct file *file, struct ll_ioc_lease *ioc, RETURN(PTR_ERR(och)); if (ioc->lil_flags & LL_LEASE_RESYNC) { - rc = ll_lease_file_resync(och, inode); + rc = ll_lease_file_resync(och, inode, arg); if (rc) { ll_lease_close(och, inode, NULL); RETURN(rc); @@ -3866,7 +3777,6 @@ int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end, int ll_fsync(struct file *file, loff_t start, loff_t end, int datasync) { struct dentry *dentry = file_dentry(file); - bool lock_inode; #elif defined(HAVE_FILE_FSYNC_2ARGS) int ll_fsync(struct file *file, int datasync) { @@ -3891,9 +3801,7 @@ int ll_fsync(struct file *file, struct dentry *dentry, int datasync) #ifdef HAVE_FILE_FSYNC_4ARGS rc = filemap_write_and_wait_range(inode->i_mapping, start, end); - lock_inode = !lli->lli_inode_locked; - if (lock_inode) - inode_lock(inode); + inode_lock(inode); #else /* fsync's caller has already called _fdata{sync,write}, we want * that IO to finish before calling the osc and mdc sync methods */ @@ -3933,8 +3841,7 @@ int ll_fsync(struct file *file, struct dentry *dentry, int datasync) } #ifdef HAVE_FILE_FSYNC_4ARGS - if (lock_inode) - inode_unlock(inode); + inode_unlock(inode); #endif RETURN(rc); } @@ -4422,12 +4329,15 @@ out: static int ll_merge_md_attr(struct inode *inode) { + struct ll_inode_info *lli = ll_i2info(inode); struct cl_attr attr = { 0 }; int rc; - LASSERT(ll_i2info(inode)->lli_lsm_md != NULL); + LASSERT(lli->lli_lsm_md != NULL); + down_read(&lli->lli_lsm_sem); rc = md_merge_attr(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md, &attr, ll_md_blocking_ast); + up_read(&lli->lli_lsm_sem); if (rc != 0) RETURN(rc); @@ -4496,9 +4406,9 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat) RETURN(rc); } - LTIME_S(inode->i_atime) = lli->lli_atime; - LTIME_S(inode->i_mtime) = lli->lli_mtime; - LTIME_S(inode->i_ctime) = lli->lli_ctime; + inode->i_atime.tv_sec = lli->lli_atime; + inode->i_mtime.tv_sec = lli->lli_mtime; + inode->i_ctime.tv_sec = lli->lli_ctime; } OBD_FAIL_TIMEOUT(OBD_FAIL_GETATTR_DELAY, 30); @@ -4905,7 +4815,6 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock) { struct ll_sb_info *sbi = ll_i2sbi(inode); struct ptlrpc_request *req; - struct mdt_body *body; void *lvbdata; void *lmm; int lmmsize; @@ -4925,17 +4834,20 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock) * layout here. Please note that we can't use the LVB buffer in * completion AST because it doesn't have a large enough buffer */ rc = ll_get_default_mdsize(sbi, &lmmsize); - if (rc == 0) - rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), - OBD_MD_FLXATTR, XATTR_NAME_LOV, lmmsize, &req); if (rc < 0) RETURN(rc); - body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - if (body == NULL) - GOTO(out, rc = -EPROTO); + rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), OBD_MD_FLXATTR, + XATTR_NAME_LOV, lmmsize, &req); + if (rc < 0) { + if (rc == -ENODATA) + GOTO(out, rc = 0); /* empty layout */ + else + RETURN(rc); + } - lmmsize = body->mbo_eadatasize; + lmmsize = rc; + rc = 0; if (lmmsize == 0) /* empty layout */ GOTO(out, rc = 0);