⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mds_open.c

📁 lustre 1.6.5 source code
💻 C
📖 第 1 页 / 共 5 页
字号:
                /* We didn't find the correct inode on disk either, so we                 * need to re-create it via a regular replay. */                if (!(rec->ur_flags & MDS_OPEN_CREAT)) {                        DEBUG_REQ(D_ERROR, req,"OPEN_CREAT not in open replay");                        RETURN(-EFAULT);                }        } else if (rec->ur_fid2->id) {                DEBUG_REQ(D_ERROR, req, "fid2 "LPU64"/%u on open non-replay",                          rec->ur_fid2->id, rec->ur_fid2->generation);                RETURN(-EFAULT);        }        /* If we got here, we must be called via intent */        LASSERT(offset == DLM_INTENT_REC_OFF);        med = &req->rq_export->exp_mds_data;        if (OBD_FAIL_CHECK(OBD_FAIL_MDS_OPEN_PACK)) {                CERROR("test case OBD_FAIL_MDS_OPEN_PACK\n");                RETURN(-ENOMEM);        }        /* Step 1: Find and lock the parent */        if (rec->ur_flags & (MDS_OPEN_CREAT | MDS_OPEN_JOIN_FILE))                parent_mode = LCK_EX;        dparent = mds_fid2locked_dentry(obd, rec->ur_fid1, NULL, parent_mode,                                        &parent_lockh, rec->ur_name,                                        rec->ur_namelen - 1,                                        MDS_INODELOCK_UPDATE);        if (IS_ERR(dparent)) {                rc = PTR_ERR(dparent);                if (rc != -ENOENT) {                        CERROR("parent "LPU64"/%u lookup error %d\n",                               rec->ur_fid1->id, rec->ur_fid1->generation, rc);                } else {                        /* Just cannot find parent - make it look like                         * usual negative lookup to avoid extra MDS RPC */                        intent_set_disposition(rep, DISP_LOOKUP_EXECD);                        intent_set_disposition(rep, DISP_LOOKUP_NEG);                }                GOTO(cleanup, rc);        }        LASSERT(dparent->d_inode != NULL);        cleanup_phase = 1; /* parent dentry and lock */        if (rec->ur_flags & MDS_OPEN_JOIN_FILE) {                dchild = dget(dparent);                cleanup_phase = 2; /* child dentry */                acc_mode = accmode(dchild->d_inode, rec->ur_flags);                GOTO(found_child, rc);        }        /* Step 2: Lookup the child */              if (!(lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) &&            (rec->ur_flags & MDS_OPEN_LOCK) && (rec->ur_namelen == 1)) {                /* hack for nfsd with no_subtree_check, it will use anon                 * dentry w/o filename to open the file. the anon dentry's                 * parent was set to itself, so rec->ur_fid1 is the file.                 * And in MDC it cannot derive the dentry's parent dentry,                 * hence the file's name, so we hack here in MDS,                  * refer to bug 13030. */                dchild = mds_fid2dentry(mds, rec->ur_fid1, NULL);        } else {                dchild = ll_lookup_one_len(rec->ur_name, dparent,                                           rec->ur_namelen - 1);        }        if (IS_ERR(dchild)) {                rc = PTR_ERR(dchild);                dchild = NULL; /* don't confuse mds_finish_transno() below */                GOTO(cleanup, rc);        }        cleanup_phase = 2; /* child dentry */        intent_set_disposition(rep, DISP_LOOKUP_EXECD);        if (dchild->d_inode)                intent_set_disposition(rep, DISP_LOOKUP_POS);        else                intent_set_disposition(rep, DISP_LOOKUP_NEG);        /*Step 3: If the child was negative, and we're supposed to, create it.*/        if (dchild->d_inode == NULL) {                unsigned long ino = rec->ur_fid2->id;                struct iattr iattr;                struct inode *inode;                if (!(rec->ur_flags & MDS_OPEN_CREAT)) {                        /* It's negative and we weren't supposed to create it */                        GOTO(cleanup, rc = -ENOENT);                }                if (req->rq_export->exp_connect_flags & OBD_CONNECT_RDONLY)                        GOTO(cleanup, rc = -EROFS);                if (dparent->d_inode->i_mode & S_ISGID)                        gid = dparent->d_inode->i_gid;                else                        gid = current->fsgid;                /* we try to get enough quota to write here, and let ldiskfs                 * decide if it is out of quota or not b=14783 */                lquota_chkquota(mds_quota_interface_ref, obd,                                current->fsuid, gid, 1, &rec_pending);                intent_set_disposition(rep, DISP_OPEN_CREATE);                handle = fsfilt_start(obd, dparent->d_inode, FSFILT_OP_CREATE,                                      NULL);                if (IS_ERR(handle)) {                        rc = PTR_ERR(handle);                        handle = NULL;                        GOTO(cleanup, rc);                }                dchild->d_fsdata = (void *) &dp;                dp.ldp_ptr = req;                dp.ldp_inum = ino;                rc = ll_vfs_create(dparent->d_inode, dchild, rec->ur_mode,NULL);                if (dchild->d_fsdata == (void *)(unsigned long)ino)                        dchild->d_fsdata = NULL;                if (rc) {                        CDEBUG(D_INODE, "error during create: %d\n", rc);                        GOTO(cleanup, rc);                }                inode = dchild->d_inode;                if (ino) {                        LASSERT(ino == inode->i_ino);                        /* Written as part of setattr */                        inode->i_generation = rec->ur_fid2->generation;                        CDEBUG(D_HA, "recreated ino %lu with gen %u\n",                               inode->i_ino, inode->i_generation);                }                created = 1;                LTIME_S(iattr.ia_atime) = rec->ur_time;                LTIME_S(iattr.ia_ctime) = rec->ur_time;                LTIME_S(iattr.ia_mtime) = rec->ur_time;                iattr.ia_uid = current->fsuid;  /* set by push_ctxt already */                iattr.ia_gid = gid;                iattr.ia_valid = ATTR_UID | ATTR_GID | ATTR_ATIME |                        ATTR_MTIME | ATTR_CTIME;                rc = fsfilt_setattr(obd, dchild, handle, &iattr, 0);                if (rc)                        CERROR("error on child setattr: rc = %d\n", rc);                iattr.ia_valid = ATTR_MTIME | ATTR_CTIME;                rc = fsfilt_setattr(obd, dparent, handle, &iattr, 0);                if (rc)                        CERROR("error on parent setattr: rc = %d\n", rc);                rc = fsfilt_commit(obd, dchild->d_inode, handle, 0);                handle = NULL;                acc_mode = 0;           /* Don't check for permissions */        } else {                acc_mode = accmode(dchild->d_inode, rec->ur_flags);        }        LASSERTF(!mds_inode_is_orphan(dchild->d_inode),                 "dchild %.*s (%p) inode %p/%lu/%u\n", dchild->d_name.len,                 dchild->d_name.name, dchild, dchild->d_inode,                 dchild->d_inode->i_ino, dchild->d_inode->i_generation);found_child:        mds_pack_inode2fid(&body->fid1, dchild->d_inode);        mds_pack_inode2body(body, dchild->d_inode);        if (S_ISREG(dchild->d_inode->i_mode)) {                /* Check permissions etc */                rc = ll_permission(dchild->d_inode, acc_mode, NULL);                if (rc != 0)                        GOTO(cleanup, rc);                if ((req->rq_export->exp_connect_flags & OBD_CONNECT_RDONLY) &&                    (acc_mode & MAY_WRITE))                        GOTO(cleanup, rc = -EROFS);                /* An append-only file must be opened in append mode for                 * writing */                if (IS_APPEND(dchild->d_inode) && (acc_mode & MAY_WRITE) != 0 &&                    ((rec->ur_flags & MDS_OPEN_APPEND) == 0 ||                     (rec->ur_flags & MDS_OPEN_TRUNC) != 0))                        GOTO(cleanup, rc = -EPERM);        }        if (!created && (rec->ur_flags & MDS_OPEN_CREAT) &&            (rec->ur_flags & MDS_OPEN_EXCL)) {                /* File already exists, we didn't just create it, and we                 * were passed O_EXCL; err-or. */                GOTO(cleanup, rc = -EEXIST); // returns a lock to the client        }        /* if we are following a symlink, don't open */        if (S_ISLNK(dchild->d_inode->i_mode))                GOTO(cleanup_no_trans, rc = 0);        if (S_ISDIR(dchild->d_inode->i_mode)) {                if (rec->ur_flags & MDS_OPEN_CREAT ||                    rec->ur_flags & FMODE_WRITE) {                        /* we are trying to create or write a exist dir */                        GOTO(cleanup, rc = -EISDIR);                }                if (rec->ur_flags & MDS_FMODE_EXEC) {                        /* we are trying to exec a directory */                        GOTO(cleanup, rc = -EACCES);                }                if (ll_permission(dchild->d_inode, acc_mode, NULL)) {                        intent_set_disposition(rep, DISP_OPEN_OPEN);                        GOTO(cleanup, rc = -EACCES);                }        } else if (rec->ur_flags & MDS_OPEN_DIRECTORY) {                GOTO(cleanup, rc = -ENOTDIR);        }        if (OBD_FAIL_CHECK(OBD_FAIL_MDS_OPEN_CREATE)) {                obd_fail_loc = OBD_FAIL_LDLM_REPLY | OBD_FAIL_ONCE;                GOTO(cleanup, rc = -EAGAIN);        }        /* Obtain OPEN lock as well */        policy.l_inodebits.bits |= MDS_INODELOCK_OPEN;        /* We cannot use acc_mode here, because it is zeroed in case of           creating a file, so we get wrong lockmode */        if (rec->ur_flags & FMODE_WRITE)                child_mode = LCK_CW;        else if (rec->ur_flags & MDS_FMODE_EXEC)                child_mode = LCK_PR;        else                child_mode = LCK_CR;        if (!(lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) &&              (rec->ur_flags & MDS_OPEN_LOCK)) {                /* In case of replay we do not get a lock assuming that the                   caller has it already */                child_res_id.name[0] = dchild->d_inode->i_ino;                child_res_id.name[1] = dchild->d_inode->i_generation;                rc = ldlm_cli_enqueue_local(obd->obd_namespace, &child_res_id,                                            LDLM_IBITS, &policy, child_mode,                                             &lock_flags, ldlm_blocking_ast,                                             ldlm_completion_ast, NULL, NULL,                                            0, NULL, child_lockh);                if (rc != ELDLM_OK)                        GOTO(cleanup, rc);                /* Let mds_intent_policy know that we have a lock to return */                intent_set_disposition(rep, DISP_OPEN_LOCK);                cleanup_phase = 3;        }        if (!S_ISREG(dchild->d_inode->i_mode) &&            !S_ISDIR(dchild->d_inode->i_mode) &&            (req->rq_export->exp_connect_flags & OBD_CONNECT_NODEVOH)) {                /* If client supports this, do not return open handle for                 * special device nodes */                GOTO(cleanup_no_trans, rc = 0);        }        /* Step 5: mds_open it */        rc = mds_finish_open(req, dchild, body, rec->ur_flags, &handle, rec,                             rep, &parent_lockh);        GOTO(cleanup, rc); cleanup:        rc = mds_finish_transno(mds, dchild ? dchild->d_inode : NULL, handle,                                req, rc, rep ? rep->lock_policy_res1 : 0, 0); cleanup_no_trans:        if (rec_pending)                lquota_pending_commit(mds_quota_interface_ref, obd,                                      current->fsuid, gid, 1);        switch (cleanup_phase) {        case 3:                if (rc)                        /* It is safe to leave IT_OPEN_LOCK set, if rc is not 0,                         * mds_intent_policy won't try to return any locks */                        ldlm_lock_decref(child_lockh, child_mode);        case 2:                if (rc && created) {                        int err = vfs_unlink(dparent->d_inode, dchild);                        if (err) {                                CERROR("unlink(%.*s) in error path: %d\n",                                       dchild->d_name.len, dchild->d_name.name,                                       err);                        }                } else if (created) {                        mds_lock_new_child(obd, dchild->d_inode, NULL);                        /* save uid/gid for quota acquire/release */                        qpids[USRQUOTA] = dparent->d_inode->i_uid;                        qpids[GRPQUOTA] = dparent->d_inode->i_gid;                }                l_dput(dchild);        case 1:                if (dparent == NULL)                        break;                l_dput(dparent);                if (rc)                        ldlm_lock_decref(&parent_lockh, parent_mode);                else                        ptlrpc_save_lock(req, &parent_lockh, parent_mode);        }        /* trigger dqacq on the owner of child and parent */        lquota_adjust(mds_quota_interface_ref, obd, qcids, qpids, rc,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -