ssize_t result;
ENTRY;
+restart:
io = ccc_env_thread_io(env);
ll_io_init(io, file, iot == CIT_WRITE);
GOTO(out, result);
out:
cl_io_fini(env, io);
+ if (result == 0 && io->ci_need_restart) /* need to restart whole IO */
+ goto restart;
if (iot == CIT_READ) {
if (result >= 0)
ll_stats_ops_tally(ll_i2sbi(file->f_dentry->d_inode),
LPROC_LL_WRITE_BYTES, result);
fd->fd_write_failed = false;
- } else {
+ } else if (result != -ERESTARTSYS) {
fd->fd_write_failed = true;
}
}
RETURN(rc);
}
-long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static int ll_swap_layout(struct file *file, struct file *file2,
+ struct lustre_swap_layouts *lsl)
{
- struct inode *inode = file->f_dentry->d_inode;
- struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
- int flags;
+ 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;
- ENTRY;
+ if (!S_ISREG(inode2->i_mode))
+ RETURN(-EINVAL);
+
+ if (inode_permission(inode, MAY_WRITE) ||
+ inode_permission(inode2, MAY_WRITE))
+ RETURN(-EPERM);
+
+ if (inode2->i_sb != inode->i_sb)
+ RETURN(-EXDEV);
+
+ rc = lu_fid_cmp(ll_inode2fid(inode), ll_inode2fid(inode2));
+ if (rc == 0) /* same file, done! */
+ RETURN(0);
+
+ if (rc < 0) { /* sequentialize it */
+ swap(inode, inode2);
+ swap(file, file2);
+ }
+
+ gid = lsl->sl_gid;
+ if (gid != 0) { /* application asks to flush dirty cache */
+ rc = ll_get_grouplock(inode, file, gid);
+ if (rc < 0)
+ RETURN(rc);
+
+ rc = ll_get_grouplock(inode2, file2, gid);
+ if (rc < 0) {
+ ll_put_grouplock(inode, file, gid);
+ RETURN(rc);
+ }
+ }
+
+ /* 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 */
+ rc = -ENOMEM;
+ op_data = ll_prep_md_op_data(NULL, inode, 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);
+ ll_finish_md_op_data(op_data);
+ }
+
+ if (gid != 0) {
+ ll_put_grouplock(inode2, file2, gid);
+ ll_put_grouplock(inode, file, gid);
+ }
+
+ RETURN(rc);
+}
+
+long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
+ int flags, rc;
+ ENTRY;
CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p),cmd=%x\n", inode->i_ino,
inode->i_generation, inode, cmd);
RETURN(ll_lov_setstripe(inode, file, arg));
case LL_IOC_LOV_SETEA:
RETURN(ll_lov_setea(inode, file, arg));
+ case LL_IOC_LOV_SWAP_LAYOUTS: {
+ struct file *file2;
+ struct lustre_swap_layouts lsl;
+
+ if (cfs_copy_from_user(&lsl, (char *)arg,
+ sizeof(struct lustre_swap_layouts)))
+ RETURN(-EFAULT);
+
+ if ((file->f_flags & O_ACCMODE) == 0) /* O_RDONLY */
+ RETURN(-EPERM);
+
+ file2 = cfs_get_fd(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);
+ RETURN(rc);
+ }
case LL_IOC_LOV_GETSTRIPE:
RETURN(ll_lov_getstripe(inode, arg));
case LL_IOC_RECREATE_OBJ:
rc = obd_unpackmd(sbi->ll_dt_exp, &md.lsm,
lock->l_lvb_data, lock->l_lvb_len);
if (rc >= 0) {
+ *gen = LL_LAYOUT_GEN_EMPTY;
if (md.lsm != NULL)
*gen = md.lsm->lsm_layout_gen;
rc = 0;
int rc;
ENTRY;
- *gen = LL_LAYOUT_GEN_ZERO;
+ *gen = LL_LAYOUT_GEN_NONE;
if (!(sbi->ll_flags & LL_SBI_LAYOUT_LOCK))
RETURN(0);