📄 namei.c
字号:
it = ll_convert_intent(&nd->intent.open, nd->flags); if (IS_ERR(it)) RETURN((struct dentry *)it); } de = ll_lookup_it(parent, dentry, it, nd->flags); if (de) dentry = de; if ((nd->flags & LOOKUP_OPEN) && !IS_ERR(dentry)) { /* Open */ if (dentry->d_inode && it_disposition(it, DISP_OPEN_OPEN)) { /* nocreate */#ifdef HAVE_FILE_IN_STRUCT_INTENT if (S_ISFIFO(dentry->d_inode->i_mode)) { // We cannot call open here as it would // deadlock. ptlrpc_req_finished( (struct ptlrpc_request *) it->d.lustre.it_data); } else { struct file *filp; nd->intent.open.file->private_data = it; filp =lookup_instantiate_filp(nd,dentry, NULL);#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))/* 2.6.1[456] have a bug in open_namei() that forgets to check * nd->intent.open.file for error, so we need to return it as lookup's result * instead */ if (IS_ERR(filp)) { if (de) dput(de); de = (struct dentry *) filp; }#endif }#else /* HAVE_FILE_IN_STRUCT_INTENT */ /* Release open handle as we have no way to * pass it to ll_file_open */ ll_release_openhandle(dentry, it);#endif /* HAVE_FILE_IN_STRUCT_INTENT */ } else if (it_disposition(it, DISP_OPEN_CREATE)) { // XXX This can only reliably work on assumption // that there are NO hashed negative dentries. ll_d2d(dentry)->lld_it = it; it = NULL; /* Will be freed in ll_create_nd */ /* We absolutely depend on ll_create_nd to be * called to not leak this intent and possible * data attached to it */ } } if (it) { ll_intent_release(it); OBD_FREE(it, sizeof(*it)); } } else { de = ll_lookup_it(parent, dentry, NULL, 0); } RETURN(de);}#endif#endif/* We depend on "mode" being set with the proper file type/umask by now */static struct inode *ll_create_node(struct inode *dir, const char *name, int namelen, const void *data, int datalen, int mode, __u64 extra, struct lookup_intent *it){ struct inode *inode = NULL; struct ptlrpc_request *request = NULL; struct ll_sb_info *sbi = ll_i2sbi(dir); int rc; ENTRY; LASSERT(it && it->d.lustre.it_disposition); LASSERT(it_disposition(it, DISP_ENQ_CREATE_REF)); request = it->d.lustre.it_data; it_clear_disposition(it, DISP_ENQ_CREATE_REF); rc = ll_prep_inode(sbi->ll_osc_exp, &inode, request, DLM_REPLY_REC_OFF, dir->i_sb); if (rc) GOTO(out, inode = ERR_PTR(rc)); LASSERT(list_empty(&inode->i_dentry)); /* We asked for a lock on the directory, but were granted a * lock on the inode. Since we finally have an inode pointer, * stuff it in the lock. */ CDEBUG(D_DLMTRACE, "setting l_ast_data to inode %p (%lu/%u)\n", inode, inode->i_ino, inode->i_generation); mdc_set_lock_data(&it->d.lustre.it_lock_handle, inode); EXIT; out: ptlrpc_req_finished(request); return inode;}/* * By the time this is called, we already have created the directory cache * entry for the new file, but it is so far negative - it has no inode. * * We defer creating the OBD object(s) until open, to keep the intent and * non-intent code paths similar, and also because we do not have the MDS * inode number before calling ll_create_node() (which is needed for LOV), * so we would need to do yet another RPC to the MDS to store the LOV EA * data on the MDS. If needed, we would pass the PACKED lmm as data and * lmm_size in datalen (the MDS still has code which will handle that). * * If the create succeeds, we fill in the inode information * with d_instantiate(). */static int ll_create_it(struct inode *dir, struct dentry *dentry, int mode, struct lookup_intent *it){ struct inode *inode; struct ptlrpc_request *request = it->d.lustre.it_data; int rc = 0; ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),intent=%s\n", dentry->d_name.len, dentry->d_name.name, dir->i_ino, dir->i_generation, dir, LL_IT2STR(it)); rc = it_open_error(DISP_OPEN_CREATE, it); if (rc) RETURN(rc); mdc_store_inode_generation(request, DLM_INTENT_REC_OFF, DLM_REPLY_REC_OFF); inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len, NULL, 0, mode, 0, it); if (IS_ERR(inode)) { RETURN(PTR_ERR(inode)); } d_instantiate(dentry, inode); /* Negative dentry may be unhashed if parent does not have UPDATE lock, * but some callers, e.g. do_coredump, expect dentry to be hashed after * successful create. Hash it here. */ spin_lock(&dcache_lock); if (d_unhashed(dentry)) d_rehash_cond(dentry, 0); spin_unlock(&dcache_lock); RETURN(0);}static void ll_update_times(struct ptlrpc_request *request, int offset, struct inode *inode){ struct mds_body *body = lustre_msg_buf(request->rq_repmsg, offset, sizeof(*body)); LASSERT(body); /* mtime is always updated with ctime, but can be set in past. As write and utime(2) may happen within 1 second, and utime's mtime has a priority over write's one, so take mtime from mds for the same ctimes. */ if (body->valid & OBD_MD_FLCTIME && body->ctime >= LTIME_S(inode->i_ctime)) { LTIME_S(inode->i_ctime) = body->ctime; if (body->valid & OBD_MD_FLMTIME) { CDEBUG(D_INODE, "setting ino %lu mtime from %lu " "to "LPU64"\n", inode->i_ino, LTIME_S(inode->i_mtime), body->mtime); LTIME_S(inode->i_mtime) = body->mtime; } }}static int ll_new_node(struct inode *dir, struct qstr *name, const char *tgt, int mode, int rdev, struct dentry *dchild){ struct ptlrpc_request *request = NULL; struct inode *inode = NULL; struct ll_sb_info *sbi = ll_i2sbi(dir); struct mdc_op_data op_data; int tgt_len = 0; int err; ENTRY; if (unlikely(tgt != NULL)) tgt_len = strlen(tgt)+1; err = ll_prepare_mdc_op_data(&op_data, dir, NULL, name->name, name->len, 0, NULL); if (err) GOTO(err_exit, err); err = mdc_create(sbi->ll_mdc_exp, &op_data, tgt, tgt_len, mode, current->fsuid, current->fsgid, current->cap_effective, rdev, &request); if (err) GOTO(err_exit, err); ll_update_times(request, REPLY_REC_OFF, dir); if (dchild) { err = ll_prep_inode(sbi->ll_osc_exp, &inode, request, REPLY_REC_OFF, dchild->d_sb); if (err) GOTO(err_exit, err); d_drop(dchild); d_instantiate(dchild, inode); EXIT; }err_exit: ptlrpc_req_finished(request); return err;}static int ll_mknod_generic(struct inode *dir, struct qstr *name, int mode, unsigned rdev, struct dentry *dchild){ int err; ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p) mode %o dev %x\n", name->len, name->name, dir->i_ino, dir->i_generation, dir, mode, rdev); mode &= ~current->fs->umask; switch (mode & S_IFMT) { case 0: mode |= S_IFREG; /* for mode = 0 case, fallthrough */ case S_IFREG: case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: err = ll_new_node(dir, name, NULL, mode, rdev, dchild); break; case S_IFDIR: err = -EPERM; break; default: err = -EINVAL; } RETURN(err);}#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))#ifndef HAVE_VFS_INTENT_PATCHESstatic int ll_create_nd(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd){ struct lookup_intent *it = ll_d2d(dentry)->lld_it; int rc; if (!it) return ll_mknod_generic(dir, &dentry->d_name, mode, 0, dentry); ll_d2d(dentry)->lld_it = NULL; /* Was there an error? Propagate it! */ if (it->d.lustre.it_status) { rc = it->d.lustre.it_status; goto out; } rc = ll_create_it(dir, dentry, mode, it);#ifdef HAVE_FILE_IN_STRUCT_INTENT if (nd && (nd->flags & LOOKUP_OPEN) && dentry->d_inode) { /* Open */ nd->intent.open.file->private_data = it; lookup_instantiate_filp(nd, dentry, NULL); }#else ll_release_openhandle(dentry,it);#endifout: ll_intent_release(it); OBD_FREE(it, sizeof(*it)); return rc;}#elsestatic int ll_create_nd(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd){ if (!nd || !nd->intent.d.lustre.it_disposition) /* No saved request? Just mknod the file */ return ll_mknod_generic(dir, &dentry->d_name, mode, 0, dentry); return ll_create_it(dir, dentry, mode, &nd->intent);}#endif#endifstatic int ll_symlink_generic(struct inode *dir, struct qstr *name, const char *tgt, struct dentry *dchild){ int err; ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),target=%.*s\n", name->len, name->name, dir->i_ino, dir->i_generation, dir, 3000, tgt); err = ll_new_node(dir, name, (char *)tgt, S_IFLNK | S_IRWXUGO, 0, dchild); RETURN(err);}static int ll_link_generic(struct inode *src, struct inode *dir, struct qstr *name, struct dentry *dchild){ struct ptlrpc_request *request = NULL; struct mdc_op_data op_data; int err; struct ll_sb_info *sbi = ll_i2sbi(dir); ENTRY; CDEBUG(D_VFSTRACE, "VFS Op: inode=%lu/%u(%p), dir=%lu/%u(%p), target=%.*s\n", src->i_ino, src->i_generation, src, dir->i_ino, dir->i_generation, dir, name->len, name->name); err = ll_prepare_mdc_op_data(&op_data, src, dir, name->name, name->len, 0, NULL); if (err) GOTO(out, err); err = mdc_link(sbi->ll_mdc_exp, &op_data, &request); if (err) GOTO(out, err); if (dchild) { d_drop(dchild); } ll_update_times(request, REPLY_REC_OFF, dir); EXIT;out: ptlrpc_req_finished(request); RETURN(err);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -