Whamcloud - gitweb
LU-10810 clio: SEEK_HOLE/SEEK_DATA on client side
[fs/lustre-release.git] / lustre / llite / file.c
index 927fe8b..675a5a1 100644 (file)
@@ -1158,8 +1158,8 @@ ll_lease_open(struct inode *inode, struct file *file, fmode_t fmode,
 
        /* already get lease, handle lease lock */
        ll_set_lock_data(sbi->ll_md_exp, inode, &it, NULL);
-       if (it.it_lock_mode == 0 ||
-           it.it_lock_bits != MDS_INODELOCK_OPEN) {
+       if (!it.it_lock_mode ||
+           !(it.it_lock_bits & MDS_INODELOCK_OPEN)) {
                /* open lock must return for lease */
                CERROR(DFID "lease granted but no open lock, %d/%llu.\n",
                        PFID(ll_inode2fid(inode)), it.it_lock_mode,
@@ -1481,8 +1481,8 @@ void ll_io_init(struct cl_io *io, struct file *file, enum cl_io_type iot,
                                           IS_SYNC(inode));
 #ifdef HAVE_GENERIC_WRITE_SYNC_2ARGS
                io->u.ci_wr.wr_sync  |= !!(args &&
-                                          args->via_io_subtype == IO_NORMAL &&
-                                          args->u.normal.via_iocb->ki_flags & IOCB_DSYNC);
+                                          (args->u.normal.via_iocb->ki_flags &
+                                           IOCB_DSYNC));
 #endif
        }
 
@@ -1559,8 +1559,7 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
                iot == CIT_READ ? "read" : "write", *ppos, count);
 
        io = vvp_env_thread_io(env);
-       if (args->via_io_subtype == IO_NORMAL &&
-           file->f_flags & O_DIRECT) {
+       if (file->f_flags & O_DIRECT) {
                if (!is_sync_kiocb(args->u.normal.via_iocb))
                        is_aio = true;
                ci_aio = cl_aio_alloc(args->u.normal.via_iocb);
@@ -1584,34 +1583,22 @@ restart:
                        range_lock_init(&range, *ppos, *ppos + count - 1);
 
                vio->vui_fd  = file->private_data;
-               vio->vui_io_subtype = args->via_io_subtype;
-
-               switch (vio->vui_io_subtype) {
-               case IO_NORMAL:
-                       vio->vui_iter = args->u.normal.via_iter;
-                       vio->vui_iocb = args->u.normal.via_iocb;
-                       /* Direct IO reads must also take range lock,
-                        * or multiple reads will try to work on the same pages
-                        * See LU-6227 for details. */
-                       if (((iot == CIT_WRITE) ||
-                           (iot == CIT_READ && (file->f_flags & O_DIRECT))) &&
-                           !(vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
-                               CDEBUG(D_VFSTRACE, "Range lock "RL_FMT"\n",
-                                      RL_PARA(&range));
-                               rc = range_lock(&lli->lli_write_tree, &range);
-                               if (rc < 0)
-                                       GOTO(out, rc);
+               vio->vui_iter = args->u.normal.via_iter;
+               vio->vui_iocb = args->u.normal.via_iocb;
+               /* Direct IO reads must also take range lock,
+                * or multiple reads will try to work on the same pages
+                * See LU-6227 for details.
+                */
+               if (((iot == CIT_WRITE) ||
+                   (iot == CIT_READ && (file->f_flags & O_DIRECT))) &&
+                   !(vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
+                       CDEBUG(D_VFSTRACE, "Range lock "RL_FMT"\n",
+                              RL_PARA(&range));
+                       rc = range_lock(&lli->lli_write_tree, &range);
+                       if (rc < 0)
+                               GOTO(out, rc);
 
-                               range_locked = true;
-                       }
-                       break;
-               case IO_SPLICE:
-                       vio->u.splice.vui_pipe = args->u.splice.via_pipe;
-                       vio->u.splice.vui_flags = args->u.splice.via_flags;
-                       break;
-               default:
-                       CERROR("unknown IO subtype %u\n", vio->vui_io_subtype);
-                       LBUG();
+                       range_locked = true;
                }
 
                ll_cl_add(file, env, io, LCC_RW);
@@ -1643,7 +1630,7 @@ restart:
                count -= io->ci_nob;
 
                /* prepare IO restart */
-               if (count > 0 && args->via_io_subtype == IO_NORMAL)
+               if (count > 0)
                        args->u.normal.via_iter = vio->vui_iter;
        }
 out:
@@ -1822,7 +1809,7 @@ static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
        if (IS_ERR(env))
                return PTR_ERR(env);
 
-       args = ll_env_args(env, IO_NORMAL);
+       args = ll_env_args(env);
        args->u.normal.via_iter = to;
        args->u.normal.via_iocb = iocb;
 
@@ -1957,7 +1944,7 @@ static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if (IS_ERR(env))
                return PTR_ERR(env);
 
-       args = ll_env_args(env, IO_NORMAL);
+       args = ll_env_args(env);
        args->u.normal.via_iter = from;
        args->u.normal.via_iocb = iocb;
 
@@ -2129,46 +2116,6 @@ static ssize_t ll_file_write(struct file *file, const char __user *buf,
 }
 #endif /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
 
-/*
- * Send file content (through pagecache) somewhere with helper
- */
-static ssize_t ll_file_splice_read(struct file *in_file, loff_t *ppos,
-                                   struct pipe_inode_info *pipe, size_t count,
-                                   unsigned int flags)
-{
-       struct lu_env *env;
-       struct vvp_io_args *args;
-       ssize_t result;
-       __u16 refcheck;
-       bool cached;
-
-       ENTRY;
-
-       result = pcc_file_splice_read(in_file, ppos, pipe,
-                                     count, flags, &cached);
-       if (cached)
-               RETURN(result);
-
-       ll_ras_enter(in_file, *ppos, count);
-
-       env = cl_env_get(&refcheck);
-       if (IS_ERR(env))
-               RETURN(PTR_ERR(env));
-
-       args = ll_env_args(env, IO_SPLICE);
-       args->u.splice.via_pipe = pipe;
-       args->u.splice.via_flags = flags;
-
-       result = ll_file_io_generic(env, args, in_file, CIT_READ, ppos, count);
-       cl_env_put(env, &refcheck);
-
-       if (result > 0)
-               ll_rw_stats_tally(ll_i2sbi(file_inode(in_file)), current->pid,
-                                 in_file->private_data, *ppos, result,
-                                 READ);
-       RETURN(result);
-}
-
 int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry,
                             __u64 flags, struct lov_user_md *lum, int lum_size)
 {
@@ -4133,28 +4080,79 @@ out_state:
        }
 }
 
+loff_t ll_lseek(struct inode *inode, loff_t offset, int whence)
+{
+       struct lu_env *env;
+       struct cl_io *io;
+       struct cl_lseek_io *lsio;
+       __u16 refcheck;
+       int rc;
+       loff_t retval;
+
+       ENTRY;
+
+       env = cl_env_get(&refcheck);
+       if (IS_ERR(env))
+               RETURN(PTR_ERR(env));
+
+       io = vvp_env_thread_io(env);
+       io->ci_obj = ll_i2info(inode)->lli_clob;
+
+       lsio = &io->u.ci_lseek;
+       lsio->ls_start = offset;
+       lsio->ls_whence = whence;
+       lsio->ls_result = -ENXIO;
+
+       do {
+               rc = cl_io_init(env, io, CIT_LSEEK, io->ci_obj);
+               if (!rc)
+                       rc = cl_io_loop(env, io);
+               else
+                       rc = io->ci_result;
+               retval = rc ? : lsio->ls_result;
+               cl_io_fini(env, io);
+       } while (unlikely(io->ci_need_restart));
+
+       cl_env_put(env, &refcheck);
+
+       RETURN(retval);
+}
+
 static loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
 {
        struct inode *inode = file_inode(file);
-       loff_t retval, eof = 0;
+       loff_t retval = offset, eof = 0;
        ktime_t kstart = ktime_get();
 
        ENTRY;
-       retval = offset + ((origin == SEEK_END) ? i_size_read(inode) :
-                          (origin == SEEK_CUR) ? file->f_pos : 0);
+
        CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), to=%llu=%#llx(%d)\n",
               PFID(ll_inode2fid(inode)), inode, retval, retval,
               origin);
 
-       if (origin == SEEK_END || origin == SEEK_HOLE || origin == SEEK_DATA) {
+       if (origin == SEEK_END) {
                retval = ll_glimpse_size(inode);
                if (retval != 0)
                        RETURN(retval);
                eof = i_size_read(inode);
        }
 
-       retval = generic_file_llseek_size(file, offset, origin,
-                                         ll_file_maxbytes(inode), eof);
+       if (origin == SEEK_HOLE || origin == SEEK_DATA) {
+               if (offset < 0)
+                       return -ENXIO;
+
+               /* flush local cache first if any */
+               cl_sync_file_range(inode, offset, OBD_OBJECT_EOF,
+                                  CL_FSYNC_LOCAL, 0);
+
+               retval = ll_lseek(inode, offset, origin);
+               if (retval < 0)
+                       return retval;
+               retval = vfs_setpos(file, retval, ll_file_maxbytes(inode));
+       } else {
+               retval = generic_file_llseek_size(file, offset, origin,
+                                                 ll_file_maxbytes(inode), eof);
+       }
        if (retval >= 0)
                ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LLSEEK,
                                   ktime_us_delta(ktime_get(), kstart));
@@ -4763,23 +4761,30 @@ static int ll_inode_revalidate(struct dentry *dentry, enum ldlm_intent_flags op)
        };
        struct ptlrpc_request *req = NULL;
        struct md_op_data *op_data;
+       const char *name = NULL;
+       size_t namelen = 0;
        int rc = 0;
        ENTRY;
 
        CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p),name=%s\n",
               PFID(ll_inode2fid(inode)), inode, dentry->d_name.name);
 
-       if (exp_connect_flags2(exp) & OBD_CONNECT2_GETATTR_PFID)
+       if (exp_connect_flags2(exp) & OBD_CONNECT2_GETATTR_PFID) {
                parent = dentry->d_parent->d_inode;
-       else
+               name = dentry->d_name.name;
+               namelen = dentry->d_name.len;
+       } else {
                parent = inode;
+       }
 
-       /* Call getattr by fid, so do not provide name at all. */
-       op_data = ll_prep_md_op_data(NULL, parent, inode, NULL, 0, 0,
+       op_data = ll_prep_md_op_data(NULL, parent, inode, name, namelen, 0,
                                     LUSTRE_OPC_ANY, NULL);
        if (IS_ERR(op_data))
                RETURN(PTR_ERR(op_data));
 
+       /* Call getattr by fid */
+       if (exp_connect_flags2(exp) & OBD_CONNECT2_GETATTR_PFID)
+               op_data->op_flags = MF_GETATTR_BY_FID;
        rc = md_intent_lock(exp, op_data, &oit, &req, &ll_md_blocking_ast, 0);
        ll_finish_md_op_data(op_data);
        if (rc < 0) {
@@ -5289,7 +5294,11 @@ struct file_operations ll_file_operations = {
        .release        = ll_file_release,
        .mmap           = ll_file_mmap,
        .llseek         = ll_file_seek,
-       .splice_read    = ll_file_splice_read,
+#ifndef HAVE_DEFAULT_FILE_SPLICE_READ_EXPORT
+       .splice_read    = generic_file_splice_read,
+#else
+       .splice_read    = pcc_file_splice_read,
+#endif
        .fsync          = ll_fsync,
        .flush          = ll_flush,
        .fallocate      = ll_fallocate,
@@ -5314,7 +5323,11 @@ struct file_operations ll_file_operations_flock = {
        .release        = ll_file_release,
        .mmap           = ll_file_mmap,
        .llseek         = ll_file_seek,
-       .splice_read    = ll_file_splice_read,
+#ifndef HAVE_DEFAULT_FILE_SPLICE_READ_EXPORT
+       .splice_read    = generic_file_splice_read,
+#else
+       .splice_read    = pcc_file_splice_read,
+#endif
        .fsync          = ll_fsync,
        .flush          = ll_flush,
        .flock          = ll_file_flock,
@@ -5342,7 +5355,11 @@ struct file_operations ll_file_operations_noflock = {
        .release        = ll_file_release,
        .mmap           = ll_file_mmap,
        .llseek         = ll_file_seek,
-       .splice_read    = ll_file_splice_read,
+#ifndef HAVE_DEFAULT_FILE_SPLICE_READ_EXPORT
+       .splice_read    = generic_file_splice_read,
+#else
+       .splice_read    = pcc_file_splice_read,
+#endif
        .fsync          = ll_fsync,
        .flush          = ll_flush,
        .flock          = ll_file_noflock,