- RETURN(ERR_PTR(-ENOENT));
- }
-
- if (generation && inode->i_generation != generation) {
- /* we didn't find the right inode.. */
- CDEBUG(D_INODE, "found wrong generation: inode %lu, link: %lu, "
- "count: %d, generation %u/%u\n", inode->i_ino,
- (unsigned long)inode->i_nlink,
- atomic_read(&inode->i_count), inode->i_generation,
- generation);
- dput(result);
- RETURN(ERR_PTR(-ENOENT));
- }
-
- if (mnt) {
- *mnt = mds->mds_vfsmnt;
- mntget(*mnt);
- }
-
- RETURN(result);
-}
-
-static int mds_connect_internal(struct obd_export *exp,
- struct obd_connect_data *data)
-{
- struct obd_device *obd = exp->exp_obd;
- if (data != NULL) {
- data->ocd_connect_flags &= MDT_CONNECT_SUPPORTED;
- data->ocd_ibits_known &= MDS_INODELOCK_FULL;
-
- /* If no known bits (which should not happen, probably,
- as everybody should support LOOKUP and UPDATE bits at least)
- revert to compat mode with plain locks. */
- if (!data->ocd_ibits_known &&
- data->ocd_connect_flags & OBD_CONNECT_IBITS)
- data->ocd_connect_flags &= ~OBD_CONNECT_IBITS;
-
- if (!obd->u.mds.mds_fl_acl)
- data->ocd_connect_flags &= ~OBD_CONNECT_ACL;
-
- if (!obd->u.mds.mds_fl_user_xattr)
- data->ocd_connect_flags &= ~OBD_CONNECT_XATTR;
-
- exp->exp_connect_flags = data->ocd_connect_flags;
- data->ocd_version = LUSTRE_VERSION_CODE;
- exp->exp_mds_data.med_ibits_known = data->ocd_ibits_known;
- }
-
- if (obd->u.mds.mds_fl_acl &&
- ((exp->exp_connect_flags & OBD_CONNECT_ACL) == 0)) {
- CWARN("%s: MDS requires ACL support but client does not\n",
- obd->obd_name);
- return -EBADE;
- }
- return 0;
-}
-
-static int mds_reconnect(const struct lu_env *env,
- struct obd_export *exp, struct obd_device *obd,
- struct obd_uuid *cluuid,
- struct obd_connect_data *data)
-{
- int rc;
- ENTRY;
-
- if (exp == NULL || obd == NULL || cluuid == NULL)
- RETURN(-EINVAL);
-
- rc = mds_connect_internal(exp, data);
-
- RETURN(rc);
-}
-
-/* Establish a connection to the MDS.
- *
- * This will set up an export structure for the client to hold state data
- * about that client, like open files, the last operation number it did
- * on the server, etc.
- */
-static int mds_connect(const struct lu_env *env,
- struct lustre_handle *conn, struct obd_device *obd,
- struct obd_uuid *cluuid, struct obd_connect_data *data,
- void *localdata)
-{
- struct obd_export *exp;
- struct mds_export_data *med;
- struct mds_client_data *mcd = NULL;
- int rc;
- ENTRY;
-
- if (!conn || !obd || !cluuid)
- RETURN(-EINVAL);
-
- /* XXX There is a small race between checking the list and adding a
- * new connection for the same UUID, but the real threat (list
- * corruption when multiple different clients connect) is solved.
- *
- * There is a second race between adding the export to the list,
- * and filling in the client data below. Hence skipping the case
- * of NULL mcd above. We should already be controlling multiple
- * connects at the client, and we can't hold the spinlock over
- * memory allocations without risk of deadlocking.
- */
- rc = class_connect(conn, obd, cluuid);
- if (rc)
- RETURN(rc);
- exp = class_conn2export(conn);
- LASSERT(exp);
- med = &exp->exp_mds_data;
-
- exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_NULL;
-
- rc = mds_connect_internal(exp, data);
- if (rc)
- GOTO(out, rc);
-
- OBD_ALLOC(mcd, sizeof(*mcd));
- if (!mcd)
- GOTO(out, rc = -ENOMEM);
-
- memcpy(mcd->mcd_uuid, cluuid, sizeof(mcd->mcd_uuid));
- med->med_mcd = mcd;
-
- rc = mds_client_add(obd, exp, -1, localdata);
- GOTO(out, rc);
-
-out:
- if (rc) {
- if (mcd) {
- OBD_FREE(mcd, sizeof(*mcd));
- med->med_mcd = NULL;
- }
- class_disconnect(exp);
- } else {
- class_export_put(exp);
- }
-
- RETURN(rc);
-}
-
-int mds_init_export(struct obd_export *exp)
-{
- struct mds_export_data *med = &exp->exp_mds_data;
-
- CFS_INIT_LIST_HEAD(&med->med_open_head);
- spin_lock_init(&med->med_open_lock);
-
- spin_lock(&exp->exp_lock);
- exp->exp_connecting = 1;
- spin_unlock(&exp->exp_lock);
-
- RETURN(0);
-}
-
-static int mds_destroy_export(struct obd_export *export)
-{
- struct mds_export_data *med;
- struct obd_device *obd = export->exp_obd;
- struct mds_obd *mds = &obd->u.mds;
- struct lvfs_run_ctxt saved;
- struct lov_mds_md *lmm;
- struct llog_cookie *logcookies;
- int rc = 0;
- ENTRY;
-
- med = &export->exp_mds_data;
- target_destroy_export(export);
-
- if (obd_uuid_equals(&export->exp_client_uuid, &obd->obd_uuid))
- RETURN(0);
-
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- /* Close any open files (which may also cause orphan unlinking). */
-
- OBD_ALLOC(lmm, mds->mds_max_mdsize);
- if (lmm == NULL) {
- CWARN("%s: allocation failure during cleanup; can not force "
- "close file handles on this service.\n", obd->obd_name);
- GOTO(out, rc = -ENOMEM);
- }
-
- OBD_ALLOC(logcookies, mds->mds_max_cookiesize);
- if (logcookies == NULL) {
- CWARN("%s: allocation failure during cleanup; can not force "
- "close file handles on this service.\n", obd->obd_name);
- OBD_FREE(lmm, mds->mds_max_mdsize);
- GOTO(out_lmm, rc = -ENOMEM);
- }
-
- spin_lock(&med->med_open_lock);
- while (!list_empty(&med->med_open_head)) {
- struct list_head *tmp = med->med_open_head.next;
- struct mds_file_data *mfd =
- list_entry(tmp, struct mds_file_data, mfd_list);
- int lmm_size = mds->mds_max_mdsize;
- umode_t mode = mfd->mfd_dentry->d_inode->i_mode;
- __u64 valid = 0;
-
- /* Remove mfd handle so it can't be found again.
- * We are consuming the mfd_list reference here. */
- mds_mfd_unlink(mfd, 0);
- spin_unlock(&med->med_open_lock);
-
- /* If you change this message, be sure to update
- * replay_single:test_46 */
- CDEBUG(D_INODE|D_IOCTL, "%s: force closing file handle for "
- "%.*s (ino %lu)\n", obd->obd_name,
- mfd->mfd_dentry->d_name.len,mfd->mfd_dentry->d_name.name,
- mfd->mfd_dentry->d_inode->i_ino);
-
- rc = mds_get_md(obd, mfd->mfd_dentry->d_inode, lmm, &lmm_size, 1);
- if (rc < 0)
- CWARN("mds_get_md failure, rc=%d\n", rc);
- else
- valid |= OBD_MD_FLEASIZE;
-
- /* child orphan sem protects orphan_dec_test and
- * is_orphan race, mds_mfd_close drops it */
- MDS_DOWN_WRITE_ORPHAN_SEM(mfd->mfd_dentry->d_inode);
- rc = mds_mfd_close(NULL, REQ_REC_OFF, obd, mfd,
- !(export->exp_flags & OBD_OPT_FAILOVER),
- lmm, lmm_size, logcookies,
- mds->mds_max_cookiesize,
- &valid);
-
- if (rc)
- CDEBUG(D_INODE|D_IOCTL, "Error closing file: %d\n", rc);
-
- if (valid & OBD_MD_FLCOOKIE) {
- rc = mds_osc_destroy_orphan(obd, mode, lmm,
- lmm_size, logcookies, 1);
- if (rc < 0) {
- CDEBUG(D_INODE, "%s: destroy of orphan failed,"
- " rc = %d\n", obd->obd_name, rc);
- rc = 0;
- }
- valid &= ~OBD_MD_FLCOOKIE;
- }
-
- spin_lock(&med->med_open_lock);
- }
- spin_unlock(&med->med_open_lock);
-
- OBD_FREE(logcookies, mds->mds_max_cookiesize);
-out_lmm:
- OBD_FREE(lmm, mds->mds_max_mdsize);
-out:
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
- mds_client_free(export);
- RETURN(rc);
-}
-
-static int mds_disconnect(struct obd_export *exp)
-{
- int rc;
- ENTRY;
-
- LASSERT(exp);
- class_export_get(exp);
-
- /* Disconnect early so that clients can't keep using export */
- rc = class_disconnect(exp);
- if (exp->exp_obd->obd_namespace != NULL)
- ldlm_cancel_locks_for_export(exp);
-
- /* complete all outstanding replies */
- spin_lock(&exp->exp_lock);
- while (!list_empty(&exp->exp_outstanding_replies)) {
- struct ptlrpc_reply_state *rs =
- list_entry(exp->exp_outstanding_replies.next,
- struct ptlrpc_reply_state, rs_exp_list);
- struct ptlrpc_service *svc = rs->rs_service;
-
- spin_lock(&svc->srv_lock);
- list_del_init(&rs->rs_exp_list);
- ptlrpc_schedule_difficult_reply(rs);
- spin_unlock(&svc->srv_lock);
- }
- spin_unlock(&exp->exp_lock);
-
- class_export_put(exp);
- RETURN(rc);
-}
-
-static int mds_getstatus(struct ptlrpc_request *req)
-{
- struct mds_obd *mds = mds_req2mds(req);
- struct mds_body *body;
- int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
- ENTRY;
-
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GETSTATUS_PACK))
- RETURN(req->rq_status = -ENOMEM);
- rc = lustre_pack_reply(req, 2, size, NULL);
- if (rc)
- RETURN(req->rq_status = rc);
-
- body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*body));
- memcpy(&body->fid1, &mds->mds_rootfid, sizeof(body->fid1));
-
- /* the last_committed and last_xid fields are filled in for all
- * replies already - no need to do so here also.
- */
- RETURN(0);
-}
-
-/* get the LOV EA from @inode and store it into @md. It can be at most
- * @size bytes, and @size is updated with the actual EA size.
- * The EA size is also returned on success, and -ve errno on failure.
- * If there is no EA then 0 is returned. */
-int mds_get_md(struct obd_device *obd, struct inode *inode, void *md,
- int *size, int lock)
-{
- int rc = 0;
- int lmm_size;
-
- if (lock)
- LOCK_INODE_MUTEX(inode);
- rc = fsfilt_get_md(obd, inode, md, *size, "lov");
-
- if (rc < 0) {
- CERROR("Error %d reading eadata for ino %lu\n",
- rc, inode->i_ino);
- } else if (rc > 0) {
- lmm_size = rc;
- rc = mds_convert_lov_ea(obd, inode, md, lmm_size);
-
- if (rc == 0) {
- *size = lmm_size;
- rc = lmm_size;
- } else if (rc > 0) {
- *size = rc;
- }
- } else {
- *size = 0;
- }
- if (lock)
- UNLOCK_INODE_MUTEX(inode);
-
- RETURN (rc);
-}
-
-
-/* Call with lock=1 if you want mds_pack_md to take the i_mutex.
- * Call with lock=0 if the caller has already taken the i_mutex. */
-int mds_pack_md(struct obd_device *obd, struct lustre_msg *msg, int offset,
- struct mds_body *body, struct inode *inode, int lock)
-{
- struct mds_obd *mds = &obd->u.mds;
- void *lmm;
- int lmm_size;
- int rc;
- ENTRY;
-
- lmm = lustre_msg_buf(msg, offset, 0);
- if (lmm == NULL) {
- /* Some problem with getting eadata when I sized the reply
- * buffer... */
- CDEBUG(D_INFO, "no space reserved for inode %lu MD\n",
- inode->i_ino);
- RETURN(0);
- }
- lmm_size = lustre_msg_buflen(msg, offset);
-
- /* I don't really like this, but it is a sanity check on the client
- * MD request. However, if the client doesn't know how much space
- * to reserve for the MD, it shouldn't be bad to have too much space.
- */
- if (lmm_size > mds->mds_max_mdsize) {
- CWARN("Reading MD for inode %lu of %d bytes > max %d\n",
- inode->i_ino, lmm_size, mds->mds_max_mdsize);
- // RETURN(-EINVAL);
- }
-
- rc = mds_get_md(obd, inode, lmm, &lmm_size, lock);
- if (rc > 0) {
- if (S_ISDIR(inode->i_mode))
- body->valid |= OBD_MD_FLDIREA;
- else
- body->valid |= OBD_MD_FLEASIZE;
- body->eadatasize = lmm_size;
- rc = 0;
- }
-
- RETURN(rc);
-}
-
-#ifdef CONFIG_FS_POSIX_ACL
-static
-int mds_pack_posix_acl(struct inode *inode, struct lustre_msg *repmsg,
- struct mds_body *repbody, int repoff)
-{
- struct dentry de = { .d_inode = inode };
- int buflen, rc;
- ENTRY;
-
- LASSERT(repbody->aclsize == 0);
- LASSERT(lustre_msg_bufcount(repmsg) > repoff);
-
- buflen = lustre_msg_buflen(repmsg, repoff);
- if (!buflen)
- GOTO(out, 0);
-
- if (!inode->i_op || !inode->i_op->getxattr)
- GOTO(out, 0);
-
- rc = inode->i_op->getxattr(&de, MDS_XATTR_NAME_ACL_ACCESS,
- lustre_msg_buf(repmsg, repoff, buflen),
- buflen);
-
- if (rc >= 0)
- repbody->aclsize = rc;
- else if (rc != -ENODATA) {
- CERROR("buflen %d, get acl: %d\n", buflen, rc);
- RETURN(rc);
- }
- EXIT;
-out:
- repbody->valid |= OBD_MD_FLACL;
- return 0;
-}
-#else
-#define mds_pack_posix_acl(inode, repmsg, repbody, repoff) 0
-#endif
-
-int mds_pack_acl(struct mds_export_data *med, struct inode *inode,
- struct lustre_msg *repmsg, struct mds_body *repbody,
- int repoff)
-{
- return mds_pack_posix_acl(inode, repmsg, repbody, repoff);
-}
-
-static int mds_getattr_internal(struct obd_device *obd, struct dentry *dentry,
- struct ptlrpc_request *req,
- struct mds_body *reqbody, int reply_off)
-{
- struct mds_body *body;
- struct inode *inode = dentry->d_inode;
- int rc = 0;
- ENTRY;
-
- if (inode == NULL)
- RETURN(-ENOENT);
-
- body = lustre_msg_buf(req->rq_repmsg, reply_off, sizeof(*body));
- LASSERT(body != NULL); /* caller prepped reply */
-
- mds_pack_inode2fid(&body->fid1, inode);
- body->flags = reqbody->flags; /* copy MDS_BFLAG_EXT_FLAGS if present */
- mds_pack_inode2body(body, inode);
- reply_off++;
-
- if ((S_ISREG(inode->i_mode) && (reqbody->valid & OBD_MD_FLEASIZE)) ||
- (S_ISDIR(inode->i_mode) && (reqbody->valid & OBD_MD_FLDIREA))) {
- rc = mds_pack_md(obd, req->rq_repmsg, reply_off, body,
- inode, 1);
-
- /* 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) {
- 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) {
- rc = inode->i_op->getxattr(&de, MDS_XATTR_NAME_ACL_ACCESS,
- NULL, 0);
-
- 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 = {0,};
- 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,
- 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_reply_state == NULL) {
- 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 = {0,};
- int rc = 0;
- ENTRY;
-
- OBD_COUNTER_INCREMENT(obd, getattr);
-
- body = lustre_swab_reqbuf(req, offset, sizeof(*body),
- lustre_swab_mds_body);
- if (body == NULL)
- RETURN(-EFAULT);
-
- rc = mds_init_ucred(&uc, req, offset);
- if (rc)
- GOTO(out_ucred, rc);
-
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
- de = mds_fid2dentry(mds, &body->fid1, NULL);
- if (IS_ERR(de)) {
- rc = req->rq_status = PTR_ERR(de);
- GOTO(out_pop, rc);
- }
-
- rc = mds_getattr_pack_msg(req, de->d_inode, offset);
- if (rc != 0) {
- CERROR("mds_getattr_pack_msg: %d\n", rc);
- GOTO(out_pop, rc);
- }
-
- req->rq_status = mds_getattr_internal(obd, de, req, body,
- REPLY_REC_OFF);
-
- l_dput(de);
- GOTO(out_pop, rc);
-out_pop:
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
-out_ucred:
- if (req->rq_reply_state == NULL) {
- int rc2 = lustre_pack_reply(req, 1, NULL, NULL);
- if (rc == 0)
- rc = rc2;
- req->rq_status = rc;
- }
- mds_exit_ucred(&uc, mds);
- return rc;
-}
-
-static int mds_obd_statfs(struct obd_device *obd, struct obd_statfs *osfs,
- __u64 max_age, __u32 flags)
-{
- int rc;
-
- spin_lock(&obd->obd_osfs_lock);
- rc = fsfilt_statfs(obd, obd->u.obt.obt_sb, max_age);
- if (rc == 0)
- memcpy(osfs, &obd->obd_osfs, sizeof(*osfs));
- spin_unlock(&obd->obd_osfs_lock);
-
- return rc;
-}
-
-static int mds_statfs(struct ptlrpc_request *req)
-{
- struct obd_device *obd = req->rq_export->exp_obd;
- int rc, size[2] = { sizeof(struct ptlrpc_body),
- sizeof(struct obd_statfs) };
- ENTRY;
-
- /* This will trigger a watchdog timeout */
- OBD_FAIL_TIMEOUT(OBD_FAIL_MDS_STATFS_LCW_SLEEP,
- (MDS_SERVICE_WATCHDOG_TIMEOUT / 1000) + 1);
- OBD_COUNTER_INCREMENT(obd, statfs);
-
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_STATFS_PACK))
- GOTO(out, rc = -ENOMEM);
- rc = lustre_pack_reply(req, 2, size, NULL);
- if (rc)
- GOTO(out, rc);
-
- /* We call this so that we can cache a bit - 1 jiffie worth */
- rc = mds_obd_statfs(obd, lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
- size[REPLY_REC_OFF]),
- cfs_time_current_64() - HZ, 0);
- if (rc) {
- CERROR("mds_obd_statfs failed: rc %d\n", rc);
- GOTO(out, rc);
- }
-
- EXIT;
-out:
- req->rq_status = rc;
- return 0;
-}
-
-static int mds_sync(struct ptlrpc_request *req, int offset)
-{
- struct obd_device *obd = req->rq_export->exp_obd;
- struct mds_obd *mds = &obd->u.mds;
- struct mds_body *body;
- int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
- ENTRY;
-
- body = lustre_swab_reqbuf(req, offset, sizeof(*body),
- lustre_swab_mds_body);
- if (body == NULL)
- GOTO(out, rc = -EFAULT);
-
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_SYNC_PACK))
- GOTO(out, rc = -ENOMEM);
- rc = lustre_pack_reply(req, 2, size, NULL);
- if (rc)
- GOTO(out, rc);
-
- rc = fsfilt_sync(obd, obd->u.obt.obt_sb);
- if (rc == 0 && body->fid1.id != 0) {
- struct dentry *de;
-
- de = mds_fid2dentry(mds, &body->fid1, NULL);
- if (IS_ERR(de))
- GOTO(out, rc = PTR_ERR(de));
-
- body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
- sizeof(*body));
- mds_pack_inode2fid(&body->fid1, de->d_inode);
- mds_pack_inode2body(body, de->d_inode);
-
- l_dput(de);
- }
- GOTO(out, rc);
-out:
- req->rq_status = rc;
- return 0;
-}
-
-/* mds_readpage does not take a DLM lock on the inode, because the client must
- * already have a PR lock.
- *
- * If we were to take another one here, a deadlock will result, if another
- * thread is already waiting for a PW lock. */
-static int mds_readpage(struct ptlrpc_request *req, int offset)
-{
- struct obd_device *obd = req->rq_export->exp_obd;
- struct mds_obd *mds = &obd->u.mds;
- struct vfsmount *mnt;
- struct dentry *de;
- struct file *file;
- struct mds_body *body, *repbody;
- struct lvfs_run_ctxt saved;
- int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*repbody) };
- struct lvfs_ucred uc = {0,};
- ENTRY;
-
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_READPAGE_PACK))
- RETURN(-ENOMEM);
- rc = lustre_pack_reply(req, 2, size, NULL);
- if (rc)
- GOTO(out, rc);
-
- body = lustre_swab_reqbuf(req, offset, sizeof(*body),
- lustre_swab_mds_body);
- if (body == NULL)
- GOTO (out, rc = -EFAULT);
-
- rc = mds_init_ucred(&uc, req, offset);
- if (rc)
- GOTO(out, rc);
-
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
- de = mds_fid2dentry(&obd->u.mds, &body->fid1, &mnt);
- if (IS_ERR(de))
- GOTO(out_pop, rc = PTR_ERR(de));
-
- CDEBUG(D_INODE, "ino %lu\n", de->d_inode->i_ino);
-
- file = dentry_open(de, mnt, O_RDONLY | O_LARGEFILE);
- /* note: in case of an error, dentry_open puts dentry */
- if (IS_ERR(file))
- GOTO(out_pop, rc = PTR_ERR(file));
-
- /* body->size is actually the offset -eeb */
- if ((body->size & (de->d_inode->i_sb->s_blocksize - 1)) != 0) {
- CERROR("offset "LPU64" not on a block boundary of %lu\n",
- body->size, de->d_inode->i_sb->s_blocksize);
- GOTO(out_file, rc = -EFAULT);
- }
-
- /* body->nlink is actually the #bytes to read -eeb */
- if (body->nlink & (de->d_inode->i_sb->s_blocksize - 1)) {
- CERROR("size %u is not multiple of blocksize %lu\n",
- body->nlink, de->d_inode->i_sb->s_blocksize);
- GOTO(out_file, rc = -EFAULT);
- }
-
- repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
- sizeof(*repbody));
- repbody->size = i_size_read(file->f_dentry->d_inode);
- repbody->valid = OBD_MD_FLSIZE;
-
- /* to make this asynchronous make sure that the handling function
- doesn't send a reply when this function completes. Instead a
- callback function would send the reply */
- /* body->size is actually the offset -eeb */
- rc = mds_sendpage(req, file, body->size, body->nlink);
-
-out_file:
- filp_close(file, 0);
-out_pop:
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
-out:
- mds_exit_ucred(&uc, mds);
- req->rq_status = rc;
- RETURN(0);
-}
-
-int mds_reint(struct ptlrpc_request *req, int offset,
- struct lustre_handle *lockh)
-{
- struct mds_update_record *rec; /* 116 bytes on the stack? no sir! */
- int rc;
-
- OBD_ALLOC(rec, sizeof(*rec));
- if (rec == NULL)
- RETURN(-ENOMEM);
-
- rc = mds_update_unpack(req, offset, rec);
- if (rc || OBD_FAIL_CHECK(OBD_FAIL_MDS_REINT_UNPACK)) {
- CERROR("invalid record\n");
- GOTO(out, req->rq_status = -EINVAL);
- }
-
- /* rc will be used to interrupt a for loop over multiple records */
- rc = mds_reint_rec(rec, offset, req, lockh);
- out:
- OBD_FREE(rec, sizeof(*rec));
- return rc;
-}
-
-int mds_filter_recovery_request(struct ptlrpc_request *req,
- struct obd_device *obd, int *process)
-{
- switch (lustre_msg_get_opc(req->rq_reqmsg)) {
- case MDS_CONNECT: /* This will never get here, but for completeness. */
- case OST_CONNECT: /* This will never get here, but for completeness. */
- case MDS_DISCONNECT:
- case OST_DISCONNECT:
- *process = 1;
- RETURN(0);
-
- case MDS_CLOSE:
- case MDS_DONE_WRITING:
- case MDS_SYNC: /* used in unmounting */
- case OBD_PING:
- case MDS_REINT:
- case SEQ_QUERY:
- case FLD_QUERY:
- case LDLM_ENQUEUE:
- *process = target_queue_recovery_request(req, obd);
- RETURN(0);
-
- default:
- DEBUG_REQ(D_ERROR, req, "not permitted during recovery");
- *process = -EAGAIN;
- RETURN(0);
- }
-}
-EXPORT_SYMBOL(mds_filter_recovery_request);
-
-static char *reint_names[] = {
- [REINT_SETATTR] "setattr",
- [REINT_CREATE] "create",
- [REINT_LINK] "link",
- [REINT_UNLINK] "unlink",
- [REINT_RENAME] "rename",
- [REINT_OPEN] "open",
-};
-
-static int mds_set_info_rpc(struct obd_export *exp, struct ptlrpc_request *req)
-{
- void *key, *val;
- int keylen, vallen, rc = 0;
- ENTRY;
-
- key = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, 1);
- if (key == NULL) {
- DEBUG_REQ(D_HA, req, "no set_info key");
- RETURN(-EFAULT);
- }
- keylen = lustre_msg_buflen(req->rq_reqmsg, REQ_REC_OFF);
-
- val = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 1, 0);
- vallen = lustre_msg_buflen(req->rq_reqmsg, REQ_REC_OFF + 1);
-
- rc = lustre_pack_reply(req, 1, NULL, NULL);
- if (rc)
- RETURN(rc);
-
- lustre_msg_set_status(req->rq_repmsg, 0);
-
- if (KEY_IS("read-only")) {
- if (val == NULL || vallen < sizeof(__u32)) {
- DEBUG_REQ(D_HA, req, "no set_info val");
- RETURN(-EFAULT);
- }
-
- if (*(__u32 *)val)
- exp->exp_connect_flags |= OBD_CONNECT_RDONLY;
- else
- exp->exp_connect_flags &= ~OBD_CONNECT_RDONLY;
- } else {
- RETURN(-EINVAL);
- }
-
- RETURN(0);
-}
-
-static int mds_handle_quotacheck(struct ptlrpc_request *req)
-{
- struct obd_quotactl *oqctl;
- int rc;
- ENTRY;
-
- oqctl = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*oqctl),
- lustre_swab_obd_quotactl);
- if (oqctl == NULL)
- RETURN(-EPROTO);
-
- rc = lustre_pack_reply(req, 1, NULL, NULL);
- if (rc)
- RETURN(rc);
-
- req->rq_status = obd_quotacheck(req->rq_export, oqctl);
- RETURN(0);
-}
-
-static int mds_handle_quotactl(struct ptlrpc_request *req)
-{
- struct obd_quotactl *oqctl, *repoqc;
- int rc, size[2] = { sizeof(struct ptlrpc_body), sizeof(*repoqc) };
- ENTRY;
-
- oqctl = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*oqctl),
- lustre_swab_obd_quotactl);
- if (oqctl == NULL)
- RETURN(-EPROTO);
-
- rc = lustre_pack_reply(req, 2, size, NULL);
- if (rc)
- RETURN(rc);
-
- repoqc = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*repoqc));
-
- req->rq_status = obd_quotactl(req->rq_export, oqctl);
- *repoqc = *oqctl;
- RETURN(0);
-}
-
-int mds_msg_check_version(struct lustre_msg *msg)
-{
- int rc;
-
- switch (lustre_msg_get_opc(msg)) {
- case MDS_CONNECT:
- case MDS_DISCONNECT:
- case OBD_PING:
- case SEC_CTX_INIT:
- case SEC_CTX_INIT_CONT:
- case SEC_CTX_FINI:
- rc = lustre_msg_check_version(msg, LUSTRE_OBD_VERSION);
- if (rc)
- CERROR("bad opc %u version %08x, expecting %08x\n",
- lustre_msg_get_opc(msg),
- lustre_msg_get_version(msg),
- LUSTRE_OBD_VERSION);
- break;
- case MDS_GETSTATUS:
- case MDS_GETATTR:
- case MDS_GETATTR_NAME:
- case MDS_STATFS:
- case MDS_READPAGE:
- case MDS_WRITEPAGE:
- case MDS_IS_SUBDIR:
- case MDS_REINT:
- case MDS_CLOSE:
- case MDS_DONE_WRITING:
- case MDS_PIN:
- case MDS_SYNC:
- case MDS_GETXATTR:
- case MDS_SETXATTR:
- case MDS_SET_INFO:
- case MDS_QUOTACHECK:
- case MDS_QUOTACTL:
- case QUOTA_DQACQ:
- case QUOTA_DQREL:
- case SEQ_QUERY:
- case FLD_QUERY:
- rc = lustre_msg_check_version(msg, LUSTRE_MDS_VERSION);
- if (rc)
- CERROR("bad opc %u version %08x, expecting %08x\n",
- lustre_msg_get_opc(msg),
- lustre_msg_get_version(msg),
- LUSTRE_MDS_VERSION);
- break;
- case LDLM_ENQUEUE:
- case LDLM_CONVERT:
- case LDLM_BL_CALLBACK:
- case LDLM_CP_CALLBACK:
- rc = lustre_msg_check_version(msg, LUSTRE_DLM_VERSION);
- if (rc)
- CERROR("bad opc %u version %08x, expecting %08x\n",
- lustre_msg_get_opc(msg),
- lustre_msg_get_version(msg),
- LUSTRE_DLM_VERSION);
- break;
- case OBD_LOG_CANCEL:
- case LLOG_ORIGIN_HANDLE_CREATE:
- case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
- case LLOG_ORIGIN_HANDLE_READ_HEADER:
- case LLOG_ORIGIN_HANDLE_CLOSE:
- case LLOG_ORIGIN_HANDLE_DESTROY:
- case LLOG_ORIGIN_HANDLE_PREV_BLOCK:
- case LLOG_CATINFO:
- rc = lustre_msg_check_version(msg, LUSTRE_LOG_VERSION);
- if (rc)
- CERROR("bad opc %u version %08x, expecting %08x\n",
- lustre_msg_get_opc(msg),
- lustre_msg_get_version(msg),
- LUSTRE_LOG_VERSION);
- break;
- default:
- CERROR("MDS unknown opcode %d\n", lustre_msg_get_opc(msg));
- rc = -ENOTSUPP;
- }
- return rc;
-}
-EXPORT_SYMBOL(mds_msg_check_version);
-
-int mds_handle(struct ptlrpc_request *req)
-{
- int should_process, fail = OBD_FAIL_MDS_ALL_REPLY_NET;
- int rc;
- struct mds_obd *mds = NULL; /* quell gcc overwarning */
- struct obd_device *obd = NULL;
- ENTRY;
-
- if (OBD_FAIL_CHECK_ORSET(OBD_FAIL_MDS_ALL_REQUEST_NET, OBD_FAIL_ONCE))
- RETURN(0);
-
- LASSERT(current->journal_info == NULL);
-
- rc = mds_msg_check_version(req->rq_reqmsg);
- if (rc) {
- CERROR("MDS drop mal-formed request\n");
- RETURN(rc);
- }
-
- /* XXX identical to OST */
- if (lustre_msg_get_opc(req->rq_reqmsg) != MDS_CONNECT) {
- struct mds_export_data *med;
- int recovering;
-
- if (req->rq_export == NULL) {
- CERROR("operation %d on unconnected MDS from %s\n",
- lustre_msg_get_opc(req->rq_reqmsg),
- libcfs_id2str(req->rq_peer));
- req->rq_status = -ENOTCONN;
- GOTO(out, rc = -ENOTCONN);
- }
-
- med = &req->rq_export->exp_mds_data;
- obd = req->rq_export->exp_obd;
- mds = mds_req2mds(req);
-
- /* sanity check: if the xid matches, the request must
- * be marked as a resent or replayed */
- if (req->rq_xid == le64_to_cpu(med->med_mcd->mcd_last_xid) ||
- req->rq_xid == le64_to_cpu(med->med_mcd->mcd_last_close_xid))
- if (!(lustre_msg_get_flags(req->rq_reqmsg) &
- (MSG_RESENT | MSG_REPLAY))) {
- CERROR("rq_xid "LPU64" matches last_xid, "
- "expected RESENT flag\n",
- req->rq_xid);
- req->rq_status = -ENOTCONN;
- GOTO(out, rc = -EFAULT);
- }
- /* else: note the opposite is not always true; a
- * RESENT req after a failover will usually not match
- * the last_xid, since it was likely never
- * committed. A REPLAYed request will almost never
- * match the last xid, however it could for a
- * committed, but still retained, open. */
-
- /* Check for aborted recovery. */
- spin_lock_bh(&obd->obd_processing_task_lock);
- recovering = obd->obd_recovering;
- spin_unlock_bh(&obd->obd_processing_task_lock);
- if (recovering) {
- rc = mds_filter_recovery_request(req, obd,
- &should_process);
- if (rc || !should_process)
- RETURN(rc);
- else if (should_process < 0) {
- req->rq_status = should_process;
- rc = ptlrpc_error(req);
- RETURN(rc);
- }
- }
- }
-
- switch (lustre_msg_get_opc(req->rq_reqmsg)) {
- case MDS_CONNECT:
- DEBUG_REQ(D_INODE, req, "connect");
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_CONNECT_NET))
- RETURN(0);
- rc = target_handle_connect(req);
- if (!rc) {
- /* Now that we have an export, set mds. */
- /*
- * XXX nikita: these assignments are useless: mds is
- * never used below, and obd is only used for
- * MSG_LAST_REPLAY case, which never happens for
- * MDS_CONNECT.
- */
- obd = req->rq_export->exp_obd;
- mds = mds_req2mds(req);
- }
- break;
-
- case MDS_DISCONNECT:
- DEBUG_REQ(D_INODE, req, "disconnect");
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_DISCONNECT_NET))
- RETURN(0);
- rc = target_handle_disconnect(req);
- req->rq_status = rc; /* superfluous? */
- break;
-
- case MDS_GETSTATUS:
- DEBUG_REQ(D_INODE, req, "getstatus");
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GETSTATUS_NET))
- RETURN(0);
- rc = mds_getstatus(req);
- break;
-
- case MDS_GETATTR:
- DEBUG_REQ(D_INODE, req, "getattr");
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GETATTR_NET))
- RETURN(0);
- rc = mds_getattr(req, REQ_REC_OFF);
- break;
-
- case MDS_SETXATTR:
- DEBUG_REQ(D_INODE, req, "setxattr");
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_SETXATTR_NET))
- RETURN(0);
- rc = mds_setxattr(req);
- break;
-
- case MDS_GETXATTR:
- DEBUG_REQ(D_INODE, req, "getxattr");
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GETXATTR_NET))
- RETURN(0);
- rc = mds_getxattr(req);
- break;
-
- case MDS_GETATTR_NAME: {
- struct lustre_handle lockh = { 0 };
- DEBUG_REQ(D_INODE, req, "getattr_name");
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GETATTR_NAME_NET))
- RETURN(0);
-
- /* If this request gets a reconstructed reply, we won't be
- * acquiring any new locks in mds_getattr_lock, so we don't
- * want to cancel.
- */
- rc = mds_getattr_lock(req, REQ_REC_OFF, MDS_INODELOCK_UPDATE,
- &lockh);
- /* this non-intent call (from an ioctl) is special */
- req->rq_status = rc;
- if (rc == 0 && lustre_handle_is_used(&lockh))
- ldlm_lock_decref(&lockh, LCK_CR);
- break;
- }
- case MDS_STATFS:
- DEBUG_REQ(D_INODE, req, "statfs");
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_STATFS_NET))
- RETURN(0);
- rc = mds_statfs(req);
- break;
-
- case MDS_READPAGE:
- DEBUG_REQ(D_INODE, req, "readpage");
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_READPAGE_NET))
- RETURN(0);
- rc = mds_readpage(req, REQ_REC_OFF);
-
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_SENDPAGE)) {
- RETURN(0);
- }
-
- break;
-
- case MDS_REINT: {
- __u32 *opcp = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF,
- sizeof(*opcp));
- __u32 opc;
- int op = 0;
- int size[4] = { sizeof(struct ptlrpc_body),
- sizeof(struct mds_body),
- mds->mds_max_mdsize,
- mds->mds_max_cookiesize };
- int bufcount;
-
- /* NB only peek inside req now; mds_reint() will swab it */
- if (opcp == NULL) {
- CERROR ("Can't inspect opcode\n");
- rc = -EINVAL;
- break;
- }
- opc = *opcp;
- if (lustre_msg_swabbed(req->rq_reqmsg))
- __swab32s(&opc);
-
- DEBUG_REQ(D_INODE, req, "reint %d (%s)", opc,
- (opc < sizeof(reint_names) / sizeof(reint_names[0]) ||
- reint_names[opc] == NULL) ? reint_names[opc] :
- "unknown opcode");
- switch (opc) {
- case REINT_CREATE:
- op = PTLRPC_LAST_CNTR + MDS_REINT_CREATE;
- break;
- case REINT_LINK:
- op = PTLRPC_LAST_CNTR + MDS_REINT_LINK;
- break;
- case REINT_OPEN:
- op = PTLRPC_LAST_CNTR + MDS_REINT_OPEN;
- break;
- case REINT_SETATTR:
- op = PTLRPC_LAST_CNTR + MDS_REINT_SETATTR;
- break;
- case REINT_RENAME:
- op = PTLRPC_LAST_CNTR + MDS_REINT_RENAME;
- break;
- case REINT_UNLINK:
- op = PTLRPC_LAST_CNTR + MDS_REINT_UNLINK;
- break;
- default:
- op = 0;
- break;
- }
-
- if (op && req->rq_rqbd->rqbd_service->srv_stats)
- lprocfs_counter_incr(
- req->rq_rqbd->rqbd_service->srv_stats, op);
-
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_REINT_NET))
- RETURN(0);
-
- if (opc == REINT_UNLINK || opc == REINT_RENAME)
- bufcount = 4;
- else if (opc == REINT_OPEN)
- bufcount = 3;
- else
- bufcount = 2;
-
- rc = lustre_pack_reply(req, bufcount, size, NULL);
- if (rc)
- break;
-
- rc = mds_reint(req, REQ_REC_OFF, NULL);
- fail = OBD_FAIL_MDS_REINT_NET_REP;
- break;
- }
-
- case MDS_CLOSE:
- DEBUG_REQ(D_INODE, req, "close");
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_CLOSE_NET))
- RETURN(0);
- rc = mds_close(req, REQ_REC_OFF);
- fail = OBD_FAIL_MDS_CLOSE_NET_REP;
- break;
-
- case MDS_DONE_WRITING:
- DEBUG_REQ(D_INODE, req, "done_writing");
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_DONE_WRITING_NET))
- RETURN(0);
- rc = mds_done_writing(req, REQ_REC_OFF);
- break;
-
- case MDS_PIN:
- DEBUG_REQ(D_INODE, req, "pin");
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_PIN_NET))
- RETURN(0);
- rc = mds_pin(req, REQ_REC_OFF);
- break;
-
- case MDS_SYNC:
- DEBUG_REQ(D_INODE, req, "sync");
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_SYNC_NET))
- RETURN(0);
- rc = mds_sync(req, REQ_REC_OFF);
- break;
-
- case MDS_SET_INFO:
- DEBUG_REQ(D_INODE, req, "set_info");
- rc = mds_set_info_rpc(req->rq_export, req);
- break;
-
- case MDS_QUOTACHECK:
- DEBUG_REQ(D_INODE, req, "quotacheck");
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_QUOTACHECK_NET))
- RETURN(0);
- rc = mds_handle_quotacheck(req);
- break;
-
- case MDS_QUOTACTL:
- DEBUG_REQ(D_INODE, req, "quotactl");
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_QUOTACTL_NET))
- RETURN(0);
- rc = mds_handle_quotactl(req);
- break;
-
- case OBD_PING:
- DEBUG_REQ(D_INODE, req, "ping");
- rc = target_handle_ping(req);
- break;
-
- case OBD_LOG_CANCEL:
- CDEBUG(D_INODE, "log cancel\n");
- if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOG_CANCEL_NET))
- RETURN(0);
- rc = -ENOTSUPP; /* la la la */
- break;
-
- case LDLM_ENQUEUE:
- DEBUG_REQ(D_INODE, req, "enqueue");
- if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_ENQUEUE))
- RETURN(0);
- rc = ldlm_handle_enqueue(req, ldlm_server_completion_ast,
- ldlm_server_blocking_ast, NULL);
- fail = OBD_FAIL_LDLM_REPLY;
- break;
- case LDLM_CONVERT:
- DEBUG_REQ(D_INODE, req, "convert");
- if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_CONVERT))
- RETURN(0);
- rc = ldlm_handle_convert(req);
- break;
- case LDLM_BL_CALLBACK:
- case LDLM_CP_CALLBACK:
- DEBUG_REQ(D_INODE, req, "callback");
- CERROR("callbacks should not happen on MDS\n");
- LBUG();
- if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK))
- RETURN(0);
- break;
- case LLOG_ORIGIN_HANDLE_CREATE:
- DEBUG_REQ(D_INODE, req, "llog_init");
- if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET))
- RETURN(0);
- rc = llog_origin_handle_create(req);
- break;
- case LLOG_ORIGIN_HANDLE_DESTROY:
- DEBUG_REQ(D_INODE, req, "llog_init");
- if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET))
- RETURN(0);
- rc = llog_origin_handle_destroy(req);
- break;
- case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
- DEBUG_REQ(D_INODE, req, "llog next block");
- if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET))
- RETURN(0);
- rc = llog_origin_handle_next_block(req);
- break;
- case LLOG_ORIGIN_HANDLE_PREV_BLOCK:
- DEBUG_REQ(D_INODE, req, "llog prev block");
- if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET))
- RETURN(0);
- rc = llog_origin_handle_prev_block(req);
- break;
- case LLOG_ORIGIN_HANDLE_READ_HEADER:
- DEBUG_REQ(D_INODE, req, "llog read header");
- if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET))
- RETURN(0);
- rc = llog_origin_handle_read_header(req);
- break;
- case LLOG_ORIGIN_HANDLE_CLOSE:
- DEBUG_REQ(D_INODE, req, "llog close");
- if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET))
- RETURN(0);
- rc = llog_origin_handle_close(req);
- break;
- case LLOG_CATINFO:
- DEBUG_REQ(D_INODE, req, "llog catinfo");
- if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET))
- RETURN(0);
- rc = llog_catinfo(req);
- break;
- default:
- req->rq_status = -ENOTSUPP;
- rc = ptlrpc_error(req);
- RETURN(rc);
- }
-
- LASSERT(current->journal_info == NULL);
-
- /* If we're DISCONNECTing, the mds_export_data is already freed */
- if (!rc && lustre_msg_get_opc(req->rq_reqmsg) != MDS_DISCONNECT) {
- struct mds_export_data *med = &req->rq_export->exp_mds_data;
-
- /* I don't think last_xid is used for anyway, so I'm not sure
- if we need to care about last_close_xid here.*/
- lustre_msg_set_last_xid(req->rq_repmsg,
- le64_to_cpu(med->med_mcd->mcd_last_xid));
-
- target_committed_to_req(req);
- }
-
- EXIT;
- out:
-
- target_send_reply(req, rc, fail);
- return 0;
-}
-
-/* Update the server data on disk. This stores the new mount_count and
- * also the last_rcvd value to disk. If we don't have a clean shutdown,
- * then the server last_rcvd value may be less than that of the clients.
- * This will alert us that we may need to do client recovery.
- *
- * Also assumes for mds_last_transno that we are not modifying it (no locking).
- */
-int mds_update_server_data(struct obd_device *obd, int force_sync)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct lr_server_data *lsd = mds->mds_server_data;
- struct file *filp = mds->mds_rcvd_filp;
- struct lvfs_run_ctxt saved;
- loff_t off = 0;
- int rc;
- ENTRY;