From 7d2a94e40959a63d97ca4adc9a5d7a33511faa55 Mon Sep 17 00:00:00 2001 From: Vladimir Saveliev Date: Thu, 8 Apr 2010 18:24:01 -0700 Subject: [PATCH] b=11063 set mtime to past under PW EOF extent lock (v6) (according to HLD: https://bugzilla.lustre.org/attachment.cgi?id=15441). new IO type (CIT_SETATTR) replaces CIT_TRUNC Eariler patches https://bugzilla.lustre.org/attachment.cgi?id=7933 https://bugzilla.lustre.org/attachment.cgi?id=7882 are reversed. i=ericm i=vitaly --- lustre/include/cl_object.h | 23 +++-- lustre/include/lclient.h | 21 +++-- lustre/include/obd_ost.h | 8 +- lustre/lclient/lcommon_cl.c | 56 +++---------- lustre/liblustre/file.c | 12 +-- lustre/liblustre/llite_cl.c | 14 ++-- lustre/liblustre/llite_lib.h | 2 + lustre/liblustre/rw.c | 7 ++ lustre/liblustre/super.c | 70 +++++++--------- lustre/llite/file.c | 15 +++- lustre/llite/llite_internal.h | 2 + lustre/llite/llite_lib.c | 78 ++++++++--------- lustre/llite/namei.c | 20 ++--- lustre/llite/vvp_io.c | 142 ++++++++++++++++++++----------- lustre/llite/vvp_object.c | 6 ++ lustre/lov/lov_io.c | 29 ++++--- lustre/lov/lov_lock.c | 2 +- lustre/lov/lov_merge.c | 13 +-- lustre/obdclass/linux/linux-obdo.c | 12 +-- lustre/osc/osc_cl_internal.h | 4 +- lustre/osc/osc_internal.h | 7 +- lustre/osc/osc_io.c | 167 ++++++++++++++++++++++++------------- lustre/osc/osc_lock.c | 4 +- lustre/osc/osc_request.c | 93 ++++++++++----------- 24 files changed, 436 insertions(+), 371 deletions(-) diff --git a/lustre/include/cl_object.h b/lustre/include/cl_object.h index 58ef32a..94a5b01 100644 --- a/lustre/include/cl_object.h +++ b/lustre/include/cl_object.h @@ -1890,8 +1890,8 @@ enum cl_io_type { CIT_READ, /** write system call */ CIT_WRITE, - /** truncate system call */ - CIT_TRUNC, + /** truncate, utime system calls */ + CIT_SETATTR, /** * page fault handling */ @@ -2270,11 +2270,11 @@ struct cl_io { int wr_append; } ci_wr; struct cl_io_rw_common ci_rw; - struct cl_truncate_io { - /** new size to which file is truncated */ - loff_t tr_size; - struct obd_capa *tr_capa; - } ci_truncate; + struct cl_setattr_io { + struct ost_lvb sa_attr; + unsigned int sa_valid; + struct obd_capa *sa_capa; + } ci_setattr; struct cl_fault_io { /** page index within file. */ pgoff_t ft_index; @@ -2935,6 +2935,15 @@ static inline int cl_io_is_append(const struct cl_io *io) return io->ci_type == CIT_WRITE && io->u.ci_wr.wr_append; } +/** + * True, iff \a io is a truncate(2). + */ +static inline int cl_io_is_trunc(const struct cl_io *io) +{ + return io->ci_type == CIT_SETATTR && + (io->u.ci_setattr.sa_valid & ATTR_SIZE); +} + struct cl_io *cl_io_top(struct cl_io *io); void cl_io_print(const struct lu_env *env, void *cookie, diff --git a/lustre/include/lclient.h b/lustre/include/lclient.h index 529d198..306ae11 100644 --- a/lustre/include/lclient.h +++ b/lustre/include/lclient.h @@ -48,15 +48,15 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, struct inode *inode, struct cl_object *clob); /** - * Locking policy for truncate. + * Locking policy for setattr. */ -enum ccc_trunc_lock_type { +enum ccc_setattr_lock_type { /** Locking is done by server */ - TRUNC_NOLOCK, + SETATTR_NOLOCK, /** Extent lock is enqueued */ - TRUNC_EXTENT, + SETATTR_EXTENT_LOCK, /** Existing local extent lock is used */ - TRUNC_MATCH + SETATTR_MATCH_LOCK }; @@ -87,9 +87,9 @@ struct ccc_io { union { struct { - int cui_locks_released; - enum ccc_trunc_lock_type cui_local_lock; - } trunc; + int cui_locks_released; + enum ccc_setattr_lock_type cui_local_lock; + } setattr; } u; /** * True iff io is processing glimpse right now. @@ -344,9 +344,8 @@ cfs_page_t *cl2vm_page (const struct cl_page_slice *slice); struct inode *ccc_object_inode(const struct cl_object *obj); struct ccc_object *cl_inode2ccc (struct inode *inode); -int cl_setattr_do_truncate(struct inode *inode, loff_t size, - struct obd_capa *capa); -int cl_setattr_ost(struct inode *inode, struct obd_capa *capa); +int cl_setattr_ost(struct inode *inode, const struct iattr *attr, + struct obd_capa *capa); struct cl_page *ccc_vmpage_page_transient(cfs_page_t *vmpage); int ccc_object_invariant(const struct cl_object *obj); diff --git a/lustre/include/obd_ost.h b/lustre/include/obd_ost.h index 05bd9c6..5b1c183a 100644 --- a/lustre/include/obd_ost.h +++ b/lustre/include/obd_ost.h @@ -63,10 +63,10 @@ struct osc_async_args { struct obd_info *aa_oi; }; -struct osc_punch_args { - struct obdo *pa_oa; - obd_enqueue_update_f pa_upcall; - void *pa_cookie; +struct osc_setattr_args { + struct obdo *sa_oa; + obd_enqueue_update_f sa_upcall; + void *sa_cookie; }; struct osc_enqueue_args { diff --git a/lustre/lclient/lcommon_cl.c b/lustre/lclient/lcommon_cl.c index a8322e1..2031b34 100644 --- a/lustre/lclient/lcommon_cl.c +++ b/lustre/lclient/lcommon_cl.c @@ -1010,9 +1010,8 @@ const struct cl_req_operations ccc_req_ops = { .cro_completion = ccc_req_completion }; -/* Setattr helpers */ -int cl_setattr_do_truncate(struct inode *inode, loff_t size, - struct obd_capa *capa) +int cl_setattr_ost(struct inode *inode, const struct iattr *attr, + struct obd_capa *capa) { struct lu_env *env; struct cl_io *io; @@ -1027,9 +1026,15 @@ int cl_setattr_do_truncate(struct inode *inode, loff_t size, io = &ccc_env_info(env)->cti_io; io->ci_obj = cl_i2info(inode)->lli_clob; - io->u.ci_truncate.tr_size = size; - io->u.ci_truncate.tr_capa = capa; - if (cl_io_init(env, io, CIT_TRUNC, io->ci_obj) == 0) + + io->u.ci_setattr.sa_attr.lvb_atime = LTIME_S(attr->ia_atime); + io->u.ci_setattr.sa_attr.lvb_mtime = LTIME_S(attr->ia_mtime); + io->u.ci_setattr.sa_attr.lvb_ctime = LTIME_S(attr->ia_ctime); + io->u.ci_setattr.sa_attr.lvb_size = attr->ia_size; + io->u.ci_setattr.sa_valid = attr->ia_valid; + io->u.ci_setattr.sa_capa = capa; + + if (cl_io_init(env, io, CIT_SETATTR, io->ci_obj) == 0) result = cl_io_loop(env, io); else result = io->ci_result; @@ -1038,45 +1043,6 @@ int cl_setattr_do_truncate(struct inode *inode, loff_t size, RETURN(result); } -int cl_setattr_ost(struct inode *inode, struct obd_capa *capa) -{ - struct cl_inode_info *lli = cl_i2info(inode); - struct lov_stripe_md *lsm = lli->lli_smd; - int rc; - obd_flag flags; - struct obd_info oinfo = { { { 0 } } }; - struct obdo *oa; - - OBDO_ALLOC(oa); - if (oa) { - oa->o_id = lsm->lsm_object_id; - oa->o_gr = lsm->lsm_object_gr; - oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP; - - flags = OBD_MD_FLTYPE | OBD_MD_FLATIME | - OBD_MD_FLMTIME | OBD_MD_FLCTIME | - OBD_MD_FLFID | OBD_MD_FLGENER | - OBD_MD_FLGROUP; - - obdo_from_inode(oa, inode, flags); - - oinfo.oi_oa = oa; - oinfo.oi_md = lsm; - oinfo.oi_capa = capa; - - /* XXX: this looks unnecessary now. */ - rc = obd_setattr_rqset(cl_i2sbi(inode)->ll_dt_exp, &oinfo, - NULL); - if (rc) - CERROR("obd_setattr_async fails: rc=%d\n", rc); - OBDO_FREE(oa); - } else { - rc = -ENOMEM; - } - return rc; -} - - /***************************************************************************** * * Type conversions. diff --git a/lustre/liblustre/file.c b/lustre/liblustre/file.c index 4810ef3..c166ca9 100644 --- a/lustre/liblustre/file.c +++ b/lustre/liblustre/file.c @@ -135,16 +135,10 @@ void obdo_refresh_inode(struct inode *dst, if (valid & OBD_MD_FLATIME && src->o_atime > LTIME_S(st->st_atime)) LTIME_S(st->st_atime) = src->o_atime; - - /* mtime is always updated with ctime, but can be set in past. - As write and utime(2) may happen within 1 second, and utime's - mtime has a priority over write's one, leave mtime from mds - for the same ctimes. */ - if (valid & OBD_MD_FLCTIME && src->o_ctime > LTIME_S(st->st_ctime)) { + if (valid & OBD_MD_FLMTIME && src->o_mtime > LTIME_S(st->st_mtime)) + LTIME_S(st->st_mtime) = src->o_mtime; + if (valid & OBD_MD_FLCTIME && src->o_ctime > LTIME_S(st->st_ctime)) LTIME_S(st->st_ctime) = src->o_ctime; - if (valid & OBD_MD_FLMTIME) - LTIME_S(st->st_mtime) = src->o_mtime; - } if (valid & OBD_MD_FLSIZE && src->o_size > st->st_size) st->st_size = src->o_size; /* optimum IO size */ diff --git a/lustre/liblustre/llite_cl.c b/lustre/liblustre/llite_cl.c index 12723d4..0aaa7bf 100644 --- a/lustre/liblustre/llite_cl.c +++ b/lustre/liblustre/llite_cl.c @@ -451,14 +451,14 @@ static int slp_io_rw_lock(const struct lu_env *env, } -static int slp_io_trunc_iter_init(const struct lu_env *env, - const struct cl_io_slice *ios) +static int slp_io_setattr_iter_init(const struct lu_env *env, + const struct cl_io_slice *ios) { return 0; } -static int slp_io_trunc_start(const struct lu_env *env, - const struct cl_io_slice *ios) +static int slp_io_setattr_start(const struct lu_env *env, + const struct cl_io_slice *ios) { return 0; } @@ -739,10 +739,10 @@ static const struct cl_io_operations ccc_io_ops = { .cio_end = ccc_io_end, .cio_advance = ccc_io_advance }, - [CIT_TRUNC] = { + [CIT_SETATTR] = { .cio_fini = ccc_io_fini, - .cio_iter_init = slp_io_trunc_iter_init, - .cio_start = slp_io_trunc_start + .cio_iter_init = slp_io_setattr_iter_init, + .cio_start = slp_io_setattr_start }, [CIT_MISC] = { .cio_fini = ccc_io_fini diff --git a/lustre/liblustre/llite_lib.h b/lustre/liblustre/llite_lib.h index 44f1663..ba62ba6 100644 --- a/lustre/liblustre/llite_lib.h +++ b/lustre/liblustre/llite_lib.h @@ -115,6 +115,8 @@ struct llu_inode_info { int lli_st_flags; unsigned long lli_st_generation; struct cl_object *lli_clob; + /* the most recent timestamps obtained from mds */ + struct ost_lvb lli_lvb; }; diff --git a/lustre/liblustre/rw.c b/lustre/liblustre/rw.c index aeff8db..47be4e1 100644 --- a/lustre/liblustre/rw.c +++ b/lustre/liblustre/rw.c @@ -212,7 +212,13 @@ int llu_merge_lvb(struct inode *inode) int rc; ENTRY; + lov_stripe_lock(lli->lli_smd); inode_init_lvb(inode, &lvb); + /* merge timestamps the most resently obtained from mds with + timestamps obtained from osts */ + lvb.lvb_atime = lli->lli_lvb.lvb_atime; + lvb.lvb_mtime = lli->lli_lvb.lvb_mtime; + lvb.lvb_ctime = lli->lli_lvb.lvb_ctime; rc = obd_merge_lvb(sbi->ll_dt_exp, lli->lli_smd, &lvb, 0); st->st_size = lvb.lvb_size; st->st_blocks = lvb.lvb_blocks; @@ -222,6 +228,7 @@ int llu_merge_lvb(struct inode *inode) st->st_mtime = lvb.lvb_mtime; st->st_atime = lvb.lvb_atime; st->st_ctime = lvb.lvb_ctime; + lov_stripe_unlock(lli->lli_smd); RETURN(rc); } diff --git a/lustre/liblustre/super.c b/lustre/liblustre/super.c index 100f985..cdd12ec 100644 --- a/lustre/liblustre/super.c +++ b/lustre/liblustre/super.c @@ -173,24 +173,22 @@ void llu_update_inode(struct inode *inode, struct lustre_md *md) } } - if (body->valid & OBD_MD_FLMTIME && - body->mtime > LTIME_S(st->st_mtime)) - LTIME_S(st->st_mtime) = body->mtime; - if (body->valid & OBD_MD_FLATIME && - body->atime > LTIME_S(st->st_atime)) - LTIME_S(st->st_atime) = body->atime; - - /* mtime is always updated with ctime, but can be set in past. - As write and utime(2) may happen within 1 second, and utime's - mtime has a priority over write's one, so take mtime from mds - for the same ctimes. */ - if (body->valid & OBD_MD_FLCTIME && - body->ctime >= LTIME_S(st->st_ctime)) { - LTIME_S(st->st_ctime) = body->ctime; - if (body->valid & OBD_MD_FLMTIME) + if (body->valid & OBD_MD_FLATIME) { + if (body->atime > LTIME_S(st->st_atime)) + LTIME_S(st->st_atime) = body->atime; + lli->lli_lvb.lvb_atime = body->atime; + } + if (body->valid & OBD_MD_FLMTIME) { + if (body->mtime > LTIME_S(st->st_mtime)) LTIME_S(st->st_mtime) = body->mtime; + lli->lli_lvb.lvb_mtime = body->mtime; + } + if (body->valid & OBD_MD_FLCTIME) { + if (body->ctime > LTIME_S(st->st_ctime)) + LTIME_S(st->st_ctime) = body->ctime; + lli->lli_lvb.lvb_ctime = body->ctime; } - if (S_ISREG(st->st_mode)) + if (S_ISREG(st->st_mode)) st->st_blksize = min(2UL * PTLRPC_MAX_BRW_SIZE, LL_MAX_BLKSIZE); else st->st_blksize = 4096; @@ -466,7 +464,8 @@ static int llu_have_md_lock(struct inode *inode, __u64 lockpart) static int llu_inode_revalidate(struct inode *inode) { - struct lov_stripe_md *lsm = NULL; + struct llu_inode_info *lli = llu_i2info(inode); + struct intnl_stat *st = llu_i2stat(inode); ENTRY; if (!inode) { @@ -484,7 +483,7 @@ static int llu_inode_revalidate(struct inode *inode) /* Why don't we update all valid MDS fields here, if we're * doing an RPC anyways? -phil */ - if (S_ISREG(llu_i2stat(inode)->st_mode)) { + if (S_ISREG(st->st_mode)) { ealen = obd_size_diskmd(sbi->ll_dt_exp, NULL); valid |= OBD_MD_FLEASIZE; } @@ -496,7 +495,7 @@ static int llu_inode_revalidate(struct inode *inode) rc = md_getattr(sbi->ll_md_exp, &op_data, &req); if (rc) { CERROR("failure %d inode %llu\n", rc, - (long long)llu_i2stat(inode)->st_ino); + (long long)st->st_ino); RETURN(-abs(rc)); } rc = md_get_lustre_md(sbi->ll_md_exp, req, @@ -518,14 +517,18 @@ static int llu_inode_revalidate(struct inode *inode) llu_update_inode(inode, &md); - if (md.lsm != NULL && llu_i2info(inode)->lli_smd != md.lsm) + if (md.lsm != NULL && lli->lli_smd != md.lsm) obd_free_memmd(sbi->ll_dt_exp, &md.lsm); ptlrpc_req_finished(req); } - lsm = llu_i2info(inode)->lli_smd; - if (!lsm) /* object not yet allocated, don't validate size */ + if (!lli->lli_smd) { + /* object not yet allocated, don't validate size */ + st->st_atime = lli->lli_lvb.lvb_atime; + st->st_mtime = lli->lli_lvb.lvb_mtime; + st->st_ctime = lli->lli_lvb.lvb_ctime; RETURN(0); + } /* ll_glimpse_size will prefer locally cached writes if they extend * the file */ @@ -781,16 +784,6 @@ int llu_setattr_raw(struct inode *inode, struct iattr *attr) attr->ia_mtime = CFS_CURRENT_TIME; attr->ia_valid |= ATTR_MTIME_SET; } - if ((attr->ia_valid & ATTR_CTIME) && !(attr->ia_valid & ATTR_MTIME)) { - /* To avoid stale mtime on mds, obtain it from ost and send - to mds. */ - rc = cl_glimpse_size(inode); - if (rc) - RETURN(rc); - - attr->ia_valid |= ATTR_MTIME_SET | ATTR_MTIME; - attr->ia_mtime = inode->i_stbuf.st_mtime; - } if (attr->ia_valid & (ATTR_MTIME | ATTR_CTIME)) CDEBUG(D_INODE, "setting mtime "CFS_TIME_T", ctime "CFS_TIME_T @@ -847,12 +840,13 @@ int llu_setattr_raw(struct inode *inode, struct iattr *attr) inode_setattr(inode, attr); } - if (ia_valid & ATTR_SIZE) { - rc = cl_setattr_do_truncate(inode, attr->ia_size, NULL); - } else if (ia_valid & (ATTR_MTIME | ATTR_MTIME_SET)) { - CDEBUG(D_INODE, "set mtime on OST inode %llu to %lu\n", - (long long unsigned)st->st_ino, LTIME_S(attr->ia_mtime)); - rc = cl_setattr_ost(inode, NULL); + if (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MTIME_SET)) { + /* mtime is set to past sending setattr op to osts under PW + * 0:EOF extent lock (like truncate under PW new_size:EOF), if + * mtime is not set to past setattr op is not sent to osts */ + if ((ia_valid & ATTR_SIZE) || + LTIME_S(attr->ia_mtime) < LTIME_S(attr->ia_ctime)) + rc = cl_setattr_ost(inode, attr, NULL); } EXIT; out: diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 355f4f3..211d021 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -770,6 +770,12 @@ int ll_merge_lvb(struct inode *inode) ll_inode_size_lock(inode, 1); inode_init_lvb(inode, &lvb); + + /* merge timestamps the most resently obtained from mds with + timestamps obtained from osts */ + lvb.lvb_atime = lli->lli_lvb.lvb_atime; + lvb.lvb_mtime = lli->lli_lvb.lvb_mtime; + lvb.lvb_ctime = lli->lli_lvb.lvb_ctime; rc = obd_merge_lvb(sbi->ll_dt_exp, lli->lli_smd, &lvb, 0); cl_isize_write_nolock(inode, lvb.lvb_size); inode->i_blocks = lvb.lvb_blocks; @@ -2179,6 +2185,7 @@ out: int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it) { + struct inode *inode = dentry->d_inode; int rc; ENTRY; @@ -2186,14 +2193,18 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it) MDS_INODELOCK_LOOKUP); /* if object not yet allocated, don't validate size */ - if (rc == 0 && ll_i2info(dentry->d_inode)->lli_smd == NULL) + if (rc == 0 && ll_i2info(dentry->d_inode)->lli_smd == NULL) { + LTIME_S(inode->i_atime) = ll_i2info(inode)->lli_lvb.lvb_atime; + LTIME_S(inode->i_mtime) = ll_i2info(inode)->lli_lvb.lvb_mtime; + LTIME_S(inode->i_ctime) = ll_i2info(inode)->lli_lvb.lvb_ctime; RETURN(0); + } /* cl_glimpse_size will prefer locally cached writes if they extend * the file */ if (rc == 0) - rc = cl_glimpse_size(dentry->d_inode); + rc = cl_glimpse_size(inode); RETURN(rc); } diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 1d59daf..02c0898 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -187,6 +187,8 @@ struct ll_inode_info { void *lli_opendir_key; struct ll_statahead_info *lli_sai; struct cl_object *lli_clob; + /* the most recent timestamps obtained from mds */ + struct ost_lvb lli_lvb; }; /* diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 4658c10..142f627 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -1126,23 +1126,22 @@ static int ll_setattr_done_writing(struct inode *inode, RETURN(rc); } -static int ll_setattr_do_truncate(struct inode *inode, loff_t size) +static int ll_setattr_ost(struct inode *inode, struct iattr *attr) { - struct obd_capa *capa = ll_osscapa_get(inode, CAPA_OPC_OSS_TRUNC); + struct obd_capa *capa; int rc; - rc = cl_setattr_do_truncate(inode, size, capa); - ll_truncate_free_capa(capa); - return rc; -} + if (attr->ia_valid & ATTR_SIZE) + capa = ll_osscapa_get(inode, CAPA_OPC_OSS_TRUNC); + else + capa = ll_mdscapa_get(inode); -static int ll_setattr_ost(struct inode *inode) -{ - struct obd_capa *capa = ll_mdscapa_get(inode); - int rc; + rc = cl_setattr_ost(inode, attr, capa); - rc = cl_setattr_ost(inode, capa); - capa_put(capa); + if (attr->ia_valid & ATTR_SIZE) + ll_truncate_free_capa(capa); + else + capa_put(capa); return rc; } @@ -1204,16 +1203,6 @@ int ll_setattr_raw(struct inode *inode, struct iattr *attr) attr->ia_mtime = CFS_CURRENT_TIME; attr->ia_valid |= ATTR_MTIME_SET; } - if ((attr->ia_valid & ATTR_CTIME) && !(attr->ia_valid & ATTR_MTIME)) { - /* To avoid stale mtime on mds, obtain it from ost and send - to mds. */ - rc = cl_glimpse_size(inode); - if (rc) - RETURN(rc); - - attr->ia_valid |= ATTR_MTIME_SET | ATTR_MTIME; - attr->ia_mtime = inode->i_mtime; - } if (attr->ia_valid & (ATTR_MTIME | ATTR_CTIME)) CDEBUG(D_INODE, "setting mtime %lu, ctime %lu, now = %lu\n", @@ -1243,7 +1232,8 @@ int ll_setattr_raw(struct inode *inode, struct iattr *attr) memcpy(&op_data->op_attr, attr, sizeof(*attr)); /* Open epoch for truncate. */ - if (exp_connect_som(ll_i2mdexp(inode)) && (ia_valid & ATTR_SIZE)) + if (exp_connect_som(ll_i2mdexp(inode)) && + (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MTIME_SET))) op_data->op_flags = MF_EPOCH_OPEN; rc = ll_md_setattr(inode, op_data, &mod); @@ -1257,11 +1247,14 @@ int ll_setattr_raw(struct inode *inode, struct iattr *attr) } if (ia_valid & ATTR_SIZE) - rc = ll_setattr_do_truncate(inode, attr->ia_size); - else if (ia_valid & (ATTR_MTIME | ATTR_MTIME_SET)) { - CDEBUG(D_INODE, "set mtime on OST inode %lu to %lu\n", - inode->i_ino, LTIME_S(attr->ia_mtime)); - rc = ll_setattr_ost(inode); + attr->ia_valid |= ATTR_SIZE; + if (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MTIME_SET)) { + /* mtime is set to past sending setattr op to osts under PW + * 0:EOF extent lock (like truncate under PW new_size:EOF), if + * mtime is not set to past setattr op is not sent to osts */ + if ((ia_valid & ATTR_SIZE) || + LTIME_S(attr->ia_mtime) < LTIME_S(attr->ia_ctime)) + rc = ll_setattr_ost(inode, attr); } EXIT; out: @@ -1483,23 +1476,24 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) inode->i_ino = cl_fid_build_ino(&body->fid1); inode->i_generation = cl_fid_build_gen(&body->fid1); - if (body->valid & OBD_MD_FLATIME && - body->atime > LTIME_S(inode->i_atime)) - LTIME_S(inode->i_atime) = body->atime; - - /* mtime is always updated with ctime, but can be set in past. - As write and utime(2) may happen within 1 second, and utime's - mtime has a priority over write's one, so take mtime from mds - for the same ctimes. */ - if (body->valid & OBD_MD_FLCTIME && - body->ctime >= LTIME_S(inode->i_ctime)) { - LTIME_S(inode->i_ctime) = body->ctime; - if (body->valid & OBD_MD_FLMTIME) { - CDEBUG(D_INODE, "setting ino %lu mtime " - "from %lu to "LPU64"\n", inode->i_ino, + if (body->valid & OBD_MD_FLATIME) { + if (body->atime > LTIME_S(inode->i_atime)) + LTIME_S(inode->i_atime) = body->atime; + lli->lli_lvb.lvb_atime = body->atime; + } + if (body->valid & OBD_MD_FLMTIME) { + if (body->mtime > LTIME_S(inode->i_mtime)) { + CDEBUG(D_INODE, "setting ino %lu mtime from %lu " + "to "LPU64"\n", inode->i_ino, LTIME_S(inode->i_mtime), body->mtime); LTIME_S(inode->i_mtime) = body->mtime; } + lli->lli_lvb.lvb_mtime = body->mtime; + } + if (body->valid & OBD_MD_FLCTIME) { + if (body->ctime > LTIME_S(inode->i_ctime)) + LTIME_S(inode->i_ctime) = body->ctime; + lli->lli_lvb.lvb_ctime = body->ctime; } if (body->valid & OBD_MD_FLMODE) inode->i_mode = (inode->i_mode & S_IFMT)|(body->mode & ~S_IFMT); diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 27d194b..b56af50 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -838,21 +838,15 @@ static void ll_update_times(struct ptlrpc_request *request, &RMF_MDT_BODY); LASSERT(body); - /* mtime is always updated with ctime, but can be set in past. - As write and utime(2) may happen within 1 second, and utime's - mtime has a priority over write's one, so take mtime from mds - for the same ctimes. */ + if (body->valid & OBD_MD_FLMTIME && + body->mtime > LTIME_S(inode->i_mtime)) { + CDEBUG(D_INODE, "setting ino %lu mtime from %lu to "LPU64"\n", + inode->i_ino, LTIME_S(inode->i_mtime), body->mtime); + LTIME_S(inode->i_mtime) = body->mtime; + } if (body->valid & OBD_MD_FLCTIME && - body->ctime >= LTIME_S(inode->i_ctime)) { + body->ctime > LTIME_S(inode->i_ctime)) LTIME_S(inode->i_ctime) = body->ctime; - - if (body->valid & OBD_MD_FLMTIME) { - CDEBUG(D_INODE, "setting ino %lu mtime from %lu " - "to "LPU64"\n", inode->i_ino, - LTIME_S(inode->i_mtime), body->mtime); - LTIME_S(inode->i_mtime) = body->mtime; - } - } } static int ll_new_node(struct inode *dir, struct qstr *name, diff --git a/lustre/llite/vvp_io.c b/lustre/llite/vvp_io.c index 89bb048..50adc18 100644 --- a/lustre/llite/vvp_io.c +++ b/lustre/llite/vvp_io.c @@ -262,10 +262,10 @@ static int vvp_io_write_lock(const struct lu_env *env, return vvp_io_rw_lock(env, io, CLM_WRITE, start, end); } -static int vvp_io_trunc_iter_init(const struct lu_env *env, - const struct cl_io_slice *ios) +static int vvp_io_setattr_iter_init(const struct lu_env *env, + const struct cl_io_slice *ios) { - struct ccc_io *vio = cl2ccc_io(env, ios); + struct ccc_io *cio = ccc_env_io(env); struct inode *inode = ccc_object_inode(ios->cis_obj); /* @@ -276,31 +276,38 @@ static int vvp_io_trunc_iter_init(const struct lu_env *env, * This last one is especially bad for racing o_append users on other * nodes. */ - UNLOCK_INODE_MUTEX(inode); - UP_WRITE_I_ALLOC_SEM(inode); - vio->u.trunc.cui_locks_released = 1; + if (cl_io_is_trunc(ios->cis_io)) + UP_WRITE_I_ALLOC_SEM(inode); + cio->u.setattr.cui_locks_released = 1; return 0; } /** - * Implementation of cl_io_operations::cio_lock() method for CIT_TRUNC io. + * Implementation of cl_io_operations::cio_lock() method for CIT_SETATTR io. * * Handles "lockless io" mode when extent locking is done by server. */ -static int vvp_io_trunc_lock(const struct lu_env *env, - const struct cl_io_slice *ios) +static int vvp_io_setattr_lock(const struct lu_env *env, + const struct cl_io_slice *ios) { - struct ccc_io *vio = cl2ccc_io(env, ios); - struct cl_io *io = ios->cis_io; - loff_t new_size = io->u.ci_truncate.tr_size; - __u32 enqflags = new_size == 0 ? CEF_DISCARD_DATA : 0; - int result; - - vio->u.trunc.cui_local_lock = TRUNC_EXTENT; - result = ccc_io_one_lock(env, io, enqflags, CLM_WRITE, - new_size, OBD_OBJECT_EOF); - return result; + struct ccc_io *cio = ccc_env_io(env); + struct cl_io *io = ios->cis_io; + size_t new_size; + __u32 enqflags = 0; + + if (cl_io_is_trunc(io)) { + new_size = io->u.ci_setattr.sa_attr.lvb_size; + if (new_size == 0) + enqflags = CEF_DISCARD_DATA; + } else { + LASSERT(io->u.ci_setattr.sa_attr.lvb_mtime < + io->u.ci_setattr.sa_attr.lvb_ctime); + new_size = 0; + } + cio->u.setattr.cui_local_lock = SETATTR_EXTENT_LOCK; + return ccc_io_one_lock(env, io, enqflags, CLM_WRITE, + new_size, OBD_OBJECT_EOF); } static int vvp_do_vmtruncate(struct inode *inode, size_t size) @@ -319,23 +326,17 @@ static int vvp_do_vmtruncate(struct inode *inode, size_t size) return result; } -static int vvp_io_trunc_start(const struct lu_env *env, - const struct cl_io_slice *ios) +static int vvp_io_setattr_trunc(const struct lu_env *env, + const struct cl_io_slice *ios, + struct inode *inode, loff_t size) { - struct ccc_io *cio = cl2ccc_io(env, ios); struct vvp_io *vio = cl2vvp_io(env, ios); struct cl_io *io = ios->cis_io; - struct inode *inode = ccc_object_inode(io->ci_obj); struct cl_object *obj = ios->cis_obj; - loff_t size = io->u.ci_truncate.tr_size; pgoff_t start = cl_index(obj, size); int result; - LASSERT(cio->u.trunc.cui_locks_released); - - LOCK_INODE_MUTEX(inode); DOWN_WRITE_I_ALLOC_SEM(inode); - cio->u.trunc.cui_locks_released = 0; result = vvp_do_vmtruncate(inode, size); @@ -369,14 +370,56 @@ static int vvp_io_trunc_start(const struct lu_env *env, return result; } -static void vvp_io_trunc_end(const struct lu_env *env, - const struct cl_io_slice *ios) +static int vvp_io_setattr_mtime(const struct lu_env *env, + const struct cl_io_slice *ios) { - struct vvp_io *vio = cl2vvp_io(env, ios); + struct cl_io *io = ios->cis_io; + struct cl_object *obj = io->ci_obj; + struct cl_attr *attr = ccc_env_thread_attr(env); + int result; + unsigned valid = CAT_MTIME | CAT_CTIME; + + cl_object_attr_lock(obj); + attr->cat_mtime = io->u.ci_setattr.sa_attr.lvb_mtime; + attr->cat_ctime = io->u.ci_setattr.sa_attr.lvb_ctime; + if (io->u.ci_setattr.sa_valid & ATTR_ATIME_SET) { + attr->cat_atime = io->u.ci_setattr.sa_attr.lvb_atime; + valid |= CAT_ATIME; + } + result = cl_object_attr_set(env, obj, attr, valid); + cl_object_attr_unlock(obj); + + return result; +} + +static int vvp_io_setattr_start(const struct lu_env *env, + const struct cl_io_slice *ios) +{ + struct ccc_io *cio = cl2ccc_io(env, ios); struct cl_io *io = ios->cis_io; struct inode *inode = ccc_object_inode(io->ci_obj); - loff_t size = io->u.ci_truncate.tr_size; + LASSERT(cio->u.setattr.cui_locks_released); + + LOCK_INODE_MUTEX(inode); + cio->u.setattr.cui_locks_released = 0; + + if (cl_io_is_trunc(io)) + return vvp_io_setattr_trunc(env, ios, inode, + io->u.ci_setattr.sa_attr.lvb_size); + else + return vvp_io_setattr_mtime(env, ios); +} + +static void vvp_io_setattr_end(const struct lu_env *env, + const struct cl_io_slice *ios) +{ + struct vvp_io *vio = cl2vvp_io(env, ios); + struct cl_io *io = ios->cis_io; + struct inode *inode = ccc_object_inode(io->ci_obj); + + if (!cl_io_is_trunc(io)) + return; if (vio->cui_partpage != NULL) { cl_page_disown(env, ios->cis_io, vio->cui_partpage); cl_page_put(env, vio->cui_partpage); @@ -387,19 +430,21 @@ static void vvp_io_trunc_end(const struct lu_env *env, * Do vmtruncate again, to remove possible stale pages populated by * competing read threads. bz20645. */ - vvp_do_vmtruncate(inode, size); + vvp_do_vmtruncate(inode, io->u.ci_setattr.sa_attr.lvb_size); } -static void vvp_io_trunc_fini(const struct lu_env *env, - const struct cl_io_slice *ios) +static void vvp_io_setattr_fini(const struct lu_env *env, + const struct cl_io_slice *ios) { struct ccc_io *cio = ccc_env_io(env); + struct cl_io *io = ios->cis_io; struct inode *inode = ccc_object_inode(ios->cis_io->ci_obj); - if (cio->u.trunc.cui_locks_released) { + if (cio->u.setattr.cui_locks_released) { LOCK_INODE_MUTEX(inode); - DOWN_WRITE_I_ALLOC_SEM(inode); - cio->u.trunc.cui_locks_released = 0; + if (cl_io_is_trunc(io)) + DOWN_WRITE_I_ALLOC_SEM(inode); + cio->u.setattr.cui_locks_released = 0; } vvp_io_fini(env, ios); } @@ -960,12 +1005,12 @@ static const struct cl_io_operations vvp_io_ops = { .cio_start = vvp_io_write_start, .cio_advance = ccc_io_advance }, - [CIT_TRUNC] = { - .cio_fini = vvp_io_trunc_fini, - .cio_iter_init = vvp_io_trunc_iter_init, - .cio_lock = vvp_io_trunc_lock, - .cio_start = vvp_io_trunc_start, - .cio_end = vvp_io_trunc_end + [CIT_SETATTR] = { + .cio_fini = vvp_io_setattr_fini, + .cio_iter_init = vvp_io_setattr_iter_init, + .cio_lock = vvp_io_setattr_lock, + .cio_start = vvp_io_setattr_start, + .cio_end = vvp_io_setattr_end }, [CIT_FAULT] = { .cio_fini = vvp_io_fault_fini, @@ -1015,9 +1060,12 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, cio->cui_tot_nrsegs = 0; ll_stats_ops_tally(sbi, op, count); } - } else if (io->ci_type == CIT_TRUNC) { - /* lockless truncate? */ - ll_stats_ops_tally(sbi, LPROC_LL_TRUNC, 1); + } else if (io->ci_type == CIT_SETATTR) { + if (cl_io_is_trunc(io)) + /* lockless truncate? */ + ll_stats_ops_tally(sbi, LPROC_LL_TRUNC, 1); + else + io->ci_lockreq = CILR_MANDATORY; } RETURN(result); } diff --git a/lustre/llite/vvp_object.c b/lustre/llite/vvp_object.c index 3ef1e4b..d928264 100644 --- a/lustre/llite/vvp_object.c +++ b/lustre/llite/vvp_object.c @@ -109,6 +109,12 @@ static int vvp_attr_set(const struct lu_env *env, struct cl_object *obj, inode->i_uid = attr->cat_uid; if (valid & CAT_GID) inode->i_gid = attr->cat_gid; + if (valid & CAT_ATIME) + LTIME_S(inode->i_atime) = attr->cat_atime; + if (valid & CAT_MTIME) + LTIME_S(inode->i_mtime) = attr->cat_mtime; + if (valid & CAT_CTIME) + LTIME_S(inode->i_ctime) = attr->cat_ctime; if (0 && valid & CAT_SIZE) cl_isize_write_nolock(inode, attr->cat_size); /* not currently necessary */ diff --git a/lustre/lov/lov_io.c b/lustre/lov/lov_io.c index bf7a958..20d3319 100644 --- a/lustre/lov/lov_io.c +++ b/lustre/lov/lov_io.c @@ -99,12 +99,16 @@ static void lov_io_sub_inherit(struct cl_io *io, struct lov_io *lio, struct cl_io *parent = lio->lis_cl.cis_io; switch(io->ci_type) { - case CIT_TRUNC: { - loff_t new_size = parent->u.ci_truncate.tr_size; - - new_size = lov_size_to_stripe(lsm, new_size, stripe); - io->u.ci_truncate.tr_capa = parent->u.ci_truncate.tr_capa; - io->u.ci_truncate.tr_size = new_size; + case CIT_SETATTR: { + io->u.ci_setattr.sa_attr = parent->u.ci_setattr.sa_attr; + io->u.ci_setattr.sa_valid = parent->u.ci_setattr.sa_valid; + io->u.ci_setattr.sa_capa = parent->u.ci_setattr.sa_capa; + if (cl_io_is_trunc(io)) { + loff_t new_size = parent->u.ci_setattr.sa_attr.lvb_size; + + new_size = lov_size_to_stripe(lsm, new_size, stripe); + io->u.ci_setattr.sa_attr.lvb_size = new_size; + } break; } case CIT_FAULT: { @@ -323,8 +327,11 @@ static void lov_io_slice_init(struct lov_io *lio, } break; - case CIT_TRUNC: - lio->lis_pos = io->u.ci_truncate.tr_size; + case CIT_SETATTR: + if (cl_io_is_trunc(io)) + lio->lis_pos = io->u.ci_setattr.sa_attr.lvb_size; + else + lio->lis_pos = 0; lio->lis_endpos = OBD_OBJECT_EOF; break; @@ -750,7 +757,7 @@ static const struct cl_io_operations lov_io_ops = { .cio_start = lov_io_start, .cio_end = lov_io_end }, - [CIT_TRUNC] = { + [CIT_SETATTR] = { .cio_fini = lov_io_fini, .cio_iter_init = lov_io_iter_init, .cio_iter_fini = lov_io_iter_fini, @@ -826,7 +833,7 @@ static const struct cl_io_operations lov_empty_io_ops = { .cio_start = LOV_EMPTY_IMPOSSIBLE, .cio_end = LOV_EMPTY_IMPOSSIBLE }, - [CIT_TRUNC] = { + [CIT_SETATTR] = { .cio_fini = lov_empty_io_fini, .cio_iter_init = LOV_EMPTY_IMPOSSIBLE, .cio_lock = LOV_EMPTY_IMPOSSIBLE, @@ -888,7 +895,7 @@ int lov_io_init_empty(const struct lu_env *env, struct cl_object *obj, result = 0; break; case CIT_WRITE: - case CIT_TRUNC: + case CIT_SETATTR: result = -EBADF; break; case CIT_FAULT: diff --git a/lustre/lov/lov_lock.c b/lustre/lov/lov_lock.c index 563b625..cb81e72 100644 --- a/lustre/lov/lov_lock.c +++ b/lustre/lov/lov_lock.c @@ -1033,7 +1033,7 @@ static int lov_lock_fits_into(const struct lu_env *env, cl2lov(slice->cls_obj), lov->lls_sub[0].sub_stripe, got, need); - } else if (io->ci_type != CIT_TRUNC && io->ci_type != CIT_MISC && + } else if (io->ci_type != CIT_SETATTR && io->ci_type != CIT_MISC && !cl_io_is_append(io) && need->cld_mode != CLM_PHANTOM) /* * Multi-stripe locks are only suitable for `quick' IO and for diff --git a/lustre/lov/lov_merge.c b/lustre/lov/lov_merge.c index 272d5ef..856418a 100644 --- a/lustre/lov/lov_merge.c +++ b/lustre/lov/lov_merge.c @@ -94,17 +94,12 @@ int lov_merge_lvb_kms(struct lov_stripe_md *lsm, size = lov_size; /* merge blocks, mtime, atime */ blocks += loi->loi_lvb.lvb_blocks; + if (loi->loi_lvb.lvb_mtime > current_mtime) + current_mtime = loi->loi_lvb.lvb_mtime; if (loi->loi_lvb.lvb_atime > current_atime) current_atime = loi->loi_lvb.lvb_atime; - - /* mtime is always updated with ctime, but can be set in past. - As write and utime(2) may happen within 1 second, and utime's - mtime has a priority over write's one, leave mtime from mds - for the same ctimes. */ - if (loi->loi_lvb.lvb_ctime > current_ctime) { + if (loi->loi_lvb.lvb_ctime > current_ctime) current_ctime = loi->loi_lvb.lvb_ctime; - current_mtime = loi->loi_lvb.lvb_mtime; - } } *kms_place = kms; @@ -201,8 +196,6 @@ void lov_merge_attrs(struct obdo *tgt, struct obdo *src, obd_flag valid, tgt->o_blksize += src->o_blksize; if (valid & OBD_MD_FLCTIME && tgt->o_ctime < src->o_ctime) tgt->o_ctime = src->o_ctime; - /* Only mtime from OSTs are merged here, as they cannot be set - in past (only MDS's mtime can) do not look at ctime. */ if (valid & OBD_MD_FLMTIME && tgt->o_mtime < src->o_mtime) tgt->o_mtime = src->o_mtime; } else { diff --git a/lustre/obdclass/linux/linux-obdo.c b/lustre/obdclass/linux/linux-obdo.c index 5e5a5d8..9126027 100644 --- a/lustre/obdclass/linux/linux-obdo.c +++ b/lustre/obdclass/linux/linux-obdo.c @@ -182,16 +182,10 @@ void obdo_refresh_inode(struct inode *dst, struct obdo *src, obd_flag valid) if (valid & OBD_MD_FLATIME && src->o_atime > LTIME_S(dst->i_atime)) LTIME_S(dst->i_atime) = src->o_atime; - - /* mtime is always updated with ctime, but can be set in past. - As write and utime(2) may happen within 1 second, and utime's - mtime has a priority over write's one, leave mtime from mds - for the same ctimes. */ - if (valid & OBD_MD_FLCTIME && src->o_ctime > LTIME_S(dst->i_ctime)) { + if (valid & OBD_MD_FLMTIME && src->o_mtime > LTIME_S(dst->i_mtime)) + LTIME_S(dst->i_mtime) = src->o_mtime; + if (valid & OBD_MD_FLCTIME && src->o_ctime > LTIME_S(dst->i_ctime)) LTIME_S(dst->i_ctime) = src->o_ctime; - if (valid & OBD_MD_FLMTIME) - LTIME_S(dst->i_mtime) = src->o_mtime; - } if (valid & OBD_MD_FLSIZE) i_size_write(dst, src->o_size); /* optimum IO size */ diff --git a/lustre/osc/osc_cl_internal.h b/lustre/osc/osc_cl_internal.h index d3445e2..b8e56eb 100644 --- a/lustre/osc/osc_cl_internal.h +++ b/lustre/osc/osc_cl_internal.h @@ -71,10 +71,10 @@ struct osc_io { int oi_lockless; struct obdo oi_oa; - struct osc_punch_cbargs { + struct osc_setattr_cbargs { int opc_rc; cfs_completion_t opc_sync; - } oi_punch_cbarg; + } oi_setattr_cbarg; }; /** diff --git a/lustre/osc/osc_internal.h b/lustre/osc/osc_internal.h index 0fbf8d0..0e2d042 100644 --- a/lustre/osc/osc_internal.h +++ b/lustre/osc/osc_internal.h @@ -136,8 +136,11 @@ int osc_match_base(struct obd_export *exp, struct ldlm_res_id *res_id, int *flags, void *data, struct lustre_handle *lockh, int unref); -int osc_punch_base(struct obd_export *exp, struct obdo *oa, - struct obd_capa *capa, +int osc_setattr_async_base(struct obd_export *exp, struct obd_info *oinfo, + struct obd_trans_info *oti, + obd_enqueue_update_f upcall, void *cookie, + struct ptlrpc_request_set *rqset); +int osc_punch_base(struct obd_export *exp, struct obd_info *oinfo, obd_enqueue_update_f upcall, void *cookie, struct ptlrpc_request_set *rqset); diff --git a/lustre/osc/osc_io.c b/lustre/osc/osc_io.c index 6190433..31500a1 100644 --- a/lustre/osc/osc_io.c +++ b/lustre/osc/osc_io.c @@ -375,9 +375,9 @@ static int osc_io_fault_start(const struct lu_env *env, RETURN(0); } -static int osc_punch_upcall(void *a, int rc) +static int osc_setattr_upcall(void *a, int rc) { - struct osc_punch_cbargs *args = a; + struct osc_setattr_cbargs *args = a; args->opc_rc = rc; cfs_complete(&args->opc_sync); @@ -444,8 +444,8 @@ static void osc_trunc_check(const struct lu_env *env, struct cl_io *io, # define osc_trunc_check(env, io, oio, size) do {;} while (0) #endif -static int osc_io_trunc_start(const struct lu_env *env, - const struct cl_io_slice *slice) +static int osc_io_setattr_start(const struct lu_env *env, + const struct cl_io_slice *slice) { struct cl_io *io = slice->cis_io; struct osc_io *oio = cl2osc_io(env, slice); @@ -453,24 +453,41 @@ static int osc_io_trunc_start(const struct lu_env *env, struct lov_oinfo *loi = cl2osc(obj)->oo_oinfo; struct cl_attr *attr = &osc_env_info(env)->oti_attr; struct obdo *oa = &oio->oi_oa; - struct osc_punch_cbargs *cbargs = &oio->oi_punch_cbarg; - struct obd_capa *capa; - loff_t size = io->u.ci_truncate.tr_size; + struct osc_setattr_cbargs *cbargs = &oio->oi_setattr_cbarg; + loff_t size = io->u.ci_setattr.sa_attr.lvb_size; + unsigned int ia_valid = io->u.ci_setattr.sa_valid; int result = 0; + struct obd_info oinfo = { { { 0 } } }; - osc_trunc_check(env, io, oio, size); + if (ia_valid & ATTR_SIZE) + osc_trunc_check(env, io, oio, size); if (oio->oi_lockless == 0) { cl_object_attr_lock(obj); result = cl_object_attr_get(env, obj, attr); if (result == 0) { - attr->cat_size = attr->cat_kms = size; - result = cl_object_attr_set(env, obj, attr, - CAT_SIZE|CAT_KMS); + unsigned int cl_valid = 0; + + if (ia_valid & ATTR_SIZE) { + attr->cat_size = attr->cat_kms = size; + cl_valid = (CAT_SIZE | CAT_KMS); + } + if (ia_valid & ATTR_MTIME_SET) { + attr->cat_mtime = io->u.ci_setattr.sa_attr.lvb_mtime; + cl_valid |= CAT_MTIME; + } + if (ia_valid & ATTR_ATIME_SET) { + attr->cat_atime = io->u.ci_setattr.sa_attr.lvb_atime; + cl_valid |= CAT_ATIME; + } + if (ia_valid & ATTR_CTIME_SET) { + attr->cat_ctime = io->u.ci_setattr.sa_attr.lvb_ctime; + cl_valid |= CAT_CTIME; + } + result = cl_object_attr_set(env, obj, attr, cl_valid); } cl_object_attr_unlock(obj); } - memset(oa, 0, sizeof(*oa)); if (result == 0) { oa->o_id = loi->loi_id; @@ -480,29 +497,42 @@ static int osc_io_trunc_start(const struct lu_env *env, oa->o_ctime = attr->cat_ctime; oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP | OBD_MD_FLATIME | OBD_MD_FLCTIME | OBD_MD_FLMTIME; - if (oio->oi_lockless) { - oa->o_flags = OBD_FL_SRVLOCK; - oa->o_valid |= OBD_MD_FLFLAGS; + if (ia_valid & ATTR_SIZE) { + oa->o_size = size; + oa->o_blocks = OBD_OBJECT_EOF; + oa->o_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS; + + if (oio->oi_lockless) { + oa->o_flags = OBD_FL_SRVLOCK; + oa->o_valid |= OBD_MD_FLFLAGS; + } + } else { + LASSERT(oio->oi_lockless == 0); } - oa->o_size = size; - oa->o_blocks = OBD_OBJECT_EOF; - oa->o_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS; - capa = io->u.ci_truncate.tr_capa; + oinfo.oi_oa = oa; + oinfo.oi_capa = io->u.ci_setattr.sa_capa; cfs_init_completion(&cbargs->opc_sync); - result = osc_punch_base(osc_export(cl2osc(obj)), oa, capa, - osc_punch_upcall, cbargs, PTLRPCD_SET); + + if (ia_valid & ATTR_SIZE) + result = osc_punch_base(osc_export(cl2osc(obj)), + &oinfo, osc_setattr_upcall, + cbargs, PTLRPCD_SET); + else + result = osc_setattr_async_base(osc_export(cl2osc(obj)), + &oinfo, NULL, + osc_setattr_upcall, + cbargs, PTLRPCD_SET); } return result; } -static void osc_io_trunc_end(const struct lu_env *env, - const struct cl_io_slice *slice) +static void osc_io_setattr_end(const struct lu_env *env, + const struct cl_io_slice *slice) { struct cl_io *io = slice->cis_io; struct osc_io *oio = cl2osc_io(env, slice); - struct osc_punch_cbargs *cbargs = &oio->oi_punch_cbarg; - struct obdo *oa = &oio->oi_oa; + struct osc_setattr_cbargs *cbargs = &oio->oi_setattr_cbarg; int result; cfs_wait_for_completion(&cbargs->opc_sync); @@ -510,56 +540,75 @@ static void osc_io_trunc_end(const struct lu_env *env, result = io->ci_result = cbargs->opc_rc; if (result == 0) { struct cl_object *obj = slice->cis_obj; - if (oio->oi_lockless == 0) { - struct cl_attr *attr = &osc_env_info(env)->oti_attr; - int valid = 0; - - /* Update kms & size */ - if (oa->o_valid & OBD_MD_FLSIZE) { - attr->cat_size = oa->o_size; - attr->cat_kms = oa->o_size; - valid |= CAT_KMS|CAT_SIZE; - } - if (oa->o_valid & OBD_MD_FLBLOCKS) { - attr->cat_blocks = oa->o_blocks; - valid |= CAT_BLOCKS; - } - if (oa->o_valid & OBD_MD_FLMTIME) { - attr->cat_mtime = oa->o_mtime; - valid |= CAT_MTIME; - } - if (oa->o_valid & OBD_MD_FLCTIME) { - attr->cat_ctime = oa->o_ctime; - valid |= CAT_CTIME; - } - if (oa->o_valid & OBD_MD_FLATIME) { - attr->cat_atime = oa->o_atime; - valid |= CAT_ATIME; - } - cl_object_attr_lock(obj); - result = cl_object_attr_set(env, obj, attr, valid); - cl_object_attr_unlock(obj); - } else { /* lockless truncate */ + if (oio->oi_lockless) { + /* lockless truncate */ struct osc_device *osd = lu2osc_dev(obj->co_lu.lo_dev); + + LASSERT(cl_io_is_trunc(io)); /* XXX: Need a lock. */ osd->od_stats.os_lockless_truncates++; } } +} - /* return result; */ +static int osc_io_read_start(const struct lu_env *env, + const struct cl_io_slice *slice) +{ + struct osc_io *oio = cl2osc_io(env, slice); + struct cl_object *obj = slice->cis_obj; + struct cl_attr *attr = &osc_env_info(env)->oti_attr; + int result = 0; + ENTRY; + + if (oio->oi_lockless == 0) { + cl_object_attr_lock(obj); + result = cl_object_attr_get(env, obj, attr); + if (result == 0) { + attr->cat_atime = LTIME_S(CFS_CURRENT_TIME); + result = cl_object_attr_set(env, obj, attr, + CAT_ATIME); + } + cl_object_attr_unlock(obj); + } + RETURN(result); +} + +static int osc_io_write_start(const struct lu_env *env, + const struct cl_io_slice *slice) +{ + struct osc_io *oio = cl2osc_io(env, slice); + struct cl_object *obj = slice->cis_obj; + struct cl_attr *attr = &osc_env_info(env)->oti_attr; + int result = 0; + ENTRY; + + if (oio->oi_lockless == 0) { + cl_object_attr_lock(obj); + result = cl_object_attr_get(env, obj, attr); + if (result == 0) { + attr->cat_mtime = attr->cat_ctime = + LTIME_S(CFS_CURRENT_TIME); + result = cl_object_attr_set(env, obj, attr, + CAT_MTIME | CAT_CTIME); + } + cl_object_attr_unlock(obj); + } + RETURN(result); } static const struct cl_io_operations osc_io_ops = { .op = { [CIT_READ] = { + .cio_start = osc_io_read_start, .cio_fini = osc_io_fini }, [CIT_WRITE] = { + .cio_start = osc_io_write_start, .cio_fini = osc_io_fini }, - [CIT_TRUNC] = { - .cio_start = osc_io_trunc_start, - .cio_end = osc_io_trunc_end + [CIT_SETATTR] = { + .cio_start = osc_io_setattr_start, + .cio_end = osc_io_setattr_end }, [CIT_FAULT] = { .cio_fini = osc_io_fini, diff --git a/lustre/osc/osc_lock.c b/lustre/osc/osc_lock.c index 5718937..0d4e383 100644 --- a/lustre/osc/osc_lock.c +++ b/lustre/osc/osc_lock.c @@ -988,14 +988,14 @@ static void osc_lock_to_lockless(const struct lu_env *env, io->ci_lockreq == CILR_NEVER); ocd = &class_exp2cliimp(osc_export(oob))->imp_connect_data; - ols->ols_locklessable = (io->ci_type != CIT_TRUNC) && + ols->ols_locklessable = (io->ci_type != CIT_SETATTR) && (io->ci_lockreq == CILR_MAYBE) && (ocd->ocd_connect_flags & OBD_CONNECT_SRVLOCK); if (io->ci_lockreq == CILR_NEVER || /* lockless IO */ (ols->ols_locklessable && osc_object_is_contended(oob)) || /* lockless truncate */ - (io->ci_type == CIT_TRUNC && + (cl_io_is_trunc(io) && (ocd->ocd_connect_flags & OBD_CONNECT_TRUNCLOCK) && osd->od_lockless_truncate)) { ols->ols_locklessable = 1; diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c index dbd8c3a..014edf2 100644 --- a/lustre/osc/osc_request.c +++ b/lustre/osc/osc_request.c @@ -346,7 +346,7 @@ out: static int osc_setattr_interpret(const struct lu_env *env, struct ptlrpc_request *req, - struct osc_async_args *aa, int rc) + struct osc_setattr_args *sa, int rc) { struct ost_body *body; ENTRY; @@ -358,19 +358,20 @@ static int osc_setattr_interpret(const struct lu_env *env, if (body == NULL) GOTO(out, rc = -EPROTO); - lustre_get_wire_obdo(aa->aa_oi->oi_oa, &body->oa); + lustre_get_wire_obdo(sa->sa_oa, &body->oa); out: - rc = aa->aa_oi->oi_cb_up(aa->aa_oi, rc); + rc = sa->sa_upcall(sa->sa_cookie, rc); RETURN(rc); } -static int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo, - struct obd_trans_info *oti, - struct ptlrpc_request_set *rqset) +int osc_setattr_async_base(struct obd_export *exp, struct obd_info *oinfo, + struct obd_trans_info *oti, + obd_enqueue_update_f upcall, void *cookie, + struct ptlrpc_request_set *rqset) { - struct ptlrpc_request *req; - struct osc_async_args *aa; - int rc; + struct ptlrpc_request *req; + struct osc_setattr_args *sa; + int rc; ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_SETATTR); @@ -384,7 +385,7 @@ static int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo, RETURN(rc); } - if (oinfo->oi_oa->o_valid & OBD_MD_FLCOOKIE) + if (oti && oinfo->oi_oa->o_valid & OBD_MD_FLCOOKIE) oinfo->oi_oa->o_lcookie = *oti->oti_logcookies; osc_pack_req_body(req, oinfo); @@ -399,16 +400,29 @@ static int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo, req->rq_interpret_reply = (ptlrpc_interpterer_t)osc_setattr_interpret; - CLASSERT (sizeof(*aa) <= sizeof(req->rq_async_args)); - aa = ptlrpc_req_async_args(req); - aa->aa_oi = oinfo; + CLASSERT (sizeof(*sa) <= sizeof(req->rq_async_args)); + sa = ptlrpc_req_async_args(req); + sa->sa_oa = oinfo->oi_oa; + sa->sa_upcall = upcall; + sa->sa_cookie = cookie; - ptlrpc_set_add_req(rqset, req); + if (rqset == PTLRPCD_SET) + ptlrpcd_add_req(req, PSCOPE_OTHER); + else + ptlrpc_set_add_req(rqset, req); } RETURN(0); } +static int osc_setattr_async(struct obd_export *exp, struct obd_info *oinfo, + struct obd_trans_info *oti, + struct ptlrpc_request_set *rqset) +{ + return osc_setattr_async_base(exp, oinfo, oti, + oinfo->oi_cb_up, oinfo, rqset); +} + int osc_real_create(struct obd_export *exp, struct obdo *oa, struct lov_stripe_md **ea, struct obd_trans_info *oti) { @@ -494,42 +508,21 @@ out: RETURN(rc); } -static int osc_punch_interpret(const struct lu_env *env, - struct ptlrpc_request *req, - struct osc_punch_args *aa, int rc) -{ - struct ost_body *body; - ENTRY; - - if (rc != 0) - GOTO(out, rc); - - body = req_capsule_server_get(&req->rq_pill, &RMF_OST_BODY); - if (body == NULL) - GOTO(out, rc = -EPROTO); - - lustre_get_wire_obdo(aa->pa_oa, &body->oa); -out: - rc = aa->pa_upcall(aa->pa_cookie, rc); - RETURN(rc); -} - -int osc_punch_base(struct obd_export *exp, struct obdo *oa, - struct obd_capa *capa, +int osc_punch_base(struct obd_export *exp, struct obd_info *oinfo, obd_enqueue_update_f upcall, void *cookie, struct ptlrpc_request_set *rqset) { - struct ptlrpc_request *req; - struct osc_punch_args *aa; - struct ost_body *body; - int rc; + struct ptlrpc_request *req; + struct osc_setattr_args *sa; + struct ost_body *body; + int rc; ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_PUNCH); if (req == NULL) RETURN(-ENOMEM); - osc_set_capa_size(req, &RMF_CAPA1, capa); + osc_set_capa_size(req, &RMF_CAPA1, oinfo->oi_capa); rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_PUNCH); if (rc) { ptlrpc_request_free(req); @@ -540,18 +533,18 @@ int osc_punch_base(struct obd_export *exp, struct obdo *oa, body = req_capsule_client_get(&req->rq_pill, &RMF_OST_BODY); LASSERT(body); - lustre_set_wire_obdo(&body->oa, oa); - osc_pack_capa(req, body, capa); + lustre_set_wire_obdo(&body->oa, oinfo->oi_oa); + osc_pack_capa(req, body, oinfo->oi_capa); ptlrpc_request_set_replen(req); - req->rq_interpret_reply = (ptlrpc_interpterer_t)osc_punch_interpret; - CLASSERT (sizeof(*aa) <= sizeof(req->rq_async_args)); - aa = ptlrpc_req_async_args(req); - aa->pa_oa = oa; - aa->pa_upcall = upcall; - aa->pa_cookie = cookie; + req->rq_interpret_reply = (ptlrpc_interpterer_t)osc_setattr_interpret; + CLASSERT (sizeof(*sa) <= sizeof(req->rq_async_args)); + sa = ptlrpc_req_async_args(req); + sa->sa_oa = oinfo->oi_oa; + sa->sa_upcall = upcall; + sa->sa_cookie = cookie; if (rqset == PTLRPCD_SET) ptlrpcd_add_req(req, PSCOPE_OTHER); else @@ -567,7 +560,7 @@ static int osc_punch(struct obd_export *exp, struct obd_info *oinfo, oinfo->oi_oa->o_size = oinfo->oi_policy.l_extent.start; oinfo->oi_oa->o_blocks = oinfo->oi_policy.l_extent.end; oinfo->oi_oa->o_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS; - return osc_punch_base(exp, oinfo->oi_oa, oinfo->oi_capa, + return osc_punch_base(exp, oinfo, oinfo->oi_cb_up, oinfo, rqset); } -- 1.8.3.1