X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fllite%2Ffile.c;h=14e38cf7050c35306ea957d2579feb1ce9498d90;hp=81b36ce0d33e66076b385e374599432b3633485f;hb=a7811634d45319dc3812fa652c727367fa290a24;hpb=bb188afa0ccf4cb5c810a7a7276d8d27dd03dc27 diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 81b36ce..14e38cf 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -705,8 +705,7 @@ static int ll_lsm_getattr(struct lov_stripe_md *lsm, struct obd_export *exp, oinfo.oi_md = lsm; oinfo.oi_oa = obdo; - oinfo.oi_oa->o_id = lsm->lsm_object_id; - oinfo.oi_oa->o_seq = lsm->lsm_object_seq; + oinfo.oi_oa->o_oi = lsm->lsm_oi; oinfo.oi_oa->o_mode = S_IFREG; oinfo.oi_oa->o_ioepoch = ioepoch; oinfo.oi_oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | @@ -756,10 +755,11 @@ int ll_inode_getattr(struct inode *inode, struct obdo *obdo, capa, obdo, ioepoch, sync); capa_put(capa); if (rc == 0) { + struct ost_id *oi = lsm ? &lsm->lsm_oi : &obdo->o_oi; + obdo_refresh_inode(inode, obdo, obdo->o_valid); - CDEBUG(D_INODE, - "objid "LPX64" size %llu, blocks %llu, blksize %lu\n", - lsm ? lsm->lsm_object_id : 0, i_size_read(inode), + CDEBUG(D_INODE, "objid "DOSTID" size %llu, blocks %llu," + " blksize %lu\n", POSTID(oi), i_size_read(inode), (unsigned long long)inode->i_blocks, (unsigned long)ll_inode_blksize(inode)); } @@ -920,8 +920,16 @@ restart: GOTO(out, result); out: cl_io_fini(env, io); - if (result == 0 && io->ci_need_restart) /* need to restart whole IO */ + /* If any bit been read/written (result != 0), we just return + * short read/write instead of restart io. */ + if (result == 0 && io->ci_need_restart) { + CDEBUG(D_VFSTRACE, "Restart %s on %s from %lld, count:%zd\n", + iot == CIT_READ ? "read" : "write", + file->f_dentry->d_name.name, *ppos, count); + LASSERTF(io->u.ci_rw.crw_count == count, "%zd != %zd\n", + io->u.ci_rw.crw_count, count); goto restart; + } if (iot == CIT_READ) { if (result >= 0) @@ -1683,8 +1691,7 @@ int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap, !(fiemap->fm_flags & FIEMAP_FLAG_DEVICE_ORDER)) GOTO(out, rc = -EOPNOTSUPP); - fm_key.oa.o_id = lsm->lsm_object_id; - fm_key.oa.o_seq = lsm->lsm_object_seq; + fm_key.oa.o_oi = lsm->lsm_oi; fm_key.oa.o_valid = OBD_MD_FLID | OBD_MD_FLGROUP; obdo_from_inode(&fm_key.oa, inode, OBD_MD_FLSIZE); @@ -1740,6 +1747,7 @@ int ll_fid2path(struct inode *inode, void *arg) rc = obd_iocontrol(OBD_IOC_FID2PATH, exp, outsize, gfout, NULL); if (rc) GOTO(gf_free, rc); + if (copy_to_user(arg, gfout, outsize)) rc = -EFAULT; @@ -1846,65 +1854,154 @@ int ll_data_version(struct inode *inode, __u64 *data_version, RETURN(rc); } -static int ll_swap_layout(struct file *file, struct file *file2, - struct lustre_swap_layouts *lsl) +struct ll_swap_stack { + struct iattr ia1, ia2; + __u64 dv1, dv2; + struct inode *inode1, *inode2; + bool check_dv1, check_dv2; +}; + +static int ll_swap_layouts(struct file *file1, struct file *file2, + struct lustre_swap_layouts *lsl) { - struct mdc_swap_layouts msl = { .msl_flags = lsl->sl_flags }; - struct md_op_data *op_data; - struct inode *inode = file->f_dentry->d_inode; - struct inode *inode2 = file2->f_dentry->d_inode; - __u32 gid; - int rc; + struct mdc_swap_layouts msl; + struct md_op_data *op_data; + __u32 gid; + __u64 dv; + struct ll_swap_stack *llss = NULL; + int rc, rc1; - if (!S_ISREG(inode2->i_mode)) - RETURN(-EINVAL); + OBD_ALLOC_PTR(llss); + if (llss == NULL) + RETURN(-ENOMEM); - if (inode_permission(inode, MAY_WRITE) || - inode_permission(inode2, MAY_WRITE)) - RETURN(-EPERM); + llss->inode1 = file1->f_dentry->d_inode; + llss->inode2 = file2->f_dentry->d_inode; + + if (!S_ISREG(llss->inode2->i_mode)) + GOTO(free, rc = -EINVAL); - if (inode2->i_sb != inode->i_sb) - RETURN(-EXDEV); + if (ll_permission(llss->inode1, MAY_WRITE, NULL) || + ll_permission(llss->inode2, MAY_WRITE, NULL)) + GOTO(free, rc = -EPERM); - rc = lu_fid_cmp(ll_inode2fid(inode), ll_inode2fid(inode2)); + if (llss->inode2->i_sb != llss->inode1->i_sb) + GOTO(free, rc = -EXDEV); + + /* we use 2 bool because it is easier to swap than 2 bits */ + if (lsl->sl_flags & SWAP_LAYOUTS_CHECK_DV1) + llss->check_dv1 = true; + + if (lsl->sl_flags & SWAP_LAYOUTS_CHECK_DV2) + llss->check_dv2 = true; + + /* we cannot use lsl->sl_dvX directly because we may swap them */ + llss->dv1 = lsl->sl_dv1; + llss->dv2 = lsl->sl_dv2; + + rc = lu_fid_cmp(ll_inode2fid(llss->inode1), ll_inode2fid(llss->inode2)); if (rc == 0) /* same file, done! */ - RETURN(0); + GOTO(free, rc = 0); if (rc < 0) { /* sequentialize it */ - swap(inode, inode2); - swap(file, file2); + swap(llss->inode1, llss->inode2); + swap(file1, file2); + swap(llss->dv1, llss->dv2); + swap(llss->check_dv1, llss->check_dv2); } gid = lsl->sl_gid; if (gid != 0) { /* application asks to flush dirty cache */ - rc = ll_get_grouplock(inode, file, gid); + rc = ll_get_grouplock(llss->inode1, file1, gid); if (rc < 0) - RETURN(rc); + GOTO(free, rc); - rc = ll_get_grouplock(inode2, file2, gid); + rc = ll_get_grouplock(llss->inode2, file2, gid); if (rc < 0) { - ll_put_grouplock(inode, file, gid); - RETURN(rc); + ll_put_grouplock(llss->inode1, file1, gid); + GOTO(free, rc); } } + /* to be able to restore mtime and atime after swap + * we need to first save them */ + if (lsl->sl_flags & + (SWAP_LAYOUTS_KEEP_MTIME | SWAP_LAYOUTS_KEEP_ATIME)) { + llss->ia1.ia_mtime = llss->inode1->i_mtime; + llss->ia1.ia_atime = llss->inode1->i_atime; + llss->ia1.ia_valid = ATTR_MTIME | ATTR_ATIME; + llss->ia2.ia_mtime = llss->inode2->i_mtime; + llss->ia2.ia_atime = llss->inode2->i_atime; + llss->ia2.ia_valid = ATTR_MTIME | ATTR_ATIME; + } + + /* ultimate check, before swaping the layouts we check if + * dataversion has changed (if requested) */ + if (llss->check_dv1) { + rc = ll_data_version(llss->inode1, &dv, 0); + if (rc) + GOTO(putgl, rc); + if (dv != llss->dv1) + GOTO(putgl, rc = -EAGAIN); + } + + if (llss->check_dv2) { + rc = ll_data_version(llss->inode2, &dv, 0); + if (rc) + GOTO(putgl, rc); + if (dv != llss->dv2) + GOTO(putgl, rc = -EAGAIN); + } + /* struct md_op_data is used to send the swap args to the mdt * only flags is missing, so we use struct mdc_swap_layouts * through the md_op_data->op_data */ + /* flags from user space have to be converted before they are send to + * server, no flag is sent today, they are only used on the client */ + msl.msl_flags = 0; rc = -ENOMEM; - op_data = ll_prep_md_op_data(NULL, inode, inode2, NULL, 0, 0, - LUSTRE_OPC_ANY, &msl); + op_data = ll_prep_md_op_data(NULL, llss->inode1, llss->inode2, NULL, 0, + 0, LUSTRE_OPC_ANY, &msl); if (op_data != NULL) { - rc = obd_iocontrol(LL_IOC_LOV_SWAP_LAYOUTS, ll_i2mdexp(inode), - sizeof(*op_data), op_data, NULL); + rc = obd_iocontrol(LL_IOC_LOV_SWAP_LAYOUTS, + ll_i2mdexp(llss->inode1), + sizeof(*op_data), op_data, NULL); ll_finish_md_op_data(op_data); } +putgl: if (gid != 0) { - ll_put_grouplock(inode2, file2, gid); - ll_put_grouplock(inode, file, gid); + ll_put_grouplock(llss->inode2, file2, gid); + ll_put_grouplock(llss->inode1, file1, gid); + } + + /* rc can be set from obd_iocontrol() or from a GOTO(putgl, ...) */ + if (rc != 0) + GOTO(free, rc); + + /* clear useless flags */ + if (!(lsl->sl_flags & SWAP_LAYOUTS_KEEP_MTIME)) { + llss->ia1.ia_valid &= ~ATTR_MTIME; + llss->ia2.ia_valid &= ~ATTR_MTIME; } + if (!(lsl->sl_flags & SWAP_LAYOUTS_KEEP_ATIME)) { + llss->ia1.ia_valid &= ~ATTR_ATIME; + llss->ia2.ia_valid &= ~ATTR_ATIME; + } + + /* update time if requested */ + rc = rc1 = 0; + if (llss->ia2.ia_valid != 0) + rc = ll_setattr(file1->f_dentry, &llss->ia2); + + if (llss->ia1.ia_valid != 0) + rc1 = ll_setattr(file2->f_dentry, &llss->ia1); + +free: + if (llss != NULL) + OBD_FREE_PTR(llss); + RETURN(rc); } @@ -1964,14 +2061,14 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if ((file->f_flags & O_ACCMODE) == 0) /* O_RDONLY */ RETURN(-EPERM); - file2 = cfs_get_fd(lsl.sl_fd); + file2 = fget(lsl.sl_fd); if (file2 == NULL) RETURN(-EBADF); rc = -EPERM; if ((file2->f_flags & O_ACCMODE) != 0) /* O_WRONLY or O_RDWR */ - rc = ll_swap_layout(file, file2, &lsl); - cfs_put_file(file2); + rc = ll_swap_layouts(file, file2, &lsl); + fput(file2); RETURN(rc); } case LL_IOC_LOV_GETSTRIPE: @@ -2314,15 +2411,25 @@ int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end, RETURN(result); } +/* + * When dentry is provided (the 'else' case), *file->f_dentry may be + * null and dentry must be used directly rather than pulled from + * *file->f_dentry as is done otherwise. + */ + #ifdef HAVE_FILE_FSYNC_4ARGS int ll_fsync(struct file *file, loff_t start, loff_t end, int data) +{ + struct dentry *dentry = file->f_dentry; #elif defined(HAVE_FILE_FSYNC_2ARGS) int ll_fsync(struct file *file, int data) +{ + struct dentry *dentry = file->f_dentry; #else int ll_fsync(struct file *file, struct dentry *dentry, int data) -#endif { - struct inode *inode = file->f_dentry->d_inode; +#endif + struct inode *inode = dentry->d_inode; struct ll_inode_info *lli = ll_i2info(inode); struct ptlrpc_request *req; struct obd_capa *oc; @@ -3247,7 +3354,7 @@ int ll_layout_refresh(struct inode *inode, __u32 *gen) .ei_mode = LCK_CR, .ei_cb_bl = ll_md_blocking_ast, .ei_cb_cp = ldlm_completion_ast, - .ei_cbdata = inode }; + .ei_cbdata = NULL }; int rc; ENTRY; @@ -3310,6 +3417,8 @@ again: ll_finish_md_op_data(op_data); + md_set_lock_data(sbi->ll_md_exp, &it.d.lustre.it_lock_handle, inode, NULL); + mode = it.d.lustre.it_lock_mode; it.d.lustre.it_lock_mode = 0; ll_intent_drop_lock(&it);