Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / liblustre / super.c
index 6c9dc66..ad759d7 100644 (file)
 # include <sys/statfs.h>
 #endif
 
+#include <sysio.h>
 #ifdef HAVE_XTIO_H
 #include <xtio.h>
 #endif
-#include <sysio.h>
 #include <fs.h>
 #include <mount.h>
 #include <inode.h>
@@ -109,6 +109,24 @@ static void llu_fsop_gone(struct filesys *fs)
 
 static struct inode_ops llu_inode_ops;
 
+static ldlm_mode_t llu_take_md_lock(struct inode *inode, __u64 bits,
+                                    struct lustre_handle *lockh)
+{
+        ldlm_policy_data_t policy = { .l_inodebits = {bits}};
+        struct lu_fid *fid;
+        ldlm_mode_t rc;
+        int flags;
+        ENTRY;
+
+        fid = &llu_i2info(inode)->lli_fid;
+        CDEBUG(D_INFO, "trying to match res "DFID"\n", PFID(fid));
+
+        flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING;
+        rc = md_lock_match(llu_i2mdexp(inode), flags, fid, LDLM_IBITS, &policy,
+                           LCK_CR|LCK_CW|LCK_PR|LCK_PW, lockh);
+        RETURN(rc);
+}
+
 void llu_update_inode(struct inode *inode, struct mdt_body *body,
                       struct lov_stripe_md *lsm)
 {
@@ -164,12 +182,32 @@ void llu_update_inode(struct inode *inode, struct mdt_body *body,
                 st->st_nlink = body->nlink;
         if (body->valid & OBD_MD_FLRDEV)
                 st->st_rdev = body->rdev;
-        if (body->valid & OBD_MD_FLSIZE)
-                st->st_size = body->size;
-        if (body->valid & OBD_MD_FLBLOCKS)
-                st->st_blocks = body->blocks;
         if (body->valid & OBD_MD_FLFLAGS)
                 lli->lli_st_flags = body->flags;
+        if (body->valid & OBD_MD_FLSIZE) {
+                if ((llu_i2sbi(inode)->ll_lco.lco_flags & OBD_CONNECT_SOM) && 
+                    S_ISREG(st->st_mode) && lli->lli_smd) {
+                        struct lustre_handle lockh;
+                        ldlm_mode_t mode;
+                        
+                        /* As it is possible a blocking ast has been processed
+                         * by this time, we need to check there is an UPDATE 
+                         * lock on the client and set LLIF_MDS_SIZE_LOCK holding
+                         * it. */
+                        mode = llu_take_md_lock(inode, MDS_INODELOCK_UPDATE,
+                                                &lockh);
+                        if (mode) {
+                                st->st_size = body->size;
+                                lli->lli_flags |= LLIF_MDS_SIZE_LOCK;
+                                ldlm_lock_decref(&lockh, mode);
+                        }
+                } else {
+                    st->st_size = body->size;
+                }
+                
+                if (body->valid & OBD_MD_FLBLOCKS)
+                        st->st_blocks = body->blocks;
+        }
 }
 
 void obdo_to_inode(struct inode *dst, struct obdo *src, obd_flag valid)
@@ -378,27 +416,20 @@ static struct inode* llu_new_inode(struct filesys *fs,
 
 static int llu_have_md_lock(struct inode *inode, __u64 lockpart)
 {
-        struct llu_sb_info *sbi = llu_i2sbi(inode);
-        struct llu_inode_info *lli = llu_i2info(inode);
         struct lustre_handle lockh;
-        struct ldlm_res_id res_id = { .name = {0} };
-        struct obd_device *obddev;
         ldlm_policy_data_t policy = { .l_inodebits = { lockpart } };
+        struct lu_fid *fid;
         int flags;
         ENTRY;
 
         LASSERT(inode);
 
-        obddev = sbi->ll_md_exp->exp_obd;
-        res_id.name[0] = fid_seq(&lli->lli_fid);
-        res_id.name[1] = fid_oid(&lli->lli_fid);
-        res_id.name[2] = fid_ver(&lli->lli_fid);
-
-        CDEBUG(D_INFO, "trying to match res "LPU64"\n", res_id.name[0]);
+        fid = &llu_i2info(inode)->lli_fid;
+        CDEBUG(D_INFO, "trying to match res "DFID"\n", PFID(fid));
 
         flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING | LDLM_FL_TEST_LOCK;
-        if (ldlm_lock_match(obddev->obd_namespace, flags, &res_id, LDLM_IBITS,
-                            &policy, LCK_PW | LCK_PR, &lockh)) {
+        if (md_lock_match(llu_i2mdexp(inode), flags, fid, LDLM_IBITS, &policy,
+                          LCK_CR|LCK_CW|LCK_PR|LCK_PW, &lockh)) {
                 RETURN(1);
         }
         RETURN(0);
@@ -455,9 +486,6 @@ static int llu_inode_revalidate(struct inode *inode)
                 llu_update_inode(inode, md.body, md.lsm);
                 if (md.lsm != NULL && llu_i2info(inode)->lli_smd != md.lsm)
                         obd_free_memmd(sbi->ll_dt_exp, &md.lsm);
-                if (md.body->valid & OBD_MD_FLSIZE &&
-                    sbi->ll_lco.lco_flags & OBD_CONNECT_SOM)
-                        llu_i2info(inode)->lli_flags |= LLIF_MDS_SIZE_LOCK;
                 ptlrpc_req_finished(req);
         }
 
@@ -594,7 +622,8 @@ static int inode_setattr(struct inode * inode, struct iattr * attr)
         return error;
 }
 
-int llu_md_setattr(struct inode *inode, struct md_op_data *op_data)
+int llu_md_setattr(struct inode *inode, struct md_op_data *op_data,
+                   struct md_open_data **mod)
 {
         struct lustre_md md;
         struct llu_sb_info *sbi = llu_i2sbi(inode);
@@ -603,7 +632,8 @@ int llu_md_setattr(struct inode *inode, struct md_op_data *op_data)
         ENTRY;
 
         llu_prep_md_op_data(op_data, inode, NULL, NULL, 0, 0, LUSTRE_OPC_ANY);
-        rc = md_setattr(sbi->ll_md_exp, op_data, NULL, 0, NULL, 0, &request);
+        rc = md_setattr(sbi->ll_md_exp, op_data, NULL, 0, NULL,
+                        0, &request, mod);
 
         if (rc) {
                 ptlrpc_req_finished(request);
@@ -633,7 +663,8 @@ int llu_md_setattr(struct inode *inode, struct md_op_data *op_data)
 
 /* Close IO epoch and send Size-on-MDS attribute update. */
 static int llu_setattr_done_writing(struct inode *inode,
-                                    struct md_op_data *op_data)
+                                    struct md_op_data *op_data,
+                                    struct md_open_data *mod)
 {
         struct llu_inode_info *lli = llu_i2info(inode);
         struct intnl_stat *st = llu_i2stat(inode);
@@ -649,11 +680,11 @@ static int llu_setattr_done_writing(struct inode *inode,
                op_data->op_ioepoch, PFID(&lli->lli_fid));
 
         op_data->op_flags = MF_EPOCH_CLOSE | MF_SOM_CHANGE;
-        rc = md_done_writing(llu_i2sbi(inode)->ll_md_exp, op_data, NULL);
+        rc = md_done_writing(llu_i2sbi(inode)->ll_md_exp, op_data, mod);
         if (rc == -EAGAIN) {
                 /* MDS has instructed us to obtain Size-on-MDS attribute
                  * from OSTs and send setattr to back to MDS. */
-                rc = llu_sizeonmds_update(inode, &op_data->op_handle,
+                rc = llu_sizeonmds_update(inode, mod, &op_data->op_handle,
                                           op_data->op_ioepoch);
         } else if (rc) {
                 CERROR("inode %llu mdc truncate failed: rc = %d\n",
@@ -682,7 +713,8 @@ int llu_setattr_raw(struct inode *inode, struct iattr *attr)
         struct intnl_stat *st = llu_i2stat(inode);
         int ia_valid = attr->ia_valid;
         struct md_op_data op_data = { { 0 } };
-        int rc = 0;
+        struct md_open_data *mod = NULL;
+        int rc = 0, rc1 = 0;
         ENTRY;
 
         CDEBUG(D_VFSTRACE, "VFS Op:inode=%llu\n", (long long)st->st_ino);
@@ -741,15 +773,18 @@ int llu_setattr_raw(struct inode *inode, struct iattr *attr)
                 /* Open epoch for truncate. */
                 if (ia_valid & ATTR_SIZE)
                         op_data.op_flags = MF_EPOCH_OPEN;
-                rc = llu_md_setattr(inode, &op_data);
+                rc = llu_md_setattr(inode, &op_data, &mod);
                 if (rc)
                         RETURN(rc);
 
+                if (op_data.op_ioepoch)
+                        CDEBUG(D_INODE, "Epoch "LPU64" opened on "DFID" for "
+                               "truncate\n", op_data.op_ioepoch,
+                               PFID(&llu_i2info(inode)->lli_fid));
+
                 if (!lsm || !S_ISREG(st->st_mode)) {
                         CDEBUG(D_INODE, "no lsm: not setting attrs on OST\n");
-                        if (op_data.op_ioepoch)
-                                rc = llu_setattr_done_writing(inode, &op_data);
-                        RETURN(rc);
+                        GOTO(out, rc);
                 }
         } else {
                 /* The OST doesn't check permissions, but the alternative is
@@ -810,10 +845,9 @@ int llu_setattr_raw(struct inode *inode, struct iattr *attr)
                                      &lockh, flags);
                 if (rc != ELDLM_OK) {
                         if (rc > 0)
-                                RETURN(-ENOLCK);
-                        RETURN(rc);
+                                GOTO(out, rc = -ENOLCK);
+                        GOTO(out, rc);
                 }
-
                 rc = llu_vmtruncate(inode, attr->ia_size, obd_flags);
 
                 /* unlock now as we don't mind others file lockers racing with
@@ -824,9 +858,6 @@ int llu_setattr_raw(struct inode *inode, struct iattr *attr)
                         if (!rc)
                                 rc = err;
                 }
-
-                if (op_data.op_ioepoch)
-                        rc = llu_setattr_done_writing(inode, &op_data);
         } else if (ia_valid & (ATTR_MTIME | ATTR_MTIME_SET)) {
                 struct obd_info oinfo = { { { 0 } } };
                 struct obdo oa;
@@ -846,7 +877,11 @@ int llu_setattr_raw(struct inode *inode, struct iattr *attr)
                 if (rc)
                         CERROR("obd_setattr_async fails: rc=%d\n", rc);
         }
-        RETURN(rc);
+        EXIT;
+out:
+        if (op_data.op_ioepoch)
+                rc1 = llu_setattr_done_writing(inode, &op_data, mod);
+        return rc ? rc : rc1;
 }
 
 /* here we simply act as a thin layer to glue it with
@@ -960,7 +995,7 @@ static int llu_readlink_internal(struct inode *inode,
         body = lustre_msg_buf((*request)->rq_repmsg, REPLY_REC_OFF,
                               sizeof(*body));
         LASSERT(body != NULL);
-        LASSERT_REPSWABBED(*request, REPLY_REC_OFF);
+        LASSERT(lustre_rep_swabbed(*request, REPLY_REC_OFF));
 
         if ((body->valid & OBD_MD_LINKNAME) == 0) {
                 CERROR ("OBD_MD_LINKNAME not set on reply\n");
@@ -1404,7 +1439,7 @@ static int llu_file_flock(struct inode *ino,
                flock.l_flock.pid, flags, einfo.ei_mode, flock.l_flock.start,
                flock.l_flock.end);
 
-        rc = ldlm_cli_enqueue(llu_i2mdcexp(ino), NULL, &einfo, &res_id, 
+        rc = ldlm_cli_enqueue(llu_i2mdexp(ino), NULL, &einfo, &res_id, 
                               &flock, &flags, NULL, 0, NULL, &lockh, 0);
         RETURN(rc);
 }
@@ -1671,7 +1706,7 @@ static int llu_lov_dir_setstripe(struct inode *ino, unsigned long arg)
 
         /* swabbing is done in lov_setstripe() on server side */
         rc = md_setattr(sbi->ll_md_exp, &op_data, &lum,
-                        sizeof(lum), NULL, 0, &request);
+                        sizeof(lum), NULL, 0, &request, NULL);
         if (rc) {
                 ptlrpc_req_finished(request);
                 if (rc != -EPERM && rc != -EACCES)