diff -Naur s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45/sysv/dir.c s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45-fixed/sysv/dir.c --- s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45/sysv/dir.c 2022-10-24 04:25:15.000000000 +0300 +++ s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45-fixed/sysv/dir.c 2024-12-21 13:17:00.777822352 +0300 @@ -28,37 +28,45 @@ .fsync = generic_file_fsync, }; -static inline void dir_put_page(struct page *page) +static void dir_commit_chunk(struct folio *folio, loff_t pos, unsigned len) { - kunmap(page); - put_page(page); -} - -static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len) -{ - struct address_space *mapping = page->mapping; + struct address_space *mapping = folio->mapping; struct inode *dir = mapping->host; - int err = 0; - block_write_end(NULL, mapping, pos, len, len, page, NULL); + block_write_end(NULL, mapping, pos, len, len, folio, NULL); if (pos+len > dir->i_size) { i_size_write(dir, pos+len); mark_inode_dirty(dir); } - if (IS_DIRSYNC(dir)) - err = write_one_page(page); - else - unlock_page(page); + folio_unlock(folio); +} + +static int sysv_handle_dirsync(struct inode *dir) +{ + int err; + + err = filemap_write_and_wait(dir->i_mapping); + if (!err) + err = sync_inode_metadata(dir, 1); return err; } -static struct page * dir_get_page(struct inode *dir, unsigned long n) +/* + * Calls to dir_get_folio()/folio_release_kmap() must be nested according to the + * rules documented in mm/highmem.rst. + * + * NOTE: sysv_find_entry() and sysv_dotdot() act as calls to dir_get_folio() + * and must be treated accordingly for nesting purposes. + */ +static void *dir_get_folio(struct inode *dir, unsigned long n, + struct folio **foliop) { - struct address_space *mapping = dir->i_mapping; - struct page *page = read_mapping_page(mapping, n, NULL); - if (!IS_ERR(page)) - kmap(page); - return page; + struct folio *folio = read_mapping_folio(dir->i_mapping, n, NULL); + + if (IS_ERR(folio)) + return ERR_CAST(folio); + *foliop = folio; + return kmap_local_folio(folio, 0); } static int sysv_readdir(struct file *file, struct dir_context *ctx) @@ -80,11 +88,11 @@ for ( ; n < npages; n++, offset = 0) { char *kaddr, *limit; struct sysv_dir_entry *de; - struct page *page = dir_get_page(inode, n); + struct folio *folio; - if (IS_ERR(page)) + kaddr = dir_get_folio(inode, n, &folio); + if (IS_ERR(kaddr)) continue; - kaddr = (char *)page_address(page); de = (struct sysv_dir_entry *)(kaddr+offset); limit = kaddr + PAGE_SIZE - SYSV_DIRSIZE; for ( ;(char*)de <= limit; de++, ctx->pos += sizeof(*de)) { @@ -96,11 +104,11 @@ if (!dir_emit(ctx, name, strnlen(name,SYSV_NAMELEN), fs16_to_cpu(SYSV_SB(sb), de->inode), DT_UNKNOWN)) { - dir_put_page(page); + folio_release_kmap(folio, kaddr); return 0; } } - dir_put_page(page); + folio_release_kmap(folio, kaddr); } return 0; } @@ -124,30 +132,26 @@ * itself (as a parameter - res_dir). It does NOT read the inode of the * entry - you'll have to do that yourself if you want to. */ -struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_page) +struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct folio **foliop) { const char * name = dentry->d_name.name; int namelen = dentry->d_name.len; struct inode * dir = d_inode(dentry->d_parent); unsigned long start, n; unsigned long npages = dir_pages(dir); - struct page *page = NULL; struct sysv_dir_entry *de; - *res_page = NULL; - start = SYSV_I(dir)->i_dir_start_lookup; if (start >= npages) start = 0; n = start; do { - char *kaddr; - page = dir_get_page(dir, n); - if (!IS_ERR(page)) { - kaddr = (char*)page_address(page); - de = (struct sysv_dir_entry *) kaddr; - kaddr += PAGE_SIZE - SYSV_DIRSIZE; + char *kaddr = dir_get_folio(dir, n, foliop); + + if (!IS_ERR(kaddr)) { + de = (struct sysv_dir_entry *)kaddr; + kaddr += folio_size(*foliop) - SYSV_DIRSIZE; for ( ; (char *) de <= kaddr ; de++) { if (!de->inode) continue; @@ -155,7 +159,7 @@ name, de->name)) goto found; } - dir_put_page(page); + folio_release_kmap(*foliop, kaddr); } if (++n >= npages) @@ -166,7 +170,6 @@ found: SYSV_I(dir)->i_dir_start_lookup = n; - *res_page = page; return de; } @@ -175,7 +178,7 @@ struct inode *dir = d_inode(dentry->d_parent); const char * name = dentry->d_name.name; int namelen = dentry->d_name.len; - struct page *page = NULL; + struct folio *folio = NULL; struct sysv_dir_entry * de; unsigned long npages = dir_pages(dir); unsigned long n; @@ -185,96 +188,94 @@ /* We take care of directory expansion in the same loop */ for (n = 0; n <= npages; n++) { - page = dir_get_page(dir, n); - err = PTR_ERR(page); - if (IS_ERR(page)) - goto out; - kaddr = (char*)page_address(page); + kaddr = dir_get_folio(dir, n, &folio); + if (IS_ERR(kaddr)) + return PTR_ERR(kaddr); de = (struct sysv_dir_entry *)kaddr; kaddr += PAGE_SIZE - SYSV_DIRSIZE; + while ((char *)de <= kaddr) { if (!de->inode) goto got_it; err = -EEXIST; if (namecompare(namelen, SYSV_NAMELEN, name, de->name)) - goto out_page; + goto out_folio; de++; } - dir_put_page(page); + folio_release_kmap(folio, kaddr); } BUG(); return -EINVAL; got_it: - pos = page_offset(page) + - (char*)de - (char*)page_address(page); - lock_page(page); - err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE); + pos = folio_pos(folio) + offset_in_folio(folio, de); + folio_lock(folio); + err = sysv_prepare_chunk(folio, pos, SYSV_DIRSIZE); if (err) goto out_unlock; memcpy (de->name, name, namelen); memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2); de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); - err = dir_commit_chunk(page, pos, SYSV_DIRSIZE); - dir->i_mtime = dir->i_ctime = current_time(dir); + dir_commit_chunk(folio, pos, SYSV_DIRSIZE); + inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); mark_inode_dirty(dir); -out_page: - dir_put_page(page); -out: + err = sysv_handle_dirsync(dir); +out_folio: + folio_release_kmap(folio, kaddr); return err; out_unlock: - unlock_page(page); - goto out_page; + folio_unlock(folio); + goto out_folio; } -int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page) +int sysv_delete_entry(struct sysv_dir_entry *de, struct folio *folio) { - struct inode *inode = page->mapping->host; - char *kaddr = (char*)page_address(page); - loff_t pos = page_offset(page) + (char *)de - kaddr; + struct inode *inode = folio->mapping->host; + loff_t pos = folio_pos(folio) + offset_in_folio(folio, de); int err; - lock_page(page); - err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE); - BUG_ON(err); + folio_lock(folio); + err = sysv_prepare_chunk(folio, pos, SYSV_DIRSIZE); + if (err) { + folio_unlock(folio); + return err; + } de->inode = 0; - err = dir_commit_chunk(page, pos, SYSV_DIRSIZE); - dir_put_page(page); - inode->i_ctime = inode->i_mtime = current_time(inode); + dir_commit_chunk(folio, pos, SYSV_DIRSIZE); + inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); mark_inode_dirty(inode); - return err; + return sysv_handle_dirsync(inode);; } int sysv_make_empty(struct inode *inode, struct inode *dir) { - struct page *page = grab_cache_page(inode->i_mapping, 0); + struct folio *folio = filemap_grab_folio(inode->i_mapping, 0); struct sysv_dir_entry * de; - char *base; + char *kaddr; int err; - if (!page) - return -ENOMEM; - err = sysv_prepare_chunk(page, 0, 2 * SYSV_DIRSIZE); + if (IS_ERR(folio)) + return PTR_ERR(folio); + err = sysv_prepare_chunk(folio, 0, 2 * SYSV_DIRSIZE); if (err) { - unlock_page(page); + folio_unlock(folio); goto fail; } - kmap(page); - - base = (char*)page_address(page); - memset(base, 0, PAGE_SIZE); + kaddr = kmap_local_folio(folio, 0); + memset(kaddr, 0, folio_size(folio)); - de = (struct sysv_dir_entry *) base; + de = (struct sysv_dir_entry *)kaddr; de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); strcpy(de->name,"."); de++; de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), dir->i_ino); strcpy(de->name,".."); - kunmap(page); - err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE); + kunmap_local(kaddr); + dir_commit_chunk(folio, 0, 2 * SYSV_DIRSIZE); + err = sysv_handle_dirsync(inode); fail: - put_page(page); + folio_put(folio); return err; } @@ -284,21 +285,17 @@ int sysv_empty_dir(struct inode * inode) { struct super_block *sb = inode->i_sb; - struct page *page = NULL; + struct folio *folio = NULL; unsigned long i, npages = dir_pages(inode); + char *kaddr; for (i = 0; i < npages; i++) { - char *kaddr; struct sysv_dir_entry * de; - page = dir_get_page(inode, i); - if (IS_ERR(page)) + kaddr = dir_get_folio(inode, i, &folio); + if (IS_ERR(kaddr)) continue; - kaddr = (char *)page_address(page); - de = (struct sysv_dir_entry *)kaddr; - kaddr += PAGE_SIZE-SYSV_DIRSIZE; - for ( ;(char *)de <= kaddr; de++) { if (!de->inode) continue; @@ -314,55 +311,55 @@ if (de->name[1] != '.' || de->name[2]) goto not_empty; } - dir_put_page(page); + folio_release_kmap(folio, kaddr); } return 1; not_empty: - dir_put_page(page); + folio_release_kmap(folio, kaddr); return 0; } /* Releases the page */ -void sysv_set_link(struct sysv_dir_entry *de, struct page *page, +int sysv_set_link(struct sysv_dir_entry *de, struct folio *folio, struct inode *inode) { - struct inode *dir = page->mapping->host; - loff_t pos = page_offset(page) + - (char *)de-(char*)page_address(page); + struct inode *dir = folio->mapping->host; + loff_t pos = folio_pos(folio) + offset_in_folio(folio, de); int err; - lock_page(page); - err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE); - BUG_ON(err); + folio_lock(folio); + err = sysv_prepare_chunk(folio, pos, SYSV_DIRSIZE); + if (err) { + folio_unlock(folio); + return err; + } de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); - err = dir_commit_chunk(page, pos, SYSV_DIRSIZE); - dir_put_page(page); - dir->i_mtime = dir->i_ctime = current_time(dir); + dir_commit_chunk(folio, pos, SYSV_DIRSIZE); + inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); mark_inode_dirty(dir); + return sysv_handle_dirsync(inode); } -struct sysv_dir_entry * sysv_dotdot (struct inode *dir, struct page **p) +struct sysv_dir_entry * sysv_dotdot (struct inode *dir, struct folio **foliop) { - struct page *page = dir_get_page(dir, 0); - struct sysv_dir_entry *de = NULL; + struct sysv_dir_entry *de = dir_get_folio(dir, 0, foliop);; - if (!IS_ERR(page)) { - de = (struct sysv_dir_entry*) page_address(page) + 1; - *p = page; + if (IS_ERR(de)) { + return NULL; } - return de; + return de + 1; } ino_t sysv_inode_by_name(struct dentry *dentry) { - struct page *page; - struct sysv_dir_entry *de = sysv_find_entry (dentry, &page); + struct folio *folio; + struct sysv_dir_entry *de = sysv_find_entry (dentry, &folio); ino_t res = 0; if (de) { res = fs16_to_cpu(SYSV_SB(dentry->d_sb), de->inode); - dir_put_page(page); + folio_release_kmap(folio, de); } return res; } diff -Naur s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45/sysv/file.c s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45-fixed/sysv/file.c --- s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45/sysv/file.c 2022-10-24 04:25:15.000000000 +0300 +++ s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45-fixed/sysv/file.c 2024-12-21 01:25:47.187888337 +0300 @@ -26,15 +26,16 @@ .write_iter = generic_file_write_iter, .mmap = generic_file_mmap, .fsync = generic_file_fsync, - .splice_read = generic_file_splice_read, + .splice_read = filemap_splice_read, }; -static int sysv_setattr(struct dentry *dentry, struct iattr *attr) +static int sysv_setattr(struct mnt_idmap *idmap, +struct dentry *dentry, struct iattr *attr) { struct inode *inode = d_inode(dentry); int error; - error = setattr_prepare(dentry, attr); + error = setattr_prepare(&nop_mnt_idmap, dentry, attr); if (error) return error; @@ -47,7 +48,7 @@ sysv_truncate(inode); } - setattr_copy(inode, attr); + setattr_copy(&nop_mnt_idmap, inode, attr); mark_inode_dirty(inode); return 0; } diff -Naur s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45/sysv/ialloc.c s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45-fixed/sysv/ialloc.c --- s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45/sysv/ialloc.c 2022-10-24 04:25:15.000000000 +0300 +++ s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45-fixed/sysv/ialloc.c 2024-12-21 00:59:36.165038026 +0300 @@ -163,9 +163,9 @@ *sbi->s_sb_fic_count = cpu_to_fs16(sbi, count); fs16_add(sbi, sbi->s_sb_total_free_inodes, -1); dirty_sb(sb); - inode_init_owner(inode, dir, mode); + inode_init_owner(&nop_mnt_idmap, inode, dir, mode); inode->i_ino = fs16_to_cpu(sbi, ino); - inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); + simple_inode_init_ts(inode); inode->i_blocks = 0; memset(SYSV_I(inode)->i_data, 0, sizeof(SYSV_I(inode)->i_data)); SYSV_I(inode)->i_dir_start_lookup = 0; diff -Naur s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45/sysv/inode.c s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45-fixed/sysv/inode.c --- s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45/sysv/inode.c 2022-10-24 04:25:15.000000000 +0300 +++ s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45-fixed/sysv/inode.c 2024-12-21 01:07:57.623990247 +0300 @@ -209,12 +209,9 @@ i_gid_write(inode, (gid_t)fs16_to_cpu(sbi, raw_inode->i_gid)); set_nlink(inode, fs16_to_cpu(sbi, raw_inode->i_nlink)); inode->i_size = fs32_to_cpu(sbi, raw_inode->i_size); - inode->i_atime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_atime); - inode->i_mtime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_mtime); - inode->i_ctime.tv_sec = fs32_to_cpu(sbi, raw_inode->i_ctime); - inode->i_ctime.tv_nsec = 0; - inode->i_atime.tv_nsec = 0; - inode->i_mtime.tv_nsec = 0; + inode_set_atime(inode, fs32_to_cpu(sbi, raw_inode->i_atime), 0); + inode_set_mtime(inode, fs32_to_cpu(sbi, raw_inode->i_mtime), 0); + inode_set_ctime(inode, fs32_to_cpu(sbi, raw_inode->i_ctime), 0); inode->i_blocks = 0; #ifdef dbrower_ @@ -268,9 +265,9 @@ raw_inode->i_gid = cpu_to_fs16(sbi, fs_high2lowgid(i_gid_read(inode))); raw_inode->i_nlink = cpu_to_fs16(sbi, inode->i_nlink); raw_inode->i_size = cpu_to_fs32(sbi, inode->i_size); - raw_inode->i_atime = cpu_to_fs32(sbi, inode->i_atime.tv_sec); - raw_inode->i_mtime = cpu_to_fs32(sbi, inode->i_mtime.tv_sec); - raw_inode->i_ctime = cpu_to_fs32(sbi, inode->i_ctime.tv_sec); + raw_inode->i_atime = cpu_to_fs32(sbi, inode_get_atime_sec(inode)); + raw_inode->i_mtime = cpu_to_fs32(sbi, inode_get_mtime_sec(inode)); + raw_inode->i_ctime = cpu_to_fs32(sbi, inode_get_ctime_sec(inode)); si = SYSV_I(inode); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) @@ -360,7 +357,7 @@ { sysv_inode_cachep = kmem_cache_create("sysv_inode_cache", sizeof(struct sysv_inode_info), 0, - SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD|SLAB_ACCOUNT, + SLAB_RECLAIM_ACCOUNT|SLAB_ACCOUNT, init_once); if (!sysv_inode_cachep) return -ENOMEM; diff -Naur s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45/sysv/itree.c s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45-fixed/sysv/itree.c --- s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45/sysv/itree.c 2022-10-24 04:25:15.000000000 +0300 +++ s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45-fixed/sysv/itree.c 2024-12-21 01:23:38.646900585 +0300 @@ -8,6 +8,7 @@ #include #include +#include #include #include "sysv.h" @@ -179,7 +180,7 @@ *where->p = where->key; write_unlock(&pointers_lock); - inode->i_ctime = current_time(inode); + inode_set_ctime_current(inode); /* had we spliced it onto indirect block? */ if (where->bh) @@ -419,7 +420,7 @@ } n++; } - inode->i_mtime = inode->i_ctime = current_time(inode); + inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); if (IS_SYNC(inode)) sysv_sync_inode (inode); else @@ -441,29 +442,29 @@ return blocks; } -int sysv_getattr(const struct path *path, struct kstat *stat, +int sysv_getattr(struct mnt_idmap *idmap, const struct path *path, struct kstat *stat, u32 request_mask, unsigned int flags) { struct super_block *s = path->dentry->d_sb; - generic_fillattr(d_inode(path->dentry), stat); + generic_fillattr(&nop_mnt_idmap, request_mask, d_inode(path->dentry), stat); stat->blocks = (s->s_blocksize / 512) * sysv_nblocks(s, stat->size); stat->blksize = s->s_blocksize; return 0; } -static int sysv_writepage(struct page *page, struct writeback_control *wbc) +static int sysv_writepages(struct address_space *mapping, struct writeback_control *wbc) { - return block_write_full_page(page,get_block,wbc); + return mpage_writepages(mapping, wbc, get_block); } -static int sysv_readpage(struct file *file, struct page *page) +static int sysv_read_folio(struct file *file, struct folio *folio) { - return block_read_full_page(page,get_block); + return block_read_full_folio(folio, get_block); } -int sysv_prepare_chunk(struct page *page, loff_t pos, unsigned len) +int sysv_prepare_chunk(struct folio *folio, loff_t pos, unsigned len) { - return __block_write_begin(page, pos, len, get_block); + return __block_write_begin(folio, pos, len, get_block); } static void sysv_write_failed(struct address_space *mapping, loff_t to) @@ -477,12 +478,12 @@ } static int sysv_write_begin(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, unsigned flags, - struct page **pagep, void **fsdata) + loff_t pos, unsigned len, + struct folio **foliop, void **fsdata) { int ret; - ret = block_write_begin(mapping, pos, len, flags, pagep, get_block); + ret = block_write_begin(mapping, pos, len, foliop, get_block); if (unlikely(ret)) sysv_write_failed(mapping, pos + len); @@ -495,9 +496,12 @@ } const struct address_space_operations sysv_aops = { - .readpage = sysv_readpage, - .writepage = sysv_writepage, + .dirty_folio = block_dirty_folio, + .invalidate_folio = block_invalidate_folio, + .read_folio = sysv_read_folio, + .writepages = sysv_writepages, .write_begin = sysv_write_begin, .write_end = generic_write_end, + .migrate_folio = buffer_migrate_folio, .bmap = sysv_bmap }; diff -Naur s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45/sysv/namei.c s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45-fixed/sysv/namei.c --- s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45/sysv/namei.c 2022-10-24 04:25:15.000000000 +0300 +++ s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45-fixed/sysv/namei.c 2024-12-21 13:05:12.343889852 +0300 @@ -61,7 +61,8 @@ return NULL; } -static int sysv_mknod(struct inode * dir, struct dentry * dentry, umode_t mode, dev_t rdev) +static int sysv_mknod(struct mnt_idmap *idmap, struct inode * dir, + struct dentry * dentry, umode_t mode, dev_t rdev) { struct inode * inode; int err; @@ -80,13 +81,14 @@ return err; } -static int sysv_create(struct inode * dir, struct dentry * dentry, umode_t mode, bool excl) +static int sysv_create(struct mnt_idmap *idmap, struct inode * dir, + struct dentry * dentry, umode_t mode, bool excl) { - return sysv_mknod(dir, dentry, mode, 0); + return sysv_mknod(&nop_mnt_idmap, dir, dentry, mode, 0); } -static int sysv_symlink(struct inode * dir, struct dentry * dentry, - const char * symname) +static int sysv_symlink(struct mnt_idmap *idmap, struct inode * dir, + struct dentry * dentry, const char * symname) { int err = -ENAMETOOLONG; int l = strlen(symname)+1; @@ -121,14 +123,15 @@ { struct inode *inode = d_inode(old_dentry); - inode->i_ctime = current_time(inode); + inode_set_ctime_current(inode); inode_inc_link_count(inode); ihold(inode); return add_nondir(dentry, inode); } -static int sysv_mkdir(struct inode * dir, struct dentry *dentry, umode_t mode) +static int sysv_mkdir(struct mnt_idmap *idmap, struct inode * dir, + struct dentry *dentry, umode_t mode) { struct inode * inode; int err; @@ -168,21 +171,20 @@ static int sysv_unlink(struct inode * dir, struct dentry * dentry) { struct inode * inode = d_inode(dentry); - struct page * page; + struct folio *folio; struct sysv_dir_entry * de; int err = -ENOENT; - de = sysv_find_entry(dentry, &page); + de = sysv_find_entry(dentry, &folio); if (!de) - goto out; - - err = sysv_delete_entry (de, page); - if (err) - goto out; + return -ENOENT; - inode->i_ctime = dir->i_ctime; - inode_dec_link_count(inode); -out: + err = sysv_delete_entry (de, folio); + if (!err) { + inode_set_ctime_to_ts(inode, inode_get_ctime(dir)); + inode_dec_link_count(inode); + } + folio_release_kmap(folio, de); return err; } @@ -206,34 +208,34 @@ * Anybody can rename anything with this: the permission checks are left to the * higher-level routines. */ -static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry, - struct inode * new_dir, struct dentry * new_dentry, - unsigned int flags) +static int sysv_rename(struct mnt_idmap *idmap, struct inode * old_dir, + struct dentry * old_dentry, struct inode * new_dir, + struct dentry * new_dentry, unsigned int flags) { struct inode * old_inode = d_inode(old_dentry); struct inode * new_inode = d_inode(new_dentry); - struct page * dir_page = NULL; + struct folio *dir_folio; struct sysv_dir_entry * dir_de = NULL; - struct page * old_page; + struct folio *old_folio; struct sysv_dir_entry * old_de; int err = -ENOENT; if (flags & ~RENAME_NOREPLACE) return -EINVAL; - old_de = sysv_find_entry(old_dentry, &old_page); + old_de = sysv_find_entry(old_dentry, &old_folio); if (!old_de) goto out; if (S_ISDIR(old_inode->i_mode)) { err = -EIO; - dir_de = sysv_dotdot(old_inode, &dir_page); + dir_de = sysv_dotdot(old_inode, &dir_folio); if (!dir_de) goto out_old; } if (new_inode) { - struct page * new_page; + struct folio *new_folio; struct sysv_dir_entry * new_de; err = -ENOTEMPTY; @@ -241,11 +243,14 @@ goto out_dir; err = -ENOENT; - new_de = sysv_find_entry(new_dentry, &new_page); + new_de = sysv_find_entry(new_dentry, &new_folio); if (!new_de) goto out_dir; - sysv_set_link(new_de, new_page, old_inode); - new_inode->i_ctime = current_time(new_inode); + err = sysv_set_link(new_de, new_folio, old_inode); + folio_release_kmap(new_folio, new_de); + if (err) + goto out_dir; + inode_set_ctime_current(new_inode); if (dir_de) drop_nlink(new_inode); inode_dec_link_count(new_inode); @@ -257,23 +262,25 @@ inode_inc_link_count(new_dir); } - sysv_delete_entry(old_de, old_page); + err = sysv_delete_entry(old_de, old_folio); + if (err) + goto out_dir; + mark_inode_dirty(old_inode); if (dir_de) { - sysv_set_link(dir_de, dir_page, new_dir); - inode_dec_link_count(old_dir); + err = sysv_set_link(dir_de, dir_folio, new_dir); + if (!err) + inode_dec_link_count(old_dir); } return 0; out_dir: if (dir_de) { - kunmap(dir_page); - put_page(dir_page); + folio_release_kmap(dir_folio, dir_de); } out_old: - kunmap(old_page); - put_page(old_page); + folio_release_kmap(old_folio, old_de); out: return err; } diff -Naur s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45/sysv/sysv.h s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45-fixed/sysv/sysv.h --- s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45/sysv/sysv.h 2022-10-24 04:25:15.000000000 +0300 +++ s4-3b1-pc7300-efe55b8cc917e3e27bcae9786c5b5dec0469be45-fixed/sysv/sysv.h 2024-12-21 12:59:55.650920027 +0300 @@ -139,27 +139,27 @@ /* itree.c */ extern void sysv_truncate(struct inode *); -extern int sysv_prepare_chunk(struct page *page, loff_t pos, unsigned len); +extern int sysv_prepare_chunk(struct folio *folio, loff_t pos, unsigned len); /* inode.c */ extern struct inode *sysv_iget(struct super_block *, unsigned int); extern int sysv_write_inode(struct inode *, struct writeback_control *wbc); extern int sysv_sync_inode(struct inode *); extern void sysv_set_inode(struct inode *, dev_t); -extern int sysv_getattr(const struct path *, struct kstat *, u32, unsigned int); +extern int sysv_getattr(struct mnt_idmap *, const struct path *, struct kstat *, u32, unsigned int); extern int sysv_init_icache(void); extern void sysv_destroy_icache(void); /* dir.c */ -extern struct sysv_dir_entry *sysv_find_entry(struct dentry *, struct page **); +extern struct sysv_dir_entry *sysv_find_entry(struct dentry *, struct folio **); extern int sysv_add_link(struct dentry *, struct inode *); -extern int sysv_delete_entry(struct sysv_dir_entry *, struct page *); +extern int sysv_delete_entry(struct sysv_dir_entry *, struct folio *); extern int sysv_make_empty(struct inode *, struct inode *); extern int sysv_empty_dir(struct inode *); -extern void sysv_set_link(struct sysv_dir_entry *, struct page *, +extern int sysv_set_link(struct sysv_dir_entry *, struct folio *, struct inode *); -extern struct sysv_dir_entry *sysv_dotdot(struct inode *, struct page **); +extern struct sysv_dir_entry *sysv_dotdot(struct inode *, struct folio **); extern ino_t sysv_inode_by_name(struct dentry *);