hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/fs/incfs/vfs.c
....@@ -5,6 +5,7 @@
55
66 #include <linux/blkdev.h>
77 #include <linux/compat.h>
8
+#include <linux/delay.h>
89 #include <linux/file.h>
910 #include <linux/fs.h>
1011 #include <linux/fs_stack.h>
....@@ -477,7 +478,8 @@
477478
478479 static int read_single_page_timeouts(struct data_file *df, struct file *f,
479480 int block_index, struct mem_range range,
480
- struct mem_range tmp)
481
+ struct mem_range tmp,
482
+ unsigned int *delayed_min_us)
481483 {
482484 struct mount_info *mi = df->df_mount_info;
483485 struct incfs_read_data_file_timeouts timeouts = {
....@@ -509,7 +511,23 @@
509511 }
510512
511513 return incfs_read_data_file_block(range, f, block_index, tmp,
512
- &timeouts);
514
+ &timeouts, delayed_min_us);
515
+}
516
+
517
+static int usleep_interruptible(u32 us)
518
+{
519
+ /* See:
520
+ * https://www.kernel.org/doc/Documentation/timers/timers-howto.txt
521
+ * for explanation
522
+ */
523
+ if (us < 10) {
524
+ udelay(us);
525
+ return 0;
526
+ } else if (us < 20000) {
527
+ usleep_range(us, us + us / 10);
528
+ return 0;
529
+ } else
530
+ return msleep_interruptible(us / 1000);
513531 }
514532
515533 static int read_single_page(struct file *f, struct page *page)
....@@ -522,6 +540,7 @@
522540 int result = 0;
523541 void *page_start;
524542 int block_index;
543
+ unsigned int delayed_min_us = 0;
525544
526545 if (!df) {
527546 SetPageError(page);
....@@ -547,7 +566,8 @@
547566 bytes_to_read = min_t(loff_t, size - offset, PAGE_SIZE);
548567
549568 read_result = read_single_page_timeouts(df, f, block_index,
550
- range(page_start, bytes_to_read), tmp);
569
+ range(page_start, bytes_to_read), tmp,
570
+ &delayed_min_us);
551571
552572 free_pages((unsigned long)tmp.data, get_order(tmp.len));
553573 } else {
....@@ -569,6 +589,8 @@
569589 flush_dcache_page(page);
570590 kunmap(page);
571591 unlock_page(page);
592
+ if (delayed_min_us)
593
+ usleep_interruptible(delayed_min_us);
572594 return result;
573595 }
574596
....@@ -662,8 +684,7 @@
662684 dput(file);
663685 }
664686
665
-static void maybe_delete_incomplete_file(struct file *f,
666
- struct data_file *df)
687
+static void handle_file_completed(struct file *f, struct data_file *df)
667688 {
668689 struct backing_file_context *bfc;
669690 struct mount_info *mi = df->df_mount_info;
....@@ -671,9 +692,6 @@
671692 struct dentry *incomplete_file_dentry = NULL;
672693 const struct cred *old_cred = override_creds(mi->mi_owner);
673694 int error;
674
-
675
- if (atomic_read(&df->df_data_blocks_written) < df->df_data_block_count)
676
- goto out;
677695
678696 /* Truncate file to remove any preallocated space */
679697 bfc = df->df_backing_file_context;
....@@ -733,6 +751,7 @@
733751 u8 *data_buf = NULL;
734752 ssize_t error = 0;
735753 int i = 0;
754
+ bool complete = false;
736755
737756 if (!df)
738757 return -EBADF;
....@@ -774,7 +793,7 @@
774793 data_buf);
775794 } else {
776795 error = incfs_process_new_data_block(df, &fill_block,
777
- data_buf);
796
+ data_buf, &complete);
778797 }
779798 if (error)
780799 break;
....@@ -783,7 +802,8 @@
783802 if (data_buf)
784803 free_pages((unsigned long)data_buf, get_order(data_buf_size));
785804
786
- maybe_delete_incomplete_file(f, df);
805
+ if (complete)
806
+ handle_file_completed(f, df);
787807
788808 /*
789809 * Only report the error if no records were processed, otherwise
....@@ -1908,6 +1928,13 @@
19081928
19091929 pr_debug("incfs: unmount\n");
19101930
1931
+ /*
1932
+ * We must kill the super before freeing mi, since killing the super
1933
+ * triggers inode eviction, which triggers the final update of the
1934
+ * backing file, which uses certain information for mi
1935
+ */
1936
+ kill_anon_super(sb);
1937
+
19111938 if (mi) {
19121939 if (mi->mi_backing_dir_path.dentry)
19131940 dinode = d_inode(mi->mi_backing_dir_path.dentry);
....@@ -1923,7 +1950,6 @@
19231950 incfs_free_mount_info(mi);
19241951 sb->s_fs_info = NULL;
19251952 }
1926
- kill_anon_super(sb);
19271953 }
19281954
19291955 static int show_options(struct seq_file *m, struct dentry *root)