📄 dir.c
字号:
} return nr;}int ll_readdir(struct file *filp, void *dirent, filldir_t filldir){ struct inode *inode = filp->f_dentry->d_inode; loff_t pos = filp->f_pos; unsigned offset = pos & ~CFS_PAGE_MASK; pgoff_t idx = pos >> CFS_PAGE_SHIFT; pgoff_t npages = dir_pages(inode); unsigned chunk_mask = ll_dir_page_mask(inode); int need_revalidate = (filp->f_version != inode->i_version); int rc = 0; int done; /* when this becomes negative --- stop iterating */ ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) pos %llu/%llu\n", inode->i_ino, inode->i_generation, inode, pos, i_size_read(inode)); /* * Checking ->i_size without the lock. Should be harmless, as server * re-checks. */ if (pos > i_size_read(inode) - ll_dir_rec_len(1)) RETURN(0); for (done = 0; idx < npages; idx++, offset = 0) { /* * We can assume that all blocks on this page are filled with * entries, because ll_dir_check_page() placed special dummy * entries for us. */ char *kaddr; struct page *page; CDEBUG(D_EXT2,"read %lu of dir %lu/%u page %lu/%lu " "size %llu\n", CFS_PAGE_SIZE, inode->i_ino, inode->i_generation, idx, npages, i_size_read(inode)); page = ll_get_dir_page(inode, idx); /* size might have been updated by mdc_readpage */ npages = dir_pages(inode); if (IS_ERR(page)) { rc = PTR_ERR(page); CERROR("error reading dir %lu/%u page %lu: rc %d\n", inode->i_ino, inode->i_generation, idx, rc); continue; } kaddr = page_address(page); if (need_revalidate) { /* * File offset was changed by lseek() and possibly * points in the middle of an entry. Re-scan from the * beginning of the chunk. */ offset = ll_dir_validate_entry(kaddr, offset, chunk_mask); need_revalidate = 0; } done = ll_readdir_page(kaddr, idx << CFS_PAGE_SHIFT, &offset, filldir, dirent); kunmap(page); page_cache_release(page); if (done > 0) /* * Some entries were sent to the user space, return * success. */ rc = 0; else if (done < 0) /* * filldir is satisfied. */ break; } filp->f_pos = (idx << CFS_PAGE_SHIFT) | offset; filp->f_version = inode->i_version; touch_atime(filp->f_vfsmnt, filp->f_dentry); RETURN(rc);}#define QCTL_COPY(out, in) \do { \ Q_COPY(out, in, qc_cmd); \ Q_COPY(out, in, qc_type); \ Q_COPY(out, in, qc_id); \ Q_COPY(out, in, qc_stat); \ Q_COPY(out, in, qc_dqinfo); \ Q_COPY(out, in, qc_dqblk); \} while (0)int ll_send_mgc_param(struct obd_export *mgc, char *string){ struct mgs_send_param *msp; int rc = 0; OBD_ALLOC_PTR(msp); if (!msp) return -ENOMEM; strncpy(msp->mgs_param, string, MGS_PARAM_MAXLEN); rc = obd_set_info_async(mgc, strlen(KEY_SET_INFO), KEY_SET_INFO, sizeof(struct mgs_send_param), msp, NULL); if (rc) CERROR("Failed to set parameter: %d\n", rc); OBD_FREE_PTR(msp); return rc;}char *ll_get_fsname(struct inode *inode){ struct lustre_sb_info *lsi = s2lsi(inode->i_sb); char *ptr, *fsname; int len; OBD_ALLOC(fsname, MGS_PARAM_MAXLEN); len = strlen(lsi->lsi_lmd->lmd_profile); ptr = strrchr(lsi->lsi_lmd->lmd_profile, '-'); if (ptr && (strcmp(ptr, "-client") == 0)) len -= 7; strncpy(fsname, lsi->lsi_lmd->lmd_profile, len); fsname[len] = '\0'; return fsname;}int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump, int set_default){ struct ll_sb_info *sbi = ll_i2sbi(inode); struct mdc_op_data data; struct ptlrpc_request *req = NULL; struct lustre_sb_info *lsi = s2lsi(inode->i_sb); struct obd_device *mgc = lsi->lsi_mgc; char *fsname = NULL, *param = NULL; struct iattr attr = { 0 }; int rc = 0; /* * This is coming from userspace, so should be in * local endian. But the MDS would like it in little * endian, so we swab it before we send it. */ if (lump->lmm_magic != LOV_USER_MAGIC) RETURN(-EINVAL); if (lump->lmm_magic != cpu_to_le32(LOV_USER_MAGIC)) lustre_swab_lov_user_md(lump); ll_prepare_mdc_op_data(&data, inode, NULL, NULL, 0, 0, NULL); /* swabbing is done in lov_setstripe() on server side */ rc = mdc_setattr(sbi->ll_mdc_exp, &data, &attr, lump, sizeof(*lump), NULL, 0, &req); if (rc) { ptlrpc_req_finished(req); if (rc != -EPERM && rc != -EACCES) CERROR("mdc_setattr fails: rc = %d\n", rc); return rc; } ptlrpc_req_finished(req); if (set_default && mgc->u.cli.cl_mgc_mgsexp) { OBD_ALLOC(param, MGS_PARAM_MAXLEN); /* Get fsname and assume devname to be -MDT0000. */ fsname = ll_get_fsname(inode); /* Set root stripesize */ sprintf(param, "%s-MDT0000.lov.stripesize=%u", fsname, lump->lmm_stripe_size); rc = ll_send_mgc_param(mgc->u.cli.cl_mgc_mgsexp, param); if (rc) goto end; /* Set root stripecount */ sprintf(param, "%s-MDT0000.lov.stripecount=%u", fsname, lump->lmm_stripe_count); rc = ll_send_mgc_param(mgc->u.cli.cl_mgc_mgsexp, param); if (rc) goto end; /* Set root stripeoffset */ sprintf(param, "%s-MDT0000.lov.stripeoffset=%u", fsname, lump->lmm_stripe_offset); rc = ll_send_mgc_param(mgc->u.cli.cl_mgc_mgsexp, param); if (rc) goto end;end: if (fsname) OBD_FREE(fsname, MGS_PARAM_MAXLEN); if (param) OBD_FREE(param, MGS_PARAM_MAXLEN); } return rc;}int ll_dir_getstripe(struct inode *inode, struct lov_mds_md **lmmp, int *lmm_size, struct ptlrpc_request **request){ struct ll_sb_info *sbi = ll_i2sbi(inode); struct ll_fid fid; struct mds_body *body; struct lov_mds_md *lmm = NULL; struct ptlrpc_request *req = NULL; int rc, lmmsize; ll_inode2fid(&fid, inode); rc = ll_get_max_mdsize(sbi, &lmmsize); if (rc) RETURN(rc); rc = mdc_getattr(sbi->ll_mdc_exp, &fid, OBD_MD_FLEASIZE|OBD_MD_FLDIREA, lmmsize, &req); if (rc < 0) { CDEBUG(D_INFO, "mdc_getattr failed on inode " "%lu/%u: rc %d\n", inode->i_ino, inode->i_generation, rc); GOTO(out, rc); } body = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF, sizeof(*body)); LASSERT(body != NULL); /* checked by mdc_getattr_name */ /* swabbed by mdc_getattr_name */ LASSERT(lustre_rep_swabbed(req, REPLY_REC_OFF)); lmmsize = body->eadatasize; if (!(body->valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) || lmmsize == 0) { GOTO(out, rc = -ENODATA); } lmm = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF + 1, lmmsize); LASSERT(lmm != NULL); LASSERT(lustre_rep_swabbed(req, REPLY_REC_OFF + 1)); /* * This is coming from the MDS, so is probably in * little endian. We convert it to host endian before * passing it to userspace. */ if (lmm->lmm_magic == __swab32(LOV_MAGIC)) { lustre_swab_lov_user_md((struct lov_user_md *)lmm); }out: *lmmp = lmm; *lmm_size = lmmsize; *request = req; return rc;}static int ll_dir_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct ll_sb_info *sbi = ll_i2sbi(inode); struct obd_ioctl_data *data; ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), cmd=%#x\n", inode->i_ino, inode->i_generation, inode, cmd); /* asm-ppc{,64} declares TCGETS, et. al. as type 't' not 'T' */ if (_IOC_TYPE(cmd) == 'T' || _IOC_TYPE(cmd) == 't') /* tty ioctls */ return -ENOTTY; ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_IOCTL, 1); switch(cmd) { case EXT3_IOC_GETFLAGS: case EXT3_IOC_SETFLAGS: RETURN(ll_iocontrol(inode, file, cmd, arg)); case EXT3_IOC_GETVERSION_OLD: case EXT3_IOC_GETVERSION: RETURN(put_user(inode->i_generation, (int *)arg)); /* We need to special case any other ioctls we want to handle, * to send them to the MDS/OST as appropriate and to properly * network encode the arg field. case EXT3_IOC_SETVERSION_OLD: case EXT3_IOC_SETVERSION: */ case IOC_MDC_LOOKUP: { struct ptlrpc_request *request = NULL; struct ll_fid fid; char *buf = NULL; char *filename; int namelen, rc, len = 0; rc = obd_ioctl_getdata(&buf, &len, (void *)arg); if (rc) RETURN(rc); data = (void *)buf; filename = data->ioc_inlbuf1; namelen = data->ioc_inllen1; if (namelen < 1) { CDEBUG(D_INFO, "IOC_MDC_LOOKUP missing filename\n"); GOTO(out, rc = -EINVAL); } ll_inode2fid(&fid, inode); rc = mdc_getattr_name(sbi->ll_mdc_exp, &fid, filename, namelen, OBD_MD_FLID, 0, &request); if (rc < 0) { CDEBUG(D_INFO, "mdc_getattr_name: %d\n", rc); GOTO(out, rc); } ptlrpc_req_finished(request); EXIT; out: obd_ioctl_freedata(buf, len); return rc; } case LL_IOC_LOV_SETSTRIPE: { struct lov_user_md lum, *lump = (struct lov_user_md *)arg; int rc = 0; int set_default = 0; LASSERT(sizeof(lum) == sizeof(*lump)); LASSERT(sizeof(lum.lmm_objects[0]) == sizeof(lump->lmm_objects[0])); rc = copy_from_user(&lum, lump, sizeof(lum)); if (rc) return(-EFAULT); if (inode->i_sb->s_root == file->f_dentry) set_default = 1; rc = ll_dir_setstripe(inode, &lum, set_default); return rc; } case LL_IOC_OBD_STATFS: RETURN(ll_obd_statfs(inode, (void *)arg)); case LL_IOC_LOV_GETSTRIPE: case LL_IOC_MDC_GETINFO: case IOC_MDC_GETFILEINFO: case IOC_MDC_GETFILESTRIPE: { struct ptlrpc_request *request = NULL; struct mds_body *body; struct lov_user_md *lump; struct lov_mds_md *lmm = NULL; char *filename = NULL; int rc, lmmsize; if (cmd == IOC_MDC_GETFILEINFO || cmd == IOC_MDC_GETFILESTRIPE) { filename = getname((const char *)arg); if (IS_ERR(filename))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -