📄 super.c
字号:
obddev = sbi->ll_mdc_exp->exp_obd; res_id.name[0] = llu_i2stat(inode)->st_ino; res_id.name[1] = lli->lli_st_generation; CDEBUG(D_INFO, "trying to match res "LPU64"\n", res_id.name[0]); 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_CR|LCK_CW|LCK_PR|LCK_PW, &lockh)) { RETURN(1); } RETURN(0);}static int llu_inode_revalidate(struct inode *inode){ struct lov_stripe_md *lsm = NULL; ENTRY; if (!inode) { CERROR("REPORT THIS LINE TO PETER\n"); RETURN(0); } if (!llu_have_md_lock(inode, MDS_INODELOCK_UPDATE)) { struct lustre_md md; struct ptlrpc_request *req = NULL; struct llu_sb_info *sbi = llu_i2sbi(inode); struct ll_fid fid; unsigned long valid = OBD_MD_FLGETATTR; int rc, ealen = 0; /* 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)) { ealen = obd_size_diskmd(sbi->ll_osc_exp, NULL); valid |= OBD_MD_FLEASIZE; } ll_inode2fid(&fid, inode); rc = mdc_getattr(sbi->ll_mdc_exp, &fid, valid, ealen, &req); if (rc) { CERROR("failure %d inode %llu\n", rc, (long long)llu_i2stat(inode)->st_ino); RETURN(-abs(rc)); } rc = mdc_req2lustre_md(req, REPLY_REC_OFF, sbi->ll_osc_exp,&md); /* XXX Too paranoid? */ if (((md.body->valid ^ valid) & OBD_MD_FLEASIZE) && !((md.body->valid & OBD_MD_FLNLINK) && (md.body->nlink == 0))) { CERROR("Asked for %s eadata but got %s (%d)\n", (valid & OBD_MD_FLEASIZE) ? "some" : "no", (md.body->valid & OBD_MD_FLEASIZE) ? "some":"none", md.body->eadatasize); } if (rc) { ptlrpc_req_finished(req); RETURN(rc); } llu_update_inode(inode, md.body, md.lsm); if (md.lsm != NULL && llu_i2info(inode)->lli_smd != md.lsm) obd_free_memmd(sbi->ll_osc_exp, &md.lsm); if (md.body->valid & OBD_MD_FLSIZE) set_bit(LLI_F_HAVE_MDS_SIZE_LOCK, &llu_i2info(inode)->lli_flags); ptlrpc_req_finished(req); } lsm = llu_i2info(inode)->lli_smd; if (!lsm) /* object not yet allocated, don't validate size */ RETURN(0); /* ll_glimpse_size will prefer locally cached writes if they extend * the file */ RETURN(llu_glimpse_size(inode));}static void copy_stat_buf(struct inode *ino, struct intnl_stat *b){ *b = *llu_i2stat(ino);}static int llu_iop_getattr(struct pnode *pno, struct inode *ino, struct intnl_stat *b){ int rc; ENTRY; liblustre_wait_event(0); if (!ino) { LASSERT(pno); LASSERT(pno->p_base->pb_ino); ino = pno->p_base->pb_ino; } else { LASSERT(!pno || pno->p_base->pb_ino == ino); } /* libsysio might call us directly without intent lock, * we must re-fetch the attrs here */ rc = llu_inode_revalidate(ino); if (!rc) { copy_stat_buf(ino, b); LASSERT(!llu_i2info(ino)->lli_it); } liblustre_wait_event(0); RETURN(rc);}static int null_if_equal(struct ldlm_lock *lock, void *data){ if (data == lock->l_ast_data) { lock->l_ast_data = NULL; if (lock->l_req_mode != lock->l_granted_mode) LDLM_ERROR(lock,"clearing inode with ungranted lock\n"); } return LDLM_ITER_CONTINUE;}void llu_clear_inode(struct inode *inode){ struct ll_fid fid; struct llu_inode_info *lli = llu_i2info(inode); struct llu_sb_info *sbi = llu_i2sbi(inode); ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%llu/%lu(%p)\n", (long long)llu_i2stat(inode)->st_ino, lli->lli_st_generation, inode); ll_inode2fid(&fid, inode); clear_bit(LLI_F_HAVE_MDS_SIZE_LOCK, &(lli->lli_flags)); mdc_change_cbdata(sbi->ll_mdc_exp, &fid, null_if_equal, inode); if (lli->lli_smd) obd_change_cbdata(sbi->ll_osc_exp, lli->lli_smd, null_if_equal, inode); if (lli->lli_smd) { obd_free_memmd(sbi->ll_osc_exp, &lli->lli_smd); lli->lli_smd = NULL; } if (lli->lli_symlink_name) { OBD_FREE(lli->lli_symlink_name, strlen(lli->lli_symlink_name) + 1); lli->lli_symlink_name = NULL; } EXIT;}void llu_iop_gone(struct inode *inode){ struct llu_inode_info *lli = llu_i2info(inode); ENTRY; liblustre_wait_event(0); llu_clear_inode(inode); OBD_FREE(lli, sizeof(*lli)); EXIT;}static int inode_setattr(struct inode * inode, struct iattr * attr){ unsigned int ia_valid = attr->ia_valid; struct intnl_stat *st = llu_i2stat(inode); int error = 0; /* * inode_setattr() is only ever invoked with ATTR_SIZE (by * llu_setattr_raw()) when file has no bodies. Check this. */ LASSERT(ergo(ia_valid & ATTR_SIZE, llu_i2info(inode)->lli_smd == NULL)); if (ia_valid & ATTR_SIZE) st->st_size = attr->ia_size; if (ia_valid & ATTR_UID) st->st_uid = attr->ia_uid; if (ia_valid & ATTR_GID) st->st_gid = attr->ia_gid; if (ia_valid & ATTR_ATIME) st->st_atime = attr->ia_atime; if (ia_valid & ATTR_MTIME) st->st_mtime = attr->ia_mtime; if (ia_valid & ATTR_CTIME) st->st_ctime = attr->ia_ctime; if (ia_valid & ATTR_MODE) { st->st_mode = attr->ia_mode; if (!in_group_p(st->st_gid) && !capable(CAP_FSETID)) st->st_mode &= ~S_ISGID; } /* mark_inode_dirty(inode); */ return error;}/* If this inode has objects allocated to it (lsm != NULL), then the OST * object(s) determine the file size and mtime. Otherwise, the MDS will * keep these values until such a time that objects are allocated for it. * We do the MDS operations first, as it is checking permissions for us. * We don't to the MDS RPC if there is nothing that we want to store there, * otherwise there is no harm in updating mtime/atime on the MDS if we are * going to do an RPC anyways. * * If we are doing a truncate, we will send the mtime and ctime updates * to the OST with the punch RPC, otherwise we do an explicit setattr RPC. * I don't believe it is possible to get e.g. ATTR_MTIME_SET and ATTR_SIZE * at the same time. */int llu_setattr_raw(struct inode *inode, struct iattr *attr){ struct lov_stripe_md *lsm = llu_i2info(inode)->lli_smd; struct llu_sb_info *sbi = llu_i2sbi(inode); struct intnl_stat *st = llu_i2stat(inode); struct ptlrpc_request *request = NULL; struct mdc_op_data op_data; int ia_valid = attr->ia_valid; int rc = 0; ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%llu\n", (long long)st->st_ino); if (ia_valid & ATTR_SIZE) { if (attr->ia_size > ll_file_maxbytes(inode)) { CDEBUG(D_INODE, "file too large %llu > "LPU64"\n", (long long)attr->ia_size, ll_file_maxbytes(inode)); RETURN(-EFBIG); } attr->ia_valid |= ATTR_MTIME | ATTR_CTIME; } /* We mark all of the fields "set" so MDS/OST does not re-set them */ if (attr->ia_valid & ATTR_CTIME) { attr->ia_ctime = CURRENT_TIME; attr->ia_valid |= ATTR_CTIME_SET; } if (!(ia_valid & ATTR_ATIME_SET) && (attr->ia_valid & ATTR_ATIME)) { attr->ia_atime = CURRENT_TIME; attr->ia_valid |= ATTR_ATIME_SET; } if (!(ia_valid & ATTR_MTIME_SET) && (attr->ia_valid & ATTR_MTIME)) { attr->ia_mtime = 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 = llu_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 %lu, ctime %lu, now = %lu\n", LTIME_S(attr->ia_mtime), LTIME_S(attr->ia_ctime), LTIME_S(CURRENT_TIME)); if (lsm) attr->ia_valid &= ~ATTR_SIZE; /* If only OST attributes being set on objects, don't do MDS RPC. * In that case, we need to check permissions and update the local * inode ourselves so we can call obdo_from_inode() always. */ if (ia_valid & (lsm ? ~(ATTR_SIZE | ATTR_FROM_OPEN | ATTR_RAW) : ~0)) { struct lustre_md md; llu_prepare_mdc_op_data(&op_data, inode, NULL, NULL, 0, 0); rc = mdc_setattr(sbi->ll_mdc_exp, &op_data, attr, NULL, 0, NULL, 0, &request); if (rc) { ptlrpc_req_finished(request); if (rc != -EPERM && rc != -EACCES) CERROR("mdc_setattr fails: rc = %d\n", rc); RETURN(rc); } rc = mdc_req2lustre_md(request, REPLY_REC_OFF, sbi->ll_osc_exp, &md); if (rc) { ptlrpc_req_finished(request); RETURN(rc); } /* We call inode_setattr to adjust timestamps. * If there is at least some data in file, we cleared ATTR_SIZE * above to avoid invoking vmtruncate, otherwise it is important * to call vmtruncate in inode_setattr to update inode->i_size * (bug 6196) */ inode_setattr(inode, attr); llu_update_inode(inode, md.body, md.lsm); ptlrpc_req_finished(request); if (!lsm || !S_ISREG(st->st_mode)) { CDEBUG(D_INODE, "no lsm: not setting attrs on OST\n"); RETURN(0); } } else { /* The OST doesn't check permissions, but the alternative is * a gratuitous RPC to the MDS. We already rely on the client * to do read/write/truncate permission checks, so is mtime OK? */ if (ia_valid & (ATTR_MTIME | ATTR_ATIME)) { /* from sys_utime() */ if (!(ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET))) { if (current->fsuid != st->st_uid && (rc = ll_permission(inode, MAY_WRITE)) != 0) RETURN(rc); } else { /* from inode_change_ok() */ if (current->fsuid != st->st_uid && !capable(CAP_FOWNER)) RETURN(-EPERM); } } /* Won't invoke llu_vmtruncate(), as we already cleared * ATTR_SIZE */ inode_setattr(inode, attr); } if (ia_valid & ATTR_SIZE) { ldlm_policy_data_t policy = { .l_extent = {attr->ia_size, OBD_OBJECT_EOF} }; struct lustre_handle lockh = { 0, }; struct lustre_handle match_lockh = { 0, }; int err; int flags = LDLM_FL_TEST_LOCK; /* for assertion check below */ int lock_mode; obd_flag obd_flags; /* check that there are no matching locks */ LASSERT(obd_match(sbi->ll_osc_exp, lsm, LDLM_EXTENT, &policy, LCK_PW, &flags, inode, &match_lockh) <= 0); /* XXX when we fix the AST intents to pass the discard-range * XXX extent, make ast_flags always LDLM_AST_DISCARD_DATA * XXX here. */ flags = (attr->ia_size == 0) ? LDLM_AST_DISCARD_DATA : 0; if (sbi->ll_lco.lco_flags & OBD_CONNECT_TRUNCLOCK) { lock_mode = LCK_NL; obd_flags = OBD_FL_TRUNCLOCK; CDEBUG(D_INODE, "delegating locking to the OST"); } else { lock_mode = LCK_PW; obd_flags = 0; } /* with lock_mode == LK_NL no lock is taken. */ rc = llu_extent_lock(NULL, inode, lsm, lock_mode, &policy, &lockh, flags); if (rc != ELDLM_OK) { if (rc > 0) RETURN(-ENOLCK); RETURN(rc); } rc = llu_vmtruncate(inode, attr->ia_size, obd_flags); /* unlock now as we don't mind others file lockers racing with * the mds updates below? */ err = llu_extent_unlock(NULL, inode, lsm, lock_mode, &lockh); if (err) { CERROR("llu_extent_unlock failed: %d\n", err); if (!rc) rc = err; } } else if (ia_valid & (ATTR_MTIME | ATTR_MTIME_SET)) { struct obd_info oinfo = { { { 0 } } }; struct obdo oa; CDEBUG(D_INODE, "set mtime on OST inode %llu to %lu\n", (long long)st->st_ino, LTIME_S(attr->ia_mtime)); oa.o_id = lsm->lsm_object_id; oa.o_valid = OBD_MD_FLID; obdo_from_inode(&oa, inode, OBD_MD_FLTYPE | OBD_MD_FLATIME |
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -