xref: /openbmc/linux/fs/nilfs2/dir.c (revision d37cf9b63113f13d742713881ce691fc615d8b3b)
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