xref: /linux/fs/sysv/dir.c (revision 2775df6e5e324be9dc375f7db2c8d3042df72bbf)
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 folio * folio,loff_t pos,unsigned len)3100753fb5SMatthew Wilcox (Oracle) static void dir_commit_chunk(struct folio *folio, loff_t pos, unsigned len)
321da177e4SLinus Torvalds {
3300753fb5SMatthew Wilcox (Oracle) 	struct address_space *mapping = folio->mapping;
3426a6441aSNick Piggin 	struct inode *dir = mapping->host;
351da177e4SLinus Torvalds 
36*97edbc02SMatthew Wilcox (Oracle) 	block_write_end(NULL, mapping, pos, len, len, folio, 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 	}
4100753fb5SMatthew Wilcox (Oracle) 	folio_unlock(folio);
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 /*
55a3b4537fSMatthew Wilcox (Oracle)  * Calls to dir_get_folio()/folio_release_kmap() must be nested according to the
5683005276SFabio M. De Francesco  * rules documented in mm/highmem.rst.
5783005276SFabio M. De Francesco  *
58a3b4537fSMatthew Wilcox (Oracle)  * NOTE: sysv_find_entry() and sysv_dotdot() act as calls to dir_get_folio()
5983005276SFabio M. De Francesco  * and must be treated accordingly for nesting purposes.
6083005276SFabio M. De Francesco  */
dir_get_folio(struct inode * dir,unsigned long n,struct folio ** foliop)61a3b4537fSMatthew Wilcox (Oracle) static void *dir_get_folio(struct inode *dir, unsigned long n,
62a3b4537fSMatthew Wilcox (Oracle) 		struct folio **foliop)
631da177e4SLinus Torvalds {
64a3b4537fSMatthew Wilcox (Oracle) 	struct folio *folio = read_mapping_folio(dir->i_mapping, n, NULL);
65a3b4537fSMatthew Wilcox (Oracle) 
66a3b4537fSMatthew Wilcox (Oracle) 	if (IS_ERR(folio))
67a3b4537fSMatthew Wilcox (Oracle) 		return ERR_CAST(folio);
68a3b4537fSMatthew Wilcox (Oracle) 	*foliop = folio;
69a3b4537fSMatthew Wilcox (Oracle) 	return kmap_local_folio(folio, 0);
701da177e4SLinus Torvalds }
711da177e4SLinus Torvalds 
sysv_readdir(struct file * file,struct dir_context * ctx)7280886298SAl Viro static int sysv_readdir(struct file *file, struct dir_context *ctx)
731da177e4SLinus Torvalds {
7480886298SAl Viro 	unsigned long pos = ctx->pos;
7580886298SAl Viro 	struct inode *inode = file_inode(file);
761da177e4SLinus Torvalds 	struct super_block *sb = inode->i_sb;
771da177e4SLinus Torvalds 	unsigned long npages = dir_pages(inode);
7880886298SAl Viro 	unsigned offset;
7980886298SAl Viro 	unsigned long n;
801da177e4SLinus Torvalds 
8180886298SAl Viro 	ctx->pos = pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1);
821da177e4SLinus Torvalds 	if (pos >= inode->i_size)
8380886298SAl Viro 		return 0;
8480886298SAl Viro 
8509cbfeafSKirill A. Shutemov 	offset = pos & ~PAGE_MASK;
8609cbfeafSKirill A. Shutemov 	n = pos >> PAGE_SHIFT;
871da177e4SLinus Torvalds 
881da177e4SLinus Torvalds 	for ( ; n < npages; n++, offset = 0) {
891da177e4SLinus Torvalds 		char *kaddr, *limit;
901da177e4SLinus Torvalds 		struct sysv_dir_entry *de;
91a3b4537fSMatthew Wilcox (Oracle) 		struct folio *folio;
921da177e4SLinus Torvalds 
93a3b4537fSMatthew Wilcox (Oracle) 		kaddr = dir_get_folio(inode, n, &folio);
948dd6c7b2SFabio M. De Francesco 		if (IS_ERR(kaddr))
951da177e4SLinus Torvalds 			continue;
961da177e4SLinus Torvalds 		de = (struct sysv_dir_entry *)(kaddr+offset);
9709cbfeafSKirill A. Shutemov 		limit = kaddr + PAGE_SIZE - SYSV_DIRSIZE;
9880886298SAl Viro 		for ( ;(char*)de <= limit; de++, ctx->pos += sizeof(*de)) {
991da177e4SLinus Torvalds 			char *name = de->name;
1001da177e4SLinus Torvalds 
1011da177e4SLinus Torvalds 			if (!de->inode)
1021da177e4SLinus Torvalds 				continue;
1031da177e4SLinus Torvalds 
10480886298SAl Viro 			if (!dir_emit(ctx, name, strnlen(name,SYSV_NAMELEN),
1051da177e4SLinus Torvalds 					fs16_to_cpu(SYSV_SB(sb), de->inode),
10680886298SAl Viro 					DT_UNKNOWN)) {
107a3b4537fSMatthew Wilcox (Oracle) 				folio_release_kmap(folio, kaddr);
10880886298SAl Viro 				return 0;
1091da177e4SLinus Torvalds 			}
1101da177e4SLinus Torvalds 		}
111a3b4537fSMatthew Wilcox (Oracle) 		folio_release_kmap(folio, kaddr);
1121da177e4SLinus Torvalds 	}
1131da177e4SLinus Torvalds 	return 0;
1141da177e4SLinus Torvalds }
1151da177e4SLinus Torvalds 
1161da177e4SLinus Torvalds /* compare strings: name[0..len-1] (not zero-terminated) and
1171da177e4SLinus Torvalds  * buffer[0..] (filled with zeroes up to buffer[0..maxlen-1])
1181da177e4SLinus Torvalds  */
namecompare(int len,int maxlen,const char * name,const char * buffer)1191da177e4SLinus Torvalds static inline int namecompare(int len, int maxlen,
1201da177e4SLinus Torvalds 	const char * name, const char * buffer)
1211da177e4SLinus Torvalds {
1221da177e4SLinus Torvalds 	if (len < maxlen && buffer[len])
1231da177e4SLinus Torvalds 		return 0;
1241da177e4SLinus Torvalds 	return !memcmp(name, buffer, len);
1251da177e4SLinus Torvalds }
1261da177e4SLinus Torvalds 
1271da177e4SLinus Torvalds /*
1281da177e4SLinus Torvalds  *	sysv_find_entry()
1291da177e4SLinus Torvalds  *
130ba36ee53SMatthew Wilcox (Oracle)  * finds an entry in the specified directory with the wanted name.
131ba36ee53SMatthew Wilcox (Oracle)  * 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  *
134ba36ee53SMatthew Wilcox (Oracle)  * On Success folio_release_kmap() should be called on *foliop.
13583005276SFabio M. De Francesco  *
136a3b4537fSMatthew Wilcox (Oracle)  * sysv_find_entry() acts as a call to dir_get_folio() and must be treated
13783005276SFabio M. De Francesco  * accordingly for nesting purposes.
1381da177e4SLinus Torvalds  */
sysv_find_entry(struct dentry * dentry,struct folio ** foliop)139ba36ee53SMatthew Wilcox (Oracle) struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct folio **foliop)
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 sysv_dir_entry *de;
1471da177e4SLinus Torvalds 
1481da177e4SLinus Torvalds 	start = SYSV_I(dir)->i_dir_start_lookup;
1491da177e4SLinus Torvalds 	if (start >= npages)
1501da177e4SLinus Torvalds 		start = 0;
1511da177e4SLinus Torvalds 	n = start;
1521da177e4SLinus Torvalds 
1531da177e4SLinus Torvalds 	do {
154ba36ee53SMatthew Wilcox (Oracle) 		char *kaddr = dir_get_folio(dir, n, foliop);
1558dd6c7b2SFabio M. De Francesco 
1568dd6c7b2SFabio M. De Francesco 		if (!IS_ERR(kaddr)) {
1571da177e4SLinus Torvalds 			de = (struct sysv_dir_entry *)kaddr;
158ba36ee53SMatthew Wilcox (Oracle) 			kaddr += folio_size(*foliop) - SYSV_DIRSIZE;
1591da177e4SLinus Torvalds 			for ( ; (char *) de <= kaddr ; de++) {
1601da177e4SLinus Torvalds 				if (!de->inode)
1611da177e4SLinus Torvalds 					continue;
1621da177e4SLinus Torvalds 				if (namecompare(namelen, SYSV_NAMELEN,
1631da177e4SLinus Torvalds 							name, de->name))
1641da177e4SLinus Torvalds 					goto found;
1651da177e4SLinus Torvalds 			}
166ba36ee53SMatthew Wilcox (Oracle) 			folio_release_kmap(*foliop, kaddr);
167404e7812SDan Carpenter 		}
1681da177e4SLinus Torvalds 
1691da177e4SLinus Torvalds 		if (++n >= npages)
1701da177e4SLinus Torvalds 			n = 0;
1711da177e4SLinus Torvalds 	} while (n != start);
1721da177e4SLinus Torvalds 
1731da177e4SLinus Torvalds 	return NULL;
1741da177e4SLinus Torvalds 
1751da177e4SLinus Torvalds found:
1761da177e4SLinus Torvalds 	SYSV_I(dir)->i_dir_start_lookup = n;
1771da177e4SLinus Torvalds 	return de;
1781da177e4SLinus Torvalds }
1791da177e4SLinus Torvalds 
sysv_add_link(struct dentry * dentry,struct inode * inode)1801da177e4SLinus Torvalds int sysv_add_link(struct dentry *dentry, struct inode *inode)
1811da177e4SLinus Torvalds {
1822b0143b5SDavid Howells 	struct inode *dir = d_inode(dentry->d_parent);
1831da177e4SLinus Torvalds 	const char * name = dentry->d_name.name;
1841da177e4SLinus Torvalds 	int namelen = dentry->d_name.len;
185a3b4537fSMatthew Wilcox (Oracle) 	struct folio *folio = NULL;
1861da177e4SLinus Torvalds 	struct sysv_dir_entry * de;
1871da177e4SLinus Torvalds 	unsigned long npages = dir_pages(dir);
1881da177e4SLinus Torvalds 	unsigned long n;
1891da177e4SLinus Torvalds 	char *kaddr;
19026a6441aSNick Piggin 	loff_t pos;
1911da177e4SLinus Torvalds 	int err;
1921da177e4SLinus Torvalds 
1931da177e4SLinus Torvalds 	/* We take care of directory expansion in the same loop */
1941da177e4SLinus Torvalds 	for (n = 0; n <= npages; n++) {
195a3b4537fSMatthew Wilcox (Oracle) 		kaddr = dir_get_folio(dir, n, &folio);
1968dd6c7b2SFabio M. De Francesco 		if (IS_ERR(kaddr))
1978dd6c7b2SFabio M. De Francesco 			return PTR_ERR(kaddr);
1981da177e4SLinus Torvalds 		de = (struct sysv_dir_entry *)kaddr;
19909cbfeafSKirill A. Shutemov 		kaddr += PAGE_SIZE - SYSV_DIRSIZE;
2001da177e4SLinus Torvalds 		while ((char *)de <= kaddr) {
2011da177e4SLinus Torvalds 			if (!de->inode)
2021da177e4SLinus Torvalds 				goto got_it;
2031da177e4SLinus Torvalds 			err = -EEXIST;
2041da177e4SLinus Torvalds 			if (namecompare(namelen, SYSV_NAMELEN, name, de->name))
205a3b4537fSMatthew Wilcox (Oracle) 				goto out_folio;
2061da177e4SLinus Torvalds 			de++;
2071da177e4SLinus Torvalds 		}
208a3b4537fSMatthew Wilcox (Oracle) 		folio_release_kmap(folio, kaddr);
2091da177e4SLinus Torvalds 	}
2101da177e4SLinus Torvalds 	BUG();
2111da177e4SLinus Torvalds 	return -EINVAL;
2121da177e4SLinus Torvalds 
2131da177e4SLinus Torvalds got_it:
214a3b4537fSMatthew Wilcox (Oracle) 	pos = folio_pos(folio) + offset_in_folio(folio, de);
215a3b4537fSMatthew Wilcox (Oracle) 	folio_lock(folio);
216d3a2fa28SMatthew Wilcox (Oracle) 	err = sysv_prepare_chunk(folio, pos, SYSV_DIRSIZE);
2171da177e4SLinus Torvalds 	if (err)
2181da177e4SLinus Torvalds 		goto out_unlock;
2191da177e4SLinus Torvalds 	memcpy (de->name, name, namelen);
2201da177e4SLinus Torvalds 	memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2);
2211da177e4SLinus Torvalds 	de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
22200753fb5SMatthew Wilcox (Oracle) 	dir_commit_chunk(folio, pos, SYSV_DIRSIZE);
223ae3d362aSJeff Layton 	inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
2241da177e4SLinus Torvalds 	mark_inode_dirty(dir);
2254309093eSChristoph Hellwig 	err = sysv_handle_dirsync(dir);
226a3b4537fSMatthew Wilcox (Oracle) out_folio:
227a3b4537fSMatthew Wilcox (Oracle) 	folio_release_kmap(folio, kaddr);
2281da177e4SLinus Torvalds 	return err;
2291da177e4SLinus Torvalds out_unlock:
230a3b4537fSMatthew Wilcox (Oracle) 	folio_unlock(folio);
231a3b4537fSMatthew Wilcox (Oracle) 	goto out_folio;
2321da177e4SLinus Torvalds }
2331da177e4SLinus Torvalds 
sysv_delete_entry(struct sysv_dir_entry * de,struct folio * folio)2349b1cf779SMatthew Wilcox (Oracle) int sysv_delete_entry(struct sysv_dir_entry *de, struct folio *folio)
2351da177e4SLinus Torvalds {
2369b1cf779SMatthew Wilcox (Oracle) 	struct inode *inode = folio->mapping->host;
2379b1cf779SMatthew Wilcox (Oracle) 	loff_t pos = folio_pos(folio) + offset_in_folio(folio, de);
2381da177e4SLinus Torvalds 	int err;
2391da177e4SLinus Torvalds 
2409b1cf779SMatthew Wilcox (Oracle) 	folio_lock(folio);
241d3a2fa28SMatthew Wilcox (Oracle) 	err = sysv_prepare_chunk(folio, pos, SYSV_DIRSIZE);
242abb7c742SAl Viro 	if (err) {
2439b1cf779SMatthew Wilcox (Oracle) 		folio_unlock(folio);
244abb7c742SAl Viro 		return err;
245abb7c742SAl Viro 	}
2461da177e4SLinus Torvalds 	de->inode = 0;
24700753fb5SMatthew Wilcox (Oracle) 	dir_commit_chunk(folio, pos, SYSV_DIRSIZE);
248ae3d362aSJeff Layton 	inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
2491da177e4SLinus Torvalds 	mark_inode_dirty(inode);
2504309093eSChristoph Hellwig 	return sysv_handle_dirsync(inode);
2511da177e4SLinus Torvalds }
2521da177e4SLinus Torvalds 
sysv_make_empty(struct inode * inode,struct inode * dir)2531da177e4SLinus Torvalds int sysv_make_empty(struct inode *inode, struct inode *dir)
2541da177e4SLinus Torvalds {
2557f4fb150SMatthew Wilcox (Oracle) 	struct folio *folio = filemap_grab_folio(inode->i_mapping, 0);
2561da177e4SLinus Torvalds 	struct sysv_dir_entry * de;
2577f4fb150SMatthew Wilcox (Oracle) 	char *kaddr;
2581da177e4SLinus Torvalds 	int err;
2591da177e4SLinus Torvalds 
2607f4fb150SMatthew Wilcox (Oracle) 	if (IS_ERR(folio))
2617f4fb150SMatthew Wilcox (Oracle) 		return PTR_ERR(folio);
262d3a2fa28SMatthew Wilcox (Oracle) 	err = sysv_prepare_chunk(folio, 0, 2 * SYSV_DIRSIZE);
2631da177e4SLinus Torvalds 	if (err) {
2647f4fb150SMatthew Wilcox (Oracle) 		folio_unlock(folio);
2651da177e4SLinus Torvalds 		goto fail;
2661da177e4SLinus Torvalds 	}
2677f4fb150SMatthew Wilcox (Oracle) 	kaddr = kmap_local_folio(folio, 0);
2687f4fb150SMatthew Wilcox (Oracle) 	memset(kaddr, 0, folio_size(folio));
2691da177e4SLinus Torvalds 
2707f4fb150SMatthew Wilcox (Oracle) 	de = (struct sysv_dir_entry *)kaddr;
2711da177e4SLinus Torvalds 	de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
2721da177e4SLinus Torvalds 	strcpy(de->name,".");
2731da177e4SLinus Torvalds 	de++;
2741da177e4SLinus Torvalds 	de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), dir->i_ino);
2751da177e4SLinus Torvalds 	strcpy(de->name,"..");
2761da177e4SLinus Torvalds 
2777f4fb150SMatthew Wilcox (Oracle) 	kunmap_local(kaddr);
27800753fb5SMatthew Wilcox (Oracle) 	dir_commit_chunk(folio, 0, 2 * SYSV_DIRSIZE);
2794309093eSChristoph Hellwig 	err = sysv_handle_dirsync(inode);
2801da177e4SLinus Torvalds fail:
2817f4fb150SMatthew Wilcox (Oracle) 	folio_put(folio);
2821da177e4SLinus Torvalds 	return err;
2831da177e4SLinus Torvalds }
2841da177e4SLinus Torvalds 
2851da177e4SLinus Torvalds /*
2861da177e4SLinus Torvalds  * routine to check that the specified directory is empty (for rmdir)
2871da177e4SLinus Torvalds  */
sysv_empty_dir(struct inode * inode)2881da177e4SLinus Torvalds int sysv_empty_dir(struct inode * inode)
2891da177e4SLinus Torvalds {
2901da177e4SLinus Torvalds 	struct super_block *sb = inode->i_sb;
291a3b4537fSMatthew Wilcox (Oracle) 	struct folio *folio = NULL;
2921da177e4SLinus Torvalds 	unsigned long i, npages = dir_pages(inode);
29383005276SFabio M. De Francesco 	char *kaddr;
2941da177e4SLinus Torvalds 
2951da177e4SLinus Torvalds 	for (i = 0; i < npages; i++) {
2961da177e4SLinus Torvalds 		struct sysv_dir_entry *de;
2971da177e4SLinus Torvalds 
298a3b4537fSMatthew Wilcox (Oracle) 		kaddr = dir_get_folio(inode, i, &folio);
2998dd6c7b2SFabio M. De Francesco 		if (IS_ERR(kaddr))
3001da177e4SLinus Torvalds 			continue;
3011da177e4SLinus Torvalds 
3021da177e4SLinus Torvalds 		de = (struct sysv_dir_entry *)kaddr;
303a3b4537fSMatthew Wilcox (Oracle) 		kaddr += folio_size(folio) - SYSV_DIRSIZE;
3041da177e4SLinus Torvalds 
3051da177e4SLinus Torvalds 		for ( ;(char *)de <= kaddr; de++) {
3061da177e4SLinus Torvalds 			if (!de->inode)
3071da177e4SLinus Torvalds 				continue;
3081da177e4SLinus Torvalds 			/* check for . and .. */
3091da177e4SLinus Torvalds 			if (de->name[0] != '.')
3101da177e4SLinus Torvalds 				goto not_empty;
3111da177e4SLinus Torvalds 			if (!de->name[1]) {
3121da177e4SLinus Torvalds 				if (de->inode == cpu_to_fs16(SYSV_SB(sb),
3131da177e4SLinus Torvalds 							inode->i_ino))
3141da177e4SLinus Torvalds 					continue;
3151da177e4SLinus Torvalds 				goto not_empty;
3161da177e4SLinus Torvalds 			}
3171da177e4SLinus Torvalds 			if (de->name[1] != '.' || de->name[2])
3181da177e4SLinus Torvalds 				goto not_empty;
3191da177e4SLinus Torvalds 		}
320a3b4537fSMatthew Wilcox (Oracle) 		folio_release_kmap(folio, kaddr);
3211da177e4SLinus Torvalds 	}
3221da177e4SLinus Torvalds 	return 1;
3231da177e4SLinus Torvalds 
3241da177e4SLinus Torvalds not_empty:
325a3b4537fSMatthew Wilcox (Oracle) 	folio_release_kmap(folio, kaddr);
3261da177e4SLinus Torvalds 	return 0;
3271da177e4SLinus Torvalds }
3281da177e4SLinus Torvalds 
3291da177e4SLinus Torvalds /* Releases the page */
sysv_set_link(struct sysv_dir_entry * de,struct folio * folio,struct inode * inode)3301cfdaf97SMatthew Wilcox (Oracle) int sysv_set_link(struct sysv_dir_entry *de, struct folio *folio,
3311da177e4SLinus Torvalds 		struct inode *inode)
3321da177e4SLinus Torvalds {
3331cfdaf97SMatthew Wilcox (Oracle) 	struct inode *dir = folio->mapping->host;
3341cfdaf97SMatthew Wilcox (Oracle) 	loff_t pos = folio_pos(folio) + offset_in_folio(folio, de);
3351da177e4SLinus Torvalds 	int err;
3361da177e4SLinus Torvalds 
3371cfdaf97SMatthew Wilcox (Oracle) 	folio_lock(folio);
338d3a2fa28SMatthew Wilcox (Oracle) 	err = sysv_prepare_chunk(folio, pos, SYSV_DIRSIZE);
339abb7c742SAl Viro 	if (err) {
3401cfdaf97SMatthew Wilcox (Oracle) 		folio_unlock(folio);
341abb7c742SAl Viro 		return err;
342abb7c742SAl Viro 	}
3431da177e4SLinus Torvalds 	de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
34400753fb5SMatthew Wilcox (Oracle) 	dir_commit_chunk(folio, pos, SYSV_DIRSIZE);
345ae3d362aSJeff Layton 	inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
3461da177e4SLinus Torvalds 	mark_inode_dirty(dir);
347abb7c742SAl Viro 	return sysv_handle_dirsync(inode);
3481da177e4SLinus Torvalds }
3491da177e4SLinus Torvalds 
35083005276SFabio M. De Francesco /*
351a3b4537fSMatthew Wilcox (Oracle)  * Calls to dir_get_folio()/folio_release_kmap() must be nested according to the
35283005276SFabio M. De Francesco  * rules documented in mm/highmem.rst.
35383005276SFabio M. De Francesco  *
354a3b4537fSMatthew Wilcox (Oracle)  * sysv_dotdot() acts as a call to dir_get_folio() and must be treated
35583005276SFabio M. De Francesco  * accordingly for nesting purposes.
35683005276SFabio M. De Francesco  */
sysv_dotdot(struct inode * dir,struct folio ** foliop)3571cfdaf97SMatthew Wilcox (Oracle) struct sysv_dir_entry *sysv_dotdot(struct inode *dir, struct folio **foliop)
3581da177e4SLinus Torvalds {
3591cfdaf97SMatthew Wilcox (Oracle) 	struct sysv_dir_entry *de = dir_get_folio(dir, 0, foliop);
3601da177e4SLinus Torvalds 
3618dd6c7b2SFabio M. De Francesco 	if (IS_ERR(de))
3628dd6c7b2SFabio M. De Francesco 		return NULL;
3638dd6c7b2SFabio M. De Francesco 	/* ".." is the second directory entry */
3648dd6c7b2SFabio M. De Francesco 	return de + 1;
3651da177e4SLinus Torvalds }
3661da177e4SLinus Torvalds 
sysv_inode_by_name(struct dentry * dentry)3671da177e4SLinus Torvalds ino_t sysv_inode_by_name(struct dentry *dentry)
3681da177e4SLinus Torvalds {
369ba36ee53SMatthew Wilcox (Oracle) 	struct folio *folio;
370ba36ee53SMatthew Wilcox (Oracle) 	struct sysv_dir_entry *de = sysv_find_entry (dentry, &folio);
3711da177e4SLinus Torvalds 	ino_t res = 0;
3721da177e4SLinus Torvalds 
3731da177e4SLinus Torvalds 	if (de) {
3741da177e4SLinus Torvalds 		res = fs16_to_cpu(SYSV_SB(dentry->d_sb), de->inode);
375ba36ee53SMatthew Wilcox (Oracle) 		folio_release_kmap(folio, de);
3761da177e4SLinus Torvalds 	}
3771da177e4SLinus Torvalds 	return res;
3781da177e4SLinus Torvalds }
379