Whamcloud - gitweb
LU-16695 llite: switch to ki_flags from f_flags 93/50493/11
authorPatrick Farrell <pfarrell@whamcloud.com>
Fri, 31 Mar 2023 21:33:40 +0000 (17:33 -0400)
committerOleg Drokin <green@whamcloud.com>
Wed, 13 Dec 2023 12:19:46 +0000 (12:19 +0000)
There are possible races between IO checking f_flags and
fcntl changing f_flags.  The kernel fixed most of these by
copying most of the file flags in to the iocb.

Let's follow on and use those copied flags.  This also lets
us change them if we want, since they're now local to the
specific IO.

Signed-off-by: Patrick Farrell <pfarrell@whamcloud.com>
Signed-off-by: Guillaume Courrier <guillaume.courrier@cea.fr>
Change-Id: Ib98cccec0e7888865ec10dc5f76f1d9917a1aef7
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/50493
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Reviewed-by: Etienne AUJAMES <eaujames@ddn.com>
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/llite/rw.c
lustre/llite/rw26.c
lustre/llite/vvp_io.c

index ddaedaf..83a9d07 100644 (file)
@@ -1633,26 +1633,21 @@ void ll_io_init(struct cl_io *io, struct file *file, enum cl_io_type iot,
 {
        struct inode *inode = file_inode(file);
        struct ll_file_data *fd  = file->private_data;
+       int flags = vvp_io_args_flags(file, args);
 
        io->u.ci_rw.crw_nonblock = file->f_flags & O_NONBLOCK;
        io->ci_lock_no_expand = fd->ll_lock_no_expand;
 
        if (iot == CIT_WRITE) {
-               io->u.ci_wr.wr_append = !!(file->f_flags & O_APPEND);
-               io->u.ci_wr.wr_sync   = !!(file->f_flags & O_SYNC ||
-                                          file->f_flags & O_DIRECT ||
+               io->u.ci_wr.wr_append = iocb_ki_flags_check(flags, APPEND);
+               io->u.ci_wr.wr_sync   = !!(iocb_ki_flags_check(flags, SYNC) ||
+                                          iocb_ki_flags_check(flags, APPEND) ||
+                                          iocb_ki_flags_check(flags, DSYNC) ||
                                           IS_SYNC(inode));
-#ifdef HAVE_GENERIC_WRITE_SYNC_2ARGS
-               io->u.ci_wr.wr_sync  |= !!(args &&
-                                          (args->u.normal.via_iocb->ki_flags &
-                                           IOCB_DSYNC));
-#endif
        }
 
 #ifdef IOCB_NOWAIT
-       io->ci_iocb_nowait = !!(args &&
-                               (args->u.normal.via_iocb->ki_flags &
-                                IOCB_NOWAIT));
+       io->ci_iocb_nowait = iocb_ki_flags_check(flags, NOWAIT);
 #endif
 
        io->ci_obj = ll_i2info(inode)->lli_clob;
@@ -1660,7 +1655,7 @@ void ll_io_init(struct cl_io *io, struct file *file, enum cl_io_type iot,
        if (ll_file_nolock(file)) {
                io->ci_lockreq = CILR_NEVER;
                io->ci_no_srvlock = 1;
-       } else if (file->f_flags & O_APPEND) {
+       } else if (iocb_ki_flags_check(flags, APPEND)) {
                io->ci_lockreq = CILR_MANDATORY;
        }
        io->ci_noatime = file_is_noatime(file);
@@ -1720,9 +1715,10 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
        struct ll_sb_info *sbi = ll_i2sbi(inode);
        struct ll_file_data *fd  = file->private_data;
        struct range_lock range;
-       bool range_locked = false;
        struct cl_io *io;
+       bool range_locked = false;
        ssize_t result = 0;
+       int flags = vvp_io_args_flags(file, args);
        int rc = 0;
        int rc2 = 0;
        int retries = 1000;
@@ -1743,8 +1739,8 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
                             sbi->ll_cache->ccc_lru_max >> 2) << PAGE_SHIFT;
 
        io = vvp_env_thread_io(env);
-       if (file->f_flags & O_DIRECT) {
-               if (file->f_flags & O_APPEND)
+       if (iocb_ki_flags_check(flags, DIRECT)) {
+               if (iocb_ki_flags_check(flags, APPEND))
                        dio_lock = 1;
                if (!is_sync_kiocb(args->u.normal.via_iocb))
                        is_aio = true;
@@ -1771,7 +1767,7 @@ restart:
         * if we have small max_cached_mb but large block IO issued, io
         * could not be finished and blocked whole client.
         */
-       if (file->f_flags & O_DIRECT || bytes < max_io_bytes) {
+       if (iocb_ki_flags_check(flags, DIRECT) || bytes < max_io_bytes) {
                per_bytes = bytes;
                partial_io = false;
        } else {
@@ -1786,7 +1782,7 @@ restart:
        io->ci_parallel_dio = is_parallel_dio;
 
        if (cl_io_rw_init(env, io, iot, *ppos, per_bytes) == 0) {
-               if (file->f_flags & O_APPEND)
+               if (iocb_ki_flags_check(flags, APPEND))
                        range_lock_init(&range, 0, LUSTRE_EOF);
                else
                        range_lock_init(&range, *ppos, *ppos + per_bytes - 1);
@@ -1799,7 +1795,7 @@ restart:
                 * See LU-6227 for details.
                 */
                if (((iot == CIT_WRITE) ||
-                   (iot == CIT_READ && (file->f_flags & O_DIRECT))) &&
+                   (iot == CIT_READ && iocb_ki_flags_check(flags, DIRECT))) &&
                    !(vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
                        CDEBUG(D_VFSTRACE, "Range lock "RL_FMT"\n",
                               RL_PARA(&range));
@@ -1995,6 +1991,7 @@ static ssize_t
 ll_do_fast_read(struct kiocb *iocb, struct iov_iter *iter)
 {
        struct ll_inode_info *lli = ll_i2info(file_inode(iocb->ki_filp));
+       int flags = iocb_ki_flags_get(iocb->ki_filp, iocb);
        ssize_t result;
 
        if (!ll_sbi_has_fast_read(ll_i2sbi(file_inode(iocb->ki_filp))))
@@ -2002,7 +1999,7 @@ ll_do_fast_read(struct kiocb *iocb, struct iov_iter *iter)
 
        /* NB: we can't do direct IO for fast read because it will need a lock
         * to make IO engine happy. */
-       if (iocb->ki_filp->f_flags & O_DIRECT)
+       if (iocb_ki_flags_check(flags, DIRECT))
                return 0;
 
        if (ll_layout_version_get(lli) == CL_LAYOUT_GEN_NONE)
@@ -2262,6 +2259,7 @@ static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        struct lu_env *env;
        ssize_t rc_tiny = 0, rc_normal;
        struct file *file = iocb->ki_filp;
+       int flags = iocb_ki_flags_get(file, iocb);
        __u16 refcheck;
        bool cached;
        ktime_t kstart = ktime_get();
@@ -2298,7 +2296,8 @@ static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
         * required DLM locks are held to protect file size.
         */
        if (ll_sbi_has_tiny_write(ll_i2sbi(file_inode(file))) &&
-           !(file->f_flags & (O_DIRECT | O_SYNC | O_APPEND)))
+           !(flags &
+             (ki_flag(DIRECT) | ki_flag(DSYNC) | ki_flag(SYNC) | ki_flag(APPEND))))
                rc_tiny = ll_do_tiny_write(iocb, from);
 
        /* In case of error, go on and try normal write - Only stop if tiny
index fa238a1..26e1c44 100644 (file)
@@ -318,6 +318,14 @@ struct ll_inode_info {
 #define ll_setattr(ns, de, attr)               ll_setattr(de, attr)
 #endif
 
+#ifdef IOCB_APPEND
+#define iocb_ki_flags_check(flag, name) (!!((flag) & IOCB_ ## name))
+#define ki_flag(name) IOCB_ ## name
+#else
+#define iocb_ki_flags_check(flag, name) (!!((flag) & O_ ## name))
+#define ki_flag(name) O_ ## name
+#endif
+
 static inline void ll_trunc_sem_init(struct ll_trunc_sem *sem)
 {
        atomic_set(&sem->ll_trunc_readers, 0);
@@ -1469,6 +1477,22 @@ struct vvp_io_args {
         } u;
 };
 
+static inline unsigned int iocb_ki_flags_get(const struct file *file,
+                                            const struct kiocb *iocb)
+{
+#ifdef IOCB_APPEND
+       return iocb ? iocb->ki_flags : 0;
+#else
+       return file->f_flags;
+#endif
+}
+
+static inline unsigned int vvp_io_args_flags(const struct file *file,
+                                            const struct vvp_io_args *args)
+{
+       return iocb_ki_flags_get(file, args ? args->u.normal.via_iocb : NULL);
+}
+
 enum lcc_type {
        LCC_RW = 1,
        LCC_MMAP
index 7a060e6..34f083a 100644 (file)
@@ -2362,13 +2362,15 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr,
                                /* Call to ll_io_zero_page is not necessary if
                                 * truncating on PAGE_SIZE boundary, because
                                 * whole pages will be wiped.
-                                * In case of Direct IO, all we need is to set
-                                * new size.
+                                *
+                                * an exception is when working with the
+                                * raw ciphertext - in that case, we need to
+                                * encrypt those zeroes
                                 */
                                if (attr->ia_valid & ATTR_SIZE &&
                                    attr->ia_size & ~PAGE_MASK &&
                                    !(attr->ia_valid & ATTR_FILE &&
-                                     attr->ia_file->f_flags & O_DIRECT)) {
+                                     attr->ia_file->f_flags & O_CIPHERTEXT)) {
                                        pgoff_t offset =
                                                attr->ia_size & (PAGE_SIZE - 1);
 
index d03a729..616b18a 100644 (file)
@@ -1908,7 +1908,10 @@ int ll_readpage(struct file *file, struct page *vmpage)
        struct ll_cl_context *lcc;
        struct cl_io *io = NULL;
        struct cl_page *page;
+       struct vvp_io *vio;
        int result;
+       int flags;
+
        ENTRY;
 
        if (CFS_FAIL_PRECHECK(OBD_FAIL_LLITE_READPAGE_PAUSE)) {
@@ -2051,12 +2054,14 @@ int ll_readpage(struct file *file, struct page *vmpage)
                }
        }
 
+       vio = vvp_env_io(env);
        /**
         * Direct read can fall back to buffered read, but DIO is done
         * with lockless i/o, and buffered requires LDLM locking, so in
         * this case we must restart without lockless.
         */
-       if (file->f_flags & O_DIRECT &&
+       flags = iocb_ki_flags_get(file, vio->vui_iocb);
+       if (iocb_ki_flags_check(flags, DIRECT) &&
            lcc && lcc->lcc_type == LCC_RW &&
            !io->ci_dio_lock) {
                unlock_page(vmpage);
index a28d328..298b8f1 100644 (file)
@@ -803,6 +803,7 @@ static int ll_write_begin(struct file *file, struct address_space *mapping,
 {
        struct ll_cl_context *lcc = NULL;
        const struct lu_env  *env = NULL;
+       struct vvp_io *vio;
        struct cl_io   *io = NULL;
        struct cl_page *page = NULL;
        struct inode *inode = file_inode(file);
@@ -812,6 +813,7 @@ static int ll_write_begin(struct file *file, struct address_space *mapping,
        unsigned from = pos & (PAGE_SIZE - 1);
        unsigned to = from + len;
        int result = 0;
+       int iocb_flags;
        ENTRY;
 
        CDEBUG(D_VFSTRACE, "Writing %lu of %d to %d bytes\n", index, from, len);
@@ -825,8 +827,10 @@ static int ll_write_begin(struct file *file, struct address_space *mapping,
 
        env = lcc->lcc_env;
        io  = lcc->lcc_io;
+       vio = vvp_env_io(env);
 
-       if (file->f_flags & O_DIRECT) {
+       iocb_flags = iocb_ki_flags_get(file, vio->vui_iocb);
+       if (iocb_ki_flags_check(iocb_flags, DIRECT)) {
                /* direct IO failed because it couldn't clean up cached pages,
                 * this causes a problem for mirror write because the cached
                 * page may belong to another mirror, which will result in
index 4b27dec..8e659bf 100644 (file)
@@ -569,12 +569,16 @@ static int vvp_io_rw_lock(const struct lu_env *env, struct cl_io *io,
        if (io->ci_lock_no_expand)
                ast_flags |= CEF_LOCK_NO_EXPAND;
        if (vio->vui_fd) {
+               int flags;
+
                /* Group lock held means no lockless any more */
                if (vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)
                        io->ci_dio_lock = 1;
 
+               flags = iocb_ki_flags_get(vio->vui_iocb->ki_filp,
+                                         vio->vui_iocb);
                if (ll_file_nolock(vio->vui_fd->fd_file) ||
-                   (vio->vui_fd->fd_file->f_flags & O_DIRECT &&
+                   (iocb_ki_flags_check(flags, DIRECT) &&
                     !io->ci_dio_lock))
                        ast_flags |= CEF_NEVER;
        }
@@ -834,6 +838,7 @@ static int vvp_io_read_start(const struct lu_env *env,
        int total_bytes_read = 0;
        struct iov_iter iter;
        pgoff_t page_offset;
+       int flags;
 
        ENTRY;
 
@@ -853,7 +858,8 @@ static int vvp_io_read_start(const struct lu_env *env,
        if (!can_populate_pages(env, io, inode))
                RETURN(0);
 
-       if (!(file->f_flags & O_DIRECT)) {
+       flags = iocb_ki_flags_get(file, vio->vui_iocb);
+       if (!iocb_ki_flags_check(flags, DIRECT)) {
                result = cl_io_lru_reserve(env, io, pos, crw_bytes);
                if (result)
                        RETURN(result);
@@ -1275,6 +1281,7 @@ static int vvp_io_write_start(const struct lu_env *env,
        size_t ci_bytes = io->ci_bytes;
        struct iov_iter iter;
        size_t written = 0;
+       int flags;
 
        ENTRY;
 
@@ -1321,7 +1328,8 @@ static int vvp_io_write_start(const struct lu_env *env,
        if (CFS_FAIL_CHECK(OBD_FAIL_LLITE_IMUTEX_NOSEC) && lock_inode)
                RETURN(-EINVAL);
 
-       if (!(file->f_flags & O_DIRECT)) {
+       flags = iocb_ki_flags_get(file, vio->vui_iocb);
+       if (!iocb_ki_flags_check(flags, DIRECT)) {
                result = cl_io_lru_reserve(env, io, pos, crw_bytes);
                if (result)
                        RETURN(result);