-static int mds_extent_lock_callback(struct ldlm_lock *lock,
- struct ldlm_lock_desc *new, void *data,
- int flag)
-{
- struct lustre_handle lockh = { 0 };
- int rc;
- ENTRY;
-
- switch (flag) {
- case LDLM_CB_BLOCKING:
- ldlm_lock2handle(lock, &lockh);
- rc = ldlm_cli_cancel(&lockh);
- if (rc != ELDLM_OK)
- CERROR("ldlm_cli_cancel failed: %d\n", rc);
- break;
- case LDLM_CB_CANCELING: {
- break;
- }
- default:
- LBUG();
- }
-
- RETURN(0);
-}
-__u64 lov_merge_size(struct lov_stripe_md *lsm, int kms);
-__u64 lov_merge_blocks(struct lov_stripe_md *lsm);
-
-int mds_validate_size(struct obd_device *obd, struct inode *inode,
- struct mds_body *body, struct iattr *iattr)
-{
- ldlm_policy_data_t policy = { .l_extent = { 0, OBD_OBJECT_EOF } };
- struct lustre_handle lockh = { 0 };
- struct lov_stripe_md *lsm = NULL;
- int rc, len, flags;
- void *lmm = NULL;
- ENTRY;
-
- /* we update i_size/i_blocks only for regular files */
- if (!S_ISREG(inode->i_mode))
- RETURN(0);
-
- /* we shouldn't fetch size from OSTes during recovery - deadlock */
- if (obd->obd_recovering) {
- CERROR("size-on-mds has no support on OST yet\n");
- RETURN(0);
- }
-
- /* if nobody modified attrs. we're lucky */
- if (!mds_inode_has_old_attrs(inode))
- RETURN(0);
-
- /* 1: client didn't send actual i_size/i_blocks
- * 2: we seem to be last writer
- * 3: the file doesn't look like to be disappeared
- * conclusion: we're gonna fetch them from OSSes */
-
- down(&inode->i_sem);
- len = fsfilt_get_md(obd, inode, NULL, 0, EA_LOV);
- up(&inode->i_sem);
-
- if (len < 0) {
- CERROR("error getting inode %lu MD: %d\n", inode->i_ino, len);
- GOTO(cleanup, rc = len);
- } else if (len == 0) {
- CDEBUG(D_INODE, "no LOV in inode %lu\n", inode->i_ino);
- GOTO(cleanup, rc = 0);
- }
-
- OBD_ALLOC(lmm, len);
- if (lmm == NULL) {
- CERROR("can't allocate memory\n");
- GOTO(cleanup, rc = -ENOMEM);
- }
-
- down(&inode->i_sem);
- rc = fsfilt_get_md(obd, inode, lmm, len, EA_LOV);
- up(&inode->i_sem);
-
- if (rc < 0) {
- CERROR("error getting inode %lu MD: %d\n", inode->i_ino, rc);
- GOTO(cleanup, rc);
- }
-
- rc = obd_unpackmd(obd->u.mds.mds_dt_exp, &lsm, lmm, len);
- if (rc < 0) {
- CERROR("error getting inode %lu MD: %d\n", inode->i_ino, rc);
- GOTO(cleanup, rc);
- }
-
- CDEBUG(D_DLMTRACE, "Glimpsing inode %lu\n", inode->i_ino);
-
- flags = LDLM_FL_HAS_INTENT;
- rc = obd_enqueue(obd->u.mds.mds_dt_exp, lsm, LDLM_EXTENT, &policy,
- LCK_PR, &flags, mds_extent_lock_callback,
- ldlm_completion_ast, NULL, NULL,
- sizeof(struct ost_lvb), lustre_swab_ost_lvb, &lockh);
- if (rc != 0) {
- CERROR("obd_enqueue returned rc %d, returning -EIO\n", rc);
- GOTO(cleanup, rc);
- }
-
- CDEBUG(D_INODE, "LOV reports "LPD64"/%lu for "DLID4" [%s%s%s]\n",
- inode->i_size, inode->i_blocks, OLID4(&body->id1),
- atomic_read(&inode->i_writecount) > 1 ? "U" : "",
- mds_inode_has_old_attrs(inode) ? "D" : "",
- mds_inode_is_orphan(inode) ? "O" : "");
-
- i_size_write(inode, lov_merge_size(lsm, 0));
- inode->i_blocks = lov_merge_blocks(lsm);
- iattr->ia_size = inode->i_size;
- iattr->ia_valid |= ATTR_SIZE;
- DOWN_WRITE_I_ALLOC_SEM(inode);
- mds_inode_unset_attrs_old(inode);
- UP_WRITE_I_ALLOC_SEM(inode);
-
- obd_cancel(obd->u.mds.mds_dt_exp, lsm, LCK_PR, &lockh);
-
-cleanup:
- if (lsm != NULL)
- obd_free_memmd(obd->u.mds.mds_dt_exp, &lsm);
- if (lmm != NULL)
- OBD_FREE(lmm, len);
- RETURN(rc);
-}
-