Whamcloud - gitweb
b=11063 set mtime to past under PW EOF extent lock (v6)
authorVladimir Saveliev <Vladimir.Saveliev@sun.com>
Fri, 9 Apr 2010 01:24:01 +0000 (18:24 -0700)
committerRobert Read <robert.read@oracle.com>
Fri, 9 Apr 2010 01:24:01 +0000 (18:24 -0700)
(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

24 files changed:
lustre/include/cl_object.h
lustre/include/lclient.h
lustre/include/obd_ost.h
lustre/lclient/lcommon_cl.c
lustre/liblustre/file.c
lustre/liblustre/llite_cl.c
lustre/liblustre/llite_lib.h
lustre/liblustre/rw.c
lustre/liblustre/super.c
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/llite/namei.c
lustre/llite/vvp_io.c
lustre/llite/vvp_object.c
lustre/lov/lov_io.c
lustre/lov/lov_lock.c
lustre/lov/lov_merge.c
lustre/obdclass/linux/linux-obdo.c
lustre/osc/osc_cl_internal.h
lustre/osc/osc_internal.h
lustre/osc/osc_io.c
lustre/osc/osc_lock.c
lustre/osc/osc_request.c

index 58ef32a..94a5b01 100644 (file)
@@ -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,
index 529d198..306ae11 100644 (file)
@@ -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);
index 05bd9c6..5b1c183 100644 (file)
@@ -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 {
index a8322e1..2031b34 100644 (file)
@@ -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.
index 4810ef3..c166ca9 100644 (file)
@@ -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 */
index 12723d4..0aaa7bf 100644 (file)
@@ -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
index 44f1663..ba62ba6 100644 (file)
@@ -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;
 };
 
 
index aeff8db..47be4e1 100644 (file)
@@ -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);
 }
index 100f985..cdd12ec 100644 (file)
@@ -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:
index 355f4f3..211d021 100644 (file)
@@ -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);
 }
index 1d59daf..02c0898 100644 (file)
@@ -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;
 };
 
 /*
index 4658c10..142f627 100644 (file)
@@ -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);
index 27d194b..b56af50 100644 (file)
@@ -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,
index 89bb048..50adc18 100644 (file)
@@ -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);
 }
index 3ef1e4b..d928264 100644 (file)
@@ -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 */
index bf7a958..20d3319 100644 (file)
@@ -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:
index 563b625..cb81e72 100644 (file)
@@ -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
index 272d5ef..856418a 100644 (file)
@@ -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 {
index 5e5a5d8..9126027 100644 (file)
@@ -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 */
index d3445e2..b8e56eb 100644 (file)
@@ -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;
 };
 
 /**
index 0fbf8d0..0e2d042 100644 (file)
@@ -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);
 
index 6190433..31500a1 100644 (file)
@@ -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,
index 5718937..0d4e383 100644 (file)
@@ -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;
index dbd8c3a..014edf2 100644 (file)
@@ -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);
 }