commit 4bfa08e4d978887b7ed12dd66c26083e6a25ee23 Author: sabaebrahimi Date: Tue Jan 21 18:12:03 2025 +0000 adding test logs --- filtered_log.txt | 2345 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2345 insertions(+) diff --git a/filtered_log.txt b/filtered_log.txt new file mode 100644 index 0000000..c1a925d --- /dev/null +++ b/filtered_log.txt @@ -0,0 +1,2345 @@ +commit 6c4996b1866958b7e53f128077f238e1c9e13894 +Author: Saba Ebrahimi <66251874+sabaebrahimi@users.noreply.github.com> +Date: Tue Jan 21 21:23:19 2025 +0330 + + Update README.md +--- + README.md | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/README.md b/README.md +index ec65f74a3..015189e9a 100644 +--- a/README.md ++++ b/README.md +@@ -30,3 +30,27 @@ Save this and make a VRemoteStorage submodule. Start your nodes with VRemoteStor + insmod server_file_module.ko + ``` + You should see the message `UDP Server: Listening on port {YOUR PORT}` if everything is done fine. ++ ++To work with remote storage in your userspace applications, you should add `O_REMOTE` flag when opening the file. Also, for opening the files that originally belonged to the node, add `O_ORIGIN` too. Example: ++```c ++#include ++#include ++#include ++#include ++#define O_REMOTE 00000020 ++#define O_ORIGIN 10000000 ++int main() { ++ int fd; ++ fd = open("YOURFILE.txt", O_RDWR | O_REMOTE | O_ORIGIN); ++ ++ char* buffer = (char* )malloc(512 * sizeof(char)); ++ ++ if (fd < 0) { ++ perror("Error openning file\n"); ++ exit(1); ++ } ++ int fsize = read(fd, buffer, 256); ++ printf("file content: %s\n", buffer); ++ free(buffer); ++} ++``` + +commit d7adae8a5fde1292d248c5a87be04603624aa8b0 +Merge: 6b148c33c b91b15c2b +Author: sabaebrahimi +Date: Tue Jan 21 16:33:14 2025 +0000 + + Merge branch 'master' of https://github.com/sabaebrahimi/VRemoteStorage + Merger master for readme + +commit 6b148c33c0975e6ca21085b58676e7b493869661 +Author: sabaebrahimi +Date: Tue Jan 21 16:30:00 2025 +0000 + + Rename README +--- + README => README.md | 0 + x.sh | 2 ++ + 2 files changed, 2 insertions(+) + +diff --git a/README b/README.md +similarity index 100% +rename from README +rename to README.md +diff --git a/x.sh b/x.sh +new file mode 100755 +index 000000000..0446d6032 +--- /dev/null ++++ b/x.sh +@@ -0,0 +1,2 @@ ++#!/bin/bash ++cd ../VRemoteStorage-submodule && make && scp server_file_module.ko 192.168.122.79: && scp server_file_module.ko 192.168.122.78: + +commit b91b15c2bf667ea6efcac52679e56de23c170c74 +Author: Saba Ebrahimi <66251874+sabaebrahimi@users.noreply.github.com> +Date: Tue Jan 21 19:56:36 2025 +0330 + + Update README +--- + README | 42 ++++++++++++++++++++++++++++-------------- + 1 file changed, 28 insertions(+), 14 deletions(-) + +diff --git a/README b/README +index fd903645e..ec65f74a3 100644 +--- a/README ++++ b/README +@@ -1,18 +1,32 @@ +-Linux kernel +-============ ++# VRemote Storage: In-kernel multi-node file management + +-There are several guides for kernel developers and users. These guides can +-be rendered in a number of formats, like HTML and PDF. Please read +-Documentation/admin-guide/README.rst first. ++## Overview ++VRemote Storage consists of 2 parts: the VRemote Storage [kernel module](https://github.com/sabaebrahimi/VRemoteStorage-submodule) and this kernel code. The kernel module runs with the kernel code to simultaneously handle messages between two nodes. ++The main job is to synchronize the shared PageCache between nodes. + +-In order to build the documentation, use ``make htmldocs`` or +-``make pdfdocs``. The formatted documentation can also be read online at: ++## How to get started ++First, clone this repository, which is the modified kernel version 6.11.6, and the [submodule](https://github.com/sabaebrahimi/VRemoteStorage-submodule). You can change the port and IPs of the nodes by modifying `fs/udp_module.c`: ++``` ++#define VM2_IP {NODE2_IP} ++#define VM1_IP {NODE1_IP} ++#define DEST_PORT {YOUR_PORT} ++``` ++Make the kernel using: ++``` ++make -j 50 ++``` ++Change the directory to the VRemoteStorage-submodule and change the MakeFile KERNEL_SOURCE with your own directory of the modified kernel: ++``` ++KERNEL_SOURCE := {Your/Path/to/VRemoteStorageKernel} ++``` + +- https://www.kernel.org/doc/html/latest/ ++Also, you can change the port by modifying server_file_module.c: ++``` ++#define SERVER_PORT {YOUR_PORT} ++``` + +-There are various text files in the Documentation/ subdirectory, +-several of them using the reStructuredText markup notation. +- +-Please read the Documentation/process/changes.rst file, as it contains the +-requirements for building and running the kernel, and information about +-the problems which may result by upgrading your kernel. ++Save this and make a VRemoteStorage submodule. Start your nodes with VRemoteStorage Kernel and copy `server_file_module.ko` in them. Append `server_file_module.ko` to their kernels using: ++``` ++insmod server_file_module.ko ++``` ++You should see the message `UDP Server: Listening on port {YOUR PORT}` if everything is done fine. + +commit b8441cb7523f806702908cd800301f117035a599 +Author: sabaebrahimi +Date: Tue Jan 21 15:41:36 2025 +0000 + + Fix writer errors +--- + fs/ext4/inode.c | 78 ++++++++++++++++++---------- + fs/fcntl.c | 2 +- + fs/udp_module.c | 109 ++++++++++++++++++++++++++++++++++----- + include/linux/fcntl.h | 2 +- + include/linux/pagemap.h | 11 ++++ + include/uapi/asm-generic/fcntl.h | 1 + + mm/filemap.c | 73 ++++++++++++++++++++++---- + 7 files changed, 225 insertions(+), 51 deletions(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index b8bc65b40..30227ee4b 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -49,6 +49,8 @@ + + #include + ++int print_mamad = 0; ++ + static __u32 ext4_inode_csum(struct inode *inode, struct ext4_inode *raw, + struct ext4_inode_info *ei) + { +@@ -2924,29 +2926,29 @@ static int ext4_nonda_switch(struct super_block *sb) + return 0; + } + +-// static char *get_file_name_from_inode(struct inode *inode) +-// { +-// struct dentry *dentry; +-// struct qstr dname; +-// char *filename = NULL; +- +-// /* First, get the dentry for the inode */ +-// dentry = d_find_any_alias(inode); +-// if (dentry) { +-// /* We have found the dentry, now get the filename */ +-// dname = dentry->d_name; ++static char *get_file_name_from_inode(struct inode *inode) ++{ ++ struct dentry *dentry; ++ struct qstr dname; ++ char *filename = NULL; ++ ++ /* First, get the dentry for the inode */ ++ dentry = d_find_any_alias(inode); ++ if (dentry) { ++ /* We have found the dentry, now get the filename */ ++ dname = dentry->d_name; + +-// /* Allocate memory for the filename and copy it */ +-// filename = kzalloc(dname.len + 1, GFP_KERNEL); +-// if (filename) { +-// memcpy(filename, dname.name, dname.len); +-// filename[dname.len] = '\0'; // Null-terminate the string +-// } +-// dput(dentry); // Don't forget to release the reference to the dentry +-// } +- +-// return filename; +-// } ++ /* Allocate memory for the filename and copy it */ ++ filename = kzalloc(dname.len + 1, GFP_KERNEL); ++ if (filename) { ++ memcpy(filename, dname.name, dname.len); ++ filename[dname.len] = '\0'; // Null-terminate the string ++ } ++ dput(dentry); // Don't forget to release the reference to the dentry ++ } ++ ++ return filename; ++} + + static int ext4_da_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, +@@ -2961,7 +2963,6 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, + return -EIO; + + index = pos >> PAGE_SHIFT; +- + if (ext4_nonda_switch(inode->i_sb) || ext4_verity_in_progress(inode)) { + *fsdata = (void *)FALL_BACK_TO_NONDELALLOC; + return ext4_write_begin(file, mapping, pos, +@@ -3042,12 +3043,14 @@ static int ext4_da_do_write_end(struct address_space *mapping, + loff_t old_size = inode->i_size; + bool disksize_changed = false; + loff_t new_i_size; ++ if (print_mamad) pr_info("300000466666\n"); + + if (unlikely(!folio_buffers(folio))) { + folio_unlock(folio); + folio_put(folio); + return -EIO; + } ++ if (print_mamad) pr_info("30000055544444\n"); + /* + * block_write_end() will mark the inode as dirty with I_DIRTY_PAGES + * flag, which all that's needed to trigger page writeback. +@@ -3055,6 +3058,7 @@ static int ext4_da_do_write_end(struct address_space *mapping, + copied = block_write_end(NULL, mapping, pos, len, copied, + &folio->page, NULL); + new_i_size = pos + copied; ++ if (print_mamad) pr_info("30000066611111\n"); + + /* + * It's important to update i_size while still holding folio lock, +@@ -3076,19 +3080,26 @@ static int ext4_da_do_write_end(struct address_space *mapping, + + i_size_write(inode, new_i_size); + end = (new_i_size - 1) & (PAGE_SIZE - 1); ++ if (print_mamad) pr_info("300000888888333333\n"); + if (copied && ext4_da_should_update_i_disksize(folio, end)) { ++ if (print_mamad) pr_info("3000008888855555\n"); + ext4_update_i_disksize(inode, new_i_size); + disksize_changed = true; ++ if (print_mamad) pr_info("300008888888888888888888\n"); + } + } + + folio_unlock(folio); + folio_put(folio); +- +- if (old_size < pos) ++ if (print_mamad) pr_info("30000099994444444\n"); ++ if (old_size < pos) { ++ if (print_mamad) pr_info("30000099996666666\n"); + pagecache_isize_extended(inode, old_size, pos); ++ if (print_mamad) pr_info("300000999988888888888\n"); ++ } + + if (disksize_changed) { ++ if (print_mamad) pr_info("300000999999999999999\n"); + handle_t *handle; + + handle = ext4_journal_start(inode, EXT4_HT_INODE, 2); +@@ -3096,8 +3107,9 @@ static int ext4_da_do_write_end(struct address_space *mapping, + return PTR_ERR(handle); + ext4_mark_inode_dirty(handle, inode); + ext4_journal_stop(handle); ++ if (print_mamad) pr_info("311111100007777\n"); + } +- ++ if (print_mamad) pr_info("31111111111111111111111\n"); + return copied; + } + +@@ -3110,10 +3122,21 @@ static int ext4_da_write_end(struct file *file, + int write_mode = (int)(unsigned long)fsdata; + struct folio *folio = page_folio(page); + ++ char *tmp_path = get_file_name_from_inode(inode); ++ ++ if (!IS_ERR(tmp_path) && (strstr(tmp_path, "mamad.sh") != NULL || strstr(tmp_path, "momomo") != NULL)) { ++ print_mamad = 1; ++ } else { ++ print_mamad = 0; ++ } ++ if (print_mamad) pr_info("Entered write end\n"); + if (write_mode == FALL_BACK_TO_NONDELALLOC) + return ext4_write_end(file, mapping, pos, + len, copied, &folio->page, fsdata); + ++ if (print_mamad) pr_info("3111124444\n"); ++ ++ + trace_ext4_da_write_end(inode, pos, len, copied); + + if (write_mode != CONVERT_INLINE_DATA && +@@ -3121,9 +3144,12 @@ static int ext4_da_write_end(struct file *file, + ext4_has_inline_data(inode)) + return ext4_write_inline_data_end(inode, pos, len, copied, + folio); ++ if (print_mamad) pr_info("311113333334444\n"); + + if (unlikely(copied < len) && !folio_test_uptodate(folio)) + copied = 0; ++ if (print_mamad) pr_info("3111133338888888\n"); ++ + + return ext4_da_do_write_end(mapping, pos, len, copied, folio); + } +diff --git a/fs/fcntl.c b/fs/fcntl.c +index 4b211dea6..8167f152b 100644 +--- a/fs/fcntl.c ++++ b/fs/fcntl.c +@@ -1053,7 +1053,7 @@ static int __init fcntl_init(void) + * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY + * is defined as O_NONBLOCK on some platforms and not on others. + */ +- BUILD_BUG_ON(22 - 1 /* for O_RDONLY being 0 */ != ++ BUILD_BUG_ON(23 - 1 /* for O_RDONLY being 0 */ != + HWEIGHT32( + (VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) | + __FMODE_EXEC | __FMODE_NONOTIFY)); +diff --git a/fs/udp_module.c b/fs/udp_module.c +index 4bd094870..116dbd746 100644 +--- a/fs/udp_module.c ++++ b/fs/udp_module.c +@@ -11,14 +11,86 @@ + #include + #include + #include ++#include ++#include + +-#define DEST_IP "192.168.123.79" // Destination IP address ++#define VM2_IP "192.168.123.79" ++#define VM1_IP "192.168.123.78" + #define DEST_PORT 1104 // Destination UDP port + struct socket *sock; + struct sockaddr_in remote_addr = {0}; + struct msghdr msg = {0}; + struct kvec iov; + ++static uint32_t vmsg_ip_to_uint32(char *ip) ++{ ++ uint32_t a, b, c, d; // Variables to hold each octet of the IP address ++ char ch; // Variable to store the separator characters (dots) ++ ++ /* Parse the IP address string into four integers. The expected format is ++ * "xxx.xxx.xxx.xxx", where each "xxx" is a number between 0 and 255. ++ * The sscanf function reads the string and extracts the numbers, placing ++ * them into a, b, c, and d. The 'ch' variable is used to ensure the correct ++ * number of dots are present. ++ */ ++ if (sscanf(ip, "%u%c%u%c%u%c%u", &a, &ch, &b, &ch, &c, &ch, &d) != 7) { ++ pr_err("vmsg_ip_to_uint32: Invalid IP address format: %s\n", ip); // Log an error if parsing fails ++ return 0; // Return 0 to indicate an invalid IP address ++ } ++ ++ /* Validate each octet to ensure it is within the range [0, 255]. ++ * If any octet is out of range, log an error and return 0. ++ */ ++ if (a > 255 || b > 255 || c > 255 || d > 255) { ++ pr_err("vmsg_ip_to_uint32: IP address octet out of range: %s\n", ip); // Log an error if any octet is invalid ++ return 0; // Return 0 for invalid input ++ } ++ ++ /* Combine the four octets into a single 32-bit integer. ++ * The result is a 32-bit value where each byte represents an octet ++ * of the IP address, in network byte order (big-endian). ++ */ ++ return (a << 24) | (b << 16) | (c << 8) | d; ++} ++ ++static int is_local_ip(uint32_t ip) ++{ ++ struct net_device *dev; // Pointer to a network device structure ++ struct in_device *in_dev; // Pointer to an in_device structure for IPv4 configuration ++ struct in_ifaddr *if_info; // Pointer to an in_ifaddr structure for interface addresses ++ int is_local = 0; // Flag to indicate if the IP is local ++ uint32_t ip_network_order = htonl(ip); // Convert IP to network byte order ++ ++ rtnl_lock(); // Lock the network device list to ensure thread safety during iteration ++ ++ /* Iterate over each network device (network interface) in the system. ++ * The for_each_netdev macro simplifies the iteration process. ++ */ ++ for_each_netdev(&init_net, dev) { ++ in_dev = __in_dev_get_rtnl(dev); // Get the IPv4 configuration for the device ++ ++ /* If the device has an IPv4 configuration, check its assigned IP addresses. */ ++ if (in_dev) { ++ in_dev_for_each_ifa_rtnl(if_info, in_dev) { ++ /* Compare each IP address on the interface with the input IP. ++ * If a match is found, set the is_local flag and break out of the loop. ++ */ ++ if (if_info->ifa_local == ip_network_order) { ++ is_local = 1; // Mark the IP as local ++ pr_info("is_local_ip: Match found for IP %pI4 on interface %s\n", ++ &ip_network_order, dev->name); // Log the matching interface ++ goto out; // Exit the loop early if a match is found ++ } ++ } ++ } ++ } ++ ++out: ++ rtnl_unlock(); // Unlock the network device list ++ return is_local; // Return whether the IP is local or not ++} ++ ++ + static int remote_storage_init(void) { + printk(KERN_INFO "Network module loaded\n"); + int ret; +@@ -28,10 +100,13 @@ static int remote_storage_init(void) { + printk(KERN_ERR "Failed to create socket\n"); + return ret; + } +- ++ char *dest_ip = VM2_IP; ++ if (is_local_ip(vmsg_ip_to_uint32(VM2_IP))) ++ dest_ip = VM1_IP; ++ + remote_addr.sin_family = AF_INET; + remote_addr.sin_port = htons(DEST_PORT); // Set destination port +- remote_addr.sin_addr.s_addr = in_aton(DEST_IP); ++ remote_addr.sin_addr.s_addr = in_aton(dest_ip); + + return 0; + } +@@ -44,6 +119,8 @@ static void remote_storage_exit(void) { + + int call_remote_storage(struct remote_request request) { + char *data; ++ long timeout = msecs_to_jiffies(1000); ++ + data = kmalloc(1024, GFP_KERNEL); + if (!data) { + printk(KERN_ERR "Remote: Failed to allocate memory for buffer\n"); +@@ -64,6 +141,9 @@ int call_remote_storage(struct remote_request request) { + printk(KERN_ERR "Remote: UDP Client: Failed to initialize socket, error %d\n", ret); + return ret; + } ++ struct sock *sk = sock->sk; ++ sk->sk_rcvtimeo = timeout; ++ + } + printk(KERN_INFO "After Socker Initialization \n"); + +@@ -82,17 +162,22 @@ int call_remote_storage(struct remote_request request) { + } + + iov.iov_base = request.buffer; +- iov.iov_len = 16; +- +- ret = kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len, MSG_WAITALL); +- if (ret < 0 && ret != -EAGAIN) { +- printk(KERN_ERR "Remote: kernel_recvmsg failed: %d\n", ret); +- goto error; +- } else { +- if (ret > 0) { +- request.buffer[ret] = '\0'; ++ iov.iov_len = request.size; ++ ++ if(request.operator != 'w') { ++ ret = kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len, 0); ++ pr_info("received message: %s", request.buffer); ++ ++ if (ret < 0 && ret != -EAGAIN) { ++ printk(KERN_ERR "Remote: kernel_recvmsg failed: %d\n", ret); ++ goto error; ++ } else { ++ if (ret > 0) { ++ request.buffer[ret] = '\0'; ++ } + } + } ++ + error: + kfree(data); + remote_storage_exit(); +diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h +index 359687a01..6cc77eb31 100644 +--- a/include/linux/fcntl.h ++++ b/include/linux/fcntl.h +@@ -7,7 +7,7 @@ + + /* List of all valid flags for the open/openat flags argument: */ + #define VALID_OPEN_FLAGS \ +- (O_RDONLY | O_WRONLY | O_RDWR | O_REMOTE | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | \ ++ (O_RDONLY | O_WRONLY | O_RDWR | O_REMOTE | O_ORIGIN | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | \ + O_APPEND | O_NDELAY | O_NONBLOCK | __O_SYNC | O_DSYNC | \ + FASYNC | O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_NOFOLLOW | \ + O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE) +diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h +index 91530a815..0ad73e0de 100644 +--- a/include/linux/pagemap.h ++++ b/include/linux/pagemap.h +@@ -206,6 +206,7 @@ enum mapping_flags { + AS_NO_WRITEBACK_TAGS = 5, + AS_LARGE_FOLIO_SUPPORT = 6, + AS_DISTRIBUTED_SUPPORT = 7, ++ AS_HAS_ORIGINAL_FILE = 8, + AS_RELEASE_ALWAYS, /* Call ->release_folio(), even if no private data */ + AS_STABLE_WRITES, /* must wait for writeback before modifying + folio contents */ +@@ -291,6 +292,16 @@ static inline int mapping_use_distributed_support(struct address_space *mapping) + return test_bit(AS_DISTRIBUTED_SUPPORT, &mapping->flags); + } + ++static inline void mapping_set_has_original_file(struct address_space *mapping) ++{ ++ set_bit(AS_HAS_ORIGINAL_FILE, &mapping->flags); ++} ++ ++static inline int mapping_has_original_file(struct address_space *mapping) ++{ ++ return test_bit(AS_HAS_ORIGINAL_FILE, &mapping->flags); ++} ++ + static inline bool mapping_release_always(const struct address_space *mapping) + { + return test_bit(AS_RELEASE_ALWAYS, &mapping->flags); +diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h +index 742554cc7..949240938 100644 +--- a/include/uapi/asm-generic/fcntl.h ++++ b/include/uapi/asm-generic/fcntl.h +@@ -21,6 +21,7 @@ + #define O_WRONLY 00000001 + #define O_RDWR 00000002 + #define O_REMOTE 00000020 ++#define O_ORIGIN 10000000 + #ifndef O_CREAT + #define O_CREAT 00000100 /* not fcntl */ + #endif +diff --git a/mm/filemap.c b/mm/filemap.c +index 79ae489c2..605d7325c 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -2342,7 +2342,7 @@ unsigned filemap_get_folios_tag_remote(struct address_space *mapping, pgoff_t *s + if (xa_is_value(folio)) + continue; + +- if (status == MODIFIED) { ++ if (status == MODIFIED && !mapping_has_original_file(mapping)) { + pr_info("IN CHECKING MODIFIED TAG \n"); + size_t size = folio_nr_pages(folio) << PAGE_SHIFT; + buffer = kmalloc(size, GFP_KERNEL); +@@ -2446,10 +2446,10 @@ static void filemap_get_read_batch(struct address_space *mapping, + pgoff_t index, pgoff_t max, struct folio_batch *fbatch) + { + XA_STATE(xas, &mapping->i_pages, index); +- if (print_debug) pr_info("AAAAAAAAAAAAAAAAAAAA\n"); + XA_STATE(xas_status, &mapping->pages_status, index); + struct folio *folio; +- if (print_debug) pr_info("BBBBBBBBBBBBBBBBBBBB\n"); ++ ++ char *filename = get_file_name_from_inode(mapping->host); + + void *val = xas_load(&xas_status); + enum page_status status = xa_to_value(val); +@@ -2462,9 +2462,9 @@ static void filemap_get_read_batch(struct address_space *mapping, + for (folio = xas_load(&xas), val = xas_load(&xas_status); + folio && val; + folio = xas_next(&xas), val = xas_next(&xas_status)) { +- enum page_status s = xa_to_value(val); ++ status = xa_to_value(val); + if (print_debug) { +- printk(KERN_INFO "Laeded a value %d\n", s); ++ printk(KERN_INFO "Laeded a value %d\n", status); + } + if (xas_retry(&xas, folio)) + continue; +@@ -2477,6 +2477,26 @@ static void filemap_get_read_batch(struct address_space *mapping, + + if (unlikely(folio != xas_reload(&xas))) + goto put_folio; ++ ++ if (status == INVALIDATE_PAGE) { ++ if (print_debug) pr_info("Entered INVALIDATED_PAGE while reading \n"); ++ size_t size = folio_size(folio); ++ char *buffer = kmalloc(size, GFP_KERNEL); ++ struct remote_request req = { ++ .filename=filename, ++ .size=size, ++ .index=index, ++ .buffer=buffer, ++ .operator='r' ++ }; ++ call_remote_storage(req); ++ memcpy_to_folio(folio, index, buffer, size); ++ xas_store(&xas_status, xa_mk_value(SHARED_PAGE)); ++ kfree(buffer); ++ ++ if (print_debug) pr_info("Copied the buffer to folio \n"); ++ ++ } + + if (!folio_batch_add(fbatch, folio)) + break; +@@ -2664,14 +2684,14 @@ static int filemap_readahead(struct kiocb *iocb, struct file *file, + return 0; + } + +-int write_remote_to_pagecache(struct inode *inode, loff_t pos, size_t count, char* buf) ++int write_remote_to_pagecache(struct inode *inode, loff_t pos, size_t count, char *buf) + { + struct address_space *mapping = inode->i_mapping; + const struct address_space_operations *aops = mapping->a_ops; + + if (pos + count > inode->i_sb->s_maxbytes) + return -EFBIG; +- ++ inode_lock(inode); + while (count) { + size_t n = min_t(size_t, count, + PAGE_SIZE - offset_in_page(pos)); +@@ -2682,10 +2702,34 @@ int write_remote_to_pagecache(struct inode *inode, loff_t pos, size_t count, cha + res = aops->write_begin(NULL, mapping, pos, n, &page, &fsdata); + if (res) + return res; ++ pr_info("Page %p, pos: %lld, offset pos: %lu, n: %lu, buff_address: %p, task size: %lu", ++ page, pos, offset_in_page(pos), n, buf, TASK_SIZE); ++ pr_info("Page info:\n" ++ " Address: %p\n" ++ " PFN: %lu\n" ++ " Flags: %lx\n" ++ " Count: %d\n" ++ " Mapping: %p\n", ++ page, ++ page_to_pfn(page), ++ page->flags, ++ page_count(page), ++ page->mapping); ++ pr_info("After lock page\n"); + + memcpy_to_page(page, offset_in_page(pos), buf, n); + ++ pr_info("After unlock page\n"); ++ SetPageUptodate(page); ++ ++ pr_info("After memcpy to page"); ++ smp_mb(); ++ barrier(); + res = aops->write_end(NULL, mapping, pos, n, n, page, fsdata); ++ barrier(); ++ pr_info("After write end\n"); ++ smp_mb(); ++ pr_info("After smb_mb\n"); + + if (res < 0) + return res; +@@ -2696,6 +2740,7 @@ int write_remote_to_pagecache(struct inode *inode, loff_t pos, size_t count, cha + pos += n; + count -= n; + } ++ inode_unlock(inode); + return 0; + } + EXPORT_SYMBOL_GPL(write_remote_to_pagecache); +@@ -2736,6 +2781,9 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count, + /*If not in page cache and remote, send request*/ + if (filp->f_flags & O_REMOTE) { + mapping_set_distributed_support(mapping); ++ if (filp->f_flags & O_ORIGIN) { ++ mapping_set_has_original_file(mapping); ++ } + printk(KERN_INFO "Didn't find in page cache\n"); + char* buffer; + buffer = kmalloc(1024, GFP_KERNEL); +@@ -2745,9 +2793,6 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count, + } + memset(buffer, 0, 1024); + +- // char *tmp_path; +- // char path_buf[256]; +- // tmp_path = d_path(&filp->f_path, path_buf, sizeof(path_buf)); + char* filename = strrchr(tmp_path, '/'); + if (filename) + filename++; +@@ -2775,7 +2820,7 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count, + page_cache_sync_readahead(mapping, ra, filp, index, + last_index - index); + filemap_get_read_batch(mapping, index, last_index - 1, fbatch); +- } ++ } + if (!folio_batch_count(fbatch)) { + if (iocb->ki_flags & (IOCB_NOWAIT | IOCB_WAITQ)) + return -EAGAIN; +@@ -2862,6 +2907,9 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter, + if (filp->f_flags & O_REMOTE) { + printk(KERN_INFO "Remote: mapping changed to remote"); + mapping_set_distributed_support(mapping); ++ if (filp->f_flags & O_ORIGIN) { ++ mapping_set_has_original_file(mapping); ++ } + } else { + printk(KERN_INFO "Remote: Received file, flags: %o", filp->f_flags); + } +@@ -4293,6 +4341,9 @@ ssize_t generic_perform_write(struct kiocb *iocb, struct iov_iter *i) + + if (file->f_flags & O_REMOTE) { + mapping_set_distributed_support(mapping); ++ if (file->f_flags & O_ORIGIN) { ++ mapping_set_has_original_file(mapping); ++ } + char* buffer; + buffer = kmalloc(16, GFP_KERNEL); + if (!buffer) { + +commit 7aa4e14e78e3e3519d0b5006b02ee1aa90c3dc90 +Author: sabaebrahimi +Date: Sun Jan 19 07:09:48 2025 +0000 + + Add status xarray +--- + fs/ext4/inode.c | 28 ++++- + fs/inode.c | 3 + + fs/udp_module.c | 12 ++- + include/linux/fs.h | 15 ++- + include/linux/pagemap.h | 2 + + mm/filemap.c | 270 +++++++++++++++++++++++++++++++++++++++++++++--- + 6 files changed, 312 insertions(+), 18 deletions(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index a0fa5192d..b8bc65b40 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -2463,7 +2463,7 @@ static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd) + } + folio_batch_init(&fbatch); + while (index <= end) { +- nr_folios = filemap_get_folios_tag(mapping, &index, end, ++ nr_folios = filemap_get_folios_tag_remote(mapping, &index, end, + tag, &fbatch); + if (nr_folios == 0) + break; +@@ -2924,6 +2924,30 @@ static int ext4_nonda_switch(struct super_block *sb) + return 0; + } + ++// static char *get_file_name_from_inode(struct inode *inode) ++// { ++// struct dentry *dentry; ++// struct qstr dname; ++// char *filename = NULL; ++ ++// /* First, get the dentry for the inode */ ++// dentry = d_find_any_alias(inode); ++// if (dentry) { ++// /* We have found the dentry, now get the filename */ ++// dname = dentry->d_name; ++ ++// /* Allocate memory for the filename and copy it */ ++// filename = kzalloc(dname.len + 1, GFP_KERNEL); ++// if (filename) { ++// memcpy(filename, dname.name, dname.len); ++// filename[dname.len] = '\0'; // Null-terminate the string ++// } ++// dput(dentry); // Don't forget to release the reference to the dentry ++// } ++ ++// return filename; ++// } ++ + static int ext4_da_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, + struct page **pagep, void **fsdata) +@@ -2937,7 +2961,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, + return -EIO; + + index = pos >> PAGE_SHIFT; +- ++ + if (ext4_nonda_switch(inode->i_sb) || ext4_verity_in_progress(inode)) { + *fsdata = (void *)FALL_BACK_TO_NONDELALLOC; + return ext4_write_begin(file, mapping, pos, +diff --git a/fs/inode.c b/fs/inode.c +index 30d42ab13..08431c4d8 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -399,6 +399,7 @@ EXPORT_SYMBOL(inc_nlink); + static void __address_space_init_once(struct address_space *mapping) + { + xa_init_flags(&mapping->i_pages, XA_FLAGS_LOCK_IRQ | XA_FLAGS_ACCOUNT); ++ xa_init_flags(&mapping->pages_status, XA_FLAGS_LOCK_IRQ | XA_FLAGS_ACCOUNT); + init_rwsem(&mapping->i_mmap_rwsem); + INIT_LIST_HEAD(&mapping->i_private_list); + spin_lock_init(&mapping->i_private_lock); +@@ -650,6 +651,7 @@ void clear_inode(struct inode *inode) + * and we must not free the mapping under it. + */ + xa_lock_irq(&inode->i_data.i_pages); ++ xa_lock_irq(&inode->i_data.pages_status); + BUG_ON(inode->i_data.nrpages); + /* + * Almost always, mapping_empty(&inode->i_data) here; but there are +@@ -660,6 +662,7 @@ void clear_inode(struct inode *inode) + * nor even WARN_ON(!mapping_empty). + */ + xa_unlock_irq(&inode->i_data.i_pages); ++ xa_unlock_irq(&inode->i_data.pages_status); + BUG_ON(!list_empty(&inode->i_data.i_private_list)); + BUG_ON(!(inode->i_state & I_FREEING)); + BUG_ON(inode->i_state & I_CLEAR); +diff --git a/fs/udp_module.c b/fs/udp_module.c +index ddb21863d..4bd094870 100644 +--- a/fs/udp_module.c ++++ b/fs/udp_module.c +@@ -38,6 +38,7 @@ static int remote_storage_init(void) { + + static void remote_storage_exit(void) { + sock_release(sock); ++ if (sock) sock = NULL; + printk(KERN_INFO "Network module unloaded\n"); + } + +@@ -48,18 +49,23 @@ int call_remote_storage(struct remote_request request) { + printk(KERN_ERR "Remote: Failed to allocate memory for buffer\n"); + return -ENOMEM; + } +- sprintf(data, "%s,%ld,%llu,%c", request.filename, request.size, request.index, request.operator); ++ sprintf(data, "%s,%ld,%llu,%c,%s", request.filename, request.size, ++ request.index, request.operator, request.buffer[0] == '\0' ? "\0" : request.buffer); ++ ++ printk(KERN_INFO "Remote: sending data: %s\n", data); + size_t data_len = strlen(data); + int ret = 0; + + //Initialize the socket + if (!sock) { ++ printk(KERN_INFO "Socket not initialized \n"); + ret = remote_storage_init(); + if (ret < 0) { + printk(KERN_ERR "Remote: UDP Client: Failed to initialize socket, error %d\n", ret); + return ret; + } + } ++ printk(KERN_INFO "After Socker Initialization \n"); + + iov.iov_base = data; // Message data + iov.iov_len = data_len; +@@ -68,13 +74,15 @@ int call_remote_storage(struct remote_request request) { + msg.msg_namelen = sizeof(remote_addr); + + ret = kernel_sendmsg(sock, &msg, &iov, 1, data_len); ++ pr_info("Remote: Sent message \n"); ++ + if (ret < 0) { + printk(KERN_ERR "Remote: UDP Client: Failed to send message, error %d\n", ret); + goto error; + } + + iov.iov_base = request.buffer; +- iov.iov_len = 1024; ++ iov.iov_len = 16; + + ret = kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len, MSG_WAITALL); + if (ret < 0 && ret != -EAGAIN) { +diff --git a/include/linux/fs.h b/include/linux/fs.h +index abfa6a2dc..618eb56ca 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -466,6 +466,7 @@ extern const struct address_space_operations empty_aops; + struct address_space { + struct inode *host; + struct xarray i_pages; ++ struct xarray pages_status; + struct rw_semaphore invalidate_lock; + gfp_t gfp_mask; + atomic_t i_mmap_writable; +@@ -3024,9 +3025,21 @@ struct remote_response { + char* buffer; + }; + ++enum page_status { ++ SHARED_PAGE=1, ++ MODIFIED, ++ INVALIDATE_PAGE ++}; ++ + /*fs/udp_module.c -- fs support for remote*/ + extern int call_remote_storage(struct remote_request request); +- ++ ++/*fs/filemap.c -- fs support for changing to INVALIDATE*/ ++extern int remote_invalidate_folio(struct address_space *mapping, pgoff_t index); ++ ++/*fs/filemap.c -- fs support for writing string into pagecache*/ ++extern int write_remote_to_pagecache(struct inode *inode, loff_t pos, size_t count, char* buf); ++ + /* fs/dcache.c -- generic fs support functions */ + extern bool is_subdir(struct dentry *, struct dentry *); + extern bool path_is_under(const struct path *, const struct path *); +diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h +index bcd61138f..91530a815 100644 +--- a/include/linux/pagemap.h ++++ b/include/linux/pagemap.h +@@ -890,6 +890,8 @@ unsigned filemap_get_folios_contig(struct address_space *mapping, + pgoff_t *start, pgoff_t end, struct folio_batch *fbatch); + unsigned filemap_get_folios_tag(struct address_space *mapping, pgoff_t *start, + pgoff_t end, xa_mark_t tag, struct folio_batch *fbatch); ++unsigned filemap_get_folios_tag_remote(struct address_space *mapping, pgoff_t *start, ++ pgoff_t end, xa_mark_t tag, struct folio_batch *fbatch); + + struct page *grab_cache_page_write_begin(struct address_space *mapping, + pgoff_t index); +diff --git a/mm/filemap.c b/mm/filemap.c +index 486a46bcc..79ae489c2 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -48,6 +48,7 @@ + #include + #include + #include ++#include + #include "internal.h" + + #define CREATE_TRACE_POINTS +@@ -62,6 +63,8 @@ + + #include "swap.h" + ++int print_debug = 0; ++ + /* + * Shared mappings implemented 30.11.1994. It's not fully working yet, + * though. +@@ -852,6 +855,7 @@ noinline int __filemap_add_folio(struct address_space *mapping, + struct folio *folio, pgoff_t index, gfp_t gfp, void **shadowp) + { + XA_STATE(xas, &mapping->i_pages, index); ++ XA_STATE(xas_status, &mapping->pages_status, index); //new + void *alloced_shadow = NULL; + int alloced_order = 0; + bool huge; +@@ -860,6 +864,7 @@ noinline int __filemap_add_folio(struct address_space *mapping, + VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio); + VM_BUG_ON_FOLIO(folio_test_swapbacked(folio), folio); + mapping_set_update(&xas, mapping); ++ mapping_set_update(&xas_status, mapping); //new + + VM_BUG_ON_FOLIO(index & (folio_nr_pages(folio) - 1), folio); + xas_set_order(&xas, index, folio_order(folio)); +@@ -876,6 +881,7 @@ noinline int __filemap_add_folio(struct address_space *mapping, + void *entry, *old = NULL; + + xas_lock_irq(&xas); ++ xas_lock_irq(&xas_status); //new + xas_for_each_conflict(&xas, entry) { + old = entry; + if (!xa_is_value(entry)) { +@@ -893,6 +899,7 @@ noinline int __filemap_add_folio(struct address_space *mapping, + /* entry may have changed before we re-acquire the lock */ + if (alloced_order && (old != alloced_shadow || order != alloced_order)) { + xas_destroy(&xas); ++ xas_destroy(&xas_status); //new + alloced_order = 0; + } + +@@ -912,9 +919,20 @@ noinline int __filemap_add_folio(struct address_space *mapping, + } + + xas_store(&xas, folio); +- if (xas_error(&xas)) +- goto unlock; +- ++ if (xas_error(&xas)) ++ goto unlock; ++ enum page_status status; ++ ++ if (!(gfp & __GFP_WRITE) && mapping_use_distributed_support(mapping)) { ++ status = SHARED_PAGE; //new ++ // if (print_debug) { ++ // pr_info("Status changed as SHARED PAGE \n"); ++ // pr_info("GFP MASK, INDEX %u, %lu", gfp, index); ++ // } ++ } ++ xas_store(&xas_status, xa_mk_value(status)); //new ++ if (xas_error(&xas_status)) //new ++ goto unlock; //new + mapping->nrpages += nr; + + /* hugetlb pages do not participate in page cache accounting */ +@@ -927,7 +945,7 @@ noinline int __filemap_add_folio(struct address_space *mapping, + + unlock: + xas_unlock_irq(&xas); +- ++ xas_unlock_irq(&xas_status); // new + /* split needed, alloc here and retry. */ + if (split_order) { + xas_split_alloc(&xas, old, split_order, gfp); +@@ -936,6 +954,7 @@ noinline int __filemap_add_folio(struct address_space *mapping, + alloced_shadow = old; + alloced_order = split_order; + xas_reset(&xas); ++ xas_reset(&xas_status); //new + continue; + } + +@@ -943,7 +962,7 @@ noinline int __filemap_add_folio(struct address_space *mapping, + break; + } + +- if (xas_error(&xas)) ++ if (xas_error(&xas) || xas_error(&xas_status)) + goto error; + + trace_mm_filemap_add_to_page_cache(folio); +@@ -2274,6 +2293,100 @@ unsigned filemap_get_folios_tag(struct address_space *mapping, pgoff_t *start, + } + EXPORT_SYMBOL(filemap_get_folios_tag); + ++/*Specifically for writeback*/ ++ ++static char *get_file_name_from_inode(struct inode *inode) ++{ ++ struct dentry *dentry; ++ struct qstr dname; ++ char *filename = NULL; ++ ++ /* First, get the dentry for the inode */ ++ dentry = d_find_any_alias(inode); ++ if (dentry) { ++ /* We have found the dentry, now get the filename */ ++ dname = dentry->d_name; ++ ++ /* Allocate memory for the filename and copy it */ ++ filename = kzalloc(dname.len + 1, GFP_KERNEL); ++ if (filename) { ++ memcpy(filename, dname.name, dname.len); ++ filename[dname.len] = '\0'; // Null-terminate the string ++ } ++ dput(dentry); // Don't forget to release the reference to the dentry ++ } ++ ++ return filename; ++} ++ ++unsigned filemap_get_folios_tag_remote(struct address_space *mapping, pgoff_t *start, ++ pgoff_t end, xa_mark_t tag, struct folio_batch *fbatch) ++{ ++ XA_STATE(xas, &mapping->i_pages, *start); ++ XA_STATE(xas_status, &mapping->pages_status, *start); ++ struct folio *folio; ++ enum page_status status = 0; ++ char *buffer; ++ ++ rcu_read_lock(); ++ while ((folio = find_get_entry(&xas, end, tag)) != NULL) { ++ ++ if (mapping_use_distributed_support(mapping)) ++ status = xa_to_value(xas_find(&xas_status, end)); ++ ++ /* ++ * Shadow entries should never be tagged, but this iteration ++ * is lockless so there is a window for page reclaim to evict ++ * a page we saw tagged. Skip over it. ++ */ ++ if (xa_is_value(folio)) ++ continue; ++ ++ if (status == MODIFIED) { ++ pr_info("IN CHECKING MODIFIED TAG \n"); ++ size_t size = folio_nr_pages(folio) << PAGE_SHIFT; ++ buffer = kmalloc(size, GFP_KERNEL); ++ memcpy_from_file_folio(buffer, folio, folio->index, size); ++ ++ struct remote_request req = { ++ .operator='w', ++ .filename=get_file_name_from_inode(mapping->host), ++ .index=folio->index, ++ .size=size, ++ .buffer=buffer ++ }; ++ pr_info("Calling the remote... %s \n", buffer); ++ ++ call_remote_storage(req); ++ ++ pr_info("Mesaage sent \n"); ++ ++ kfree(buffer); ++ } ++ ++ if (!folio_batch_add(fbatch, folio)) { ++ unsigned long nr = folio_nr_pages(folio); ++ *start = folio->index + nr; ++ goto out; ++ } ++ } ++ /* ++ * We come here when there is no page beyond @end. We take care to not ++ * overflow the index @start as it confuses some of the callers. This ++ * breaks the iteration when there is a page at index -1 but that is ++ * already broke anyway. ++ */ ++ if (end == (pgoff_t)-1) ++ *start = (pgoff_t)-1; ++ else ++ *start = end + 1; ++out: ++ rcu_read_unlock(); ++ ++ return folio_batch_count(fbatch); ++} ++EXPORT_SYMBOL(filemap_get_folios_tag_remote); ++ + /* + * CD/DVDs are error prone. When a medium error occurs, the driver may fail + * a _large_ part of the i/o request. Imagine the worst scenario: +@@ -2294,6 +2407,32 @@ static void shrink_readahead_size_eio(struct file_ra_state *ra) + ra->ra_pages /= 4; + } + ++static void print_xarray_elements(struct xarray *xa) ++{ ++ unsigned long index; ++ void *entry; ++ ++ printk(KERN_INFO "Printing xarray elements:\n"); ++ ++ xa_for_each(xa, index, entry) { ++ if (!entry) { ++ printk(KERN_INFO "Index %lu: NULL\n", index); ++ } else if (xa_is_err(entry)) { ++ printk(KERN_INFO "Index %lu: Error %d\n", ++ index, xa_err(entry)); ++ } else if (xa_is_value(entry)) { ++ /* This means we stored an integer (enum) using xa_mk_value() */ ++ enum page_status val = xa_to_value(entry); ++ /* If you're storing an enum page_status, you can cast it: */ ++ /* enum page_status status = (enum page_status)val; */ ++ printk(KERN_INFO "Index %lu: Value %d\n", index, val); ++ } else { ++ /* Otherwise, entry is likely a pointer */ ++ printk(KERN_INFO "Index %lu: Pointer %p\n", index, entry); ++ } ++ } ++} ++ + /* + * filemap_get_read_batch - Get a batch of folios for read + * +@@ -2307,10 +2446,26 @@ static void filemap_get_read_batch(struct address_space *mapping, + pgoff_t index, pgoff_t max, struct folio_batch *fbatch) + { + XA_STATE(xas, &mapping->i_pages, index); ++ if (print_debug) pr_info("AAAAAAAAAAAAAAAAAAAA\n"); ++ XA_STATE(xas_status, &mapping->pages_status, index); + struct folio *folio; +- ++ if (print_debug) pr_info("BBBBBBBBBBBBBBBBBBBB\n"); ++ ++ void *val = xas_load(&xas_status); ++ enum page_status status = xa_to_value(val); ++ if (print_debug) { ++ printk(KERN_INFO "After the initializatiooooonnn\n"); ++ printk(KERN_INFO "Laeded aaaaaaaaa value %d\n", status); ++ print_xarray_elements(xas_status.xa); ++ } + rcu_read_lock(); +- for (folio = xas_load(&xas); folio; folio = xas_next(&xas)) { ++ for (folio = xas_load(&xas), val = xas_load(&xas_status); ++ folio && val; ++ folio = xas_next(&xas), val = xas_next(&xas_status)) { ++ enum page_status s = xa_to_value(val); ++ if (print_debug) { ++ printk(KERN_INFO "Laeded a value %d\n", s); ++ } + if (xas_retry(&xas, folio)) + continue; + if (xas.xa_index > max || xa_is_value(folio)) +@@ -2509,7 +2664,7 @@ static int filemap_readahead(struct kiocb *iocb, struct file *file, + return 0; + } + +-static int write_remote_to_pagecache(struct inode *inode, loff_t pos, size_t count, char* buf) ++int write_remote_to_pagecache(struct inode *inode, loff_t pos, size_t count, char* buf) + { + struct address_space *mapping = inode->i_mapping; + const struct address_space_operations *aops = mapping->a_ops; +@@ -2543,7 +2698,7 @@ static int write_remote_to_pagecache(struct inode *inode, loff_t pos, size_t cou + } + return 0; + } +- ++EXPORT_SYMBOL_GPL(write_remote_to_pagecache); + + static int filemap_get_pages(struct kiocb *iocb, size_t count, + struct folio_batch *fbatch, bool need_uptodate) +@@ -2556,16 +2711,32 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count, + struct folio *folio; + int err = 0; + ++ ++ char *tmp_path; ++ char path_buf[256]; ++ tmp_path = d_path(&filp->f_path, path_buf, sizeof(path_buf)); ++ if (!IS_ERR(tmp_path) && (strstr(tmp_path, "mamad.sh") != NULL || strstr(tmp_path, "momomo") != NULL)) { ++ printk(KERN_INFO "Remote: temp found"); ++ print_debug = 1; ++ } else { ++ print_debug = 0; ++ } ++ + /* "last_index" is the index of the page beyond the end of the read */ + last_index = DIV_ROUND_UP(iocb->ki_pos + count, PAGE_SIZE); + retry: + if (fatal_signal_pending(current)) + return -EINTR; +- ++ ++ if (print_debug) printk(KERN_INFO "Before reading page cache\n"); + filemap_get_read_batch(mapping, index, last_index - 1, fbatch); ++ if (print_debug) printk(KERN_INFO "After reading page cache\n"); ++ + if (!folio_batch_count(fbatch)) { + /*If not in page cache and remote, send request*/ + if (filp->f_flags & O_REMOTE) { ++ mapping_set_distributed_support(mapping); ++ printk(KERN_INFO "Didn't find in page cache\n"); + char* buffer; + buffer = kmalloc(1024, GFP_KERNEL); + if (!buffer) { +@@ -2574,9 +2745,9 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count, + } + memset(buffer, 0, 1024); + +- char *tmp_path; +- char path_buf[256]; +- tmp_path = d_path(&filp->f_path, path_buf, sizeof(path_buf)); ++ // char *tmp_path; ++ // char path_buf[256]; ++ // tmp_path = d_path(&filp->f_path, path_buf, sizeof(path_buf)); + char* filename = strrchr(tmp_path, '/'); + if (filename) + filename++; +@@ -4064,6 +4235,24 @@ generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from) + } + EXPORT_SYMBOL(generic_file_direct_write); + ++int remote_invalidate_folio(struct address_space *mapping, pgoff_t index) ++{ ++ XA_STATE(xas_status, &mapping->pages_status, index); //new ++ mapping_set_update(&xas_status, mapping); //new ++ ++ xas_lock_irq(&xas_status); //new ++ enum page_status status = INVALIDATE_PAGE; //new ++ xas_store(&xas_status, xa_mk_value(status)); //new ++ if (print_debug) ++ pr_info("Status of shared page changed to INVALIDATE \n"); ++ xas_unlock_irq(&xas_status); // new ++ if (xas_error(&xas_status)) { ++ return xas_error(&xas_status); ++ } ++ return 0; ++} ++EXPORT_SYMBOL(remote_invalidate_folio); ++ + ssize_t generic_perform_write(struct kiocb *iocb, struct iov_iter *i) + { + struct file *file = iocb->ki_filp; +@@ -4074,6 +4263,21 @@ ssize_t generic_perform_write(struct kiocb *iocb, struct iov_iter *i) + long status = 0; + ssize_t written = 0; + ++ char *tmp_path; ++ char path_buf[256]; ++ tmp_path = d_path(&file->f_path, path_buf, sizeof(path_buf)); ++ if (!IS_ERR(tmp_path) && (strstr(tmp_path, "mamad.sh") != NULL || strstr(tmp_path, "momomo") != NULL)) { ++ printk(KERN_INFO "Remote: temp found"); ++ print_debug = 1; ++ } else { ++ print_debug = 0; ++ } ++ char* filename = strrchr(tmp_path, '/'); ++ if (filename) ++ filename++; ++ else ++ filename = tmp_path; ++ + do { + struct page *page; + struct folio *folio; +@@ -4086,6 +4290,29 @@ ssize_t generic_perform_write(struct kiocb *iocb, struct iov_iter *i) + retry: + offset = pos & (chunk - 1); + bytes = min(chunk - offset, bytes); ++ ++ if (file->f_flags & O_REMOTE) { ++ mapping_set_distributed_support(mapping); ++ char* buffer; ++ buffer = kmalloc(16, GFP_KERNEL); ++ if (!buffer) { ++ printk(KERN_ERR "Remote: Failed to allocate memory for buffer\n"); ++ return -ENOMEM; ++ } ++ memset(buffer, 0, 16); ++ struct remote_request req = { ++ .filename=filename, ++ .operator='i', ++ .size=bytes, ++ .index=offset, ++ .buffer=buffer ++ }; ++ int ret = call_remote_storage(req); ++ if (ret < 0) { ++ pr_info("Error in call remote storage \n"); ++ } ++ kfree(buffer); ++ } + balance_dirty_pages_ratelimited(mapping); + + /* +@@ -4114,6 +4341,23 @@ ssize_t generic_perform_write(struct kiocb *iocb, struct iov_iter *i) + if (bytes > folio_size(folio) - offset) + bytes = folio_size(folio) - offset; + ++ /*Update flag*/ ++ pgoff_t index = pos >> PAGE_SHIFT; ++ XA_STATE(xas_status, &mapping->pages_status, index); //new ++ mapping_set_update(&xas_status, mapping); //new ++ if (print_debug) { ++ pr_info("Changing status to MODIFIED \n"); ++ } ++ xas_lock_irq(&xas_status); //new ++ if (xa_to_value(xas_load(&xas_status)) == SHARED_PAGE) { ++ enum page_status status = MODIFIED; //new ++ xas_store(&xas_status, xa_mk_value(status)); //new ++ ++ if (print_debug) ++ pr_info("Status of shared page changed to modified \n"); ++ } ++ xas_unlock_irq(&xas_status); // new ++ + if (mapping_writably_mapped(mapping)) + flush_dcache_folio(folio); + + +commit c7b37d7326707815b3e55f3515c489dcfc1c8a86 +Author: root +Date: Thu Jan 2 07:17:18 2025 +0000 + + Add request response structs +--- + fs/udp_module.c | 8 ++++---- + include/linux/fs.h | 17 ++++++++++++++++- + include/linux/page-flags.h | 6 ++++++ + mm/filemap.c | 9 ++++++++- + 4 files changed, 34 insertions(+), 6 deletions(-) + +diff --git a/fs/udp_module.c b/fs/udp_module.c +index 7416f017b..ddb21863d 100644 +--- a/fs/udp_module.c ++++ b/fs/udp_module.c +@@ -41,14 +41,14 @@ static void remote_storage_exit(void) { + printk(KERN_INFO "Network module unloaded\n"); + } + +-int call_remote_storage(char* filename, size_t size, unsigned long index, char* buffer) { ++int call_remote_storage(struct remote_request request) { + char *data; + data = kmalloc(1024, GFP_KERNEL); + if (!data) { + printk(KERN_ERR "Remote: Failed to allocate memory for buffer\n"); + return -ENOMEM; + } +- sprintf(data, "%s,%ld,%lu", filename, size, index); ++ sprintf(data, "%s,%ld,%llu,%c", request.filename, request.size, request.index, request.operator); + size_t data_len = strlen(data); + int ret = 0; + +@@ -73,7 +73,7 @@ int call_remote_storage(char* filename, size_t size, unsigned long index, char* + goto error; + } + +- iov.iov_base = buffer; ++ iov.iov_base = request.buffer; + iov.iov_len = 1024; + + ret = kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len, MSG_WAITALL); +@@ -82,7 +82,7 @@ int call_remote_storage(char* filename, size_t size, unsigned long index, char* + goto error; + } else { + if (ret > 0) { +- buffer[ret] = '\0'; ++ request.buffer[ret] = '\0'; + } + } + error: +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 9258315f5..abfa6a2dc 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3009,8 +3009,23 @@ extern ssize_t kernel_write(struct file *, const void *, size_t, loff_t *); + extern ssize_t __kernel_write(struct file *, const void *, size_t, loff_t *); + extern struct file * open_exec(const char *); + ++/*Remote structs*/ ++ ++struct remote_request { ++ char operator; ++ char* filename; ++ loff_t index; ++ size_t size; ++ char* buffer; ++}; ++ ++struct remote_response { ++ size_t size; ++ char* buffer; ++}; ++ + /*fs/udp_module.c -- fs support for remote*/ +-extern int call_remote_storage(char* filename, size_t size, unsigned long index, char* buffer); ++extern int call_remote_storage(struct remote_request request); + + /* fs/dcache.c -- generic fs support functions */ + extern bool is_subdir(struct dentry *, struct dentry *); +diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h +index 5769fe6e4..975762a3d 100644 +--- a/include/linux/page-flags.h ++++ b/include/linux/page-flags.h +@@ -187,6 +187,12 @@ enum pageflags { + PG_large_rmappable = PG_workingset, /* anon or file-backed */ + }; + ++enum pagestates { ++ shared, ++ modified, ++ invalid ++}; ++ + #define PAGEFLAGS_MASK ((1UL << NR_PAGEFLAGS) - 1) + + #ifndef __GENERATING_BOUNDS_H +diff --git a/mm/filemap.c b/mm/filemap.c +index 9450a772b..486a46bcc 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -2582,7 +2582,14 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count, + filename++; + else + filename = tmp_path; +- err = call_remote_storage(filename, count, index, buffer); ++ struct remote_request req = { ++ .filename=filename, ++ .size=count, ++ .index=index, ++ .buffer=buffer, ++ .operator='r' ++ }; ++ err = call_remote_storage(req); + if (err >= 0) { + struct inode *inode = filp->f_inode; + //if no error, write to page cache + +commit 6fc9f2bab98a75e1d2288269bc603201fdcc8e03 +Merge: b5918c59d e76eaa6a2 +Author: Saba Ebrahimi <66251874+sabaebrahimi@users.noreply.github.com> +Date: Sat Dec 28 15:18:11 2024 +0330 + + Merge pull request #2 from sabaebrahimi/main + + Strings fixed, Delete extra messages + +commit e76eaa6a2062bdf2a0fc179183764ff9c04e4f73 +Author: sabaebrahimi +Date: Wed Dec 18 06:48:25 2024 -0700 + + Strings fixed, Delete extra messages +--- + fs/udp_module.c | 57 +++++---------------------------------------------------- + mm/filemap.c | 36 ++++++++++++++---------------------- + 2 files changed, 19 insertions(+), 74 deletions(-) + +diff --git a/fs/udp_module.c b/fs/udp_module.c +index 4e6cf4046..7416f017b 100644 +--- a/fs/udp_module.c ++++ b/fs/udp_module.c +@@ -19,38 +19,6 @@ struct sockaddr_in remote_addr = {0}; + struct msghdr msg = {0}; + struct kvec iov; + +-// int perform_udp_request(void); +-/* +-static int write_file_from_kernel(const char *path, const char *data, size_t size) +-{ +- struct file *filp; +- loff_t pos = 0; +- ssize_t bytes_written; +- +- // Open (or create) the file with write-only mode. Using O_CREAT and O_TRUNC will overwrite if exists. +- filp = filp_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); +- if (IS_ERR(filp)) { +- pr_err("Failed to open file: %s, error: %ld\n", path, PTR_ERR(filp)); +- return PTR_ERR(filp); +- } +- +- // Write data to the file +- bytes_written = kernel_write(filp, data, size, &pos); +- if (bytes_written < 0) { +- pr_err("Failed to write to file: %s, error: %zd\n", path, bytes_written); +- filp_close(filp, NULL); +- return bytes_written; +- } +- +- pr_info("Successfully wrote %zd bytes to %s\n", bytes_written, path); +- +- // Close the file +- filp_close(filp, NULL); +- +- return 0; +-} +-*/ +- + static int remote_storage_init(void) { + printk(KERN_INFO "Network module loaded\n"); + int ret; +@@ -61,16 +29,10 @@ static int remote_storage_init(void) { + return ret; + } + +- printk(KERN_INFO "Socket created\n"); +- +- // sock->file->f_flags |= O_NONBLOCK; +- + remote_addr.sin_family = AF_INET; + remote_addr.sin_port = htons(DEST_PORT); // Set destination port + remote_addr.sin_addr.s_addr = in_aton(DEST_IP); + +- printk(KERN_INFO "UDP Client: Destination address set to %s:%d\n", DEST_IP, DEST_PORT); +- + return 0; + } + +@@ -92,7 +54,6 @@ int call_remote_storage(char* filename, size_t size, unsigned long index, char* + + //Initialize the socket + if (!sock) { +- printk(KERN_INFO "Remote: UDP Client: Socket is not initialized. Initializing now...\n"); + ret = remote_storage_init(); + if (ret < 0) { + printk(KERN_ERR "Remote: UDP Client: Failed to initialize socket, error %d\n", ret); +@@ -109,10 +70,8 @@ int call_remote_storage(char* filename, size_t size, unsigned long index, char* + ret = kernel_sendmsg(sock, &msg, &iov, 1, data_len); + if (ret < 0) { + printk(KERN_ERR "Remote: UDP Client: Failed to send message, error %d\n", ret); +- } else { +- printk(KERN_INFO "Remote: UDP Client: Successfully sent %d bytes to %s:%d\n", ret, DEST_IP, DEST_PORT); ++ goto error; + } +- kfree(data); + + iov.iov_base = buffer; + iov.iov_len = 1024; +@@ -120,22 +79,16 @@ int call_remote_storage(char* filename, size_t size, unsigned long index, char* + ret = kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len, MSG_WAITALL); + if (ret < 0 && ret != -EAGAIN) { + printk(KERN_ERR "Remote: kernel_recvmsg failed: %d\n", ret); +- return ret; ++ goto error; + } else { + if (ret > 0) { + buffer[ret] = '\0'; +- pr_info("Remote: Received message: %s\n", buffer); +- // char* path = "/tmp/"; +- // strcat(path, filename); +- // write_file_from_kernel(path, buffer, size); + } + } +- // kfree(buffer); +- // Step 4: Clean up the socket ++error: ++ kfree(data); + remote_storage_exit(); +- printk(KERN_INFO "Remote: UDP Client: Socket released\n"); +- +- return 0; ++ return ret; + } + EXPORT_SYMBOL(call_remote_storage); + +diff --git a/mm/filemap.c b/mm/filemap.c +index 432f79835..9450a772b 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -2531,7 +2531,7 @@ static int write_remote_to_pagecache(struct inode *inode, loff_t pos, size_t cou + memcpy_to_page(page, offset_in_page(pos), buf, n); + + res = aops->write_end(NULL, mapping, pos, n, n, page, fsdata); +- pr_info("After write begin\n"); ++ + if (res < 0) + return res; + if (res != n) +@@ -2556,31 +2556,17 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count, + struct folio *folio; + int err = 0; + +- char *tmp_path; +- char path_buf[256]; +- int printedd = 0; +- tmp_path = d_path(&filp->f_path, path_buf, sizeof(path_buf)); +- +- if (!IS_ERR(tmp_path) && strstr(tmp_path, "mamad.sh") != NULL) { +- printk(KERN_INFO "Remote: temp found"); +- printedd = 1; +- } +- + /* "last_index" is the index of the page beyond the end of the read */ + last_index = DIV_ROUND_UP(iocb->ki_pos + count, PAGE_SIZE); + retry: + if (fatal_signal_pending(current)) + return -EINTR; +- +- if (printedd) printk(KERN_INFO "Remote: Before page cache1"); ++ + filemap_get_read_batch(mapping, index, last_index - 1, fbatch); +- if (printedd) printk(KERN_INFO "Remote: Affteerrr page cache1"); + if (!folio_batch_count(fbatch)) { +- if (printedd) printk(KERN_INFO "Remote: READAHEAD"); + /*If not in page cache and remote, send request*/ + if (filp->f_flags & O_REMOTE) { + char* buffer; +- // char* buffer; + buffer = kmalloc(1024, GFP_KERNEL); + if (!buffer) { + printk(KERN_ERR "Remote: Failed to allocate memory for buffer\n"); +@@ -2588,12 +2574,21 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count, + } + memset(buffer, 0, 1024); + +- int ret = 0; +- ret = call_remote_storage("load.sh", count, index, buffer); +- if (ret >= 0) { ++ char *tmp_path; ++ char path_buf[256]; ++ tmp_path = d_path(&filp->f_path, path_buf, sizeof(path_buf)); ++ char* filename = strrchr(tmp_path, '/'); ++ if (filename) ++ filename++; ++ else ++ filename = tmp_path; ++ err = call_remote_storage(filename, count, index, buffer); ++ if (err >= 0) { + struct inode *inode = filp->f_inode; + //if no error, write to page cache + write_remote_to_pagecache(inode, index, count, buffer); ++ } else { ++ goto err; + } + } + +@@ -2601,12 +2596,9 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count, + return -EAGAIN; + page_cache_sync_readahead(mapping, ra, filp, index, + last_index - index); +- if (printedd) printk(KERN_INFO "Remote: Affteerrr readahead"); + filemap_get_read_batch(mapping, index, last_index - 1, fbatch); +- if (printedd) printk(KERN_INFO "Remote: Affteerrr page cache222"); + } + if (!folio_batch_count(fbatch)) { +- if (printedd) printk(KERN_INFO "Remote: Inside reaad disk"); + if (iocb->ki_flags & (IOCB_NOWAIT | IOCB_WAITQ)) + return -EAGAIN; + err = filemap_create_folio(filp, mapping, + +commit b5918c59dae6bbd60539c99a8213b84040baceb0 +Merge: 7be70b0b6 56bf279ec +Author: Saba Ebrahimi <66251874+sabaebrahimi@users.noreply.github.com> +Date: Mon Dec 16 13:08:12 2024 +0330 + + Merge pull request #1 from sabaebrahimi/main + + Main + +commit 56bf279ec152c5a9933c31155b9ef22a34fa162c +Author: sabaebrahimi +Date: Mon Dec 16 02:36:31 2024 -0700 + + Add to pagecache complete +--- + fs/udp_module.c | 23 ++++++++--------------- + include/linux/fs.h | 2 +- + mm/filemap.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 61 insertions(+), 17 deletions(-) + +diff --git a/fs/udp_module.c b/fs/udp_module.c +index 1cf3acddf..4e6cf4046 100644 +--- a/fs/udp_module.c ++++ b/fs/udp_module.c +@@ -20,7 +20,7 @@ struct msghdr msg = {0}; + struct kvec iov; + + // int perform_udp_request(void); +- ++/* + static int write_file_from_kernel(const char *path, const char *data, size_t size) + { + struct file *filp; +@@ -49,6 +49,7 @@ static int write_file_from_kernel(const char *path, const char *data, size_t siz + + return 0; + } ++*/ + + static int remote_storage_init(void) { + printk(KERN_INFO "Network module loaded\n"); +@@ -78,7 +79,7 @@ static void remote_storage_exit(void) { + printk(KERN_INFO "Network module unloaded\n"); + } + +-int call_remote_storage(char* filename, size_t size, unsigned long index) { ++int call_remote_storage(char* filename, size_t size, unsigned long index, char* buffer) { + char *data; + data = kmalloc(1024, GFP_KERNEL); + if (!data) { +@@ -113,31 +114,23 @@ int call_remote_storage(char* filename, size_t size, unsigned long index) { + } + kfree(data); + +- +- char* buffer; +- buffer = kmalloc(1024, GFP_KERNEL); +- if (!buffer) { +- printk(KERN_ERR "Remote: Failed to allocate memory for buffer\n"); +- return -ENOMEM; +- } +- memset(buffer, 0, 1024); +- + iov.iov_base = buffer; + iov.iov_len = 1024; + + ret = kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len, MSG_WAITALL); + if (ret < 0 && ret != -EAGAIN) { + printk(KERN_ERR "Remote: kernel_recvmsg failed: %d\n", ret); +- // Handle error ++ return ret; + } else { + if (ret > 0) { + buffer[ret] = '\0'; + pr_info("Remote: Received message: %s\n", buffer); +- +- write_file_from_kernel("/tmp/load.sh", buffer, size); ++ // char* path = "/tmp/"; ++ // strcat(path, filename); ++ // write_file_from_kernel(path, buffer, size); + } + } +- kfree(buffer); ++ // kfree(buffer); + // Step 4: Clean up the socket + remote_storage_exit(); + printk(KERN_INFO "Remote: UDP Client: Socket released\n"); +diff --git a/include/linux/fs.h b/include/linux/fs.h +index dc96db858..9258315f5 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3010,7 +3010,7 @@ extern ssize_t __kernel_write(struct file *, const void *, size_t, loff_t *); + extern struct file * open_exec(const char *); + + /*fs/udp_module.c -- fs support for remote*/ +-extern int call_remote_storage(char* filename, size_t size, unsigned long index); ++extern int call_remote_storage(char* filename, size_t size, unsigned long index, char* buffer); + + /* fs/dcache.c -- generic fs support functions */ + extern bool is_subdir(struct dentry *, struct dentry *); +diff --git a/mm/filemap.c b/mm/filemap.c +index 6f6cf83c3..432f79835 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -2509,6 +2509,42 @@ static int filemap_readahead(struct kiocb *iocb, struct file *file, + return 0; + } + ++static int write_remote_to_pagecache(struct inode *inode, loff_t pos, size_t count, char* buf) ++{ ++ struct address_space *mapping = inode->i_mapping; ++ const struct address_space_operations *aops = mapping->a_ops; ++ ++ if (pos + count > inode->i_sb->s_maxbytes) ++ return -EFBIG; ++ ++ while (count) { ++ size_t n = min_t(size_t, count, ++ PAGE_SIZE - offset_in_page(pos)); ++ struct page *page; ++ void *fsdata = NULL; ++ int res; ++ pr_info("Before write begin\n"); ++ res = aops->write_begin(NULL, mapping, pos, n, &page, &fsdata); ++ if (res) ++ return res; ++ ++ memcpy_to_page(page, offset_in_page(pos), buf, n); ++ ++ res = aops->write_end(NULL, mapping, pos, n, n, page, fsdata); ++ pr_info("After write begin\n"); ++ if (res < 0) ++ return res; ++ if (res != n) ++ return -EIO; ++ ++ buf += n; ++ pos += n; ++ count -= n; ++ } ++ return 0; ++} ++ ++ + static int filemap_get_pages(struct kiocb *iocb, size_t count, + struct folio_batch *fbatch, bool need_uptodate) + { +@@ -2543,7 +2579,22 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count, + if (printedd) printk(KERN_INFO "Remote: READAHEAD"); + /*If not in page cache and remote, send request*/ + if (filp->f_flags & O_REMOTE) { +- call_remote_storage("load.sh", count, index); ++ char* buffer; ++ // char* buffer; ++ buffer = kmalloc(1024, GFP_KERNEL); ++ if (!buffer) { ++ printk(KERN_ERR "Remote: Failed to allocate memory for buffer\n"); ++ return -ENOMEM; ++ } ++ memset(buffer, 0, 1024); ++ ++ int ret = 0; ++ ret = call_remote_storage("load.sh", count, index, buffer); ++ if (ret >= 0) { ++ struct inode *inode = filp->f_inode; ++ //if no error, write to page cache ++ write_remote_to_pagecache(inode, index, count, buffer); ++ } + } + + if (iocb->ki_flags & IOCB_NOIO) + +commit cd733a0ae4cb8bc7320e7d32b76ddcdbefae866e +Author: sabaebrahimi +Date: Tue Dec 10 13:20:37 2024 -0700 + + Add kernel write file +--- + fs/udp_module.c | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/fs/udp_module.c b/fs/udp_module.c +index 0f5d44a20..1cf3acddf 100644 +--- a/fs/udp_module.c ++++ b/fs/udp_module.c +@@ -7,6 +7,10 @@ + #include + #include + #include ++#include ++#include ++#include ++#include + + #define DEST_IP "192.168.123.79" // Destination IP address + #define DEST_PORT 1104 // Destination UDP port +@@ -17,6 +21,35 @@ struct kvec iov; + + // int perform_udp_request(void); + ++static int write_file_from_kernel(const char *path, const char *data, size_t size) ++{ ++ struct file *filp; ++ loff_t pos = 0; ++ ssize_t bytes_written; ++ ++ // Open (or create) the file with write-only mode. Using O_CREAT and O_TRUNC will overwrite if exists. ++ filp = filp_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); ++ if (IS_ERR(filp)) { ++ pr_err("Failed to open file: %s, error: %ld\n", path, PTR_ERR(filp)); ++ return PTR_ERR(filp); ++ } ++ ++ // Write data to the file ++ bytes_written = kernel_write(filp, data, size, &pos); ++ if (bytes_written < 0) { ++ pr_err("Failed to write to file: %s, error: %zd\n", path, bytes_written); ++ filp_close(filp, NULL); ++ return bytes_written; ++ } ++ ++ pr_info("Successfully wrote %zd bytes to %s\n", bytes_written, path); ++ ++ // Close the file ++ filp_close(filp, NULL); ++ ++ return 0; ++} ++ + static int remote_storage_init(void) { + printk(KERN_INFO "Network module loaded\n"); + int ret; +@@ -100,6 +133,8 @@ int call_remote_storage(char* filename, size_t size, unsigned long index) { + if (ret > 0) { + buffer[ret] = '\0'; + pr_info("Remote: Received message: %s\n", buffer); ++ ++ write_file_from_kernel("/tmp/load.sh", buffer, size); + } + } + kfree(buffer); + +commit 35c9e9fdb54b7590b85ddc39e20fc3d81d770ff1 +Author: sabaebrahimi +Date: Tue Dec 10 12:44:34 2024 -0700 + + Add size and index +--- + fs/udp_module.c | 12 ++++++++++-- + include/linux/fs.h | 2 +- + mm/filemap.c | 2 +- + 3 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/fs/udp_module.c b/fs/udp_module.c +index cf8815a86..0f5d44a20 100644 +--- a/fs/udp_module.c ++++ b/fs/udp_module.c +@@ -45,8 +45,14 @@ static void remote_storage_exit(void) { + printk(KERN_INFO "Network module unloaded\n"); + } + +-int call_remote_storage(char* filename) { +- char *data = filename; ++int call_remote_storage(char* filename, size_t size, unsigned long index) { ++ char *data; ++ data = kmalloc(1024, GFP_KERNEL); ++ if (!data) { ++ printk(KERN_ERR "Remote: Failed to allocate memory for buffer\n"); ++ return -ENOMEM; ++ } ++ sprintf(data, "%s,%ld,%lu", filename, size, index); + size_t data_len = strlen(data); + int ret = 0; + +@@ -72,6 +78,7 @@ int call_remote_storage(char* filename) { + } else { + printk(KERN_INFO "Remote: UDP Client: Successfully sent %d bytes to %s:%d\n", ret, DEST_IP, DEST_PORT); + } ++ kfree(data); + + + char* buffer; +@@ -95,6 +102,7 @@ int call_remote_storage(char* filename) { + pr_info("Remote: Received message: %s\n", buffer); + } + } ++ kfree(buffer); + // Step 4: Clean up the socket + remote_storage_exit(); + printk(KERN_INFO "Remote: UDP Client: Socket released\n"); +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 0359afe0d..dc96db858 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3010,7 +3010,7 @@ extern ssize_t __kernel_write(struct file *, const void *, size_t, loff_t *); + extern struct file * open_exec(const char *); + + /*fs/udp_module.c -- fs support for remote*/ +-extern int call_remote_storage(char* filename); ++extern int call_remote_storage(char* filename, size_t size, unsigned long index); + + /* fs/dcache.c -- generic fs support functions */ + extern bool is_subdir(struct dentry *, struct dentry *); +diff --git a/mm/filemap.c b/mm/filemap.c +index d3cb52a97..6f6cf83c3 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -2543,7 +2543,7 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count, + if (printedd) printk(KERN_INFO "Remote: READAHEAD"); + /*If not in page cache and remote, send request*/ + if (filp->f_flags & O_REMOTE) { +- call_remote_storage("load.sh"); ++ call_remote_storage("load.sh", count, index); + } + + if (iocb->ki_flags & IOCB_NOIO) + +commit 5c386ce89aa7246ba752a755ba455c84ec0479a7 +Author: sabaebrahimi +Date: Mon Dec 9 23:39:20 2024 -0700 + + Add send and receive modules +--- + fs/open.c | 2 +- + fs/udp_module.c | 37 ++++++++++++++++++++++++------------- + include/linux/fs.h | 2 +- + mm/filemap.c | 30 +++++++++++++++++++++++------- + 4 files changed, 49 insertions(+), 22 deletions(-) + +diff --git a/fs/open.c b/fs/open.c +index 30bfcddd5..492fe798e 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -1208,7 +1208,7 @@ inline struct open_how build_open_how(int flags, umode_t mode) + if (how.flags & O_PATH) + how.flags &= O_PATH_FLAGS; + /* Modes should only be set for create-like flags. */ +- if (!WILL_CREATE(how.flags)) ++ if (!WILL_CREATE(how.flags) /*|| how.flags & O_REMOTE)*/) + how.mode = 0; + return how; + } +diff --git a/fs/udp_module.c b/fs/udp_module.c +index 1b185ba33..cf8815a86 100644 +--- a/fs/udp_module.c ++++ b/fs/udp_module.c +@@ -34,11 +34,6 @@ static int remote_storage_init(void) { + remote_addr.sin_family = AF_INET; + remote_addr.sin_port = htons(DEST_PORT); // Set destination port + remote_addr.sin_addr.s_addr = in_aton(DEST_IP); +- // ret = in4_pton(DEST_IP, -1, (u8 *)&remote_addr.sin_addr.s_addr, '\0', NULL); // Convert IP address +- // if (ret == 0) { +- // printk(KERN_ERR "UDP Client: Invalid IP address format\n"); +- // return -EINVAL; +- // } + + printk(KERN_INFO "UDP Client: Destination address set to %s:%d\n", DEST_IP, DEST_PORT); + +@@ -50,8 +45,8 @@ static void remote_storage_exit(void) { + printk(KERN_INFO "Network module unloaded\n"); + } + +-int call_remote_storage(void) { +- char *data = "Remote: Hello, from kernel space!"; ++int call_remote_storage(char* filename) { ++ char *data = filename; + size_t data_len = strlen(data); + int ret = 0; + +@@ -78,16 +73,32 @@ int call_remote_storage(void) { + printk(KERN_INFO "Remote: UDP Client: Successfully sent %d bytes to %s:%d\n", ret, DEST_IP, DEST_PORT); + } + ++ ++ char* buffer; ++ buffer = kmalloc(1024, GFP_KERNEL); ++ if (!buffer) { ++ printk(KERN_ERR "Remote: Failed to allocate memory for buffer\n"); ++ return -ENOMEM; ++ } ++ memset(buffer, 0, 1024); ++ ++ iov.iov_base = buffer; ++ iov.iov_len = 1024; ++ ++ ret = kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len, MSG_WAITALL); ++ if (ret < 0 && ret != -EAGAIN) { ++ printk(KERN_ERR "Remote: kernel_recvmsg failed: %d\n", ret); ++ // Handle error ++ } else { ++ if (ret > 0) { ++ buffer[ret] = '\0'; ++ pr_info("Remote: Received message: %s\n", buffer); ++ } ++ } + // Step 4: Clean up the socket + remote_storage_exit(); + printk(KERN_INFO "Remote: UDP Client: Socket released\n"); + +- +- // ret = kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len, MSG_DONTWAIT); +- // if (ret < 0 && ret != -EAGAIN) { +- // printk(KERN_ERR "kernel_recvmsg failed: %d\n", ret); +- // // Handle error +- // } + return 0; + } + EXPORT_SYMBOL(call_remote_storage); +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 76ecff0d8..0359afe0d 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3010,7 +3010,7 @@ extern ssize_t __kernel_write(struct file *, const void *, size_t, loff_t *); + extern struct file * open_exec(const char *); + + /*fs/udp_module.c -- fs support for remote*/ +-extern int call_remote_storage(void); ++extern int call_remote_storage(char* filename); + + /* fs/dcache.c -- generic fs support functions */ + extern bool is_subdir(struct dentry *, struct dentry *); +diff --git a/mm/filemap.c b/mm/filemap.c +index 20e5bb666..d3cb52a97 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -2308,12 +2308,7 @@ static void filemap_get_read_batch(struct address_space *mapping, + { + XA_STATE(xas, &mapping->i_pages, index); + struct folio *folio; +- if (mapping_use_distributed_support(mapping)) { +- int ret = call_remote_storage(); +- if (ret < 0) { +- printk(KERN_ERR "Remote: UDP request failed with error %d\n", ret); +- } +- } ++ + rcu_read_lock(); + for (folio = xas_load(&xas); folio; folio = xas_next(&xas)) { + if (xas_retry(&xas, folio)) +@@ -2525,21 +2520,42 @@ static int filemap_get_pages(struct kiocb *iocb, size_t count, + struct folio *folio; + int err = 0; + ++ char *tmp_path; ++ char path_buf[256]; ++ int printedd = 0; ++ tmp_path = d_path(&filp->f_path, path_buf, sizeof(path_buf)); ++ ++ if (!IS_ERR(tmp_path) && strstr(tmp_path, "mamad.sh") != NULL) { ++ printk(KERN_INFO "Remote: temp found"); ++ printedd = 1; ++ } ++ + /* "last_index" is the index of the page beyond the end of the read */ + last_index = DIV_ROUND_UP(iocb->ki_pos + count, PAGE_SIZE); + retry: + if (fatal_signal_pending(current)) + return -EINTR; + ++ if (printedd) printk(KERN_INFO "Remote: Before page cache1"); + filemap_get_read_batch(mapping, index, last_index - 1, fbatch); ++ if (printedd) printk(KERN_INFO "Remote: Affteerrr page cache1"); + if (!folio_batch_count(fbatch)) { ++ if (printedd) printk(KERN_INFO "Remote: READAHEAD"); ++ /*If not in page cache and remote, send request*/ ++ if (filp->f_flags & O_REMOTE) { ++ call_remote_storage("load.sh"); ++ } ++ + if (iocb->ki_flags & IOCB_NOIO) + return -EAGAIN; + page_cache_sync_readahead(mapping, ra, filp, index, + last_index - index); ++ if (printedd) printk(KERN_INFO "Remote: Affteerrr readahead"); + filemap_get_read_batch(mapping, index, last_index - 1, fbatch); ++ if (printedd) printk(KERN_INFO "Remote: Affteerrr page cache222"); + } + if (!folio_batch_count(fbatch)) { ++ if (printedd) printk(KERN_INFO "Remote: Inside reaad disk"); + if (iocb->ki_flags & (IOCB_NOWAIT | IOCB_WAITQ)) + return -EAGAIN; + err = filemap_create_folio(filp, mapping, +@@ -2621,7 +2637,7 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter, + char path_buf[256]; + tmp_path = d_path(&filp->f_path, path_buf, sizeof(path_buf)); + +- if (!IS_ERR(tmp_path) && strstr(tmp_path, "load.sh") != NULL) { ++ if (!IS_ERR(tmp_path) && strstr(tmp_path, "mamad.sh") != NULL) { + if (filp->f_flags & O_REMOTE) { + printk(KERN_INFO "Remote: mapping changed to remote"); + mapping_set_distributed_support(mapping); + +commit 6e148ea692a7e9ac1445381c37984399fff71232 +Author: sabaebrahimi +Date: Tue Dec 3 09:37:38 2024 -0700 + + Add udp module +--- + fs/Kconfig | 4 +++ + fs/Makefile | 1 + + fs/udp_module.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/fs.h | 3 ++ + mm/filemap.c | 8 ++--- + 5 files changed, 106 insertions(+), 4 deletions(-) + +diff --git a/fs/Kconfig b/fs/Kconfig +index a46b0cbc4..02de3acb2 100644 +--- a/fs/Kconfig ++++ b/fs/Kconfig +@@ -25,6 +25,10 @@ config FS_STACK + config BUFFER_HEAD + bool + ++config REMOTE_STORAGE ++ bool "Enable Remote Storage" ++ default y ++ + # old blockdev_direct_IO implementation. Use iomap for new code instead + config LEGACY_DIRECT_IO + depends on BUFFER_HEAD +diff --git a/fs/Makefile b/fs/Makefile +index 6ecc9b0a5..1676e85c1 100644 +--- a/fs/Makefile ++++ b/fs/Makefile +@@ -27,6 +27,7 @@ obj-$(CONFIG_SIGNALFD) += signalfd.o + obj-$(CONFIG_TIMERFD) += timerfd.o + obj-$(CONFIG_EVENTFD) += eventfd.o + obj-$(CONFIG_USERFAULTFD) += userfaultfd.o ++obj-$(CONFIG_REMOTE_STORAGE) += udp_module.o + obj-$(CONFIG_AIO) += aio.o + obj-$(CONFIG_FS_DAX) += dax.o + obj-$(CONFIG_FS_ENCRYPTION) += crypto/ +diff --git a/fs/udp_module.c b/fs/udp_module.c +new file mode 100644 +index 000000000..1b185ba33 +--- /dev/null ++++ b/fs/udp_module.c +@@ -0,0 +1,94 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DEST_IP "192.168.123.79" // Destination IP address ++#define DEST_PORT 1104 // Destination UDP port ++struct socket *sock; ++struct sockaddr_in remote_addr = {0}; ++struct msghdr msg = {0}; ++struct kvec iov; ++ ++// int perform_udp_request(void); ++ ++static int remote_storage_init(void) { ++ printk(KERN_INFO "Network module loaded\n"); ++ int ret; ++ ++ ret = sock_create_kern(&init_net, AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); ++ if (ret < 0) { ++ printk(KERN_ERR "Failed to create socket\n"); ++ return ret; ++ } ++ ++ printk(KERN_INFO "Socket created\n"); ++ ++ // sock->file->f_flags |= O_NONBLOCK; ++ ++ remote_addr.sin_family = AF_INET; ++ remote_addr.sin_port = htons(DEST_PORT); // Set destination port ++ remote_addr.sin_addr.s_addr = in_aton(DEST_IP); ++ // ret = in4_pton(DEST_IP, -1, (u8 *)&remote_addr.sin_addr.s_addr, '\0', NULL); // Convert IP address ++ // if (ret == 0) { ++ // printk(KERN_ERR "UDP Client: Invalid IP address format\n"); ++ // return -EINVAL; ++ // } ++ ++ printk(KERN_INFO "UDP Client: Destination address set to %s:%d\n", DEST_IP, DEST_PORT); ++ ++ return 0; ++} ++ ++static void remote_storage_exit(void) { ++ sock_release(sock); ++ printk(KERN_INFO "Network module unloaded\n"); ++} ++ ++int call_remote_storage(void) { ++ char *data = "Remote: Hello, from kernel space!"; ++ size_t data_len = strlen(data); ++ int ret = 0; ++ ++ //Initialize the socket ++ if (!sock) { ++ printk(KERN_INFO "Remote: UDP Client: Socket is not initialized. Initializing now...\n"); ++ ret = remote_storage_init(); ++ if (ret < 0) { ++ printk(KERN_ERR "Remote: UDP Client: Failed to initialize socket, error %d\n", ret); ++ return ret; ++ } ++ } ++ ++ iov.iov_base = data; // Message data ++ iov.iov_len = data_len; ++ ++ msg.msg_name = &remote_addr; // Set destination address ++ msg.msg_namelen = sizeof(remote_addr); ++ ++ ret = kernel_sendmsg(sock, &msg, &iov, 1, data_len); ++ if (ret < 0) { ++ printk(KERN_ERR "Remote: UDP Client: Failed to send message, error %d\n", ret); ++ } else { ++ printk(KERN_INFO "Remote: UDP Client: Successfully sent %d bytes to %s:%d\n", ret, DEST_IP, DEST_PORT); ++ } ++ ++ // Step 4: Clean up the socket ++ remote_storage_exit(); ++ printk(KERN_INFO "Remote: UDP Client: Socket released\n"); ++ ++ ++ // ret = kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len, MSG_DONTWAIT); ++ // if (ret < 0 && ret != -EAGAIN) { ++ // printk(KERN_ERR "kernel_recvmsg failed: %d\n", ret); ++ // // Handle error ++ // } ++ return 0; ++} ++EXPORT_SYMBOL(call_remote_storage); ++ +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 6ca11e241..76ecff0d8 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3008,6 +3008,9 @@ ssize_t __kernel_read(struct file *file, void *buf, size_t count, loff_t *pos); + extern ssize_t kernel_write(struct file *, const void *, size_t, loff_t *); + extern ssize_t __kernel_write(struct file *, const void *, size_t, loff_t *); + extern struct file * open_exec(const char *); ++ ++/*fs/udp_module.c -- fs support for remote*/ ++extern int call_remote_storage(void); + + /* fs/dcache.c -- generic fs support functions */ + extern bool is_subdir(struct dentry *, struct dentry *); +diff --git a/mm/filemap.c b/mm/filemap.c +index 982056675..20e5bb666 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -2309,10 +2309,10 @@ static void filemap_get_read_batch(struct address_space *mapping, + XA_STATE(xas, &mapping->i_pages, index); + struct folio *folio; + if (mapping_use_distributed_support(mapping)) { +- // int ret = perform_udp_request(); +- // if (ret < 0) { +- // printk(KERN_ERR "Remote: UDP request failed with error %d\n", ret); +- // } ++ int ret = call_remote_storage(); ++ if (ret < 0) { ++ printk(KERN_ERR "Remote: UDP request failed with error %d\n", ret); ++ } + } + rcu_read_lock(); + for (folio = xas_load(&xas); folio; folio = xas_next(&xas)) { commit e91c8bbcceedad09631cc2f46332341af44730b7 Author: sabaebrahimi Date: Tue Jan 21 15:44:21 2025 +0000 Add write modifications --- server_file_module.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server_file_module.c b/server_file_module.c index 264a03e..cc4c1a1 100755 --- a/server_file_module.c +++ b/server_file_module.c @@ -68,7 +68,7 @@ static int write_to_pagecache(const char *file_path, loff_t pos, size_t size, ch struct dentry *dentry = path.dentry; struct inode *inode = dentry->d_inode; - return write_remote_to_pagecache(inode, pos >> PAGE_SHIFT, size, buffer); + return write_remote_to_pagecache(inode, pos >> PAGE_SHIFT, 1024, buffer); } static int read_page_cache(const char *file_path, loff_t pos, size_t size, char *buffer) @@ -172,6 +172,7 @@ static int udp_server_thread(void *data) char *buffer_ptr = buffer; pr_info("Received elements: %s\n", buffer); + pr_info("msg_len: %zu\n", msg.msg_iter.count); char *token; int i = 0; @@ -180,7 +181,7 @@ static int udp_server_thread(void *data) received_elements[1] = kmalloc(16, GFP_KERNEL); received_elements[2] = kmalloc(16, GFP_KERNEL); received_elements[3] = kmalloc(16, GFP_KERNEL); - received_elements[4] = kmalloc(PAGE_SIZE, GFP_KERNEL); + received_elements[4] = kmalloc(1024, GFP_KERNEL); token = strsep(&buffer_ptr, ","); while (token != NULL && i < 5) @@ -247,7 +248,6 @@ static int udp_server_thread(void *data) result = write_to_pagecache(path, loff_index, size, received_elements[4]); if (result) pr_err("Error in writing data to pagecache\n"); - send_response(udp_socket, &client_addr, "OK"); break; } commit 572a65f38d08d30a84c07e3cdb794ede55266b6c Author: sabaebrahimi Date: Sun Jan 19 07:15:30 2025 +0000 Add invalidate and write operations --- Makefile | 4 +-- server_file_module.c | 97 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 82 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index b4c0f91..f9efbb7 100755 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ obj-m += server_file_module.o BUILD_DIR := build -KERNEL_SOURCE := /users/saba_er/saba/linux-6.11.6 +KERNEL_SOURCE := /home/amirmnoohi/linux-6.11.6 PWD := $(shell pwd) default: $(BUILD_DIR) - make -C $(KERNEL_SOURCE) M=$(PWD) modules \ No newline at end of file + make -C $(KERNEL_SOURCE) M=$(PWD) modules diff --git a/server_file_module.c b/server_file_module.c index faa5099..264a03e 100755 --- a/server_file_module.c +++ b/server_file_module.c @@ -27,6 +27,50 @@ MODULE_VERSION("1.0"); static struct socket *udp_socket = NULL; // Socket for the UDP server static struct task_struct *udp_thread = NULL; // Kernel thread for listening +static int invalidate_page_cache_item(const char *file_path, loff_t pos, size_t size) +{ + struct path path; + int ret; + ret = kern_path(file_path, LOOKUP_FOLLOW, &path); + if (ret) + { + pr_err("Failed to resolve path: %d\n", ret); + return 1; + } + + struct dentry *dentry = path.dentry; + struct address_space *mapping = dentry->d_inode->i_mapping; + while(size) + { + size_t n = min_t(size_t, size, + PAGE_SIZE - offset_in_page(pos)); + ret = remote_invalidate_folio(mapping, pos >> PAGE_SHIFT); + if (ret) + return ret; + pos += n; + size -= n; + + } + return ret; +} + +static int write_to_pagecache(const char *file_path, loff_t pos, size_t size, char *buffer) +{ + struct path path; + int ret; + ret = kern_path(file_path, LOOKUP_FOLLOW, &path); + if (ret) + { + pr_err("Failed to resolve path: %d\n", ret); + return 1; + } + + struct dentry *dentry = path.dentry; + struct inode *inode = dentry->d_inode; + + return write_remote_to_pagecache(inode, pos >> PAGE_SHIFT, size, buffer); +} + static int read_page_cache(const char *file_path, loff_t pos, size_t size, char *buffer) { struct path path; @@ -90,7 +134,7 @@ static int udp_server_thread(void *data) struct msghdr msg; struct kvec iov; char buffer[BUFFER_SIZE]; - char *received_elements[3]; + char *received_elements[5]; int ret; struct sockaddr_in server_addr = { @@ -126,15 +170,20 @@ static int udp_server_thread(void *data) { buffer[ret] = '\0'; char *buffer_ptr = buffer; + + pr_info("Received elements: %s\n", buffer); + char *token; int i = 0; received_elements[0] = kmalloc(256, GFP_KERNEL); received_elements[1] = kmalloc(16, GFP_KERNEL); received_elements[2] = kmalloc(16, GFP_KERNEL); + received_elements[3] = kmalloc(16, GFP_KERNEL); + received_elements[4] = kmalloc(PAGE_SIZE, GFP_KERNEL); token = strsep(&buffer_ptr, ","); - while (token != NULL && i < 3) + while (token != NULL && i < 5) { received_elements[i++] = token; // Store token in the array token = strsep(&buffer_ptr, ","); @@ -172,25 +221,39 @@ static int udp_server_thread(void *data) loff_t loff_index = (loff_t)index; char *path = kmalloc(256, GFP_KERNEL); sprintf(path, "/root/%s", received_elements[0]); - - ssize_t result = read_page_cache(path, loff_index, size, file_content); - - // if (result >= 0) - // { - // pr_info("Read %zd bytes from file %s\n", result, received_elements[0]); - // } - if (return < 0) - pr_err("Error reading file: %zd\n", result); + pr_info("The last element: %s\n", received_elements[3]); + + ssize_t result = 0; + switch (received_elements[3][0]) { + case 'r': + pr_info("Entered read modeeee\n"); + result = read_page_cache(path, loff_index, size, file_content); + if (result) { + pr_err("Error reading file: %zd\n", result); + file_content = NULL; + } + send_response(udp_socket, &client_addr, file_content); + break; + case 'i': + pr_info("Enter invalidate mode\n"); + result = invalidate_page_cache_item(path, loff_index, size); + if (result) + pr_err("Error in invalidating page cache %zd\n", result); + send_response(udp_socket, &client_addr, "Invalidated!!"); + break; + case 'w': + pr_info("Entered Write mode \n"); + pr_info("The content is: %s\n", received_elements[4]); + result = write_to_pagecache(path, loff_index, size, received_elements[4]); + if (result) + pr_err("Error in writing data to pagecache\n"); + send_response(udp_socket, &client_addr, "OK"); + break; + } // Send a response to the client - send_response(udp_socket, &client_addr, file_content); - kfree(file_content); kfree(path); - kfree(received_elements[0]); - kfree(received_elements[1]); - kfree(received_elements[2]); - } else if (ret < 0) { commit 45e8fd33971104394a2824a7ce33b5f15ca0fcc1 Author: sabaebrahimi Date: Wed Dec 18 06:49:00 2024 -0700 Strings fixed, Delete extra prints --- server_file_module.c | 85 +++++++++++----------------------------------------- 1 file changed, 17 insertions(+), 68 deletions(-) diff --git a/server_file_module.c b/server_file_module.c index b50e1ee..faa5099 100755 --- a/server_file_module.c +++ b/server_file_module.c @@ -18,7 +18,6 @@ #define SERVER_PORT 1104 #define BUFFER_SIZE 1024 -#define RESPONSE_MESSAGE "Saba Saba" MODULE_LICENSE("GPL"); MODULE_AUTHOR("Saba Ebrahimi"); @@ -28,43 +27,11 @@ MODULE_VERSION("1.0"); static struct socket *udp_socket = NULL; // Socket for the UDP server static struct task_struct *udp_thread = NULL; // Kernel thread for listening -// Read file -static ssize_t read_file_from_kernel(const char *path, loff_t start, size_t size, char *buffer) -{ - struct file *filp; - ssize_t bytes_read = 0; - - pr_info("the path is: %s, start is: %llu, size is: %ld\n", path, start, size); - - // Open the file - filp = filp_open(path, O_RDONLY, 0); - if (IS_ERR(filp)) - { - pr_err("Failed to open file: %s\n", path); - return PTR_ERR(filp); - } - - // Read data from file - bytes_read = kernel_read(filp, buffer, size, &start); - if (bytes_read < 0) - { - pr_err("Failed to read file: %s\n", path); - } - - printk(KERN_INFO "Received Data: %s\n", buffer); - - filp_close(filp, NULL); - - return bytes_read; -} - static int read_page_cache(const char *file_path, loff_t pos, size_t size, char *buffer) { struct path path; int ret; - pr_info("before kern_path\n"); ret = kern_path(file_path, LOOKUP_FOLLOW, &path); - pr_info("After kern_info\n"); if (ret) { pr_err("Failed to resolve path: %d\n", ret); @@ -78,14 +45,11 @@ static int read_page_cache(const char *file_path, loff_t pos, size_t size, char { struct folio *folio; size_t n; - pr_info("read mapping folio: \n"); folio = read_mapping_folio(inode->i_mapping, pos >> PAGE_SHIFT, NULL); if (IS_ERR(folio)) return PTR_ERR(folio); - pr_info("After read mapping folio: \n"); n = memcpy_from_file_folio(buffer, folio, pos, size); - pr_info("After memcpy from file folio \n"); folio_put(folio); buffer += n; @@ -114,13 +78,7 @@ static int send_response(struct socket *sock, struct sockaddr_in *client_addr, c ret = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len); if (ret < 0) - { pr_err("UDP Server: Failed to send response, error %d\n", ret); - } - else - { - pr_info("UDP Server: Response sent to client\n"); - } return ret; } @@ -135,10 +93,6 @@ static int udp_server_thread(void *data) char *received_elements[3]; int ret; - received_elements[0] = kmalloc(256, GFP_KERNEL); - received_elements[1] = kmalloc(64, GFP_KERNEL); - received_elements[2] = kmalloc(64, GFP_KERNEL); - struct sockaddr_in server_addr = { .sin_family = AF_INET, .sin_port = htons(SERVER_PORT), @@ -172,9 +126,12 @@ static int udp_server_thread(void *data) { buffer[ret] = '\0'; char *buffer_ptr = buffer; - pr_info("UDP Server: Received message: %s\n", buffer); char *token; int i = 0; + + received_elements[0] = kmalloc(256, GFP_KERNEL); + received_elements[1] = kmalloc(16, GFP_KERNEL); + received_elements[2] = kmalloc(16, GFP_KERNEL); token = strsep(&buffer_ptr, ","); while (token != NULL && i < 3) @@ -213,32 +170,27 @@ static int udp_server_thread(void *data) } loff_t loff_index = (loff_t)index; - char *path = "/root/load.sh"; - // path = "/root/"; - // strcat(path, received_elements[0]); + char *path = kmalloc(256, GFP_KERNEL); + sprintf(path, "/root/%s", received_elements[0]); + ssize_t result = read_page_cache(path, loff_index, size, file_content); - printk(KERN_INFO "page cache read %s \n", file_content); - if (file_content[0] == '\0') - { - pr_info("Entered open file \n"); - result = read_file_from_kernel(path, loff_index, size, file_content); - } - if (result >= 0) - { - pr_info("Read %zd bytes from file %s\n", result, received_elements[0]); - // Process buffer as needed - } - else - { + // if (result >= 0) + // { + // pr_info("Read %zd bytes from file %s\n", result, received_elements[0]); + // } + if (return < 0) pr_err("Error reading file: %zd\n", result); - } // Send a response to the client send_response(udp_socket, &client_addr, file_content); - // kfree(buffer); + kfree(file_content); kfree(path); + kfree(received_elements[0]); + kfree(received_elements[1]); + kfree(received_elements[2]); + } else if (ret < 0) { @@ -257,8 +209,6 @@ static int __init udp_server_init(void) int ret; - pr_info("UDP Server: Initializing module\n"); - // Create a UDP socket ret = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &udp_socket); if (ret < 0) @@ -275,7 +225,6 @@ static int __init udp_server_init(void) sock_release(udp_socket); return PTR_ERR(udp_thread); } - pr_info("UDP Server: Module loaded\n"); return 0; }