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 |
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));
}
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)
!(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);
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;
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);
}
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:
eof = i_size_read(inode);
}
- retval = generic_file_llseek_size(file, offset, origin,
+ retval = ll_generic_file_llseek_size(file, offset, origin,
ll_file_maxbytes(inode), eof);
RETURN(retval);
}
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;
.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;
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);