# 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>
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)
{
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)
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);
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);
}
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);
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);
/* 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);
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",
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);
/* 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
&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
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;
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
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");
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);
}
/* 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)