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
nilfs_rec_len_from_disk(__le16 dlen)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
nilfs_rec_len_to_disk(unsigned int len)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 */
nilfs_chunk_size(struct inode * inode)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 */
nilfs_last_byte(struct inode * inode,unsigned long page_nr)710c6c44cbSRyusuke Konishi static unsigned int nilfs_last_byte(struct inode *inode, unsigned long page_nr)
722ba466d7SYoshiji Amagai {
73c3afea07SRyusuke Konishi u64 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
nilfs_prepare_chunk(struct page * page,unsigned int from,unsigned int to)810c6c44cbSRyusuke Konishi static int nilfs_prepare_chunk(struct page *page, unsigned int from,
820c6c44cbSRyusuke Konishi unsigned int to)
832ba466d7SYoshiji Amagai {
842ba466d7SYoshiji Amagai loff_t pos = page_offset(page) + from;
854ad364caSRyusuke Konishi
866e1db88dSChristoph Hellwig return __block_write_begin(page, pos, to - from, nilfs_get_block);
872ba466d7SYoshiji Amagai }
882ba466d7SYoshiji Amagai
nilfs_commit_chunk(struct page * page,struct address_space * mapping,unsigned int from,unsigned int to)892093abf9SJiro SEKIBA static void nilfs_commit_chunk(struct page *page,
902ba466d7SYoshiji Amagai struct address_space *mapping,
910c6c44cbSRyusuke Konishi unsigned int from, unsigned int to)
922ba466d7SYoshiji Amagai {
932ba466d7SYoshiji Amagai struct inode *dir = mapping->host;
942ba466d7SYoshiji Amagai loff_t pos = page_offset(page) + from;
950c6c44cbSRyusuke Konishi unsigned int len = to - from;
960c6c44cbSRyusuke Konishi unsigned int nr_dirty, copied;
972ba466d7SYoshiji Amagai int err;
982ba466d7SYoshiji Amagai
992ba466d7SYoshiji Amagai nr_dirty = nilfs_page_count_clean_buffers(page, from, to);
1002ba466d7SYoshiji Amagai copied = block_write_end(NULL, mapping, pos, len, len, page, NULL);
10158d55471SJiro SEKIBA if (pos + copied > dir->i_size)
1022ba466d7SYoshiji Amagai i_size_write(dir, pos + copied);
1032ba466d7SYoshiji Amagai if (IS_DIRSYNC(dir))
1042ba466d7SYoshiji Amagai nilfs_set_transaction_flag(NILFS_TI_SYNC);
105bcbc8c64SRyusuke Konishi err = nilfs_set_file_dirty(dir, nr_dirty);
1062093abf9SJiro SEKIBA WARN_ON(err); /* do not happen */
1072ba466d7SYoshiji Amagai unlock_page(page);
1082ba466d7SYoshiji Amagai }
1092ba466d7SYoshiji Amagai
nilfs_check_page(struct page * page)110be5b82dbSAl Viro static bool nilfs_check_page(struct page *page)
1112ba466d7SYoshiji Amagai {
1122ba466d7SYoshiji Amagai struct inode *dir = page->mapping->host;
1132ba466d7SYoshiji Amagai struct super_block *sb = dir->i_sb;
1140c6c44cbSRyusuke Konishi unsigned int chunk_size = nilfs_chunk_size(dir);
1152ba466d7SYoshiji Amagai char *kaddr = page_address(page);
1160c6c44cbSRyusuke Konishi unsigned int offs, rec_len;
1170c6c44cbSRyusuke Konishi unsigned int limit = PAGE_SIZE;
1182ba466d7SYoshiji Amagai struct nilfs_dir_entry *p;
1192ba466d7SYoshiji Amagai char *error;
1202ba466d7SYoshiji Amagai
12109cbfeafSKirill A. Shutemov if ((dir->i_size >> PAGE_SHIFT) == page->index) {
12209cbfeafSKirill A. Shutemov limit = dir->i_size & ~PAGE_MASK;
1232ba466d7SYoshiji Amagai if (limit & (chunk_size - 1))
1242ba466d7SYoshiji Amagai goto Ebadsize;
1252ba466d7SYoshiji Amagai if (!limit)
1262ba466d7SYoshiji Amagai goto out;
1272ba466d7SYoshiji Amagai }
1282ba466d7SYoshiji Amagai for (offs = 0; offs <= limit - NILFS_DIR_REC_LEN(1); offs += rec_len) {
1292ba466d7SYoshiji Amagai p = (struct nilfs_dir_entry *)(kaddr + offs);
1306cda9fa2SRyusuke Konishi rec_len = nilfs_rec_len_from_disk(p->rec_len);
1312ba466d7SYoshiji Amagai
1322ba466d7SYoshiji Amagai if (rec_len < NILFS_DIR_REC_LEN(1))
1332ba466d7SYoshiji Amagai goto Eshort;
1342ba466d7SYoshiji Amagai if (rec_len & 3)
1352ba466d7SYoshiji Amagai goto Ealign;
1362ba466d7SYoshiji Amagai if (rec_len < NILFS_DIR_REC_LEN(p->name_len))
1372ba466d7SYoshiji Amagai goto Enamelen;
1382ba466d7SYoshiji Amagai if (((offs + rec_len - 1) ^ offs) & ~(chunk_size-1))
1392ba466d7SYoshiji Amagai goto Espan;
1403ab40870SRyusuke Konishi if (unlikely(p->inode &&
1413ab40870SRyusuke Konishi NILFS_PRIVATE_INODE(le64_to_cpu(p->inode))))
1423ab40870SRyusuke Konishi goto Einumber;
1432ba466d7SYoshiji Amagai }
1442ba466d7SYoshiji Amagai if (offs != limit)
1452ba466d7SYoshiji Amagai goto Eend;
1462ba466d7SYoshiji Amagai out:
1472ba466d7SYoshiji Amagai SetPageChecked(page);
148be5b82dbSAl Viro return true;
1492ba466d7SYoshiji Amagai
1502ba466d7SYoshiji Amagai /* Too bad, we had an error */
1512ba466d7SYoshiji Amagai
1522ba466d7SYoshiji Amagai Ebadsize:
153cae3d4caSRyusuke Konishi nilfs_error(sb,
1542ba466d7SYoshiji Amagai "size of directory #%lu is not a multiple of chunk size",
155cae3d4caSRyusuke Konishi dir->i_ino);
1562ba466d7SYoshiji Amagai goto fail;
1572ba466d7SYoshiji Amagai Eshort:
1582ba466d7SYoshiji Amagai error = "rec_len is smaller than minimal";
1592ba466d7SYoshiji Amagai goto bad_entry;
1602ba466d7SYoshiji Amagai Ealign:
1612ba466d7SYoshiji Amagai error = "unaligned directory entry";
1622ba466d7SYoshiji Amagai goto bad_entry;
1632ba466d7SYoshiji Amagai Enamelen:
1642ba466d7SYoshiji Amagai error = "rec_len is too small for name_len";
1652ba466d7SYoshiji Amagai goto bad_entry;
1662ba466d7SYoshiji Amagai Espan:
1672ba466d7SYoshiji Amagai error = "directory entry across blocks";
1683ab40870SRyusuke Konishi goto bad_entry;
1693ab40870SRyusuke Konishi Einumber:
1703ab40870SRyusuke Konishi error = "disallowed inode number";
1712ba466d7SYoshiji Amagai bad_entry:
172cae3d4caSRyusuke Konishi nilfs_error(sb,
173cae3d4caSRyusuke Konishi "bad entry in directory #%lu: %s - offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
17409cbfeafSKirill A. Shutemov dir->i_ino, error, (page->index << PAGE_SHIFT) + offs,
1752ba466d7SYoshiji Amagai (unsigned long)le64_to_cpu(p->inode),
1762ba466d7SYoshiji Amagai rec_len, p->name_len);
1772ba466d7SYoshiji Amagai goto fail;
1782ba466d7SYoshiji Amagai Eend:
1792ba466d7SYoshiji Amagai p = (struct nilfs_dir_entry *)(kaddr + offs);
180cae3d4caSRyusuke Konishi nilfs_error(sb,
181cae3d4caSRyusuke Konishi "entry in directory #%lu spans the page boundary offset=%lu, inode=%lu",
18209cbfeafSKirill A. Shutemov dir->i_ino, (page->index << PAGE_SHIFT) + offs,
1832ba466d7SYoshiji Amagai (unsigned long)le64_to_cpu(p->inode));
1842ba466d7SYoshiji Amagai fail:
1852ba466d7SYoshiji Amagai SetPageError(page);
186be5b82dbSAl Viro return false;
1872ba466d7SYoshiji Amagai }
1882ba466d7SYoshiji Amagai
nilfs_get_page(struct inode * dir,unsigned long n,struct page ** pagep)1898394dce1SMatthew Wilcox (Oracle) static void *nilfs_get_page(struct inode *dir, unsigned long n,
1908394dce1SMatthew Wilcox (Oracle) struct page **pagep)
1912ba466d7SYoshiji Amagai {
1922ba466d7SYoshiji Amagai struct address_space *mapping = dir->i_mapping;
193c28e69d9SRyusuke Konishi struct page *page = read_mapping_page(mapping, n, NULL);
1948394dce1SMatthew Wilcox (Oracle) void *kaddr;
195c28e69d9SRyusuke Konishi
1968394dce1SMatthew Wilcox (Oracle) if (IS_ERR(page))
1978394dce1SMatthew Wilcox (Oracle) return page;
1988394dce1SMatthew Wilcox (Oracle)
1998394dce1SMatthew Wilcox (Oracle) kaddr = kmap(page);
200be5b82dbSAl Viro if (unlikely(!PageChecked(page))) {
20179ea6556SMatthew Wilcox (Oracle) if (!nilfs_check_page(page))
2022ba466d7SYoshiji Amagai goto fail;
2032ba466d7SYoshiji Amagai }
2048394dce1SMatthew Wilcox (Oracle)
2058394dce1SMatthew Wilcox (Oracle) *pagep = page;
2068394dce1SMatthew Wilcox (Oracle) return kaddr;
2072ba466d7SYoshiji Amagai
2082ba466d7SYoshiji Amagai fail:
2092ba466d7SYoshiji Amagai nilfs_put_page(page);
2102ba466d7SYoshiji Amagai return ERR_PTR(-EIO);
2112ba466d7SYoshiji Amagai }
2122ba466d7SYoshiji Amagai
2132ba466d7SYoshiji Amagai /*
2142ba466d7SYoshiji Amagai * NOTE! unlike strncmp, nilfs_match returns 1 for success, 0 for failure.
2152ba466d7SYoshiji Amagai *
2162ba466d7SYoshiji Amagai * len <= NILFS_NAME_LEN and de != NULL are guaranteed by caller.
2172ba466d7SYoshiji Amagai */
2182ba466d7SYoshiji Amagai static int
nilfs_match(int len,const unsigned char * name,struct nilfs_dir_entry * de)219072f98b4SAl Viro nilfs_match(int len, const unsigned char *name, struct nilfs_dir_entry *de)
2202ba466d7SYoshiji Amagai {
2212ba466d7SYoshiji Amagai if (len != de->name_len)
2222ba466d7SYoshiji Amagai return 0;
2232ba466d7SYoshiji Amagai if (!de->inode)
2242ba466d7SYoshiji Amagai return 0;
2252ba466d7SYoshiji Amagai return !memcmp(name, de->name, len);
2262ba466d7SYoshiji Amagai }
2272ba466d7SYoshiji Amagai
2282ba466d7SYoshiji Amagai /*
2292ba466d7SYoshiji Amagai * p is at least 6 bytes before the end of page
2302ba466d7SYoshiji Amagai */
nilfs_next_entry(struct nilfs_dir_entry * p)2312ba466d7SYoshiji Amagai static struct nilfs_dir_entry *nilfs_next_entry(struct nilfs_dir_entry *p)
2322ba466d7SYoshiji Amagai {
2336cda9fa2SRyusuke Konishi return (struct nilfs_dir_entry *)((char *)p +
2346cda9fa2SRyusuke Konishi nilfs_rec_len_from_disk(p->rec_len));
2352ba466d7SYoshiji Amagai }
2362ba466d7SYoshiji Amagai
2372ba466d7SYoshiji Amagai static unsigned char
2382ba466d7SYoshiji Amagai nilfs_filetype_table[NILFS_FT_MAX] = {
2392ba466d7SYoshiji Amagai [NILFS_FT_UNKNOWN] = DT_UNKNOWN,
2402ba466d7SYoshiji Amagai [NILFS_FT_REG_FILE] = DT_REG,
2412ba466d7SYoshiji Amagai [NILFS_FT_DIR] = DT_DIR,
2422ba466d7SYoshiji Amagai [NILFS_FT_CHRDEV] = DT_CHR,
2432ba466d7SYoshiji Amagai [NILFS_FT_BLKDEV] = DT_BLK,
2442ba466d7SYoshiji Amagai [NILFS_FT_FIFO] = DT_FIFO,
2452ba466d7SYoshiji Amagai [NILFS_FT_SOCK] = DT_SOCK,
2462ba466d7SYoshiji Amagai [NILFS_FT_SYMLINK] = DT_LNK,
2472ba466d7SYoshiji Amagai };
2482ba466d7SYoshiji Amagai
2492ba466d7SYoshiji Amagai #define S_SHIFT 12
2502ba466d7SYoshiji Amagai static unsigned char
2512382eae6SJeongjun Park nilfs_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = {
2522ba466d7SYoshiji Amagai [S_IFREG >> S_SHIFT] = NILFS_FT_REG_FILE,
2532ba466d7SYoshiji Amagai [S_IFDIR >> S_SHIFT] = NILFS_FT_DIR,
2542ba466d7SYoshiji Amagai [S_IFCHR >> S_SHIFT] = NILFS_FT_CHRDEV,
2552ba466d7SYoshiji Amagai [S_IFBLK >> S_SHIFT] = NILFS_FT_BLKDEV,
2562ba466d7SYoshiji Amagai [S_IFIFO >> S_SHIFT] = NILFS_FT_FIFO,
2572ba466d7SYoshiji Amagai [S_IFSOCK >> S_SHIFT] = NILFS_FT_SOCK,
2582ba466d7SYoshiji Amagai [S_IFLNK >> S_SHIFT] = NILFS_FT_SYMLINK,
2592ba466d7SYoshiji Amagai };
2602ba466d7SYoshiji Amagai
nilfs_set_de_type(struct nilfs_dir_entry * de,struct inode * inode)2612ba466d7SYoshiji Amagai static void nilfs_set_de_type(struct nilfs_dir_entry *de, struct inode *inode)
2622ba466d7SYoshiji Amagai {
263c6e49e3fSAl Viro umode_t mode = inode->i_mode;
2642ba466d7SYoshiji Amagai
2652ba466d7SYoshiji Amagai de->file_type = nilfs_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
2662ba466d7SYoshiji Amagai }
2672ba466d7SYoshiji Amagai
nilfs_readdir(struct file * file,struct dir_context * ctx)2681616abe8SAl Viro static int nilfs_readdir(struct file *file, struct dir_context *ctx)
2692ba466d7SYoshiji Amagai {
2701616abe8SAl Viro loff_t pos = ctx->pos;
2711616abe8SAl Viro struct inode *inode = file_inode(file);
2722ba466d7SYoshiji Amagai struct super_block *sb = inode->i_sb;
27309cbfeafSKirill A. Shutemov unsigned int offset = pos & ~PAGE_MASK;
27409cbfeafSKirill A. Shutemov unsigned long n = pos >> PAGE_SHIFT;
2752ba466d7SYoshiji Amagai unsigned long npages = dir_pages(inode);
2762ba466d7SYoshiji Amagai
2772ba466d7SYoshiji Amagai if (pos > inode->i_size - NILFS_DIR_REC_LEN(1))
2781616abe8SAl Viro return 0;
2792ba466d7SYoshiji Amagai
2802ba466d7SYoshiji Amagai for ( ; n < npages; n++, offset = 0) {
2812ba466d7SYoshiji Amagai char *kaddr, *limit;
2822ba466d7SYoshiji Amagai struct nilfs_dir_entry *de;
2838394dce1SMatthew Wilcox (Oracle) struct page *page;
2842ba466d7SYoshiji Amagai
2858394dce1SMatthew Wilcox (Oracle) kaddr = nilfs_get_page(inode, n, &page);
2868394dce1SMatthew Wilcox (Oracle) if (IS_ERR(kaddr)) {
287cae3d4caSRyusuke Konishi nilfs_error(sb, "bad page in #%lu", inode->i_ino);
28809cbfeafSKirill A. Shutemov ctx->pos += PAGE_SIZE - offset;
2891616abe8SAl Viro return -EIO;
2902ba466d7SYoshiji Amagai }
2912ba466d7SYoshiji Amagai de = (struct nilfs_dir_entry *)(kaddr + offset);
2922ba466d7SYoshiji Amagai limit = kaddr + nilfs_last_byte(inode, n) -
2932ba466d7SYoshiji Amagai NILFS_DIR_REC_LEN(1);
2942ba466d7SYoshiji Amagai for ( ; (char *)de <= limit; de = nilfs_next_entry(de)) {
2952ba466d7SYoshiji Amagai if (de->rec_len == 0) {
296cae3d4caSRyusuke Konishi nilfs_error(sb, "zero-length directory entry");
2972ba466d7SYoshiji Amagai nilfs_put_page(page);
2981616abe8SAl Viro return -EIO;
2992ba466d7SYoshiji Amagai }
3002ba466d7SYoshiji Amagai if (de->inode) {
3011616abe8SAl Viro unsigned char t;
3022ba466d7SYoshiji Amagai
3031616abe8SAl Viro if (de->file_type < NILFS_FT_MAX)
3041616abe8SAl Viro t = nilfs_filetype_table[de->file_type];
3051616abe8SAl Viro else
3061616abe8SAl Viro t = DT_UNKNOWN;
3072ba466d7SYoshiji Amagai
3081616abe8SAl Viro if (!dir_emit(ctx, de->name, de->name_len,
3091616abe8SAl Viro le64_to_cpu(de->inode), t)) {
3102ba466d7SYoshiji Amagai nilfs_put_page(page);
3111616abe8SAl Viro return 0;
3122ba466d7SYoshiji Amagai }
3132ba466d7SYoshiji Amagai }
3141616abe8SAl Viro ctx->pos += nilfs_rec_len_from_disk(de->rec_len);
3152ba466d7SYoshiji Amagai }
3162ba466d7SYoshiji Amagai nilfs_put_page(page);
3172ba466d7SYoshiji Amagai }
3181616abe8SAl Viro return 0;
3192ba466d7SYoshiji Amagai }
3202ba466d7SYoshiji Amagai
3212ba466d7SYoshiji Amagai /*
3222ba466d7SYoshiji Amagai * nilfs_find_entry()
3232ba466d7SYoshiji Amagai *
3242ba466d7SYoshiji Amagai * finds an entry in the specified directory with the wanted name. It
3252ba466d7SYoshiji Amagai * returns the page in which the entry was found, and the entry itself
3262ba466d7SYoshiji Amagai * (as a parameter - res_dir). Page is returned mapped and unlocked.
3272ba466d7SYoshiji Amagai * Entry is guaranteed to be valid.
3289698088aSRyusuke Konishi *
3299698088aSRyusuke Konishi * On failure, returns an error pointer and the caller should ignore res_page.
3302ba466d7SYoshiji Amagai */
3312ba466d7SYoshiji Amagai struct nilfs_dir_entry *
nilfs_find_entry(struct inode * dir,const struct qstr * qstr,struct page ** res_page)3320319003dSAl Viro nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
3332ba466d7SYoshiji Amagai struct page **res_page)
3342ba466d7SYoshiji Amagai {
3350319003dSAl Viro const unsigned char *name = qstr->name;
3360319003dSAl Viro int namelen = qstr->len;
3370c6c44cbSRyusuke Konishi unsigned int reclen = NILFS_DIR_REC_LEN(namelen);
3382ba466d7SYoshiji Amagai unsigned long start, n;
3392ba466d7SYoshiji Amagai unsigned long npages = dir_pages(dir);
3402ba466d7SYoshiji Amagai struct page *page = NULL;
3412ba466d7SYoshiji Amagai struct nilfs_inode_info *ei = NILFS_I(dir);
3422ba466d7SYoshiji Amagai struct nilfs_dir_entry *de;
3432ba466d7SYoshiji Amagai
3442ba466d7SYoshiji Amagai if (npages == 0)
3452ba466d7SYoshiji Amagai goto out;
3462ba466d7SYoshiji Amagai
3472ba466d7SYoshiji Amagai /* OFFSET_CACHE */
3482ba466d7SYoshiji Amagai *res_page = NULL;
3492ba466d7SYoshiji Amagai
3502ba466d7SYoshiji Amagai start = ei->i_dir_start_lookup;
3512ba466d7SYoshiji Amagai if (start >= npages)
3522ba466d7SYoshiji Amagai start = 0;
3532ba466d7SYoshiji Amagai n = start;
3542ba466d7SYoshiji Amagai do {
3558394dce1SMatthew Wilcox (Oracle) char *kaddr = nilfs_get_page(dir, n, &page);
3564ad364caSRyusuke Konishi
3579698088aSRyusuke Konishi if (IS_ERR(kaddr))
3589698088aSRyusuke Konishi return ERR_CAST(kaddr);
3599698088aSRyusuke Konishi
3602ba466d7SYoshiji Amagai de = (struct nilfs_dir_entry *)kaddr;
3612ba466d7SYoshiji Amagai kaddr += nilfs_last_byte(dir, n) - reclen;
3622ba466d7SYoshiji Amagai while ((char *)de <= kaddr) {
3632ba466d7SYoshiji Amagai if (de->rec_len == 0) {
364cae3d4caSRyusuke Konishi nilfs_error(dir->i_sb,
3652ba466d7SYoshiji Amagai "zero-length directory entry");
3662ba466d7SYoshiji Amagai nilfs_put_page(page);
3672ba466d7SYoshiji Amagai goto out;
3682ba466d7SYoshiji Amagai }
3692ba466d7SYoshiji Amagai if (nilfs_match(namelen, name, de))
3702ba466d7SYoshiji Amagai goto found;
3712ba466d7SYoshiji Amagai de = nilfs_next_entry(de);
3722ba466d7SYoshiji Amagai }
3732ba466d7SYoshiji Amagai nilfs_put_page(page);
3749698088aSRyusuke Konishi
3752ba466d7SYoshiji Amagai if (++n >= npages)
3762ba466d7SYoshiji Amagai n = 0;
3772ba466d7SYoshiji Amagai /* next page is past the blocks we've got */
37809cbfeafSKirill A. Shutemov if (unlikely(n > (dir->i_blocks >> (PAGE_SHIFT - 9)))) {
379cae3d4caSRyusuke Konishi nilfs_error(dir->i_sb,
3801621562bSRyusuke Konishi "dir %lu size %lld exceeds block count %llu",
3812ba466d7SYoshiji Amagai dir->i_ino, dir->i_size,
3822ba466d7SYoshiji Amagai (unsigned long long)dir->i_blocks);
3832ba466d7SYoshiji Amagai goto out;
3842ba466d7SYoshiji Amagai }
3852ba466d7SYoshiji Amagai } while (n != start);
3862ba466d7SYoshiji Amagai out:
3879698088aSRyusuke Konishi return ERR_PTR(-ENOENT);
3882ba466d7SYoshiji Amagai
3892ba466d7SYoshiji Amagai found:
3902ba466d7SYoshiji Amagai *res_page = page;
3912ba466d7SYoshiji Amagai ei->i_dir_start_lookup = n;
3922ba466d7SYoshiji Amagai return de;
3932ba466d7SYoshiji Amagai }
3942ba466d7SYoshiji Amagai
nilfs_dotdot(struct inode * dir,struct page ** p)3952ba466d7SYoshiji Amagai struct nilfs_dir_entry *nilfs_dotdot(struct inode *dir, struct page **p)
3962ba466d7SYoshiji Amagai {
39760f61514SRyusuke Konishi struct page *page;
39860f61514SRyusuke Konishi struct nilfs_dir_entry *de, *next_de;
39960f61514SRyusuke Konishi size_t limit;
40060f61514SRyusuke Konishi char *msg;
4012ba466d7SYoshiji Amagai
40260f61514SRyusuke Konishi de = nilfs_get_page(dir, 0, &page);
4038394dce1SMatthew Wilcox (Oracle) if (IS_ERR(de))
4048394dce1SMatthew Wilcox (Oracle) return NULL;
40560f61514SRyusuke Konishi
40660f61514SRyusuke Konishi limit = nilfs_last_byte(dir, 0); /* is a multiple of chunk size */
40760f61514SRyusuke Konishi if (unlikely(!limit || le64_to_cpu(de->inode) != dir->i_ino ||
40860f61514SRyusuke Konishi !nilfs_match(1, ".", de))) {
40960f61514SRyusuke Konishi msg = "missing '.'";
41060f61514SRyusuke Konishi goto fail;
41160f61514SRyusuke Konishi }
41260f61514SRyusuke Konishi
41360f61514SRyusuke Konishi next_de = nilfs_next_entry(de);
41460f61514SRyusuke Konishi /*
41560f61514SRyusuke Konishi * If "next_de" has not reached the end of the chunk, there is
41660f61514SRyusuke Konishi * at least one more record. Check whether it matches "..".
41760f61514SRyusuke Konishi */
41860f61514SRyusuke Konishi if (unlikely((char *)next_de == (char *)de + nilfs_chunk_size(dir) ||
41960f61514SRyusuke Konishi !nilfs_match(2, "..", next_de))) {
42060f61514SRyusuke Konishi msg = "missing '..'";
42160f61514SRyusuke Konishi goto fail;
42260f61514SRyusuke Konishi }
42360f61514SRyusuke Konishi *p = page;
42460f61514SRyusuke Konishi return next_de;
42560f61514SRyusuke Konishi
42660f61514SRyusuke Konishi fail:
42760f61514SRyusuke Konishi nilfs_error(dir->i_sb, "directory #%lu %s", dir->i_ino, msg);
42860f61514SRyusuke Konishi nilfs_put_page(page);
42960f61514SRyusuke Konishi return NULL;
4302ba466d7SYoshiji Amagai }
4312ba466d7SYoshiji Amagai
nilfs_inode_by_name(struct inode * dir,const struct qstr * qstr,ino_t * ino)4329698088aSRyusuke Konishi int nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr, ino_t *ino)
4332ba466d7SYoshiji Amagai {
4342ba466d7SYoshiji Amagai struct nilfs_dir_entry *de;
4352ba466d7SYoshiji Amagai struct page *page;
4362ba466d7SYoshiji Amagai
4370319003dSAl Viro de = nilfs_find_entry(dir, qstr, &page);
4389698088aSRyusuke Konishi if (IS_ERR(de))
4399698088aSRyusuke Konishi return PTR_ERR(de);
4409698088aSRyusuke Konishi
4419698088aSRyusuke Konishi *ino = le64_to_cpu(de->inode);
4422ba466d7SYoshiji Amagai kunmap(page);
44309cbfeafSKirill A. Shutemov put_page(page);
4449698088aSRyusuke Konishi return 0;
4452ba466d7SYoshiji Amagai }
4462ba466d7SYoshiji Amagai
nilfs_set_link(struct inode * dir,struct nilfs_dir_entry * de,struct page * page,struct inode * inode)447*7891ac3bSRyusuke Konishi int nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
4482ba466d7SYoshiji Amagai struct page *page, struct inode *inode)
4492ba466d7SYoshiji Amagai {
4500c6c44cbSRyusuke Konishi unsigned int from = (char *)de - (char *)page_address(page);
4510c6c44cbSRyusuke Konishi unsigned int to = from + nilfs_rec_len_from_disk(de->rec_len);
4522ba466d7SYoshiji Amagai struct address_space *mapping = page->mapping;
4532ba466d7SYoshiji Amagai int err;
4542ba466d7SYoshiji Amagai
4552ba466d7SYoshiji Amagai lock_page(page);
456f4e420dcSChristoph Hellwig err = nilfs_prepare_chunk(page, from, to);
457*7891ac3bSRyusuke Konishi if (unlikely(err)) {
458*7891ac3bSRyusuke Konishi unlock_page(page);
459*7891ac3bSRyusuke Konishi return err;
460*7891ac3bSRyusuke Konishi }
4612ba466d7SYoshiji Amagai de->inode = cpu_to_le64(inode->i_ino);
4622ba466d7SYoshiji Amagai nilfs_set_de_type(de, inode);
4632093abf9SJiro SEKIBA nilfs_commit_chunk(page, mapping, from, to);
464e21d4f41SJeff Layton dir->i_mtime = inode_set_ctime_current(dir);
465*7891ac3bSRyusuke Konishi return 0;
4662ba466d7SYoshiji Amagai }
4672ba466d7SYoshiji Amagai
4682ba466d7SYoshiji Amagai /*
4692ba466d7SYoshiji Amagai * Parent is locked.
4702ba466d7SYoshiji Amagai */
nilfs_add_link(struct dentry * dentry,struct inode * inode)4712ba466d7SYoshiji Amagai int nilfs_add_link(struct dentry *dentry, struct inode *inode)
4722ba466d7SYoshiji Amagai {
4732b0143b5SDavid Howells struct inode *dir = d_inode(dentry->d_parent);
474072f98b4SAl Viro const unsigned char *name = dentry->d_name.name;
4752ba466d7SYoshiji Amagai int namelen = dentry->d_name.len;
4760c6c44cbSRyusuke Konishi unsigned int chunk_size = nilfs_chunk_size(dir);
4770c6c44cbSRyusuke Konishi unsigned int reclen = NILFS_DIR_REC_LEN(namelen);
4782ba466d7SYoshiji Amagai unsigned short rec_len, name_len;
4792ba466d7SYoshiji Amagai struct page *page = NULL;
4802ba466d7SYoshiji Amagai struct nilfs_dir_entry *de;
4812ba466d7SYoshiji Amagai unsigned long npages = dir_pages(dir);
4822ba466d7SYoshiji Amagai unsigned long n;
4832ba466d7SYoshiji Amagai char *kaddr;
4840c6c44cbSRyusuke Konishi unsigned int from, to;
4852ba466d7SYoshiji Amagai int err;
4862ba466d7SYoshiji Amagai
4872ba466d7SYoshiji Amagai /*
4882ba466d7SYoshiji Amagai * We take care of directory expansion in the same loop.
4892ba466d7SYoshiji Amagai * This code plays outside i_size, so it locks the page
4902ba466d7SYoshiji Amagai * to protect that region.
4912ba466d7SYoshiji Amagai */
4922ba466d7SYoshiji Amagai for (n = 0; n <= npages; n++) {
4932ba466d7SYoshiji Amagai char *dir_end;
4942ba466d7SYoshiji Amagai
4958394dce1SMatthew Wilcox (Oracle) kaddr = nilfs_get_page(dir, n, &page);
4968394dce1SMatthew Wilcox (Oracle) err = PTR_ERR(kaddr);
4978394dce1SMatthew Wilcox (Oracle) if (IS_ERR(kaddr))
4982ba466d7SYoshiji Amagai goto out;
4992ba466d7SYoshiji Amagai lock_page(page);
5002ba466d7SYoshiji Amagai dir_end = kaddr + nilfs_last_byte(dir, n);
5012ba466d7SYoshiji Amagai de = (struct nilfs_dir_entry *)kaddr;
50209cbfeafSKirill A. Shutemov kaddr += PAGE_SIZE - reclen;
5032ba466d7SYoshiji Amagai while ((char *)de <= kaddr) {
5042ba466d7SYoshiji Amagai if ((char *)de == dir_end) {
5052ba466d7SYoshiji Amagai /* We hit i_size */
5062ba466d7SYoshiji Amagai name_len = 0;
5072ba466d7SYoshiji Amagai rec_len = chunk_size;
5086cda9fa2SRyusuke Konishi de->rec_len = nilfs_rec_len_to_disk(chunk_size);
5092ba466d7SYoshiji Amagai de->inode = 0;
5102ba466d7SYoshiji Amagai goto got_it;
5112ba466d7SYoshiji Amagai }
5122ba466d7SYoshiji Amagai if (de->rec_len == 0) {
513cae3d4caSRyusuke Konishi nilfs_error(dir->i_sb,
5142ba466d7SYoshiji Amagai "zero-length directory entry");
5152ba466d7SYoshiji Amagai err = -EIO;
5162ba466d7SYoshiji Amagai goto out_unlock;
5172ba466d7SYoshiji Amagai }
5182ba466d7SYoshiji Amagai err = -EEXIST;
5192ba466d7SYoshiji Amagai if (nilfs_match(namelen, name, de))
5202ba466d7SYoshiji Amagai goto out_unlock;
5212ba466d7SYoshiji Amagai name_len = NILFS_DIR_REC_LEN(de->name_len);
5226cda9fa2SRyusuke Konishi rec_len = nilfs_rec_len_from_disk(de->rec_len);
5232ba466d7SYoshiji Amagai if (!de->inode && rec_len >= reclen)
5242ba466d7SYoshiji Amagai goto got_it;
5252ba466d7SYoshiji Amagai if (rec_len >= name_len + reclen)
5262ba466d7SYoshiji Amagai goto got_it;
5272ba466d7SYoshiji Amagai de = (struct nilfs_dir_entry *)((char *)de + rec_len);
5282ba466d7SYoshiji Amagai }
5292ba466d7SYoshiji Amagai unlock_page(page);
5302ba466d7SYoshiji Amagai nilfs_put_page(page);
5312ba466d7SYoshiji Amagai }
5322ba466d7SYoshiji Amagai BUG();
5332ba466d7SYoshiji Amagai return -EINVAL;
5342ba466d7SYoshiji Amagai
5352ba466d7SYoshiji Amagai got_it:
5362ba466d7SYoshiji Amagai from = (char *)de - (char *)page_address(page);
5372ba466d7SYoshiji Amagai to = from + rec_len;
538f4e420dcSChristoph Hellwig err = nilfs_prepare_chunk(page, from, to);
5392ba466d7SYoshiji Amagai if (err)
5402ba466d7SYoshiji Amagai goto out_unlock;
5412ba466d7SYoshiji Amagai if (de->inode) {
5422ba466d7SYoshiji Amagai struct nilfs_dir_entry *de1;
5432ba466d7SYoshiji Amagai
5442ba466d7SYoshiji Amagai de1 = (struct nilfs_dir_entry *)((char *)de + name_len);
5456cda9fa2SRyusuke Konishi de1->rec_len = nilfs_rec_len_to_disk(rec_len - name_len);
5466cda9fa2SRyusuke Konishi de->rec_len = nilfs_rec_len_to_disk(name_len);
5472ba466d7SYoshiji Amagai de = de1;
5482ba466d7SYoshiji Amagai }
5492ba466d7SYoshiji Amagai de->name_len = namelen;
5502ba466d7SYoshiji Amagai memcpy(de->name, name, namelen);
5512ba466d7SYoshiji Amagai de->inode = cpu_to_le64(inode->i_ino);
5522ba466d7SYoshiji Amagai nilfs_set_de_type(de, inode);
5532093abf9SJiro SEKIBA nilfs_commit_chunk(page, page->mapping, from, to);
554e21d4f41SJeff Layton dir->i_mtime = inode_set_ctime_current(dir);
555abdb318bSJiro SEKIBA nilfs_mark_inode_dirty(dir);
5562ba466d7SYoshiji Amagai /* OFFSET_CACHE */
5572ba466d7SYoshiji Amagai out_put:
5582ba466d7SYoshiji Amagai nilfs_put_page(page);
5592ba466d7SYoshiji Amagai out:
5602ba466d7SYoshiji Amagai return err;
5612ba466d7SYoshiji Amagai out_unlock:
5622ba466d7SYoshiji Amagai unlock_page(page);
5632ba466d7SYoshiji Amagai goto out_put;
5642ba466d7SYoshiji Amagai }
5652ba466d7SYoshiji Amagai
5662ba466d7SYoshiji Amagai /*
5672ba466d7SYoshiji Amagai * nilfs_delete_entry deletes a directory entry by merging it with the
568944a4f8fSRyusuke Konishi * previous entry. Page is up-to-date.
5692ba466d7SYoshiji Amagai */
nilfs_delete_entry(struct nilfs_dir_entry * dir,struct page * page)5702ba466d7SYoshiji Amagai int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page)
5712ba466d7SYoshiji Amagai {
5722ba466d7SYoshiji Amagai struct address_space *mapping = page->mapping;
5732ba466d7SYoshiji Amagai struct inode *inode = mapping->host;
5742ba466d7SYoshiji Amagai char *kaddr = page_address(page);
5750c6c44cbSRyusuke Konishi unsigned int from, to;
5760c6c44cbSRyusuke Konishi struct nilfs_dir_entry *de, *pde = NULL;
5772ba466d7SYoshiji Amagai int err;
5782ba466d7SYoshiji Amagai
5790c6c44cbSRyusuke Konishi from = ((char *)dir - kaddr) & ~(nilfs_chunk_size(inode) - 1);
5800c6c44cbSRyusuke Konishi to = ((char *)dir - kaddr) + nilfs_rec_len_from_disk(dir->rec_len);
5810c6c44cbSRyusuke Konishi de = (struct nilfs_dir_entry *)(kaddr + from);
5820c6c44cbSRyusuke Konishi
5832ba466d7SYoshiji Amagai while ((char *)de < (char *)dir) {
5842ba466d7SYoshiji Amagai if (de->rec_len == 0) {
585cae3d4caSRyusuke Konishi nilfs_error(inode->i_sb,
5862ba466d7SYoshiji Amagai "zero-length directory entry");
5872ba466d7SYoshiji Amagai err = -EIO;
5882ba466d7SYoshiji Amagai goto out;
5892ba466d7SYoshiji Amagai }
5902ba466d7SYoshiji Amagai pde = de;
5912ba466d7SYoshiji Amagai de = nilfs_next_entry(de);
5922ba466d7SYoshiji Amagai }
5932ba466d7SYoshiji Amagai if (pde)
5942ba466d7SYoshiji Amagai from = (char *)pde - (char *)page_address(page);
5952ba466d7SYoshiji Amagai lock_page(page);
596f4e420dcSChristoph Hellwig err = nilfs_prepare_chunk(page, from, to);
597*7891ac3bSRyusuke Konishi if (unlikely(err)) {
598*7891ac3bSRyusuke Konishi unlock_page(page);
599*7891ac3bSRyusuke Konishi goto out;
600*7891ac3bSRyusuke Konishi }
6012ba466d7SYoshiji Amagai if (pde)
6026cda9fa2SRyusuke Konishi pde->rec_len = nilfs_rec_len_to_disk(to - from);
6032ba466d7SYoshiji Amagai dir->inode = 0;
6042093abf9SJiro SEKIBA nilfs_commit_chunk(page, mapping, from, to);
605e21d4f41SJeff Layton inode->i_mtime = inode_set_ctime_current(inode);
6062ba466d7SYoshiji Amagai out:
6072ba466d7SYoshiji Amagai return err;
6082ba466d7SYoshiji Amagai }
6092ba466d7SYoshiji Amagai
6102ba466d7SYoshiji Amagai /*
6112ba466d7SYoshiji Amagai * Set the first fragment of directory.
6122ba466d7SYoshiji Amagai */
nilfs_make_empty(struct inode * inode,struct inode * parent)6132ba466d7SYoshiji Amagai int nilfs_make_empty(struct inode *inode, struct inode *parent)
6142ba466d7SYoshiji Amagai {
6152ba466d7SYoshiji Amagai struct address_space *mapping = inode->i_mapping;
6162ba466d7SYoshiji Amagai struct page *page = grab_cache_page(mapping, 0);
6170c6c44cbSRyusuke Konishi unsigned int chunk_size = nilfs_chunk_size(inode);
6182ba466d7SYoshiji Amagai struct nilfs_dir_entry *de;
6192ba466d7SYoshiji Amagai int err;
6202ba466d7SYoshiji Amagai void *kaddr;
6212ba466d7SYoshiji Amagai
6222ba466d7SYoshiji Amagai if (!page)
6232ba466d7SYoshiji Amagai return -ENOMEM;
6242ba466d7SYoshiji Amagai
625f4e420dcSChristoph Hellwig err = nilfs_prepare_chunk(page, 0, chunk_size);
6262ba466d7SYoshiji Amagai if (unlikely(err)) {
6272ba466d7SYoshiji Amagai unlock_page(page);
6282ba466d7SYoshiji Amagai goto fail;
6292ba466d7SYoshiji Amagai }
6307b9c0976SCong Wang kaddr = kmap_atomic(page);
6312ba466d7SYoshiji Amagai memset(kaddr, 0, chunk_size);
6322ba466d7SYoshiji Amagai de = (struct nilfs_dir_entry *)kaddr;
6332ba466d7SYoshiji Amagai de->name_len = 1;
6346cda9fa2SRyusuke Konishi de->rec_len = nilfs_rec_len_to_disk(NILFS_DIR_REC_LEN(1));
6352ba466d7SYoshiji Amagai memcpy(de->name, ".\0\0", 4);
6362ba466d7SYoshiji Amagai de->inode = cpu_to_le64(inode->i_ino);
6372ba466d7SYoshiji Amagai nilfs_set_de_type(de, inode);
6382ba466d7SYoshiji Amagai
6392ba466d7SYoshiji Amagai de = (struct nilfs_dir_entry *)(kaddr + NILFS_DIR_REC_LEN(1));
6402ba466d7SYoshiji Amagai de->name_len = 2;
6416cda9fa2SRyusuke Konishi de->rec_len = nilfs_rec_len_to_disk(chunk_size - NILFS_DIR_REC_LEN(1));
6422ba466d7SYoshiji Amagai de->inode = cpu_to_le64(parent->i_ino);
6432ba466d7SYoshiji Amagai memcpy(de->name, "..\0", 4);
6442ba466d7SYoshiji Amagai nilfs_set_de_type(de, inode);
6457b9c0976SCong Wang kunmap_atomic(kaddr);
6462093abf9SJiro SEKIBA nilfs_commit_chunk(page, mapping, 0, chunk_size);
6472ba466d7SYoshiji Amagai fail:
64809cbfeafSKirill A. Shutemov put_page(page);
6492ba466d7SYoshiji Amagai return err;
6502ba466d7SYoshiji Amagai }
6512ba466d7SYoshiji Amagai
6522ba466d7SYoshiji Amagai /*
6532ba466d7SYoshiji Amagai * routine to check that the specified directory is empty (for rmdir)
6542ba466d7SYoshiji Amagai */
nilfs_empty_dir(struct inode * inode)6552ba466d7SYoshiji Amagai int nilfs_empty_dir(struct inode *inode)
6562ba466d7SYoshiji Amagai {
6572ba466d7SYoshiji Amagai struct page *page = NULL;
6582ba466d7SYoshiji Amagai unsigned long i, npages = dir_pages(inode);
6592ba466d7SYoshiji Amagai
6602ba466d7SYoshiji Amagai for (i = 0; i < npages; i++) {
6612ba466d7SYoshiji Amagai char *kaddr;
6622ba466d7SYoshiji Amagai struct nilfs_dir_entry *de;
6632ba466d7SYoshiji Amagai
6648394dce1SMatthew Wilcox (Oracle) kaddr = nilfs_get_page(inode, i, &page);
6658394dce1SMatthew Wilcox (Oracle) if (IS_ERR(kaddr))
666d18b05edSRyusuke Konishi return 0;
6672ba466d7SYoshiji Amagai
6682ba466d7SYoshiji Amagai de = (struct nilfs_dir_entry *)kaddr;
6692ba466d7SYoshiji Amagai kaddr += nilfs_last_byte(inode, i) - NILFS_DIR_REC_LEN(1);
6702ba466d7SYoshiji Amagai
6712ba466d7SYoshiji Amagai while ((char *)de <= kaddr) {
6722ba466d7SYoshiji Amagai if (de->rec_len == 0) {
673cae3d4caSRyusuke Konishi nilfs_error(inode->i_sb,
67406f4abf6SRyusuke Konishi "zero-length directory entry (kaddr=%p, de=%p)",
67506f4abf6SRyusuke Konishi kaddr, de);
6762ba466d7SYoshiji Amagai goto not_empty;
6772ba466d7SYoshiji Amagai }
6782ba466d7SYoshiji Amagai if (de->inode != 0) {
6792ba466d7SYoshiji Amagai /* check for . and .. */
6802ba466d7SYoshiji Amagai if (de->name[0] != '.')
6812ba466d7SYoshiji Amagai goto not_empty;
6822ba466d7SYoshiji Amagai if (de->name_len > 2)
6832ba466d7SYoshiji Amagai goto not_empty;
6842ba466d7SYoshiji Amagai if (de->name_len < 2) {
6852ba466d7SYoshiji Amagai if (de->inode !=
6862ba466d7SYoshiji Amagai cpu_to_le64(inode->i_ino))
6872ba466d7SYoshiji Amagai goto not_empty;
6882ba466d7SYoshiji Amagai } else if (de->name[1] != '.')
6892ba466d7SYoshiji Amagai goto not_empty;
6902ba466d7SYoshiji Amagai }
6912ba466d7SYoshiji Amagai de = nilfs_next_entry(de);
6922ba466d7SYoshiji Amagai }
6932ba466d7SYoshiji Amagai nilfs_put_page(page);
6942ba466d7SYoshiji Amagai }
6952ba466d7SYoshiji Amagai return 1;
6962ba466d7SYoshiji Amagai
6972ba466d7SYoshiji Amagai not_empty:
6982ba466d7SYoshiji Amagai nilfs_put_page(page);
6992ba466d7SYoshiji Amagai return 0;
7002ba466d7SYoshiji Amagai }
7012ba466d7SYoshiji Amagai
702828c0950SAlexey Dobriyan const struct file_operations nilfs_dir_operations = {
7032ba466d7SYoshiji Amagai .llseek = generic_file_llseek,
7042ba466d7SYoshiji Amagai .read = generic_read_dir,
705c51da20cSAl Viro .iterate_shared = nilfs_readdir,
7067a946193SRyusuke Konishi .unlocked_ioctl = nilfs_ioctl,
7072ba466d7SYoshiji Amagai #ifdef CONFIG_COMPAT
708828b1c50SRyusuke Konishi .compat_ioctl = nilfs_compat_ioctl,
7092ba466d7SYoshiji Amagai #endif /* CONFIG_COMPAT */
7102ba466d7SYoshiji Amagai .fsync = nilfs_sync_file,
7112ba466d7SYoshiji Amagai
7122ba466d7SYoshiji Amagai };
713