Whamcloud - gitweb
b=18801
authoranserper <anserper>
Thu, 16 Jul 2009 09:03:28 +0000 (09:03 +0000)
committeranserper <anserper>
Thu, 16 Jul 2009 09:03:28 +0000 (09:03 +0000)
  i=Oleg Drokin
  i=Alexander Zarochentsev

  atime, mtime and additional POSIX compliance stuff for direct I/O and lockless I/O

lustre/autoconf/lustre-core.m4
lustre/include/linux/lustre_compat25.h
lustre/llite/file.c
lustre/tests/sanityN.sh

index be856f9..1d2eaf3 100644 (file)
@@ -964,6 +964,23 @@ LB_LINUX_TRY_COMPILE([
 EXTRA_KCFLAGS="$tmp_flags"
 ])
 
+# LC_FILE_UPDATE_TIME
+# 2.6.9 has inode_update_time instead of file_update_time
+AC_DEFUN([LC_FILE_UPDATE_TIME],
+[AC_MSG_CHECKING([if file_update_time is exported])
+LB_LINUX_TRY_COMPILE([
+        #include <linux/fs.h>
+],[
+        file_update_time(NULL);
+],[
+        AC_MSG_RESULT(yes)
+        AC_DEFINE(HAVE_FILE_UPDATE_TIME, 1,
+                [use file_update_time])
+],[
+       AC_MSG_RESULT(no)
+])
+])
+
 # LC_FILE_WRITEV
 # 2.6.19 replaced writev with aio_write
 AC_DEFUN([LC_FILE_WRITEV],
@@ -982,6 +999,7 @@ LB_LINUX_TRY_COMPILE([
 ])
 ])
 
+
 # LC_GENERIC_FILE_READ
 # 2.6.19 replaced readv with aio_read
 AC_DEFUN([LC_FILE_READV],
@@ -1875,6 +1893,7 @@ AC_DEFUN([LC_PROG_LINUX],
           # 2.6.19
           LC_INODE_BLKSIZE
           LC_VFS_READDIR_U64_INO
+          LC_FILE_UPDATE_TIME
           LC_FILE_WRITEV
           LC_FILE_READV
 
index 62eeb47..34ea09e 100644 (file)
@@ -615,5 +615,11 @@ static inline int ll_quota_off(struct super_block *sb, int off, int remount)
 #define bio_hw_segments(q, bio) 0
 #endif
 
+#ifdef HAVE_FILE_UPDATE_TIME
+#define ll_update_time(file) file_update_time(file)
+#else
+#define ll_update_time(file) inode_update_time(file->f_mapping->host, 1)
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _COMPAT25_H */
index dfdd142..3425a46 100644 (file)
@@ -1649,9 +1649,10 @@ repeat:
         } else {
                 retval = ll_direct_IO(READ, file, iov_copy, *ppos, nr_segs, 0);
                 if (retval > 0) {
-                       lprocfs_counter_add(sbi->ll_stats,
-                                           LPROC_LL_LOCKLESS_READ,
-                                           (long)retval);
+                        file_accessed(file);
+                        lprocfs_counter_add(sbi->ll_stats,
+                                            LPROC_LL_LOCKLESS_READ,
+                                            (long)retval);
                         *ppos += retval;
                 }
         }
@@ -1696,6 +1697,56 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count,
 #endif
 }
 
+/* iov_shorten from linux kernel */
+static unsigned long ll_iov_shorten(struct iovec *iov,
+                                    unsigned long nr_segs,
+                                    size_t to)
+{
+        unsigned long seg = 0;
+        size_t len = 0;
+
+        while (seg < nr_segs) {
+                seg++;
+                if (len + iov->iov_len >= to) {
+                        iov->iov_len = to - len;
+                        break;
+                }
+                len += iov->iov_len;
+                iov++;
+        }
+        return seg;
+}
+
+/* 2.6.22 and 2.6.27 export this as generic_segment_checks */
+static int ll_generic_segment_checks(const struct iovec *iov,
+                                     unsigned long *nr_segs,
+                                     size_t *count,
+                                     int access_flags)
+{
+        unsigned long   seg;
+        size_t cnt = 0;
+        for (seg = 0; seg < *nr_segs; seg++) {
+                const struct iovec *iv = &iov[seg];
+
+                /*
+                 * If any segment has a negative length, or the cumulative
+                 * length ever wraps negative then return -EINVAL.
+                 */
+                cnt += iv->iov_len;
+                if (unlikely((ssize_t)(cnt|iv->iov_len) < 0))
+                        return -EINVAL;
+                if (access_ok(access_flags, iv->iov_base, iv->iov_len))
+                        continue;
+                if (seg == 0)
+                        return -EFAULT;
+                *nr_segs = seg;
+                cnt -= iv->iov_len;  /* This segment is no good */
+                break;
+        }
+        *count = cnt;
+        return 0;
+}
+
 /*
  * Write to a file (through the page cache).
  */
@@ -1860,11 +1911,34 @@ repeat:
                                                 *ppos);
 #endif
         } else {
+                size_t ocount, ncount;
+
+                retval = ll_generic_segment_checks(iov_copy, &nrsegs_copy,
+                                                   &ocount, VERIFY_READ);
+                if (retval)
+                        GOTO(out, retval);
+
+                retval = generic_write_checks(file, ppos, &ncount, 0);
+                if (retval)
+                        GOTO(out, retval);
+
+                if (unlikely(ocount != ncount)) {
+                        /* we are allowed to modify the original iov too */
+                        nrsegs_copy = ll_iov_shorten(iov_copy, nrsegs_copy,
+                                                     ncount);
+                        chunk = 0; /* no repetition after the short write */
+                }
+
+                retval = ll_remove_suid(file, file->f_vfsmnt);
+                if (retval)
+                        GOTO(out, retval);
+
+                ll_update_time(file);
                 retval = ll_direct_IO(WRITE, file, iov_copy, *ppos, nr_segs, 0);
                 if (retval > 0) {
-                       lprocfs_counter_add(sbi->ll_stats,
-                                           LPROC_LL_LOCKLESS_WRITE,
-                                           (long)retval);
+                        lprocfs_counter_add(sbi->ll_stats,
+                                            LPROC_LL_LOCKLESS_WRITE,
+                                            (long)retval);
                         *ppos += retval;
                 }
         }
index e3fb5d6..7d42930 100644 (file)
@@ -880,6 +880,23 @@ test_38() { # bug 18801, based on the code of test_32b
 }
 run_test 38 "lockless i/o with O_DIRECT and unaligned writes"
 
+test_39() {
+        local originaltime
+        local updatedtime
+        local delay=3
+
+        touch $DIR1/$tfile
+        originaltime=$(stat -c %Y $DIR1/$tfile)
+        log "original modification time is $originaltime"
+        sleep $delay
+        multiop $DIR1/$tfile oO_DIRECT:O_WRONLY:w$((10*1048576))c || error "multiop has failed"
+        updatedtime=$(stat -c %Y $DIR2/$tfile)
+        log "updated modification time is $updatedtime"
+        [ $((updatedtime - originaltime)) -ge $delay ] || error "invalid modification time"
+        rm -rf $DIR/$tfile
+}
+run_test 39 "direct I/O writes should update mtime ========="
+
 log "cleanup: ======================================================"
 
 check_and_cleanup_lustre