xref: /openbmc/linux/fs/sysv/dir.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *  linux/fs/sysv/dir.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *  minix/dir.c
61da177e4SLinus Torvalds  *  Copyright (C) 1991, 1992  Linus Torvalds
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  *  coh/dir.c
91da177e4SLinus Torvalds  *  Copyright (C) 1993  Pascal Haible, Bruno Haible
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  *  sysv/dir.c
121da177e4SLinus Torvalds  *  Copyright (C) 1993  Bruno Haible
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  *  SystemV/Coherent directory handling functions
151da177e4SLinus Torvalds  */
161da177e4SLinus Torvalds 
171da177e4SLinus Torvalds #include <linux/pagemap.h>
181da177e4SLinus Torvalds #include <linux/highmem.h>
1926a6441aSNick Piggin #include <linux/swap.h>
201da177e4SLinus Torvalds #include "sysv.h"
211da177e4SLinus Torvalds 
2280886298SAl Viro static int sysv_readdir(struct file *, struct dir_context *);
231da177e4SLinus Torvalds 
244b6f5d20SArjan van de Ven const struct file_operations sysv_dir_operations = {
255ac3455aSAl Viro 	.llseek		= generic_file_llseek,
261da177e4SLinus Torvalds 	.read		= generic_read_dir,
273b0a3c1aSAl Viro 	.iterate_shared	= sysv_readdir,
281b061d92SChristoph Hellwig 	.fsync		= generic_file_fsync,
291da177e4SLinus Torvalds };
301da177e4SLinus Torvalds 
dir_commit_chunk(struct page * page,loff_t pos,unsigned len)314309093eSChristoph Hellwig static void dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
321da177e4SLinus Torvalds {
3326a6441aSNick Piggin 	struct address_space *mapping = page->mapping;
3426a6441aSNick Piggin 	struct inode *dir = mapping->host;
351da177e4SLinus Torvalds 
3626a6441aSNick Piggin 	block_write_end(NULL, mapping, pos, len, len, page, NULL);
3726a6441aSNick Piggin 	if (pos+len > dir->i_size) {
3826a6441aSNick Piggin 		i_size_write(dir, pos+len);
3926a6441aSNick Piggin 		mark_inode_dirty(dir);
4026a6441aSNick Piggin 	}
411da177e4SLinus Torvalds 	unlock_page(page);
424309093eSChristoph Hellwig }
434309093eSChristoph Hellwig 
sysv_handle_dirsync(struct inode * dir)444309093eSChristoph Hellwig static int sysv_handle_dirsync(struct inode *dir)
454309093eSChristoph Hellwig {
464309093eSChristoph Hellwig 	int err;
474309093eSChristoph Hellwig 
484309093eSChristoph Hellwig 	err = filemap_write_and_wait(dir->i_mapping);
494309093eSChristoph Hellwig 	if (!err)
504309093eSChristoph Hellwig 		err = sync_inode_metadata(dir, 1);
511da177e4SLinus Torvalds 	return err;
521da177e4SLinus Torvalds }
531da177e4SLinus Torvalds 
5483005276SFabio M. De Francesco /*
55d0e13540SFabio M. De Francesco  * Calls to dir_get_page()/unmap_and_put_page() must be nested according to the
5683005276SFabio M. De Francesco  * rules documented in mm/highmem.rst.
5783005276SFabio M. De Francesco  *
5883005276SFabio M. De Francesco  * NOTE: sysv_find_entry() and sysv_dotdot() act as calls to dir_get_page()
5983005276SFabio M. De Francesco  * and must be treated accordingly for nesting purposes.
6083005276SFabio M. De Francesco  */
dir_get_page(struct inode * dir,unsigned long n,struct page ** p)618dd6c7b2SFabio M. De Francesco static void *dir_get_page(struct inode *dir, unsigned long n, struct page **p)
621da177e4SLinus Torvalds {
631da177e4SLinus Torvalds 	struct address_space *mapping = dir->i_mapping;
64090d2b18SPekka Enberg 	struct page *page = read_mapping_page(mapping, n, NULL);
658dd6c7b2SFabio M. De Francesco 	if (IS_ERR(page))
668dd6c7b2SFabio M. De Francesco 		return ERR_CAST(page);
678dd6c7b2SFabio M. De Francesco 	*p = page;
6883005276SFabio M. De Francesco 	return kmap_local_page(page);
691da177e4SLinus Torvalds }
701da177e4SLinus Torvalds 
sysv_readdir(struct file * file,struct dir_context * ctx)7180886298SAl Viro static int sysv_readdir(struct file *file, struct dir_context *ctx)
721da177e4SLinus Torvalds {
7380886298SAl Viro 	unsigned long pos = ctx->pos;
7480886298SAl Viro 	struct inode *inode = file_inode(file);
751da177e4SLinus Torvalds 	struct super_block *sb = inode->i_sb;
761da177e4SLinus Torvalds 	unsigned long npages = dir_pages(inode);
7780886298SAl Viro 	unsigned offset;
7880886298SAl Viro 	unsigned long n;
791da177e4SLinus Torvalds 
8080886298SAl Viro 	ctx->pos = pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1);
811da177e4SLinus Torvalds 	if (pos >= inode->i_size)
8280886298SAl Viro 		return 0;
8380886298SAl Viro 
8409cbfeafSKirill A. Shutemov 	offset = pos & ~PAGE_MASK;
8509cbfeafSKirill A. Shutemov 	n = pos >> PAGE_SHIFT;
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds 	for ( ; n < npages; n++, offset = 0) {
881da177e4SLinus Torvalds 		char *kaddr, *limit;
891da177e4SLinus Torvalds 		struct sysv_dir_entry *de;
908dd6c7b2SFabio M. De Francesco 		struct page *page;
911da177e4SLinus Torvalds 
928dd6c7b2SFabio M. De Francesco 		kaddr = dir_get_page(inode, n, &page);
938dd6c7b2SFabio M. De Francesco 		if (IS_ERR(kaddr))
941da177e4SLinus Torvalds 			continue;
951da177e4SLinus Torvalds 		de = (struct sysv_dir_entry *)(kaddr+offset);
9609cbfeafSKirill A. Shutemov 		limit = kaddr + PAGE_SIZE - SYSV_DIRSIZE;
9780886298SAl Viro 		for ( ;(char*)de <= limit; de++, ctx->pos += sizeof(*de)) {
981da177e4SLinus Torvalds 			char *name = de->name;
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds 			if (!de->inode)
1011da177e4SLinus Torvalds 				continue;
1021da177e4SLinus Torvalds 
10380886298SAl Viro 			if (!dir_emit(ctx, name, strnlen(name,SYSV_NAMELEN),
1041da177e4SLinus Torvalds 					fs16_to_cpu(SYSV_SB(sb), de->inode),
10580886298SAl Viro 					DT_UNKNOWN)) {
106d0e13540SFabio M. De Francesco 				unmap_and_put_page(page, kaddr);
10780886298SAl Viro 				return 0;
1081da177e4SLinus Torvalds 			}
1091da177e4SLinus Torvalds 		}
110d0e13540SFabio M. De Francesco 		unmap_and_put_page(page, kaddr);
1111da177e4SLinus Torvalds 	}
1121da177e4SLinus Torvalds 	return 0;
1131da177e4SLinus Torvalds }
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds /* compare strings: name[0..len-1] (not zero-terminated) and
1161da177e4SLinus Torvalds  * buffer[0..] (filled with zeroes up to buffer[0..maxlen-1])
1171da177e4SLinus Torvalds  */
namecompare(int len,int maxlen,const char * name,const char * buffer)1181da177e4SLinus Torvalds static inline int namecompare(int len, int maxlen,
1191da177e4SLinus Torvalds 	const char * name, const char * buffer)
1201da177e4SLinus Torvalds {
1211da177e4SLinus Torvalds 	if (len < maxlen && buffer[len])
1221da177e4SLinus Torvalds 		return 0;
1231da177e4SLinus Torvalds 	return !memcmp(name, buffer, len);
1241da177e4SLinus Torvalds }
1251da177e4SLinus Torvalds 
1261da177e4SLinus Torvalds /*
1271da177e4SLinus Torvalds  *	sysv_find_entry()
1281da177e4SLinus Torvalds  *
1291da177e4SLinus Torvalds  * finds an entry in the specified directory with the wanted name. It
1301da177e4SLinus Torvalds  * returns the cache buffer in which the entry was found, and the entry
1311da177e4SLinus Torvalds  * itself (as a parameter - res_dir). It does NOT read the inode of the
1321da177e4SLinus Torvalds  * entry - you'll have to do that yourself if you want to.
13383005276SFabio M. De Francesco  *
134d0e13540SFabio M. De Francesco  * On Success unmap_and_put_page() should be called on *res_page.
13583005276SFabio M. De Francesco  *
13683005276SFabio M. De Francesco  * sysv_find_entry() acts as a call to dir_get_page() and must be treated
13783005276SFabio M. De Francesco  * accordingly for nesting purposes.
1381da177e4SLinus Torvalds  */
sysv_find_entry(struct dentry * dentry,struct page ** res_page)1391da177e4SLinus Torvalds struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_page)
1401da177e4SLinus Torvalds {
1411da177e4SLinus Torvalds 	const char * name = dentry->d_name.name;
1421da177e4SLinus Torvalds 	int namelen = dentry->d_name.len;
1432b0143b5SDavid Howells 	struct inode * dir = d_inode(dentry->d_parent);
1441da177e4SLinus Torvalds 	unsigned long start, n;
1451da177e4SLinus Torvalds 	unsigned long npages = dir_pages(dir);
1461da177e4SLinus Torvalds 	struct page *page = NULL;
1471da177e4SLinus Torvalds 	struct sysv_dir_entry *de;
1481da177e4SLinus Torvalds 
1491da177e4SLinus Torvalds 	*res_page = NULL;
1501da177e4SLinus Torvalds 
1511da177e4SLinus Torvalds 	start = SYSV_I(dir)->i_dir_start_lookup;
1521da177e4SLinus Torvalds 	if (start >= npages)
1531da177e4SLinus Torvalds 		start = 0;
1541da177e4SLinus Torvalds 	n = start;
1551da177e4SLinus Torvalds 
1561da177e4SLinus Torvalds 	do {
1578dd6c7b2SFabio M. De Francesco 		char *kaddr = dir_get_page(dir, n, &page);
1588dd6c7b2SFabio M. De Francesco 
1598dd6c7b2SFabio M. De Francesco 		if (!IS_ERR(kaddr)) {
1601da177e4SLinus Torvalds 			de = (struct sysv_dir_entry *)kaddr;
16109cbfeafSKirill A. Shutemov 			kaddr += PAGE_SIZE - SYSV_DIRSIZE;
1621da177e4SLinus Torvalds 			for ( ; (char *) de <= kaddr ; de++) {
1631da177e4SLinus Torvalds 				if (!de->inode)
1641da177e4SLinus Torvalds 					continue;
1651da177e4SLinus Torvalds 				if (namecompare(namelen, SYSV_NAMELEN,
1661da177e4SLinus Torvalds 							name, de->name))
1671da177e4SLinus Torvalds 					goto found;
1681da177e4SLinus Torvalds 			}
169d0e13540SFabio M. De Francesco 			unmap_and_put_page(page, kaddr);
170404e7812SDan Carpenter 		}
1711da177e4SLinus Torvalds 
1721da177e4SLinus Torvalds 		if (++n >= npages)
1731da177e4SLinus Torvalds 			n = 0;
1741da177e4SLinus Torvalds 	} while (n != start);
1751da177e4SLinus Torvalds 
1761da177e4SLinus Torvalds 	return NULL;
1771da177e4SLinus Torvalds 
1781da177e4SLinus Torvalds found:
1791da177e4SLinus Torvalds 	SYSV_I(dir)->i_dir_start_lookup = n;
1801da177e4SLinus Torvalds 	*res_page = page;
1811da177e4SLinus Torvalds 	return de;
1821da177e4SLinus Torvalds }
1831da177e4SLinus Torvalds 
sysv_add_link(struct dentry * dentry,struct inode * inode)1841da177e4SLinus Torvalds int sysv_add_link(struct dentry *dentry, struct inode *inode)
1851da177e4SLinus Torvalds {
1862b0143b5SDavid Howells 	struct inode *dir = d_inode(dentry->d_parent);
1871da177e4SLinus Torvalds 	const char * name = dentry->d_name.name;
1881da177e4SLinus Torvalds 	int namelen = dentry->d_name.len;
1891da177e4SLinus Torvalds 	struct page *page = NULL;
1901da177e4SLinus Torvalds 	struct sysv_dir_entry * de;
1911da177e4SLinus Torvalds 	unsigned long npages = dir_pages(dir);
1921da177e4SLinus Torvalds 	unsigned long n;
1931da177e4SLinus Torvalds 	char *kaddr;
19426a6441aSNick Piggin 	loff_t pos;
1951da177e4SLinus Torvalds 	int err;
1961da177e4SLinus Torvalds 
1971da177e4SLinus Torvalds 	/* We take care of directory expansion in the same loop */
1981da177e4SLinus Torvalds 	for (n = 0; n <= npages; n++) {
1998dd6c7b2SFabio M. De Francesco 		kaddr = dir_get_page(dir, n, &page);
2008dd6c7b2SFabio M. De Francesco 		if (IS_ERR(kaddr))
2018dd6c7b2SFabio M. De Francesco 			return PTR_ERR(kaddr);
2021da177e4SLinus Torvalds 		de = (struct sysv_dir_entry *)kaddr;
20309cbfeafSKirill A. Shutemov 		kaddr += PAGE_SIZE - SYSV_DIRSIZE;
2041da177e4SLinus Torvalds 		while ((char *)de <= kaddr) {
2051da177e4SLinus Torvalds 			if (!de->inode)
2061da177e4SLinus Torvalds 				goto got_it;
2071da177e4SLinus Torvalds 			err = -EEXIST;
2081da177e4SLinus Torvalds 			if (namecompare(namelen, SYSV_NAMELEN, name, de->name))
2091da177e4SLinus Torvalds 				goto out_page;
2101da177e4SLinus Torvalds 			de++;
2111da177e4SLinus Torvalds 		}
212d0e13540SFabio M. De Francesco 		unmap_and_put_page(page, kaddr);
2131da177e4SLinus Torvalds 	}
2141da177e4SLinus Torvalds 	BUG();
2151da177e4SLinus Torvalds 	return -EINVAL;
2161da177e4SLinus Torvalds 
2171da177e4SLinus Torvalds got_it:
2184bb1a137SFabio M. De Francesco 	pos = page_offset(page) + offset_in_page(de);
2191da177e4SLinus Torvalds 	lock_page(page);
220f4e420dcSChristoph Hellwig 	err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
2211da177e4SLinus Torvalds 	if (err)
2221da177e4SLinus Torvalds 		goto out_unlock;
2231da177e4SLinus Torvalds 	memcpy (de->name, name, namelen);
2241da177e4SLinus Torvalds 	memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2);
2251da177e4SLinus Torvalds 	de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
2264309093eSChristoph Hellwig 	dir_commit_chunk(page, pos, SYSV_DIRSIZE);
227*c801b095SJeff Layton 	dir->i_mtime = inode_set_ctime_current(dir);
2281da177e4SLinus Torvalds 	mark_inode_dirty(dir);
2294309093eSChristoph Hellwig 	err = sysv_handle_dirsync(dir);
2301da177e4SLinus Torvalds out_page:
231d0e13540SFabio M. De Francesco 	unmap_and_put_page(page, kaddr);
2321da177e4SLinus Torvalds 	return err;
2331da177e4SLinus Torvalds out_unlock:
2341da177e4SLinus Torvalds 	unlock_page(page);
2351da177e4SLinus Torvalds 	goto out_page;
2361da177e4SLinus Torvalds }
2371da177e4SLinus Torvalds 
sysv_delete_entry(struct sysv_dir_entry * de,struct page * page)2381da177e4SLinus Torvalds int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page)
2391da177e4SLinus Torvalds {
240f4e420dcSChristoph Hellwig 	struct inode *inode = page->mapping->host;
2414bb1a137SFabio M. De Francesco 	loff_t pos = page_offset(page) + offset_in_page(de);
2421da177e4SLinus Torvalds 	int err;
2431da177e4SLinus Torvalds 
2441da177e4SLinus Torvalds 	lock_page(page);
245f4e420dcSChristoph Hellwig 	err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
246abb7c742SAl Viro 	if (err) {
247abb7c742SAl Viro 		unlock_page(page);
248abb7c742SAl Viro 		return err;
249abb7c742SAl Viro 	}
2501da177e4SLinus Torvalds 	de->inode = 0;
2514309093eSChristoph Hellwig 	dir_commit_chunk(page, pos, SYSV_DIRSIZE);
252*c801b095SJeff Layton 	inode->i_mtime = inode_set_ctime_current(inode);
2531da177e4SLinus Torvalds 	mark_inode_dirty(inode);
2544309093eSChristoph Hellwig 	return sysv_handle_dirsync(inode);
2551da177e4SLinus Torvalds }
2561da177e4SLinus Torvalds 
sysv_make_empty(struct inode * inode,struct inode * dir)2571da177e4SLinus Torvalds int sysv_make_empty(struct inode *inode, struct inode *dir)
2581da177e4SLinus Torvalds {
259f4e420dcSChristoph Hellwig 	struct page *page = grab_cache_page(inode->i_mapping, 0);
2601da177e4SLinus Torvalds 	struct sysv_dir_entry * de;
2611da177e4SLinus Torvalds 	char *base;
2621da177e4SLinus Torvalds 	int err;
2631da177e4SLinus Torvalds 
2641da177e4SLinus Torvalds 	if (!page)
2651da177e4SLinus Torvalds 		return -ENOMEM;
266f4e420dcSChristoph Hellwig 	err = sysv_prepare_chunk(page, 0, 2 * SYSV_DIRSIZE);
2671da177e4SLinus Torvalds 	if (err) {
2681da177e4SLinus Torvalds 		unlock_page(page);
2691da177e4SLinus Torvalds 		goto fail;
2701da177e4SLinus Torvalds 	}
27183005276SFabio M. De Francesco 	base = kmap_local_page(page);
27209cbfeafSKirill A. Shutemov 	memset(base, 0, PAGE_SIZE);
2731da177e4SLinus Torvalds 
2741da177e4SLinus Torvalds 	de = (struct sysv_dir_entry *) base;
2751da177e4SLinus Torvalds 	de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
2761da177e4SLinus Torvalds 	strcpy(de->name,".");
2771da177e4SLinus Torvalds 	de++;
2781da177e4SLinus Torvalds 	de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), dir->i_ino);
2791da177e4SLinus Torvalds 	strcpy(de->name,"..");
2801da177e4SLinus Torvalds 
28183005276SFabio M. De Francesco 	kunmap_local(base);
2824309093eSChristoph Hellwig 	dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE);
2834309093eSChristoph Hellwig 	err = sysv_handle_dirsync(inode);
2841da177e4SLinus Torvalds fail:
28509cbfeafSKirill A. Shutemov 	put_page(page);
2861da177e4SLinus Torvalds 	return err;
2871da177e4SLinus Torvalds }
2881da177e4SLinus Torvalds 
2891da177e4SLinus Torvalds /*
2901da177e4SLinus Torvalds  * routine to check that the specified directory is empty (for rmdir)
2911da177e4SLinus Torvalds  */
sysv_empty_dir(struct inode * inode)2921da177e4SLinus Torvalds int sysv_empty_dir(struct inode * inode)
2931da177e4SLinus Torvalds {
2941da177e4SLinus Torvalds 	struct super_block *sb = inode->i_sb;
2951da177e4SLinus Torvalds 	struct page *page = NULL;
2961da177e4SLinus Torvalds 	unsigned long i, npages = dir_pages(inode);
29783005276SFabio M. De Francesco 	char *kaddr;
2981da177e4SLinus Torvalds 
2991da177e4SLinus Torvalds 	for (i = 0; i < npages; i++) {
3001da177e4SLinus Torvalds 		struct sysv_dir_entry *de;
3011da177e4SLinus Torvalds 
3028dd6c7b2SFabio M. De Francesco 		kaddr = dir_get_page(inode, i, &page);
3038dd6c7b2SFabio M. De Francesco 		if (IS_ERR(kaddr))
3041da177e4SLinus Torvalds 			continue;
3051da177e4SLinus Torvalds 
3061da177e4SLinus Torvalds 		de = (struct sysv_dir_entry *)kaddr;
30709cbfeafSKirill A. Shutemov 		kaddr += PAGE_SIZE-SYSV_DIRSIZE;
3081da177e4SLinus Torvalds 
3091da177e4SLinus Torvalds 		for ( ;(char *)de <= kaddr; de++) {
3101da177e4SLinus Torvalds 			if (!de->inode)
3111da177e4SLinus Torvalds 				continue;
3121da177e4SLinus Torvalds 			/* check for . and .. */
3131da177e4SLinus Torvalds 			if (de->name[0] != '.')
3141da177e4SLinus Torvalds 				goto not_empty;
3151da177e4SLinus Torvalds 			if (!de->name[1]) {
3161da177e4SLinus Torvalds 				if (de->inode == cpu_to_fs16(SYSV_SB(sb),
3171da177e4SLinus Torvalds 							inode->i_ino))
3181da177e4SLinus Torvalds 					continue;
3191da177e4SLinus Torvalds 				goto not_empty;
3201da177e4SLinus Torvalds 			}
3211da177e4SLinus Torvalds 			if (de->name[1] != '.' || de->name[2])
3221da177e4SLinus Torvalds 				goto not_empty;
3231da177e4SLinus Torvalds 		}
324d0e13540SFabio M. De Francesco 		unmap_and_put_page(page, kaddr);
3251da177e4SLinus Torvalds 	}
3261da177e4SLinus Torvalds 	return 1;
3271da177e4SLinus Torvalds 
3281da177e4SLinus Torvalds not_empty:
329d0e13540SFabio M. De Francesco 	unmap_and_put_page(page, kaddr);
3301da177e4SLinus Torvalds 	return 0;
3311da177e4SLinus Torvalds }
3321da177e4SLinus Torvalds 
3331da177e4SLinus Torvalds /* Releases the page */
sysv_set_link(struct sysv_dir_entry * de,struct page * page,struct inode * inode)334abb7c742SAl Viro int sysv_set_link(struct sysv_dir_entry *de, struct page *page,
3351da177e4SLinus Torvalds 	struct inode *inode)
3361da177e4SLinus Torvalds {
337f4e420dcSChristoph Hellwig 	struct inode *dir = page->mapping->host;
3384bb1a137SFabio M. De Francesco 	loff_t pos = page_offset(page) + offset_in_page(de);
3391da177e4SLinus Torvalds 	int err;
3401da177e4SLinus Torvalds 
3411da177e4SLinus Torvalds 	lock_page(page);
342f4e420dcSChristoph Hellwig 	err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
343abb7c742SAl Viro 	if (err) {
344abb7c742SAl Viro 		unlock_page(page);
345abb7c742SAl Viro 		return err;
346abb7c742SAl Viro 	}
3471da177e4SLinus Torvalds 	de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
3484309093eSChristoph Hellwig 	dir_commit_chunk(page, pos, SYSV_DIRSIZE);
349*c801b095SJeff Layton 	dir->i_mtime = inode_set_ctime_current(dir);
3501da177e4SLinus Torvalds 	mark_inode_dirty(dir);
351abb7c742SAl Viro 	return sysv_handle_dirsync(inode);
3521da177e4SLinus Torvalds }
3531da177e4SLinus Torvalds 
35483005276SFabio M. De Francesco /*
355d0e13540SFabio M. De Francesco  * Calls to dir_get_page()/unmap_and_put_page() must be nested according to the
35683005276SFabio M. De Francesco  * rules documented in mm/highmem.rst.
35783005276SFabio M. De Francesco  *
35883005276SFabio M. De Francesco  * sysv_dotdot() acts as a call to dir_get_page() and must be treated
35983005276SFabio M. De Francesco  * accordingly for nesting purposes.
36083005276SFabio M. De Francesco  */
sysv_dotdot(struct inode * dir,struct page ** p)3611da177e4SLinus Torvalds struct sysv_dir_entry *sysv_dotdot(struct inode *dir, struct page **p)
3621da177e4SLinus Torvalds {
3638dd6c7b2SFabio M. De Francesco 	struct sysv_dir_entry *de = dir_get_page(dir, 0, p);
3641da177e4SLinus Torvalds 
3658dd6c7b2SFabio M. De Francesco 	if (IS_ERR(de))
3668dd6c7b2SFabio M. De Francesco 		return NULL;
3678dd6c7b2SFabio M. De Francesco 	/* ".." is the second directory entry */
3688dd6c7b2SFabio M. De Francesco 	return de + 1;
3691da177e4SLinus Torvalds }
3701da177e4SLinus Torvalds 
sysv_inode_by_name(struct dentry * dentry)3711da177e4SLinus Torvalds ino_t sysv_inode_by_name(struct dentry *dentry)
3721da177e4SLinus Torvalds {
3731da177e4SLinus Torvalds 	struct page *page;
3741da177e4SLinus Torvalds 	struct sysv_dir_entry *de = sysv_find_entry (dentry, &page);
3751da177e4SLinus Torvalds 	ino_t res = 0;
3761da177e4SLinus Torvalds 
3771da177e4SLinus Torvalds 	if (de) {
3781da177e4SLinus Torvalds 		res = fs16_to_cpu(SYSV_SB(dentry->d_sb), de->inode);
379d0e13540SFabio M. De Francesco 		unmap_and_put_page(page, de);
3801da177e4SLinus Torvalds 	}
3811da177e4SLinus Torvalds 	return res;
3821da177e4SLinus Torvalds }
383