-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 mds_body *body,
- struct mds_file_data *mfd)
-{
- ldlm_policy_data_t policy = { .l_extent = { 0, OBD_OBJECT_EOF } };
- struct inode *inode = mfd->mfd_dentry->d_inode;
- 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 update i_size/i_blocks only for writers */
- if (!(mfd->mfd_mode & FMODE_WRITE))
- RETURN(0);
-
- /* we like when client reports actual i_size/i_blocks himself */
- if (body->valid & OBD_MD_FLSIZE) {
- LASSERT(body->valid & OBD_MD_FLBLOCKS);
- CDEBUG(D_OTHER, "client reports "LPD64"/"LPD64" for "DLID4"\n",
- body->size, body->blocks, OLID4(&body->id1));
- RETURN(0);
- }
-
- /* we shouldn't fetch size from OSTes during recovery - deadlock */
- if (obd->obd_recovering)
- RETURN(0);
-
- DOWN_READ_I_ALLOC_SEM(inode);
- if (atomic_read(&inode->i_writecount) > 1
- || mds_inode_is_orphan(inode)) {
- /* there is no need to update i_size/i_blocks on orphans.
- * also, if this is not last writer, then it doesn't make
- * sense to fetch i_size/i_blocks from OSSes */
- UP_READ_I_ALLOC_SEM(inode);
- RETURN(0);
- }
- UP_READ_I_ALLOC_SEM(inode);
-
- /* 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);
- }
-
- body->size = lov_merge_size(lsm, 0);
- body->blocks = lov_merge_blocks(lsm);
- body->valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
-
- CDEBUG(D_OTHER, "LOV reports "LPD64"/"LPD64" for "DLID4"\n",
- body->size, body->blocks, OLID4(&body->id1));
-
- 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);
-}
-