📄 handler.c
字号:
if ((S_ISREG(inode->i_mode) && (reqbody->valid & OBD_MD_FLEASIZE)) || (S_ISDIR(inode->i_mode) && (reqbody->valid & OBD_MD_FLDIREA))) { if (lustre_msg_get_opc(req->rq_reqmsg) == MDS_GETATTR && ((S_ISDIR(inode->i_mode) && (reqbody->valid & OBD_MD_FLDIREA)))) flags = MDS_GETATTR; rc = mds_pack_md(obd, req->rq_repmsg, reply_off, body, inode, 1, flags); /* If we have LOV EA data, the OST holds size, atime, mtime */ if (!(body->valid & OBD_MD_FLEASIZE) && !(body->valid & OBD_MD_FLDIREA)) body->valid |= (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS | OBD_MD_FLATIME | OBD_MD_FLMTIME); lustre_shrink_reply(req, reply_off, body->eadatasize, 0); if (body->eadatasize) reply_off++; } else if (S_ISLNK(inode->i_mode) && (reqbody->valid & OBD_MD_LINKNAME) != 0) { char *symname = lustre_msg_buf(req->rq_repmsg, reply_off, 0); int len; LASSERT (symname != NULL); /* caller prepped reply */ len = lustre_msg_buflen(req->rq_repmsg, reply_off); rc = inode->i_op->readlink(dentry, symname, len); if (rc < 0) { CERROR("readlink failed: %d\n", rc); } else if (rc != len - 1) { CERROR ("Unexpected readlink rc %d: expecting %d\n", rc, len - 1); rc = -EINVAL; } else { CDEBUG(D_INODE, "read symlink dest %s\n", symname); body->valid |= OBD_MD_LINKNAME; body->eadatasize = rc + 1; symname[rc] = 0; /* NULL terminate */ rc = 0; } reply_off++; } else if (reqbody->valid == OBD_MD_FLFLAGS && reqbody->flags & MDS_BFLAG_EXT_FLAGS) { int flags; /* We only return the full set of flags on ioctl, otherwise we * get enough flags from the inode in mds_pack_inode2body(). */ rc = fsfilt_iocontrol(obd, inode, NULL, EXT3_IOC_GETFLAGS, (long)&flags); if (rc == 0) body->flags = flags | MDS_BFLAG_EXT_FLAGS; } if (reqbody->valid & OBD_MD_FLMODEASIZE) { struct mds_obd *mds = mds_req2mds(req); body->max_cookiesize = mds->mds_max_cookiesize; body->max_mdsize = mds->mds_max_mdsize; body->valid |= OBD_MD_FLMODEASIZE; } if (rc) RETURN(rc);#ifdef CONFIG_FS_POSIX_ACL if ((req->rq_export->exp_connect_flags & OBD_CONNECT_ACL) && (reqbody->valid & OBD_MD_FLACL)) { rc = mds_pack_acl(&req->rq_export->exp_mds_data, inode, req->rq_repmsg, body, reply_off); lustre_shrink_reply(req, reply_off, body->aclsize, 0); if (body->aclsize) reply_off++; }#endif RETURN(rc);}static int mds_getattr_pack_msg(struct ptlrpc_request *req, struct inode *inode, int offset){ struct mds_obd *mds = mds_req2mds(req); struct mds_body *body; int rc, bufcount = 2; int size[4] = { sizeof(struct ptlrpc_body), sizeof(*body) }; ENTRY; LASSERT(offset == REQ_REC_OFF); /* non-intent */ body = lustre_msg_buf(req->rq_reqmsg, offset, sizeof(*body)); LASSERT(body != NULL); /* checked by caller */ LASSERT(lustre_req_swabbed(req, offset)); /* swabbed by caller */ if ((S_ISREG(inode->i_mode) && (body->valid & OBD_MD_FLEASIZE)) || (S_ISDIR(inode->i_mode) && (body->valid & OBD_MD_FLDIREA))) { LOCK_INODE_MUTEX(inode); rc = fsfilt_get_md(req->rq_export->exp_obd, inode, NULL, 0, "lov"); UNLOCK_INODE_MUTEX(inode); CDEBUG(D_INODE, "got %d bytes MD data for inode %lu\n", rc, inode->i_ino); if ((rc == 0) && (lustre_msg_get_opc(req->rq_reqmsg) == MDS_GETATTR) && ((S_ISDIR(inode->i_mode) && (body->valid & OBD_MD_FLDIREA)))) rc = sizeof(struct lov_mds_md); if (rc < 0) { if (rc != -ENODATA) { CERROR("error getting inode %lu MD: rc = %d\n", inode->i_ino, rc); RETURN(rc); } size[bufcount] = 0; } else if (rc > mds->mds_max_mdsize) { size[bufcount] = 0; CERROR("MD size %d larger than maximum possible %u\n", rc, mds->mds_max_mdsize); } else { size[bufcount] = rc; } bufcount++; } else if (S_ISLNK(inode->i_mode) && (body->valid & OBD_MD_LINKNAME)) { if (i_size_read(inode) + 1 != body->eadatasize) CERROR("symlink size: %Lu, reply space: %d\n", i_size_read(inode) + 1, body->eadatasize); size[bufcount] = min_t(int, i_size_read(inode) + 1, body->eadatasize); bufcount++; CDEBUG(D_INODE, "symlink size: %Lu, reply space: %d\n", i_size_read(inode) + 1, body->eadatasize); }#ifdef CONFIG_FS_POSIX_ACL if ((req->rq_export->exp_connect_flags & OBD_CONNECT_ACL) && (body->valid & OBD_MD_FLACL)) { struct dentry de = { .d_inode = inode }; size[bufcount] = 0; if (inode->i_op && inode->i_op->getxattr) { lock_24kernel(); rc = inode->i_op->getxattr(&de, MDS_XATTR_NAME_ACL_ACCESS, NULL, 0); unlock_24kernel(); if (rc < 0) { if (rc != -ENODATA) { CERROR("got acl size: %d\n", rc); RETURN(rc); } } else size[bufcount] = rc; } bufcount++; }#endif if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GETATTR_PACK)) { CERROR("failed MDS_GETATTR_PACK test\n"); req->rq_status = -ENOMEM; RETURN(-ENOMEM); } rc = lustre_pack_reply(req, bufcount, size, NULL); if (rc) { req->rq_status = rc; RETURN(rc); } RETURN(0);}static int mds_getattr_lock(struct ptlrpc_request *req, int offset, int child_part, struct lustre_handle *child_lockh){ struct obd_device *obd = req->rq_export->exp_obd; struct mds_obd *mds = &obd->u.mds; struct ldlm_reply *rep = NULL; struct lvfs_run_ctxt saved; struct mds_body *body; struct dentry *dparent = NULL, *dchild = NULL; struct lvfs_ucred uc = {NULL,}; struct lustre_handle parent_lockh; int namesize; int rc = 0, cleanup_phase = 0, resent_req = 0; char *name; ENTRY; LASSERT(!strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME)); /* Swab now, before anyone looks inside the request */ body = lustre_swab_reqbuf(req, offset, sizeof(*body), lustre_swab_mds_body); if (body == NULL) { CERROR("Can't swab mds_body\n"); RETURN(-EFAULT); } lustre_set_req_swabbed(req, offset + 1); name = lustre_msg_string(req->rq_reqmsg, offset + 1, 0); if (name == NULL) { CERROR("Can't unpack name\n"); RETURN(-EFAULT); } namesize = lustre_msg_buflen(req->rq_reqmsg, offset + 1); /* namesize less than 2 means we have empty name, probably came from revalidate by cfid, so no point in having name to be set */ if (namesize <= 1) name = NULL; rc = mds_init_ucred(&uc, req, offset); if (rc) GOTO(cleanup, rc); LASSERT(offset == REQ_REC_OFF || offset == DLM_INTENT_REC_OFF); /* if requests were at offset 2, the getattr reply goes back at 1 */ if (offset == DLM_INTENT_REC_OFF) { rep = lustre_msg_buf(req->rq_repmsg, DLM_LOCKREPLY_OFF, sizeof(*rep)); offset = DLM_REPLY_REC_OFF; } push_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc); cleanup_phase = 1; /* kernel context */ intent_set_disposition(rep, DISP_LOOKUP_EXECD); /* FIXME: handle raw lookup */#if 0 if (body->valid == OBD_MD_FLID) { struct mds_body *mds_reply; int size = sizeof(*mds_reply); ino_t inum; // The user requested ONLY the inode number, so do a raw lookup rc = lustre_pack_reply(req, 1, &size, NULL); if (rc) { CERROR("out of memory\n"); GOTO(cleanup, rc); } rc = dir->i_op->lookup_raw(dir, name, namesize - 1, &inum); mds_reply = lustre_msg_buf(req->rq_repmsg, offset, sizeof(*mds_reply)); mds_reply->fid1.id = inum; mds_reply->valid = OBD_MD_FLID; GOTO(cleanup, rc); }#endif if (lustre_handle_is_used(child_lockh)) { LASSERT(lustre_msg_get_flags(req->rq_reqmsg) & MSG_RESENT); resent_req = 1; } if (resent_req == 0) { if (name) { OBD_FAIL_TIMEOUT(OBD_FAIL_MDS_RESEND, obd_timeout*2); rc = mds_get_parent_child_locked(obd, &obd->u.mds, &body->fid1, &parent_lockh, &dparent, LCK_CR, MDS_INODELOCK_UPDATE, name, namesize, child_lockh, &dchild, LCK_CR, child_part); } else { /* For revalidate by fid we always take UPDATE lock */ dchild = mds_fid2locked_dentry(obd, &body->fid2, NULL, LCK_CR, child_lockh, NULL, 0, child_part); LASSERT(dchild); if (IS_ERR(dchild)) rc = PTR_ERR(dchild); } if (rc) GOTO(cleanup, rc); } else { struct ldlm_lock *granted_lock; struct ll_fid child_fid; struct ldlm_resource *res; DEBUG_REQ(D_DLMTRACE, req, "resent, not enqueuing new locks"); granted_lock = ldlm_handle2lock(child_lockh); LASSERTF(granted_lock != NULL, LPU64"/%u lockh "LPX64"\n", body->fid1.id, body->fid1.generation, child_lockh->cookie); res = granted_lock->l_resource; child_fid.id = res->lr_name.name[0]; child_fid.generation = res->lr_name.name[1]; dchild = mds_fid2dentry(&obd->u.mds, &child_fid, NULL); LASSERT(!IS_ERR(dchild)); LDLM_LOCK_PUT(granted_lock); } cleanup_phase = 2; /* dchild, dparent, locks */ if (dchild->d_inode == NULL) { intent_set_disposition(rep, DISP_LOOKUP_NEG); /* in the intent case, the policy clears this error: the disposition is enough */ GOTO(cleanup, rc = -ENOENT); } else { intent_set_disposition(rep, DISP_LOOKUP_POS); } if (req->rq_repmsg == NULL) { rc = mds_getattr_pack_msg(req, dchild->d_inode, offset); if (rc != 0) { CERROR ("mds_getattr_pack_msg: %d\n", rc); GOTO (cleanup, rc); } } rc = mds_getattr_internal(obd, dchild, req, body, offset); GOTO(cleanup, rc); /* returns the lock to the client */ cleanup: switch (cleanup_phase) { case 2: if (resent_req == 0) { if (rc && dchild->d_inode) ldlm_lock_decref(child_lockh, LCK_CR); if (name) { ldlm_lock_decref(&parent_lockh, LCK_CR); l_dput(dparent); } } l_dput(dchild); case 1: pop_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc); default: mds_exit_ucred(&uc, mds); if (!req->rq_packed_final) { int rc2 = lustre_pack_reply(req, 1, NULL, NULL); if (rc == 0) rc = rc2; req->rq_status = rc; } } return rc;}static int mds_getattr(struct ptlrpc_request *req, int offset){ struct mds_obd *mds = mds_req2mds(req); struct obd_device *obd = req->rq_export->exp_obd; struct lvfs_run_ctxt saved; struct dentry *de; struct mds_body *body; struct lvfs_ucred uc = { NULL, }; int rc = 0; ENTRY; OBD_COUNTER_INCREMENT(obd, getattr); body = lustre_swab_reqbuf(req, offset, sizeof(*body),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -