1ae98043fSRyusuke Konishi // SPDX-License-Identifier: GPL-2.0+ 22ba466d7SYoshiji Amagai /* 394ee1d91SRyusuke Konishi * NILFS directory entry operations 42ba466d7SYoshiji Amagai * 52ba466d7SYoshiji Amagai * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation. 62ba466d7SYoshiji Amagai * 74b420ab4SRyusuke Konishi * Modified for NILFS by Amagai Yoshiji. 82ba466d7SYoshiji Amagai */ 92ba466d7SYoshiji Amagai /* 102ba466d7SYoshiji Amagai * linux/fs/ext2/dir.c 112ba466d7SYoshiji Amagai * 122ba466d7SYoshiji Amagai * Copyright (C) 1992, 1993, 1994, 1995 132ba466d7SYoshiji Amagai * Remy Card (card@masi.ibp.fr) 142ba466d7SYoshiji Amagai * Laboratoire MASI - Institut Blaise Pascal 152ba466d7SYoshiji Amagai * Universite Pierre et Marie Curie (Paris VI) 162ba466d7SYoshiji Amagai * 172ba466d7SYoshiji Amagai * from 182ba466d7SYoshiji Amagai * 192ba466d7SYoshiji Amagai * linux/fs/minix/dir.c 202ba466d7SYoshiji Amagai * 212ba466d7SYoshiji Amagai * Copyright (C) 1991, 1992 Linus Torvalds 222ba466d7SYoshiji Amagai * 232ba466d7SYoshiji Amagai * ext2 directory handling functions 242ba466d7SYoshiji Amagai * 252ba466d7SYoshiji Amagai * Big-endian to little-endian byte-swapping/bitmaps by 262ba466d7SYoshiji Amagai * David S. Miller (davem@caip.rutgers.edu), 1995 272ba466d7SYoshiji Amagai * 282ba466d7SYoshiji Amagai * All code that works with directory layout had been switched to pagecache 292ba466d7SYoshiji Amagai * and moved here. AV 302ba466d7SYoshiji Amagai */ 312ba466d7SYoshiji Amagai 322ba466d7SYoshiji Amagai #include <linux/pagemap.h> 332ba466d7SYoshiji Amagai #include "nilfs.h" 342ba466d7SYoshiji Amagai #include "page.h" 352ba466d7SYoshiji Amagai 36e63e88bcSRyusuke Konishi static inline unsigned int nilfs_rec_len_from_disk(__le16 dlen) 37e63e88bcSRyusuke Konishi { 38e63e88bcSRyusuke Konishi unsigned int len = le16_to_cpu(dlen); 39e63e88bcSRyusuke Konishi 40e63e88bcSRyusuke Konishi #if (PAGE_SIZE >= 65536) 41e63e88bcSRyusuke Konishi if (len == NILFS_MAX_REC_LEN) 42e63e88bcSRyusuke Konishi return 1 << 16; 43e63e88bcSRyusuke Konishi #endif 44e63e88bcSRyusuke Konishi return len; 45e63e88bcSRyusuke Konishi } 46e63e88bcSRyusuke Konishi 47e63e88bcSRyusuke Konishi static inline __le16 nilfs_rec_len_to_disk(unsigned int len) 48e63e88bcSRyusuke Konishi { 49e63e88bcSRyusuke Konishi #if (PAGE_SIZE >= 65536) 50e63e88bcSRyusuke Konishi if (len == (1 << 16)) 51e63e88bcSRyusuke Konishi return cpu_to_le16(NILFS_MAX_REC_LEN); 52e63e88bcSRyusuke Konishi 53e63e88bcSRyusuke Konishi BUG_ON(len > (1 << 16)); 54e63e88bcSRyusuke Konishi #endif 55e63e88bcSRyusuke Konishi return cpu_to_le16(len); 56e63e88bcSRyusuke Konishi } 57e63e88bcSRyusuke Konishi 582ba466d7SYoshiji Amagai /* 592ba466d7SYoshiji Amagai * nilfs uses block-sized chunks. Arguably, sector-sized ones would be 602ba466d7SYoshiji Amagai * more robust, but we have what we have 612ba466d7SYoshiji Amagai */ 620c6c44cbSRyusuke Konishi static inline unsigned int nilfs_chunk_size(struct inode *inode) 632ba466d7SYoshiji Amagai { 642ba466d7SYoshiji Amagai return inode->i_sb->s_blocksize; 652ba466d7SYoshiji Amagai } 662ba466d7SYoshiji Amagai 672ba466d7SYoshiji Amagai /* 682ba466d7SYoshiji Amagai * Return the offset into page `page_nr' of the last valid 692ba466d7SYoshiji Amagai * byte in that page, plus one. 702ba466d7SYoshiji Amagai */ 710c6c44cbSRyusuke Konishi static unsigned int nilfs_last_byte(struct inode *inode, unsigned long page_nr) 722ba466d7SYoshiji Amagai { 730c6c44cbSRyusuke Konishi unsigned int last_byte = inode->i_size; 742ba466d7SYoshiji Amagai 7509cbfeafSKirill A. Shutemov last_byte -= page_nr << PAGE_SHIFT; 7609cbfeafSKirill A. Shutemov if (last_byte > PAGE_SIZE) 7709cbfeafSKirill A. Shutemov last_byte = PAGE_SIZE; 782ba466d7SYoshiji Amagai return last_byte; 792ba466d7SYoshiji Amagai } 802ba466d7SYoshiji Amagai 819bff5f98SMatthew Wilcox (Oracle) static int nilfs_prepare_chunk(struct folio *folio, unsigned int from, 820c6c44cbSRyusuke Konishi unsigned int to) 832ba466d7SYoshiji Amagai { 849bff5f98SMatthew Wilcox (Oracle) loff_t pos = folio_pos(folio) + from; 854ad364caSRyusuke Konishi 869bff5f98SMatthew Wilcox (Oracle) return __block_write_begin(&folio->page, pos, to - from, nilfs_get_block); 872ba466d7SYoshiji Amagai } 882ba466d7SYoshiji Amagai 899bff5f98SMatthew Wilcox (Oracle) static void nilfs_commit_chunk(struct folio *folio, 909bff5f98SMatthew Wilcox (Oracle) struct address_space *mapping, size_t from, size_t to) 912ba466d7SYoshiji Amagai { 922ba466d7SYoshiji Amagai struct inode *dir = mapping->host; 939bff5f98SMatthew Wilcox (Oracle) loff_t pos = folio_pos(folio) + from; 949bff5f98SMatthew Wilcox (Oracle) size_t copied, len = to - from; 959bff5f98SMatthew Wilcox (Oracle) unsigned int nr_dirty; 962ba466d7SYoshiji Amagai int err; 972ba466d7SYoshiji Amagai 989bff5f98SMatthew Wilcox (Oracle) nr_dirty = nilfs_page_count_clean_buffers(&folio->page, from, to); 999bff5f98SMatthew Wilcox (Oracle) copied = block_write_end(NULL, mapping, pos, len, len, &folio->page, NULL); 10058d55471SJiro SEKIBA if (pos + copied > dir->i_size) 1012ba466d7SYoshiji Amagai i_size_write(dir, pos + copied); 1022ba466d7SYoshiji Amagai if (IS_DIRSYNC(dir)) 1032ba466d7SYoshiji Amagai nilfs_set_transaction_flag(NILFS_TI_SYNC); 104bcbc8c64SRyusuke Konishi err = nilfs_set_file_dirty(dir, nr_dirty); 1052093abf9SJiro SEKIBA WARN_ON(err); /* do not happen */ 1069bff5f98SMatthew Wilcox (Oracle) folio_unlock(folio); 1072ba466d7SYoshiji Amagai } 1082ba466d7SYoshiji Amagai 10975ad5db6SMatthew Wilcox (Oracle) static bool nilfs_check_folio(struct folio *folio, char *kaddr) 1102ba466d7SYoshiji Amagai { 11175ad5db6SMatthew Wilcox (Oracle) struct inode *dir = folio->mapping->host; 1122ba466d7SYoshiji Amagai struct super_block *sb = dir->i_sb; 1130c6c44cbSRyusuke Konishi unsigned int chunk_size = nilfs_chunk_size(dir); 11475ad5db6SMatthew Wilcox (Oracle) size_t offs, rec_len; 11575ad5db6SMatthew Wilcox (Oracle) size_t limit = folio_size(folio); 1162ba466d7SYoshiji Amagai struct nilfs_dir_entry *p; 1172ba466d7SYoshiji Amagai char *error; 1182ba466d7SYoshiji Amagai 11975ad5db6SMatthew Wilcox (Oracle) if (dir->i_size < folio_pos(folio) + limit) { 12075ad5db6SMatthew Wilcox (Oracle) limit = dir->i_size - folio_pos(folio); 1212ba466d7SYoshiji Amagai if (limit & (chunk_size - 1)) 1222ba466d7SYoshiji Amagai goto Ebadsize; 1232ba466d7SYoshiji Amagai if (!limit) 1242ba466d7SYoshiji Amagai goto out; 1252ba466d7SYoshiji Amagai } 1262ba466d7SYoshiji Amagai for (offs = 0; offs <= limit - NILFS_DIR_REC_LEN(1); offs += rec_len) { 1272ba466d7SYoshiji Amagai p = (struct nilfs_dir_entry *)(kaddr + offs); 1286cda9fa2SRyusuke Konishi rec_len = nilfs_rec_len_from_disk(p->rec_len); 1292ba466d7SYoshiji Amagai 1302ba466d7SYoshiji Amagai if (rec_len < NILFS_DIR_REC_LEN(1)) 1312ba466d7SYoshiji Amagai goto Eshort; 1322ba466d7SYoshiji Amagai if (rec_len & 3) 1332ba466d7SYoshiji Amagai goto Ealign; 1342ba466d7SYoshiji Amagai if (rec_len < NILFS_DIR_REC_LEN(p->name_len)) 1352ba466d7SYoshiji Amagai goto Enamelen; 1362ba466d7SYoshiji Amagai if (((offs + rec_len - 1) ^ offs) & ~(chunk_size-1)) 1372ba466d7SYoshiji Amagai goto Espan; 138bb76c6c2SRyusuke Konishi if (unlikely(p->inode && 139bb76c6c2SRyusuke Konishi NILFS_PRIVATE_INODE(le64_to_cpu(p->inode)))) 140bb76c6c2SRyusuke Konishi goto Einumber; 1412ba466d7SYoshiji Amagai } 1422ba466d7SYoshiji Amagai if (offs != limit) 1432ba466d7SYoshiji Amagai goto Eend; 1442ba466d7SYoshiji Amagai out: 14575ad5db6SMatthew Wilcox (Oracle) folio_set_checked(folio); 146be5b82dbSAl Viro return true; 1472ba466d7SYoshiji Amagai 1482ba466d7SYoshiji Amagai /* Too bad, we had an error */ 1492ba466d7SYoshiji Amagai 1502ba466d7SYoshiji Amagai Ebadsize: 151cae3d4caSRyusuke Konishi nilfs_error(sb, 1522ba466d7SYoshiji Amagai "size of directory #%lu is not a multiple of chunk size", 153cae3d4caSRyusuke Konishi dir->i_ino); 1542ba466d7SYoshiji Amagai goto fail; 1552ba466d7SYoshiji Amagai Eshort: 1562ba466d7SYoshiji Amagai error = "rec_len is smaller than minimal"; 1572ba466d7SYoshiji Amagai goto bad_entry; 1582ba466d7SYoshiji Amagai Ealign: 1592ba466d7SYoshiji Amagai error = "unaligned directory entry"; 1602ba466d7SYoshiji Amagai goto bad_entry; 1612ba466d7SYoshiji Amagai Enamelen: 1622ba466d7SYoshiji Amagai error = "rec_len is too small for name_len"; 1632ba466d7SYoshiji Amagai goto bad_entry; 1642ba466d7SYoshiji Amagai Espan: 1652ba466d7SYoshiji Amagai error = "directory entry across blocks"; 166bb76c6c2SRyusuke Konishi goto bad_entry; 167bb76c6c2SRyusuke Konishi Einumber: 168bb76c6c2SRyusuke Konishi error = "disallowed inode number"; 1692ba466d7SYoshiji Amagai bad_entry: 170cae3d4caSRyusuke Konishi nilfs_error(sb, 17175ad5db6SMatthew Wilcox (Oracle) "bad entry in directory #%lu: %s - offset=%lu, inode=%lu, rec_len=%zd, name_len=%d", 17275ad5db6SMatthew Wilcox (Oracle) dir->i_ino, error, (folio->index << PAGE_SHIFT) + offs, 1732ba466d7SYoshiji Amagai (unsigned long)le64_to_cpu(p->inode), 1742ba466d7SYoshiji Amagai rec_len, p->name_len); 1752ba466d7SYoshiji Amagai goto fail; 1762ba466d7SYoshiji Amagai Eend: 1772ba466d7SYoshiji Amagai p = (struct nilfs_dir_entry *)(kaddr + offs); 178cae3d4caSRyusuke Konishi nilfs_error(sb, 179cae3d4caSRyusuke Konishi "entry in directory #%lu spans the page boundary offset=%lu, inode=%lu", 18075ad5db6SMatthew Wilcox (Oracle) dir->i_ino, (folio->index << PAGE_SHIFT) + offs, 1812ba466d7SYoshiji Amagai (unsigned long)le64_to_cpu(p->inode)); 1822ba466d7SYoshiji Amagai fail: 183be5b82dbSAl Viro return false; 1842ba466d7SYoshiji Amagai } 1852ba466d7SYoshiji Amagai 18675ad5db6SMatthew Wilcox (Oracle) static void *nilfs_get_folio(struct inode *dir, unsigned long n, 18775ad5db6SMatthew Wilcox (Oracle) struct folio **foliop) 18875ad5db6SMatthew Wilcox (Oracle) { 18975ad5db6SMatthew Wilcox (Oracle) struct address_space *mapping = dir->i_mapping; 19075ad5db6SMatthew Wilcox (Oracle) struct folio *folio = read_mapping_folio(mapping, n, NULL); 19175ad5db6SMatthew Wilcox (Oracle) void *kaddr; 19275ad5db6SMatthew Wilcox (Oracle) 19375ad5db6SMatthew Wilcox (Oracle) if (IS_ERR(folio)) 19475ad5db6SMatthew Wilcox (Oracle) return folio; 19575ad5db6SMatthew Wilcox (Oracle) 19675ad5db6SMatthew Wilcox (Oracle) kaddr = kmap_local_folio(folio, 0); 19775ad5db6SMatthew Wilcox (Oracle) if (unlikely(!folio_test_checked(folio))) { 19875ad5db6SMatthew Wilcox (Oracle) if (!nilfs_check_folio(folio, kaddr)) 19975ad5db6SMatthew Wilcox (Oracle) goto fail; 20075ad5db6SMatthew Wilcox (Oracle) } 20175ad5db6SMatthew Wilcox (Oracle) 20275ad5db6SMatthew Wilcox (Oracle) *foliop = folio; 20375ad5db6SMatthew Wilcox (Oracle) return kaddr; 20475ad5db6SMatthew Wilcox (Oracle) 20575ad5db6SMatthew Wilcox (Oracle) fail: 20675ad5db6SMatthew Wilcox (Oracle) folio_release_kmap(folio, kaddr); 20775ad5db6SMatthew Wilcox (Oracle) return ERR_PTR(-EIO); 20875ad5db6SMatthew Wilcox (Oracle) } 20975ad5db6SMatthew Wilcox (Oracle) 2102ba466d7SYoshiji Amagai /* 2112ba466d7SYoshiji Amagai * NOTE! unlike strncmp, nilfs_match returns 1 for success, 0 for failure. 2122ba466d7SYoshiji Amagai * 2132ba466d7SYoshiji Amagai * len <= NILFS_NAME_LEN and de != NULL are guaranteed by caller. 2142ba466d7SYoshiji Amagai */ 2152ba466d7SYoshiji Amagai static int 216072f98b4SAl Viro nilfs_match(int len, const unsigned char *name, struct nilfs_dir_entry *de) 2172ba466d7SYoshiji Amagai { 2182ba466d7SYoshiji Amagai if (len != de->name_len) 2192ba466d7SYoshiji Amagai return 0; 2202ba466d7SYoshiji Amagai if (!de->inode) 2212ba466d7SYoshiji Amagai return 0; 2222ba466d7SYoshiji Amagai return !memcmp(name, de->name, len); 2232ba466d7SYoshiji Amagai } 2242ba466d7SYoshiji Amagai 2252ba466d7SYoshiji Amagai /* 2262ba466d7SYoshiji Amagai * p is at least 6 bytes before the end of page 2272ba466d7SYoshiji Amagai */ 2282ba466d7SYoshiji Amagai static struct nilfs_dir_entry *nilfs_next_entry(struct nilfs_dir_entry *p) 2292ba466d7SYoshiji Amagai { 2306cda9fa2SRyusuke Konishi return (struct nilfs_dir_entry *)((char *)p + 2316cda9fa2SRyusuke Konishi nilfs_rec_len_from_disk(p->rec_len)); 2322ba466d7SYoshiji Amagai } 2332ba466d7SYoshiji Amagai 2342ba466d7SYoshiji Amagai static unsigned char 2352ba466d7SYoshiji Amagai nilfs_filetype_table[NILFS_FT_MAX] = { 2362ba466d7SYoshiji Amagai [NILFS_FT_UNKNOWN] = DT_UNKNOWN, 2372ba466d7SYoshiji Amagai [NILFS_FT_REG_FILE] = DT_REG, 2382ba466d7SYoshiji Amagai [NILFS_FT_DIR] = DT_DIR, 2392ba466d7SYoshiji Amagai [NILFS_FT_CHRDEV] = DT_CHR, 2402ba466d7SYoshiji Amagai [NILFS_FT_BLKDEV] = DT_BLK, 2412ba466d7SYoshiji Amagai [NILFS_FT_FIFO] = DT_FIFO, 2422ba466d7SYoshiji Amagai [NILFS_FT_SOCK] = DT_SOCK, 2432ba466d7SYoshiji Amagai [NILFS_FT_SYMLINK] = DT_LNK, 2442ba466d7SYoshiji Amagai }; 2452ba466d7SYoshiji Amagai 2462ba466d7SYoshiji Amagai #define S_SHIFT 12 2472ba466d7SYoshiji Amagai static unsigned char 248c4a7dc95SJeongjun Park nilfs_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = { 2492ba466d7SYoshiji Amagai [S_IFREG >> S_SHIFT] = NILFS_FT_REG_FILE, 2502ba466d7SYoshiji Amagai [S_IFDIR >> S_SHIFT] = NILFS_FT_DIR, 2512ba466d7SYoshiji Amagai [S_IFCHR >> S_SHIFT] = NILFS_FT_CHRDEV, 2522ba466d7SYoshiji Amagai [S_IFBLK >> S_SHIFT] = NILFS_FT_BLKDEV, 2532ba466d7SYoshiji Amagai [S_IFIFO >> S_SHIFT] = NILFS_FT_FIFO, 2542ba466d7SYoshiji Amagai [S_IFSOCK >> S_SHIFT] = NILFS_FT_SOCK, 2552ba466d7SYoshiji Amagai [S_IFLNK >> S_SHIFT] = NILFS_FT_SYMLINK, 2562ba466d7SYoshiji Amagai }; 2572ba466d7SYoshiji Amagai 2582ba466d7SYoshiji Amagai static void nilfs_set_de_type(struct nilfs_dir_entry *de, struct inode *inode) 2592ba466d7SYoshiji Amagai { 260c6e49e3fSAl Viro umode_t mode = inode->i_mode; 2612ba466d7SYoshiji Amagai 2622ba466d7SYoshiji Amagai de->file_type = nilfs_type_by_mode[(mode & S_IFMT)>>S_SHIFT]; 2632ba466d7SYoshiji Amagai } 2642ba466d7SYoshiji Amagai 2651616abe8SAl Viro static int nilfs_readdir(struct file *file, struct dir_context *ctx) 2662ba466d7SYoshiji Amagai { 2671616abe8SAl Viro loff_t pos = ctx->pos; 2681616abe8SAl Viro struct inode *inode = file_inode(file); 2692ba466d7SYoshiji Amagai struct super_block *sb = inode->i_sb; 27009cbfeafSKirill A. Shutemov unsigned int offset = pos & ~PAGE_MASK; 27109cbfeafSKirill A. Shutemov unsigned long n = pos >> PAGE_SHIFT; 2722ba466d7SYoshiji Amagai unsigned long npages = dir_pages(inode); 2732ba466d7SYoshiji Amagai 2742ba466d7SYoshiji Amagai if (pos > inode->i_size - NILFS_DIR_REC_LEN(1)) 2751616abe8SAl Viro return 0; 2762ba466d7SYoshiji Amagai 2772ba466d7SYoshiji Amagai for ( ; n < npages; n++, offset = 0) { 2782ba466d7SYoshiji Amagai char *kaddr, *limit; 2792ba466d7SYoshiji Amagai struct nilfs_dir_entry *de; 280b37b2becSMatthew Wilcox (Oracle) struct folio *folio; 2812ba466d7SYoshiji Amagai 282b37b2becSMatthew Wilcox (Oracle) kaddr = nilfs_get_folio(inode, n, &folio); 28309a46acbSMatthew Wilcox (Oracle) if (IS_ERR(kaddr)) { 284cae3d4caSRyusuke Konishi nilfs_error(sb, "bad page in #%lu", inode->i_ino); 28509cbfeafSKirill A. Shutemov ctx->pos += PAGE_SIZE - offset; 2861616abe8SAl Viro return -EIO; 2872ba466d7SYoshiji Amagai } 2882ba466d7SYoshiji Amagai de = (struct nilfs_dir_entry *)(kaddr + offset); 2892ba466d7SYoshiji Amagai limit = kaddr + nilfs_last_byte(inode, n) - 2902ba466d7SYoshiji Amagai NILFS_DIR_REC_LEN(1); 2912ba466d7SYoshiji Amagai for ( ; (char *)de <= limit; de = nilfs_next_entry(de)) { 2922ba466d7SYoshiji Amagai if (de->rec_len == 0) { 293cae3d4caSRyusuke Konishi nilfs_error(sb, "zero-length directory entry"); 294b37b2becSMatthew Wilcox (Oracle) folio_release_kmap(folio, kaddr); 2951616abe8SAl Viro return -EIO; 2962ba466d7SYoshiji Amagai } 2972ba466d7SYoshiji Amagai if (de->inode) { 2981616abe8SAl Viro unsigned char t; 2992ba466d7SYoshiji Amagai 3001616abe8SAl Viro if (de->file_type < NILFS_FT_MAX) 3011616abe8SAl Viro t = nilfs_filetype_table[de->file_type]; 3021616abe8SAl Viro else 3031616abe8SAl Viro t = DT_UNKNOWN; 3042ba466d7SYoshiji Amagai 3051616abe8SAl Viro if (!dir_emit(ctx, de->name, de->name_len, 3061616abe8SAl Viro le64_to_cpu(de->inode), t)) { 307b37b2becSMatthew Wilcox (Oracle) folio_release_kmap(folio, kaddr); 3081616abe8SAl Viro return 0; 3092ba466d7SYoshiji Amagai } 3102ba466d7SYoshiji Amagai } 3111616abe8SAl Viro ctx->pos += nilfs_rec_len_from_disk(de->rec_len); 3122ba466d7SYoshiji Amagai } 313b37b2becSMatthew Wilcox (Oracle) folio_release_kmap(folio, kaddr); 3142ba466d7SYoshiji Amagai } 3151616abe8SAl Viro return 0; 3162ba466d7SYoshiji Amagai } 3172ba466d7SYoshiji Amagai 3182ba466d7SYoshiji Amagai /* 3192ba466d7SYoshiji Amagai * nilfs_find_entry() 3202ba466d7SYoshiji Amagai * 3216f133c97SMatthew Wilcox (Oracle) * Finds an entry in the specified directory with the wanted name. It 3226f133c97SMatthew Wilcox (Oracle) * returns the folio in which the entry was found, and the entry itself. 3236f133c97SMatthew Wilcox (Oracle) * The folio is mapped and unlocked. When the caller is finished with 3246f133c97SMatthew Wilcox (Oracle) * the entry, it should call folio_release_kmap(). 3256f133c97SMatthew Wilcox (Oracle) * 3266f133c97SMatthew Wilcox (Oracle) * On failure, returns NULL and the caller should ignore foliop. 3272ba466d7SYoshiji Amagai */ 3286f133c97SMatthew Wilcox (Oracle) struct nilfs_dir_entry *nilfs_find_entry(struct inode *dir, 3296f133c97SMatthew Wilcox (Oracle) const struct qstr *qstr, struct folio **foliop) 3302ba466d7SYoshiji Amagai { 3310319003dSAl Viro const unsigned char *name = qstr->name; 3320319003dSAl Viro int namelen = qstr->len; 3330c6c44cbSRyusuke Konishi unsigned int reclen = NILFS_DIR_REC_LEN(namelen); 3342ba466d7SYoshiji Amagai unsigned long start, n; 3352ba466d7SYoshiji Amagai unsigned long npages = dir_pages(dir); 3362ba466d7SYoshiji Amagai struct nilfs_inode_info *ei = NILFS_I(dir); 3372ba466d7SYoshiji Amagai struct nilfs_dir_entry *de; 3382ba466d7SYoshiji Amagai 3392ba466d7SYoshiji Amagai if (npages == 0) 3402ba466d7SYoshiji Amagai goto out; 3412ba466d7SYoshiji Amagai 3422ba466d7SYoshiji Amagai start = ei->i_dir_start_lookup; 3432ba466d7SYoshiji Amagai if (start >= npages) 3442ba466d7SYoshiji Amagai start = 0; 3452ba466d7SYoshiji Amagai n = start; 3462ba466d7SYoshiji Amagai do { 3476f133c97SMatthew Wilcox (Oracle) char *kaddr = nilfs_get_folio(dir, n, foliop); 3484ad364caSRyusuke Konishi 34909a46acbSMatthew Wilcox (Oracle) if (!IS_ERR(kaddr)) { 3502ba466d7SYoshiji Amagai de = (struct nilfs_dir_entry *)kaddr; 3512ba466d7SYoshiji Amagai kaddr += nilfs_last_byte(dir, n) - reclen; 3522ba466d7SYoshiji Amagai while ((char *) de <= kaddr) { 3532ba466d7SYoshiji Amagai if (de->rec_len == 0) { 354cae3d4caSRyusuke Konishi nilfs_error(dir->i_sb, 3552ba466d7SYoshiji Amagai "zero-length directory entry"); 3566f133c97SMatthew Wilcox (Oracle) folio_release_kmap(*foliop, kaddr); 3572ba466d7SYoshiji Amagai goto out; 3582ba466d7SYoshiji Amagai } 3592ba466d7SYoshiji Amagai if (nilfs_match(namelen, name, de)) 3602ba466d7SYoshiji Amagai goto found; 3612ba466d7SYoshiji Amagai de = nilfs_next_entry(de); 3622ba466d7SYoshiji Amagai } 3636f133c97SMatthew Wilcox (Oracle) folio_release_kmap(*foliop, kaddr); 3642ba466d7SYoshiji Amagai } 3652ba466d7SYoshiji Amagai if (++n >= npages) 3662ba466d7SYoshiji Amagai n = 0; 367a4bf041eSMatthew Wilcox (Oracle) /* next folio is past the blocks we've got */ 36809cbfeafSKirill A. Shutemov if (unlikely(n > (dir->i_blocks >> (PAGE_SHIFT - 9)))) { 369cae3d4caSRyusuke Konishi nilfs_error(dir->i_sb, 3701621562bSRyusuke Konishi "dir %lu size %lld exceeds block count %llu", 3712ba466d7SYoshiji Amagai dir->i_ino, dir->i_size, 3722ba466d7SYoshiji Amagai (unsigned long long)dir->i_blocks); 3732ba466d7SYoshiji Amagai goto out; 3742ba466d7SYoshiji Amagai } 3752ba466d7SYoshiji Amagai } while (n != start); 3762ba466d7SYoshiji Amagai out: 3772ba466d7SYoshiji Amagai return NULL; 3782ba466d7SYoshiji Amagai 3792ba466d7SYoshiji Amagai found: 3802ba466d7SYoshiji Amagai ei->i_dir_start_lookup = n; 3812ba466d7SYoshiji Amagai return de; 3822ba466d7SYoshiji Amagai } 3832ba466d7SYoshiji Amagai 3846f133c97SMatthew Wilcox (Oracle) struct nilfs_dir_entry *nilfs_dotdot(struct inode *dir, struct folio **foliop) 3852ba466d7SYoshiji Amagai { 386*a9e1ddc0SRyusuke Konishi struct folio *folio; 387*a9e1ddc0SRyusuke Konishi struct nilfs_dir_entry *de, *next_de; 388*a9e1ddc0SRyusuke Konishi size_t limit; 389*a9e1ddc0SRyusuke Konishi char *msg; 3902ba466d7SYoshiji Amagai 391*a9e1ddc0SRyusuke Konishi de = nilfs_get_folio(dir, 0, &folio); 39209a46acbSMatthew Wilcox (Oracle) if (IS_ERR(de)) 39309a46acbSMatthew Wilcox (Oracle) return NULL; 394*a9e1ddc0SRyusuke Konishi 395*a9e1ddc0SRyusuke Konishi limit = nilfs_last_byte(dir, 0); /* is a multiple of chunk size */ 396*a9e1ddc0SRyusuke Konishi if (unlikely(!limit || le64_to_cpu(de->inode) != dir->i_ino || 397*a9e1ddc0SRyusuke Konishi !nilfs_match(1, ".", de))) { 398*a9e1ddc0SRyusuke Konishi msg = "missing '.'"; 399*a9e1ddc0SRyusuke Konishi goto fail; 400*a9e1ddc0SRyusuke Konishi } 401*a9e1ddc0SRyusuke Konishi 402*a9e1ddc0SRyusuke Konishi next_de = nilfs_next_entry(de); 403*a9e1ddc0SRyusuke Konishi /* 404*a9e1ddc0SRyusuke Konishi * If "next_de" has not reached the end of the chunk, there is 405*a9e1ddc0SRyusuke Konishi * at least one more record. Check whether it matches "..". 406*a9e1ddc0SRyusuke Konishi */ 407*a9e1ddc0SRyusuke Konishi if (unlikely((char *)next_de == (char *)de + nilfs_chunk_size(dir) || 408*a9e1ddc0SRyusuke Konishi !nilfs_match(2, "..", next_de))) { 409*a9e1ddc0SRyusuke Konishi msg = "missing '..'"; 410*a9e1ddc0SRyusuke Konishi goto fail; 411*a9e1ddc0SRyusuke Konishi } 412*a9e1ddc0SRyusuke Konishi *foliop = folio; 413*a9e1ddc0SRyusuke Konishi return next_de; 414*a9e1ddc0SRyusuke Konishi 415*a9e1ddc0SRyusuke Konishi fail: 416*a9e1ddc0SRyusuke Konishi nilfs_error(dir->i_sb, "directory #%lu %s", dir->i_ino, msg); 417*a9e1ddc0SRyusuke Konishi folio_release_kmap(folio, de); 418*a9e1ddc0SRyusuke Konishi return NULL; 4192ba466d7SYoshiji Amagai } 4202ba466d7SYoshiji Amagai 4210319003dSAl Viro ino_t nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr) 4222ba466d7SYoshiji Amagai { 4232ba466d7SYoshiji Amagai ino_t res = 0; 4242ba466d7SYoshiji Amagai struct nilfs_dir_entry *de; 4256f133c97SMatthew Wilcox (Oracle) struct folio *folio; 4262ba466d7SYoshiji Amagai 4276f133c97SMatthew Wilcox (Oracle) de = nilfs_find_entry(dir, qstr, &folio); 4282ba466d7SYoshiji Amagai if (de) { 4292ba466d7SYoshiji Amagai res = le64_to_cpu(de->inode); 4306f133c97SMatthew Wilcox (Oracle) folio_release_kmap(folio, de); 4312ba466d7SYoshiji Amagai } 4322ba466d7SYoshiji Amagai return res; 4332ba466d7SYoshiji Amagai } 4342ba466d7SYoshiji Amagai 4352ba466d7SYoshiji Amagai void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de, 4366f133c97SMatthew Wilcox (Oracle) struct folio *folio, struct inode *inode) 4372ba466d7SYoshiji Amagai { 4386f133c97SMatthew Wilcox (Oracle) size_t from = offset_in_folio(folio, de); 4396f133c97SMatthew Wilcox (Oracle) size_t to = from + nilfs_rec_len_from_disk(de->rec_len); 4406f133c97SMatthew Wilcox (Oracle) struct address_space *mapping = folio->mapping; 4412ba466d7SYoshiji Amagai int err; 4422ba466d7SYoshiji Amagai 4436f133c97SMatthew Wilcox (Oracle) folio_lock(folio); 4449bff5f98SMatthew Wilcox (Oracle) err = nilfs_prepare_chunk(folio, from, to); 4452ba466d7SYoshiji Amagai BUG_ON(err); 4462ba466d7SYoshiji Amagai de->inode = cpu_to_le64(inode->i_ino); 4472ba466d7SYoshiji Amagai nilfs_set_de_type(de, inode); 4489bff5f98SMatthew Wilcox (Oracle) nilfs_commit_chunk(folio, mapping, from, to); 449b3e1cc39SJeff Layton inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); 4502ba466d7SYoshiji Amagai } 4512ba466d7SYoshiji Amagai 4522ba466d7SYoshiji Amagai /* 4532ba466d7SYoshiji Amagai * Parent is locked. 4542ba466d7SYoshiji Amagai */ 4552ba466d7SYoshiji Amagai int nilfs_add_link(struct dentry *dentry, struct inode *inode) 4562ba466d7SYoshiji Amagai { 4572b0143b5SDavid Howells struct inode *dir = d_inode(dentry->d_parent); 458072f98b4SAl Viro const unsigned char *name = dentry->d_name.name; 4592ba466d7SYoshiji Amagai int namelen = dentry->d_name.len; 4600c6c44cbSRyusuke Konishi unsigned int chunk_size = nilfs_chunk_size(dir); 4610c6c44cbSRyusuke Konishi unsigned int reclen = NILFS_DIR_REC_LEN(namelen); 4622ba466d7SYoshiji Amagai unsigned short rec_len, name_len; 463f59bb60fSMatthew Wilcox (Oracle) struct folio *folio = NULL; 4642ba466d7SYoshiji Amagai struct nilfs_dir_entry *de; 4652ba466d7SYoshiji Amagai unsigned long npages = dir_pages(dir); 4662ba466d7SYoshiji Amagai unsigned long n; 467f59bb60fSMatthew Wilcox (Oracle) size_t from, to; 4682ba466d7SYoshiji Amagai int err; 4692ba466d7SYoshiji Amagai 4702ba466d7SYoshiji Amagai /* 4712ba466d7SYoshiji Amagai * We take care of directory expansion in the same loop. 472f59bb60fSMatthew Wilcox (Oracle) * This code plays outside i_size, so it locks the folio 4732ba466d7SYoshiji Amagai * to protect that region. 4742ba466d7SYoshiji Amagai */ 4752ba466d7SYoshiji Amagai for (n = 0; n <= npages; n++) { 476f59bb60fSMatthew Wilcox (Oracle) char *kaddr = nilfs_get_folio(dir, n, &folio); 4772ba466d7SYoshiji Amagai char *dir_end; 4782ba466d7SYoshiji Amagai 47909a46acbSMatthew Wilcox (Oracle) if (IS_ERR(kaddr)) 480f59bb60fSMatthew Wilcox (Oracle) return PTR_ERR(kaddr); 481f59bb60fSMatthew Wilcox (Oracle) folio_lock(folio); 4822ba466d7SYoshiji Amagai dir_end = kaddr + nilfs_last_byte(dir, n); 4832ba466d7SYoshiji Amagai de = (struct nilfs_dir_entry *)kaddr; 484f59bb60fSMatthew Wilcox (Oracle) kaddr += folio_size(folio) - reclen; 4852ba466d7SYoshiji Amagai while ((char *)de <= kaddr) { 4862ba466d7SYoshiji Amagai if ((char *)de == dir_end) { 4872ba466d7SYoshiji Amagai /* We hit i_size */ 4882ba466d7SYoshiji Amagai name_len = 0; 4892ba466d7SYoshiji Amagai rec_len = chunk_size; 4906cda9fa2SRyusuke Konishi de->rec_len = nilfs_rec_len_to_disk(chunk_size); 4912ba466d7SYoshiji Amagai de->inode = 0; 4922ba466d7SYoshiji Amagai goto got_it; 4932ba466d7SYoshiji Amagai } 4942ba466d7SYoshiji Amagai if (de->rec_len == 0) { 495cae3d4caSRyusuke Konishi nilfs_error(dir->i_sb, 4962ba466d7SYoshiji Amagai "zero-length directory entry"); 4972ba466d7SYoshiji Amagai err = -EIO; 4982ba466d7SYoshiji Amagai goto out_unlock; 4992ba466d7SYoshiji Amagai } 5002ba466d7SYoshiji Amagai err = -EEXIST; 5012ba466d7SYoshiji Amagai if (nilfs_match(namelen, name, de)) 5022ba466d7SYoshiji Amagai goto out_unlock; 5032ba466d7SYoshiji Amagai name_len = NILFS_DIR_REC_LEN(de->name_len); 5046cda9fa2SRyusuke Konishi rec_len = nilfs_rec_len_from_disk(de->rec_len); 5052ba466d7SYoshiji Amagai if (!de->inode && rec_len >= reclen) 5062ba466d7SYoshiji Amagai goto got_it; 5072ba466d7SYoshiji Amagai if (rec_len >= name_len + reclen) 5082ba466d7SYoshiji Amagai goto got_it; 5092ba466d7SYoshiji Amagai de = (struct nilfs_dir_entry *)((char *)de + rec_len); 5102ba466d7SYoshiji Amagai } 511f59bb60fSMatthew Wilcox (Oracle) folio_unlock(folio); 512f59bb60fSMatthew Wilcox (Oracle) folio_release_kmap(folio, kaddr); 5132ba466d7SYoshiji Amagai } 5142ba466d7SYoshiji Amagai BUG(); 5152ba466d7SYoshiji Amagai return -EINVAL; 5162ba466d7SYoshiji Amagai 5172ba466d7SYoshiji Amagai got_it: 518f59bb60fSMatthew Wilcox (Oracle) from = offset_in_folio(folio, de); 5192ba466d7SYoshiji Amagai to = from + rec_len; 5209bff5f98SMatthew Wilcox (Oracle) err = nilfs_prepare_chunk(folio, from, to); 5212ba466d7SYoshiji Amagai if (err) 5222ba466d7SYoshiji Amagai goto out_unlock; 5232ba466d7SYoshiji Amagai if (de->inode) { 5242ba466d7SYoshiji Amagai struct nilfs_dir_entry *de1; 5252ba466d7SYoshiji Amagai 5262ba466d7SYoshiji Amagai de1 = (struct nilfs_dir_entry *)((char *)de + name_len); 5276cda9fa2SRyusuke Konishi de1->rec_len = nilfs_rec_len_to_disk(rec_len - name_len); 5286cda9fa2SRyusuke Konishi de->rec_len = nilfs_rec_len_to_disk(name_len); 5292ba466d7SYoshiji Amagai de = de1; 5302ba466d7SYoshiji Amagai } 5312ba466d7SYoshiji Amagai de->name_len = namelen; 5322ba466d7SYoshiji Amagai memcpy(de->name, name, namelen); 5332ba466d7SYoshiji Amagai de->inode = cpu_to_le64(inode->i_ino); 5342ba466d7SYoshiji Amagai nilfs_set_de_type(de, inode); 5359bff5f98SMatthew Wilcox (Oracle) nilfs_commit_chunk(folio, folio->mapping, from, to); 536b3e1cc39SJeff Layton inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); 537abdb318bSJiro SEKIBA nilfs_mark_inode_dirty(dir); 5382ba466d7SYoshiji Amagai /* OFFSET_CACHE */ 5392ba466d7SYoshiji Amagai out_put: 540f59bb60fSMatthew Wilcox (Oracle) folio_release_kmap(folio, de); 5412ba466d7SYoshiji Amagai return err; 5422ba466d7SYoshiji Amagai out_unlock: 543f59bb60fSMatthew Wilcox (Oracle) folio_unlock(folio); 5442ba466d7SYoshiji Amagai goto out_put; 5452ba466d7SYoshiji Amagai } 5462ba466d7SYoshiji Amagai 5472ba466d7SYoshiji Amagai /* 5482ba466d7SYoshiji Amagai * nilfs_delete_entry deletes a directory entry by merging it with the 5496f133c97SMatthew Wilcox (Oracle) * previous entry. Folio is up-to-date. 5502ba466d7SYoshiji Amagai */ 5516f133c97SMatthew Wilcox (Oracle) int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct folio *folio) 5522ba466d7SYoshiji Amagai { 5536f133c97SMatthew Wilcox (Oracle) struct address_space *mapping = folio->mapping; 5542ba466d7SYoshiji Amagai struct inode *inode = mapping->host; 5556f133c97SMatthew Wilcox (Oracle) char *kaddr = (char *)((unsigned long)dir & ~(folio_size(folio) - 1)); 5566f133c97SMatthew Wilcox (Oracle) size_t from, to; 5570c6c44cbSRyusuke Konishi struct nilfs_dir_entry *de, *pde = NULL; 5582ba466d7SYoshiji Amagai int err; 5592ba466d7SYoshiji Amagai 5600c6c44cbSRyusuke Konishi from = ((char *)dir - kaddr) & ~(nilfs_chunk_size(inode) - 1); 5610c6c44cbSRyusuke Konishi to = ((char *)dir - kaddr) + nilfs_rec_len_from_disk(dir->rec_len); 5620c6c44cbSRyusuke Konishi de = (struct nilfs_dir_entry *)(kaddr + from); 5630c6c44cbSRyusuke Konishi 5642ba466d7SYoshiji Amagai while ((char *)de < (char *)dir) { 5652ba466d7SYoshiji Amagai if (de->rec_len == 0) { 566cae3d4caSRyusuke Konishi nilfs_error(inode->i_sb, 5672ba466d7SYoshiji Amagai "zero-length directory entry"); 5682ba466d7SYoshiji Amagai err = -EIO; 5692ba466d7SYoshiji Amagai goto out; 5702ba466d7SYoshiji Amagai } 5712ba466d7SYoshiji Amagai pde = de; 5722ba466d7SYoshiji Amagai de = nilfs_next_entry(de); 5732ba466d7SYoshiji Amagai } 5742ba466d7SYoshiji Amagai if (pde) 5756af2191fSMatthew Wilcox (Oracle) from = (char *)pde - kaddr; 5766f133c97SMatthew Wilcox (Oracle) folio_lock(folio); 5779bff5f98SMatthew Wilcox (Oracle) err = nilfs_prepare_chunk(folio, from, to); 5782ba466d7SYoshiji Amagai BUG_ON(err); 5792ba466d7SYoshiji Amagai if (pde) 5806cda9fa2SRyusuke Konishi pde->rec_len = nilfs_rec_len_to_disk(to - from); 5812ba466d7SYoshiji Amagai dir->inode = 0; 5829bff5f98SMatthew Wilcox (Oracle) nilfs_commit_chunk(folio, mapping, from, to); 583b3e1cc39SJeff Layton inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); 5842ba466d7SYoshiji Amagai out: 5852ba466d7SYoshiji Amagai return err; 5862ba466d7SYoshiji Amagai } 5872ba466d7SYoshiji Amagai 5882ba466d7SYoshiji Amagai /* 5892ba466d7SYoshiji Amagai * Set the first fragment of directory. 5902ba466d7SYoshiji Amagai */ 5912ba466d7SYoshiji Amagai int nilfs_make_empty(struct inode *inode, struct inode *parent) 5922ba466d7SYoshiji Amagai { 5932ba466d7SYoshiji Amagai struct address_space *mapping = inode->i_mapping; 5940743230fSMatthew Wilcox (Oracle) struct folio *folio = filemap_grab_folio(mapping, 0); 5950c6c44cbSRyusuke Konishi unsigned int chunk_size = nilfs_chunk_size(inode); 5962ba466d7SYoshiji Amagai struct nilfs_dir_entry *de; 5972ba466d7SYoshiji Amagai int err; 5982ba466d7SYoshiji Amagai void *kaddr; 5992ba466d7SYoshiji Amagai 6000743230fSMatthew Wilcox (Oracle) if (IS_ERR(folio)) 6010743230fSMatthew Wilcox (Oracle) return PTR_ERR(folio); 6022ba466d7SYoshiji Amagai 6039bff5f98SMatthew Wilcox (Oracle) err = nilfs_prepare_chunk(folio, 0, chunk_size); 6042ba466d7SYoshiji Amagai if (unlikely(err)) { 6050743230fSMatthew Wilcox (Oracle) folio_unlock(folio); 6062ba466d7SYoshiji Amagai goto fail; 6072ba466d7SYoshiji Amagai } 6080743230fSMatthew Wilcox (Oracle) kaddr = kmap_local_folio(folio, 0); 6092ba466d7SYoshiji Amagai memset(kaddr, 0, chunk_size); 6102ba466d7SYoshiji Amagai de = (struct nilfs_dir_entry *)kaddr; 6112ba466d7SYoshiji Amagai de->name_len = 1; 6126cda9fa2SRyusuke Konishi de->rec_len = nilfs_rec_len_to_disk(NILFS_DIR_REC_LEN(1)); 6132ba466d7SYoshiji Amagai memcpy(de->name, ".\0\0", 4); 6142ba466d7SYoshiji Amagai de->inode = cpu_to_le64(inode->i_ino); 6152ba466d7SYoshiji Amagai nilfs_set_de_type(de, inode); 6162ba466d7SYoshiji Amagai 6172ba466d7SYoshiji Amagai de = (struct nilfs_dir_entry *)(kaddr + NILFS_DIR_REC_LEN(1)); 6182ba466d7SYoshiji Amagai de->name_len = 2; 6196cda9fa2SRyusuke Konishi de->rec_len = nilfs_rec_len_to_disk(chunk_size - NILFS_DIR_REC_LEN(1)); 6202ba466d7SYoshiji Amagai de->inode = cpu_to_le64(parent->i_ino); 6212ba466d7SYoshiji Amagai memcpy(de->name, "..\0", 4); 6222ba466d7SYoshiji Amagai nilfs_set_de_type(de, inode); 6230743230fSMatthew Wilcox (Oracle) kunmap_local(kaddr); 6249bff5f98SMatthew Wilcox (Oracle) nilfs_commit_chunk(folio, mapping, 0, chunk_size); 6252ba466d7SYoshiji Amagai fail: 6260743230fSMatthew Wilcox (Oracle) folio_put(folio); 6272ba466d7SYoshiji Amagai return err; 6282ba466d7SYoshiji Amagai } 6292ba466d7SYoshiji Amagai 6302ba466d7SYoshiji Amagai /* 6312ba466d7SYoshiji Amagai * routine to check that the specified directory is empty (for rmdir) 6322ba466d7SYoshiji Amagai */ 6332ba466d7SYoshiji Amagai int nilfs_empty_dir(struct inode *inode) 6342ba466d7SYoshiji Amagai { 63518f03ddfSMatthew Wilcox (Oracle) struct folio *folio = NULL; 6369b77f66fSMatthew Wilcox (Oracle) char *kaddr; 6372ba466d7SYoshiji Amagai unsigned long i, npages = dir_pages(inode); 6382ba466d7SYoshiji Amagai 6392ba466d7SYoshiji Amagai for (i = 0; i < npages; i++) { 6402ba466d7SYoshiji Amagai struct nilfs_dir_entry *de; 6412ba466d7SYoshiji Amagai 64218f03ddfSMatthew Wilcox (Oracle) kaddr = nilfs_get_folio(inode, i, &folio); 64309a46acbSMatthew Wilcox (Oracle) if (IS_ERR(kaddr)) 6447373a51eSRyusuke Konishi return 0; 6452ba466d7SYoshiji Amagai 6462ba466d7SYoshiji Amagai de = (struct nilfs_dir_entry *)kaddr; 6472ba466d7SYoshiji Amagai kaddr += nilfs_last_byte(inode, i) - NILFS_DIR_REC_LEN(1); 6482ba466d7SYoshiji Amagai 6492ba466d7SYoshiji Amagai while ((char *)de <= kaddr) { 6502ba466d7SYoshiji Amagai if (de->rec_len == 0) { 651cae3d4caSRyusuke Konishi nilfs_error(inode->i_sb, 65206f4abf6SRyusuke Konishi "zero-length directory entry (kaddr=%p, de=%p)", 65306f4abf6SRyusuke Konishi kaddr, de); 6542ba466d7SYoshiji Amagai goto not_empty; 6552ba466d7SYoshiji Amagai } 6562ba466d7SYoshiji Amagai if (de->inode != 0) { 6572ba466d7SYoshiji Amagai /* check for . and .. */ 6582ba466d7SYoshiji Amagai if (de->name[0] != '.') 6592ba466d7SYoshiji Amagai goto not_empty; 6602ba466d7SYoshiji Amagai if (de->name_len > 2) 6612ba466d7SYoshiji Amagai goto not_empty; 6622ba466d7SYoshiji Amagai if (de->name_len < 2) { 6632ba466d7SYoshiji Amagai if (de->inode != 6642ba466d7SYoshiji Amagai cpu_to_le64(inode->i_ino)) 6652ba466d7SYoshiji Amagai goto not_empty; 6662ba466d7SYoshiji Amagai } else if (de->name[1] != '.') 6672ba466d7SYoshiji Amagai goto not_empty; 6682ba466d7SYoshiji Amagai } 6692ba466d7SYoshiji Amagai de = nilfs_next_entry(de); 6702ba466d7SYoshiji Amagai } 67118f03ddfSMatthew Wilcox (Oracle) folio_release_kmap(folio, kaddr); 6722ba466d7SYoshiji Amagai } 6732ba466d7SYoshiji Amagai return 1; 6742ba466d7SYoshiji Amagai 6752ba466d7SYoshiji Amagai not_empty: 67618f03ddfSMatthew Wilcox (Oracle) folio_release_kmap(folio, kaddr); 6772ba466d7SYoshiji Amagai return 0; 6782ba466d7SYoshiji Amagai } 6792ba466d7SYoshiji Amagai 680828c0950SAlexey Dobriyan const struct file_operations nilfs_dir_operations = { 6812ba466d7SYoshiji Amagai .llseek = generic_file_llseek, 6822ba466d7SYoshiji Amagai .read = generic_read_dir, 683c51da20cSAl Viro .iterate_shared = nilfs_readdir, 6847a946193SRyusuke Konishi .unlocked_ioctl = nilfs_ioctl, 6852ba466d7SYoshiji Amagai #ifdef CONFIG_COMPAT 686828b1c50SRyusuke Konishi .compat_ioctl = nilfs_compat_ioctl, 6872ba466d7SYoshiji Amagai #endif /* CONFIG_COMPAT */ 6882ba466d7SYoshiji Amagai .fsync = nilfs_sync_file, 6892ba466d7SYoshiji Amagai 6902ba466d7SYoshiji Amagai }; 691