diff options
Diffstat (limited to 'works/life/operating-system-course-design')
4 files changed, 289 insertions, 0 deletions
| diff --git a/works/life/operating-system-course-design/0001-crupesteam-fat-patch.patch b/works/life/operating-system-course-design/0001-crupesteam-fat-patch.patch new file mode 100644 index 0000000..9f23ebb --- /dev/null +++ b/works/life/operating-system-course-design/0001-crupesteam-fat-patch.patch @@ -0,0 +1,163 @@ +From e88345bbb9a4027033254933ee2e1cad9feab6d6 Mon Sep 17 00:00:00 2001 +From: crupest <crupest@outlook.com> +Date: Thu, 24 Jun 2021 16:00:04 +0800 +Subject: [PATCH] crupesteam fat patch. + +--- + fs/fat/cache.c | 64 ++++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 57 insertions(+), 7 deletions(-) + +diff --git a/fs/fat/cache.c b/fs/fat/cache.c +index 738e427e2d21..4f32bfee6d27 100644 +--- a/fs/fat/cache.c ++++ b/fs/fat/cache.c +@@ -15,11 +15,15 @@ + /* this must be > 0. */ + #define FAT_MAX_CACHE	8 +  ++#define FAT_CACHE_PREV_CLUSTER_COUNT 8 ++ + struct fat_cache { + 	struct list_head cache_list; + 	int nr_contig;	/* number of contiguous clusters */ + 	int fcluster;	/* cluster number in the file. */ + 	int dcluster;	/* cluster number on disk. */ ++	int prev_clusters_count; ++	int prev_clusters[FAT_CACHE_PREV_CLUSTER_COUNT]; + }; +  + struct fat_cache_id { +@@ -27,6 +31,8 @@ struct fat_cache_id { + 	int nr_contig; + 	int fcluster; + 	int dcluster; ++	int prev_clusters_count; ++	int prev_clusters[FAT_CACHE_PREV_CLUSTER_COUNT]; + }; +  + static inline int fat_max_cache(struct inode *inode) +@@ -84,10 +90,17 @@ static int fat_cache_lookup(struct inode *inode, int fclus, + 	static struct fat_cache nohit = { .fcluster = 0, }; +  + 	struct fat_cache *hit = &nohit, *p; +-	int offset = -1; ++	int offset = INT_MIN; +  + 	spin_lock(&MSDOS_I(inode)->cache_lru_lock); + 	list_for_each_entry(p, &MSDOS_I(inode)->cache_lru, cache_list) { ++		if (p->fcluster > fclus && ++			p->fcluster - p->prev_clusters_count <= fclus) { ++				hit = p; ++				offset = fclus - hit->fcluster; ++				break; ++		} ++ + 		/* Find the cache of "fclus" or nearest cache. */ + 		if (p->fcluster <= fclus && hit->fcluster < p->fcluster) { + 			hit = p; +@@ -107,7 +120,11 @@ static int fat_cache_lookup(struct inode *inode, int fclus, + 		cid->fcluster = hit->fcluster; + 		cid->dcluster = hit->dcluster; + 		*cached_fclus = cid->fcluster + offset; +-		*cached_dclus = cid->dcluster + offset; ++ ++		if (offset < 0) ++			*cached_dclus = hit->prev_clusters[hit->prev_clusters_count + offset]; ++		else ++			*cached_dclus = cid->dcluster + offset; + 	} + 	spin_unlock(&MSDOS_I(inode)->cache_lru_lock); +  +@@ -145,6 +162,8 @@ static void fat_cache_add(struct inode *inode, struct fat_cache_id *new) +  + 	cache = fat_cache_merge(inode, new); + 	if (cache == NULL) { ++		int i; ++ + 		if (MSDOS_I(inode)->nr_caches < fat_max_cache(inode)) { + 			MSDOS_I(inode)->nr_caches++; + 			spin_unlock(&MSDOS_I(inode)->cache_lru_lock); +@@ -172,6 +191,10 @@ static void fat_cache_add(struct inode *inode, struct fat_cache_id *new) + 		cache->fcluster = new->fcluster; + 		cache->dcluster = new->dcluster; + 		cache->nr_contig = new->nr_contig; ++		cache->prev_clusters_count = new->prev_clusters_count; ++		for (i = 0; i < new->prev_clusters_count; i++) { ++			cache->prev_clusters[i] = new->prev_clusters[i]; ++		} + 	} + out_update_lru: + 	fat_cache_update_lru(inode, cache); +@@ -220,6 +243,7 @@ static inline void cache_init(struct fat_cache_id *cid, int fclus, int dclus) + 	cid->fcluster = fclus; + 	cid->dcluster = dclus; + 	cid->nr_contig = 0; ++	cid->prev_clusters_count = 0; + } +  + int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) +@@ -230,6 +254,10 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) + 	struct fat_entry fatent; + 	struct fat_cache_id cid; + 	int nr; ++	int offset; ++	int prev_cluster[FAT_CACHE_PREV_CLUSTER_COUNT]; ++	int prev_cluster_current = 0; ++	int prev_cluster_count = 0; +  + 	BUG_ON(MSDOS_I(inode)->i_start == 0); +  +@@ -244,12 +272,13 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) + 	if (cluster == 0) + 		return 0; +  +-	if (fat_cache_lookup(inode, cluster, &cid, fclus, dclus) < 0) { +-		/* +-		 * dummy, always not contiguous +-		 * This is reinitialized by cache_init(), later. +-		 */ ++	offset = fat_cache_lookup(inode, cluster, &cid, fclus, dclus); ++ ++	if (offset == INT_MIN) { + 		cache_init(&cid, -1, -1); ++	} else if (offset < 0) { ++		nr = 0; ++		goto out; + 	} +  + 	fatent_init(&fatent); +@@ -278,10 +307,31 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) + 		} + 		(*fclus)++; + 		*dclus = nr; ++ ++		prev_cluster[prev_cluster_current++] = *dclus; ++		if (prev_cluster_count < FAT_CACHE_PREV_CLUSTER_COUNT) { ++			prev_cluster_count++; ++		} ++		prev_cluster_current %= FAT_CACHE_PREV_CLUSTER_COUNT; ++ + 		if (!cache_contiguous(&cid, *dclus)) + 			cache_init(&cid, *fclus, *dclus); + 	} + 	nr = 0; ++ ++	if (cid.nr_contig + 1 < FAT_CACHE_PREV_CLUSTER_COUNT) { ++		int i; ++		int count = prev_cluster_count - cid.nr_contig - 1; ++		int start = ((prev_cluster_current - prev_cluster_count) ++			+ FAT_CACHE_PREV_CLUSTER_COUNT) % FAT_CACHE_PREV_CLUSTER_COUNT;  ++ ++		cid.prev_clusters_count = count; ++ ++		for (i = 0; i < count; i++) { ++			cid.prev_clusters[i] = prev_cluster[(start + i) % FAT_CACHE_PREV_CLUSTER_COUNT]; ++		} ++	} ++ + 	fat_cache_add(inode, &cid); + out: + 	fatent_brelse(&fatent); +--  +2.32.0 + diff --git a/works/life/operating-system-course-design/Vagrantfile b/works/life/operating-system-course-design/Vagrantfile new file mode 100644 index 0000000..8f4509f --- /dev/null +++ b/works/life/operating-system-course-design/Vagrantfile @@ -0,0 +1,72 @@ +# -*- mode: ruby -*-
 +# vi: set ft=ruby :
 +
 +# All Vagrant configuration is done below. The "2" in Vagrant.configure
 +# configures the configuration version (we support older styles for
 +# backwards compatibility). Please don't change it unless you know what
 +# you're doing.
 +Vagrant.configure("2") do |config|
 +  # The most common configuration options are documented and commented below.
 +  # For a complete reference, please see the online documentation at
 +  # https://docs.vagrantup.com.
 +
 +  # Every Vagrant development environment requires a box. You can search for
 +  # boxes at https://vagrantcloud.com/search.
 +  config.vm.box = "archlinux/archlinux"
 +
 +  config.vm.disk :disk, size: "10GB", name: "fat_test"
 +
 +  # Disable automatic box update checking. If you disable this, then
 +  # boxes will only be checked for updates when the user runs
 +  # `vagrant box outdated`. This is not recommended.
 +  # config.vm.box_check_update = false
 +
 +  # Create a forwarded port mapping which allows access to a specific port
 +  # within the machine from a port on the host machine. In the example below,
 +  # accessing "localhost:8080" will access port 80 on the guest machine.
 +  # NOTE: This will enable public access to the opened port
 +  # config.vm.network "forwarded_port", guest: 80, host: 8080
 +
 +  # Create a forwarded port mapping which allows access to a specific port
 +  # within the machine from a port on the host machine and only allow access
 +  # via 127.0.0.1 to disable public access
 +  # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
 +
 +  # Create a private network, which allows host-only access to the machine
 +  # using a specific IP.
 +  # config.vm.network "private_network", ip: "192.168.33.10"
 +
 +  # Create a public network, which generally matched to bridged network.
 +  # Bridged networks make the machine appear as another physical device on
 +  # your network.
 +  # config.vm.network "public_network"
 +
 +  # Share an additional folder to the guest VM. The first argument is
 +  # the path on the host to the actual folder. The second argument is
 +  # the path on the guest to mount the folder. And the optional third
 +  # argument is a set of non-required options.
 +  # config.vm.synced_folder "../data", "/vagrant_data"
 +
 +  # Provider-specific configuration so you can fine-tune various
 +  # backing providers for Vagrant. These expose provider-specific options.
 +  # Example for VirtualBox:
 +  #
 +  # config.vm.provider "virtualbox" do |vb|
 +  #   # Display the VirtualBox GUI when booting the machine
 +  #   vb.gui = true
 +  #
 +  #   # Customize the amount of memory on the VM:
 +  #   vb.memory = "1024"
 +  # end
 +  #
 +  # View the documentation for the provider you are using for more
 +  # information on available options.
 +
 +  # Enable provisioning with a shell script. Additional provisioners such as
 +  # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
 +  # documentation for more information about their specific syntax and use.
 +  # config.vm.provision "shell", inline: <<-SHELL
 +  #   apt-get update
 +  #   apt-get install -y apache2
 +  # SHELL
 +end
 diff --git a/works/life/operating-system-course-design/create-file.bash b/works/life/operating-system-course-design/create-file.bash new file mode 100644 index 0000000..4aa98b8 --- /dev/null +++ b/works/life/operating-system-course-design/create-file.bash @@ -0,0 +1,29 @@ + +let dir_count=256 +let file_count=500; + +for dir_iter in `seq $dir_count`; do +    mkdir -p /mnt/fat-test/$dir_iter +    for iter in `seq $file_count`; do +        truncate -s 4KB /mnt/fat-test/$dir_iter/$iter; +    done +    echo "Created 500 files in dir $dir_iter"; +done + +df + +for dir_iter in `seq $dir_count`; do +    mkdir -p /mnt/fat-test/$dir_iter +    for iter in `seq $file_count`; do +        if (($iter % 2 == 0)); then +            rm /mnt/fat-test/$dir_iter/$iter; +        fi +    done +    echo "Deleted 250 files in dir $dir_iter"; +done + +df + +truncate -s 200MB /mnt/fat-test/big; + +df diff --git a/works/life/operating-system-course-design/read-file.c b/works/life/operating-system-course-design/read-file.c new file mode 100644 index 0000000..fe71f94 --- /dev/null +++ b/works/life/operating-system-course-design/read-file.c @@ -0,0 +1,25 @@ +#include <bits/types.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdio.h> + +int main() { +  int fd = open("/mnt/fat-test/big", O_RDONLY); +  if (fd < 0) +    return 1; + +  __off_t size = lseek(fd, 0, SEEK_END); +  if (size < 0) +    return 2; + +  for (__off_t i = 512; i <= size; i += 512) { +    if (lseek(fd, size - i, SEEK_SET) < 0) +      return 3; +    char buffer[512]; +    if (read(fd, buffer, 512) < 0) +      return 4; +  } + +  return 0; +} | 
