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)) {