Whamcloud - gitweb
LU-13669 llite: make readahead aware of hints
[fs/lustre-release.git] / lustre / llite / file.c
index a48c0f8..2e0ca9e 100644 (file)
@@ -730,6 +730,8 @@ static int ll_local_open(struct file *file, struct lookup_intent *it,
        file->private_data = fd;
        ll_readahead_init(inode, &fd->fd_ras);
        fd->fd_omode = it->it_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
+       /* turn off the kernel's read-ahead */
+       file->f_ra.ra_pages = 0;
 
        /* ll_cl_context initialize */
        rwlock_init(&fd->fd_lock);
@@ -930,9 +932,6 @@ restart:
 
        mutex_unlock(&lli->lli_och_mutex);
 
-       /* lockless for direct IO so that it can do IO in parallel */
-       if (file->f_flags & O_DIRECT)
-               fd->fd_flags |= LL_FILE_LOCKLESS_IO;
        fd = NULL;
 
        /* Must do this outside lli_och_mutex lock to prevent deadlock where
@@ -1548,7 +1547,7 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
        struct cl_io *io;
        ssize_t result = 0;
        int rc = 0;
-       unsigned int retried = 0, ignore_lockless = 0;
+       unsigned int retried = 0, dio_lock = 0;
        bool is_aio = false;
        struct cl_dio_aio *ci_aio = NULL;
 
@@ -1571,7 +1570,7 @@ restart:
        io = vvp_env_thread_io(env);
        ll_io_init(io, file, iot, args);
        io->ci_aio = ci_aio;
-       io->ci_ignore_lockless = ignore_lockless;
+       io->ci_dio_lock = dio_lock;
        io->ci_ndelay_tried = retried;
 
        if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) {
@@ -1650,7 +1649,7 @@ out:
                       *ppos, count, result, rc);
                /* preserve the tried count for FLR */
                retried = io->ci_ndelay_tried;
-               ignore_lockless = io->ci_ignore_lockless;
+               dio_lock = io->ci_dio_lock;
                goto restart;
        }
 
@@ -4080,28 +4079,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));
@@ -4710,23 +4760,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) {
@@ -4766,7 +4823,7 @@ static int ll_merge_md_attr(struct inode *inode)
                RETURN(0);
 
        down_read(&lli->lli_lsm_sem);
-       rc = md_merge_attr(ll_i2mdexp(inode), &lli->lli_fid, lli->lli_lsm_md,
+       rc = md_merge_attr(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md,
                           &attr, ll_md_blocking_ast);
        up_read(&lli->lli_lsm_sem);
        if (rc != 0)
@@ -5028,6 +5085,14 @@ long ll_fallocate(struct file *filp, int mode, loff_t offset, loff_t len)
        ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FALLOCATE, 1);
 
        rc = cl_falloc(inode, mode, offset, len);
+       /*
+        * ENOTSUPP (524) is an NFSv3 specific error code erroneously
+        * used by Lustre in several places. Retuning it here would
+        * confuse applications that explicity test for EOPNOTSUPP
+        * (95) and fall back to ftruncate().
+        */
+       if (rc == -ENOTSUPP)
+               rc = -EOPNOTSUPP;
 
        RETURN(rc);
 }
@@ -5058,6 +5123,15 @@ static int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
 
        rc = ll_do_fiemap(inode, fiemap, num_bytes);
 
+       if (IS_ENCRYPTED(inode)) {
+               int i;
+
+               for (i = 0; i < fiemap->fm_mapped_extents; i++)
+                       fiemap->fm_extents[i].fe_flags |=
+                               FIEMAP_EXTENT_DATA_ENCRYPTED |
+                               FIEMAP_EXTENT_ENCODED;
+       }
+
        fieinfo->fi_flags = fiemap->fm_flags;
        fieinfo->fi_extents_mapped = fiemap->fm_mapped_extents;
        if (extent_count > 0 &&