11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  linux/fs/minix/dir.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 1991, 1992 Linus Torvalds
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  minix directory handling functions
7939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer *
8939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer *  Updated to filesystem version 3 by Daniel Aragones
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "minix.h"
124a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin#include <linux/buffer_head.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/highmem.h>
144a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin#include <linux/swap.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct minix_dir_entry minix_dirent;
17939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwertypedef struct minix3_dir_entry minix3_dirent;
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int minix_readdir(struct file *, void *, filldir_t);
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
214b6f5d20b04dcbc3d888555522b90ba6d36c4106Arjan van de Venconst struct file_operations minix_dir_operations = {
22cc46759a8c0ac4c6f13aa4b0f470305c05f600e1Al Viro	.llseek		= generic_file_llseek,
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read		= generic_read_dir,
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.readdir	= minix_readdir,
251b061d9247f71cd15edc4c4c4600191a903642c0Christoph Hellwig	.fsync		= generic_file_fsync,
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void dir_put_page(struct page *page)
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kunmap(page);
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	page_cache_release(page);
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return the offset into page `page_nr' of the last valid
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * byte in that page, plus one.
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsminix_last_byte(struct inode *inode, unsigned long page_nr)
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned last_byte = PAGE_CACHE_SIZE;
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (page_nr == (inode->i_size >> PAGE_CACHE_SHIFT))
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		last_byte = inode->i_size & (PAGE_CACHE_SIZE - 1);
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return last_byte;
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline unsigned long dir_pages(struct inode *inode)
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
534a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Pigginstatic int dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
554a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin	struct address_space *mapping = page->mapping;
564a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin	struct inode *dir = mapping->host;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = 0;
584a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin	block_write_end(NULL, mapping, pos, len, len, page, NULL);
594a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin
604a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin	if (pos+len > dir->i_size) {
614a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin		i_size_write(dir, pos+len);
624a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin		mark_inode_dirty(dir);
634a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin	}
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_DIRSYNC(dir))
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = write_one_page(page, 1);
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unlock_page(page);
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct page * dir_get_page(struct inode *dir, unsigned long n)
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct address_space *mapping = dir->i_mapping;
74090d2b185d8680fc26a2eaf4245d4171dcf4baf1Pekka Enberg	struct page *page = read_mapping_page(mapping, n, NULL);
7549837a80b38b79a7c06217b2c40842aeb6fa13b9Al Viro	if (!IS_ERR(page))
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kmap(page);
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return page;
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void *minix_next_entry(void *de, struct minix_sb_info *sbi)
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (void*)((char*)de + sbi->s_dirsize);
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long pos = filp->f_pos;
88dcf258ae682c2dbbe1a34624f2b3f56353d3874dJosef Sipek	struct inode *inode = filp->f_path.dentry->d_inode;
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct super_block *sb = inode->i_sb;
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned offset = pos & ~PAGE_CACHE_MASK;
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long n = pos >> PAGE_CACHE_SHIFT;
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long npages = dir_pages(inode);
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct minix_sb_info *sbi = minix_sb(sb);
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned chunk_size = sbi->s_dirsize;
95939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	char *name;
96939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	__u32 inumber;
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pos = (pos + chunk_size-1) & ~(chunk_size-1);
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pos >= inode->i_size)
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto done;
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for ( ; n < npages; n++, offset = 0) {
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		char *p, *kaddr, *limit;
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct page *page = dir_get_page(inode, n);
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (IS_ERR(page))
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kaddr = (char *)page_address(page);
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p = kaddr+offset;
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		limit = kaddr + minix_last_byte(inode, n) - chunk_size;
111939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		for ( ; p <= limit; p = minix_next_entry(p, sbi)) {
112939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			if (sbi->s_version == MINIX_V3) {
113939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				minix3_dirent *de3 = (minix3_dirent *)p;
114939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				name = de3->name;
115939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				inumber = de3->inode;
116939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	 		} else {
117939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				minix_dirent *de = (minix_dirent *)p;
118939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				name = de->name;
119939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				inumber = de->inode;
120939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			}
121939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			if (inumber) {
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				int over;
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
124939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				unsigned l = strnlen(name, sbi->s_namelen);
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				offset = p - kaddr;
126939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				over = filldir(dirent, name, l,
127939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer					(n << PAGE_CACHE_SHIFT) | offset,
128939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer					inumber, DT_UNKNOWN);
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (over) {
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dir_put_page(page);
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					goto done;
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dir_put_page(page);
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdone:
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int namecompare(int len, int maxlen,
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char * name, const char * buffer)
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (len < maxlen && buffer[len])
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return !memcmp(name, buffer, len);
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	minix_find_entry()
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * finds an entry in the specified directory with the wanted name. It
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns the cache buffer in which the entry was found, and the entry
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * itself (as a parameter - res_dir). It does NOT read the inode of the
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * entry - you'll have to do that yourself if you want to.
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsminix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page)
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char * name = dentry->d_name.name;
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int namelen = dentry->d_name.len;
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct inode * dir = dentry->d_parent->d_inode;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct super_block * sb = dir->i_sb;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct minix_sb_info * sbi = minix_sb(sb);
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long n;
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long npages = dir_pages(dir);
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct page *page = NULL;
169939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	char *p;
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	char *namx;
172939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	__u32 inumber;
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*res_page = NULL;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (n = 0; n < npages; n++) {
176939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		char *kaddr, *limit;
177939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		page = dir_get_page(dir, n);
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (IS_ERR(page))
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kaddr = (char*)page_address(page);
183939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		limit = kaddr + minix_last_byte(dir, n) - sbi->s_dirsize;
184939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
185939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			if (sbi->s_version == MINIX_V3) {
186939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				minix3_dirent *de3 = (minix3_dirent *)p;
187939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				namx = de3->name;
188939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				inumber = de3->inode;
189939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer 			} else {
190939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				minix_dirent *de = (minix_dirent *)p;
191939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				namx = de->name;
192939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				inumber = de->inode;
193939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			}
194939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			if (!inumber)
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
196939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			if (namecompare(namelen, sbi->s_namelen, name, namx))
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto found;
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dir_put_page(page);
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfound:
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*res_page = page;
205939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	return (minix_dirent *)p;
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint minix_add_link(struct dentry *dentry, struct inode *inode)
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct inode *dir = dentry->d_parent->d_inode;
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char * name = dentry->d_name.name;
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int namelen = dentry->d_name.len;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct super_block * sb = dir->i_sb;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct minix_sb_info * sbi = minix_sb(sb);
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct page *page = NULL;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long npages = dir_pages(dir);
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long n;
218939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	char *kaddr, *p;
219939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	minix_dirent *de;
220939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	minix3_dirent *de3;
2214a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin	loff_t pos;
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
223939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	char *namx = NULL;
224939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	__u32 inumber;
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We take care of directory expansion in the same loop
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * This code plays outside i_size, so it locks the page
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * to protect that region.
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (n = 0; n <= npages; n++) {
232939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		char *limit, *dir_end;
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		page = dir_get_page(dir, n);
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = PTR_ERR(page);
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (IS_ERR(page))
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto out;
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lock_page(page);
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kaddr = (char*)page_address(page);
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dir_end = kaddr + minix_last_byte(dir, n);
241939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		limit = kaddr + PAGE_CACHE_SIZE - sbi->s_dirsize;
242939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
243939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			de = (minix_dirent *)p;
244939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			de3 = (minix3_dirent *)p;
245939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			if (sbi->s_version == MINIX_V3) {
246939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				namx = de3->name;
247939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				inumber = de3->inode;
248939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		 	} else {
249939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer  				namx = de->name;
250939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				inumber = de->inode;
251939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			}
252939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			if (p == dir_end) {
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* We hit i_size */
254939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				if (sbi->s_version == MINIX_V3)
255939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer					de3->inode = 0;
256939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		 		else
257939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer					de->inode = 0;
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto got_it;
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
260939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			if (!inumber)
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto got_it;
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = -EEXIST;
263939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			if (namecompare(namelen, sbi->s_namelen, name, namx))
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto out_unlock;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unlock_page(page);
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dir_put_page(page);
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BUG();
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EINVAL;
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsgot_it:
273d6b54841f4ddd836c886d1e6ac381cf309ee98a3Evgeniy Dushistov	pos = page_offset(page) + p - (char *)page_address(page);
274f4e420dc423148fba637af1ab618fa8896dfb2d6Christoph Hellwig	err = minix_prepare_chunk(page, pos, sbi->s_dirsize);
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_unlock;
277939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	memcpy (namx, name, namelen);
278939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	if (sbi->s_version == MINIX_V3) {
279939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		memset (namx + namelen, 0, sbi->s_dirsize - namelen - 4);
280939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		de3->inode = inode->i_ino;
281939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	} else {
282939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		memset (namx + namelen, 0, sbi->s_dirsize - namelen - 2);
283939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		de->inode = inode->i_ino;
284939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	}
2854a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin	err = dir_commit_chunk(page, pos, sbi->s_dirsize);
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mark_inode_dirty(dir);
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_put:
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dir_put_page(page);
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_unlock:
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unlock_page(page);
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	goto out_put;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint minix_delete_entry(struct minix_dir_entry *de, struct page *page)
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
299f4e420dc423148fba637af1ab618fa8896dfb2d6Christoph Hellwig	struct inode *inode = page->mapping->host;
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *kaddr = page_address(page);
3014a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin	loff_t pos = page_offset(page) + (char*)de - kaddr;
3029f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
3039f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham	unsigned len = sbi->s_dirsize;
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lock_page(page);
307f4e420dc423148fba637af1ab618fa8896dfb2d6Christoph Hellwig	err = minix_prepare_chunk(page, pos, len);
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err == 0) {
3099f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham		if (sbi->s_version == MINIX_V3)
3109f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham			((minix3_dirent *) de)->inode = 0;
3119f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham		else
3129f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham			de->inode = 0;
3134a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin		err = dir_commit_chunk(page, pos, len);
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unlock_page(page);
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dir_put_page(page);
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mark_inode_dirty(inode);
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint minix_make_empty(struct inode *inode, struct inode *dir)
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
325f4e420dc423148fba637af1ab618fa8896dfb2d6Christoph Hellwig	struct page *page = grab_cache_page(inode->i_mapping, 0);
326939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *kaddr;
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!page)
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
332f4e420dc423148fba637af1ab618fa8896dfb2d6Christoph Hellwig	err = minix_prepare_chunk(page, 0, 2 * sbi->s_dirsize);
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err) {
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unlock_page(page);
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fail;
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kaddr = kmap_atomic(page, KM_USER0);
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(kaddr, 0, PAGE_CACHE_SIZE);
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	if (sbi->s_version == MINIX_V3) {
342939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		minix3_dirent *de3 = (minix3_dirent *)kaddr;
343939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer
344939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		de3->inode = inode->i_ino;
345939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		strcpy(de3->name, ".");
346939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		de3 = minix_next_entry(de3, sbi);
347939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		de3->inode = dir->i_ino;
348939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		strcpy(de3->name, "..");
349939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	} else {
350939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		minix_dirent *de = (minix_dirent *)kaddr;
351939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer
352939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		de->inode = inode->i_ino;
353939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		strcpy(de->name, ".");
354939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		de = minix_next_entry(de, sbi);
355939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		de->inode = dir->i_ino;
356939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		strcpy(de->name, "..");
357939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	}
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kunmap_atomic(kaddr, KM_USER0);
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize);
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfail:
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	page_cache_release(page);
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * routine to check that the specified directory is empty (for rmdir)
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint minix_empty_dir(struct inode * inode)
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct page *page = NULL;
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long i, npages = dir_pages(inode);
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
374939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	char *name;
375939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer	__u32 inumber;
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < npages; i++) {
378939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		char *p, *kaddr, *limit;
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
380939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		page = dir_get_page(inode, i);
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (IS_ERR(page))
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kaddr = (char *)page_address(page);
385939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		limit = kaddr + minix_last_byte(inode, i) - sbi->s_dirsize;
386939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer		for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
387939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			if (sbi->s_version == MINIX_V3) {
388939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				minix3_dirent *de3 = (minix3_dirent *)p;
389939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				name = de3->name;
390939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				inumber = de3->inode;
391939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			} else {
392939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				minix_dirent *de = (minix_dirent *)p;
393939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				name = de->name;
394939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				inumber = de->inode;
395939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			}
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
397939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer			if (inumber != 0) {
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* check for . and .. */
399939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				if (name[0] != '.')
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					goto not_empty;
401939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				if (!name[1]) {
402939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer					if (inumber != inode->i_ino)
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						goto not_empty;
404939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				} else if (name[1] != '.')
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					goto not_empty;
406939b00df0306bc4b5cd25c3c3c78e89b91e72fc8Andries Brouwer				else if (name[2])
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					goto not_empty;
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dir_put_page(page);
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnot_empty:
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dir_put_page(page);
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Releases the page */
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid minix_set_link(struct minix_dir_entry *de, struct page *page,
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct inode *inode)
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
423f4e420dc423148fba637af1ab618fa8896dfb2d6Christoph Hellwig	struct inode *dir = page->mapping->host;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct minix_sb_info *sbi = minix_sb(dir->i_sb);
4254a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin	loff_t pos = page_offset(page) +
4264a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin			(char *)de-(char*)page_address(page);
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lock_page(page);
4304a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin
431f4e420dc423148fba637af1ab618fa8896dfb2d6Christoph Hellwig	err = minix_prepare_chunk(page, pos, sbi->s_dirsize);
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err == 0) {
4339f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham		if (sbi->s_version == MINIX_V3)
4349f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham			((minix3_dirent *) de)->inode = inode->i_ino;
4359f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham		else
4369f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham			de->inode = inode->i_ino;
4374a66af9eaa9531372cfcb9e20103ed147c729ff9Nick Piggin		err = dir_commit_chunk(page, pos, sbi->s_dirsize);
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unlock_page(page);
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dir_put_page(page);
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mark_inode_dirty(dir);
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct minix_dir_entry * minix_dotdot (struct inode *dir, struct page **p)
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct page *page = dir_get_page(dir, 0);
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct minix_sb_info *sbi = minix_sb(dir->i_sb);
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct minix_dir_entry *de = NULL;
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!IS_ERR(page)) {
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		de = minix_next_entry(page_address(page), sbi);
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*p = page;
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return de;
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsino_t minix_inode_by_name(struct dentry *dentry)
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct page *page;
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct minix_dir_entry *de = minix_find_entry(dentry, &page);
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ino_t res = 0;
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (de) {
4669f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham		struct address_space *mapping = page->mapping;
4679f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham		struct inode *inode = mapping->host;
4689f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham		struct minix_sb_info *sbi = minix_sb(inode->i_sb);
4699f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham
4709f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham		if (sbi->s_version == MINIX_V3)
4719f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham			res = ((minix3_dirent *) de)->inode;
4729f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham		else
4739f6c1333938c5d93da8be8f29f3b5469a3c00f95Doug Graham			res = de->inode;
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dir_put_page(page);
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
478