VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
59bd9ded4d780 (Thomas Gleixner   2019-05-28 10:10:12 -0700   1) // SPDX-License-Identifier: GPL-2.0-only
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700   2) /*
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700   3)  * OMFS (as used by RIO Karma) directory operations.
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700   4)  * Copyright (C) 2005 Bob Copeland <me@bobcopeland.com>
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700   5)  */
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700   6) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700   7) #include <linux/fs.h>
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700   8) #include <linux/ctype.h>
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700   9) #include <linux/buffer_head.h>
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  10) #include "omfs.h"
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  11) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  12) static int omfs_hash(const char *name, int namelen, int mod)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  13) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  14) 	int i, hash = 0;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  15) 	for (i = 0; i < namelen; i++)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  16) 		hash ^= tolower(name[i]) << (i % 24);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  17) 	return hash % mod;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  18) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  19) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  20) /*
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  21)  * Finds the bucket for a given name and reads the containing block;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  22)  * *ofs is set to the offset of the first list entry.
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  23)  */
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  24) static struct buffer_head *omfs_get_bucket(struct inode *dir,
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  25) 		const char *name, int namelen, int *ofs)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  26) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  27) 	int nbuckets = (dir->i_size - OMFS_DIR_START)/8;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  28) 	int bucket = omfs_hash(name, namelen, nbuckets);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  29) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  30) 	*ofs = OMFS_DIR_START + bucket * 8;
f068272cb2f13 (Bob Copeland      2008-09-06 17:51:53 -0400  31) 	return omfs_bread(dir->i_sb, dir->i_ino);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  32) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  33) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  34) static struct buffer_head *omfs_scan_list(struct inode *dir, u64 block,
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  35) 				const char *name, int namelen,
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  36) 				u64 *prev_block)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  37) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  38) 	struct buffer_head *bh;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  39) 	struct omfs_inode *oi;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  40) 	int err = -ENOENT;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  41) 	*prev_block = ~0;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  42) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  43) 	while (block != ~0) {
f068272cb2f13 (Bob Copeland      2008-09-06 17:51:53 -0400  44) 		bh = omfs_bread(dir->i_sb, block);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  45) 		if (!bh) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  46) 			err = -EIO;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  47) 			goto err;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  48) 		}
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  49) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  50) 		oi = (struct omfs_inode *) bh->b_data;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  51) 		if (omfs_is_bad(OMFS_SB(dir->i_sb), &oi->i_head, block)) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  52) 			brelse(bh);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  53) 			goto err;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  54) 		}
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  55) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  56) 		if (strncmp(oi->i_name, name, namelen) == 0)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  57) 			return bh;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  58) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  59) 		*prev_block = block;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  60) 		block = be64_to_cpu(oi->i_sibling);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  61) 		brelse(bh);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  62) 	}
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  63) err:
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  64) 	return ERR_PTR(err);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  65) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  66) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  67) static struct buffer_head *omfs_find_entry(struct inode *dir,
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  68) 					   const char *name, int namelen)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  69) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  70) 	struct buffer_head *bh;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  71) 	int ofs;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  72) 	u64 block, dummy;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  73) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  74) 	bh = omfs_get_bucket(dir, name, namelen, &ofs);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  75) 	if (!bh)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  76) 		return ERR_PTR(-EIO);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  77) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  78) 	block = be64_to_cpu(*((__be64 *) &bh->b_data[ofs]));
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  79) 	brelse(bh);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  80) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  81) 	return omfs_scan_list(dir, block, name, namelen, &dummy);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  82) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  83) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  84) int omfs_make_empty(struct inode *inode, struct super_block *sb)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  85) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  86) 	struct omfs_sb_info *sbi = OMFS_SB(sb);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  87) 	struct buffer_head *bh;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  88) 	struct omfs_inode *oi;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  89) 
f068272cb2f13 (Bob Copeland      2008-09-06 17:51:53 -0400  90) 	bh = omfs_bread(sb, inode->i_ino);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  91) 	if (!bh)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  92) 		return -ENOMEM;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  93) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  94) 	memset(bh->b_data, 0, sizeof(struct omfs_inode));
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  95) 
41c96486f238e (Al Viro           2011-07-26 02:34:33 -0400  96) 	if (S_ISDIR(inode->i_mode)) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  97) 		memset(&bh->b_data[OMFS_DIR_START], 0xff,
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  98) 			sbi->s_sys_blocksize - OMFS_DIR_START);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700  99) 	} else
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 100) 		omfs_make_empty_table(bh, OMFS_EXTENT_START);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 101) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 102) 	oi = (struct omfs_inode *) bh->b_data;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 103) 	oi->i_head.h_self = cpu_to_be64(inode->i_ino);
d406f66ddb0d7 (Harvey Harrison   2008-07-29 22:33:46 -0700 104) 	oi->i_sibling = ~cpu_to_be64(0ULL);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 105) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 106) 	mark_buffer_dirty(bh);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 107) 	brelse(bh);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 108) 	return 0;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 109) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 110) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 111) static int omfs_add_link(struct dentry *dentry, struct inode *inode)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 112) {
2b0143b5c986b (David Howells     2015-03-17 22:25:59 +0000 113) 	struct inode *dir = d_inode(dentry->d_parent);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 114) 	const char *name = dentry->d_name.name;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 115) 	int namelen = dentry->d_name.len;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 116) 	struct omfs_inode *oi;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 117) 	struct buffer_head *bh;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 118) 	u64 block;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 119) 	__be64 *entry;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 120) 	int ofs;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 121) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 122) 	/* just prepend to head of queue in proper bucket */
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 123) 	bh = omfs_get_bucket(dir, name, namelen, &ofs);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 124) 	if (!bh)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 125) 		goto out;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 126) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 127) 	entry = (__be64 *) &bh->b_data[ofs];
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 128) 	block = be64_to_cpu(*entry);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 129) 	*entry = cpu_to_be64(inode->i_ino);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 130) 	mark_buffer_dirty(bh);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 131) 	brelse(bh);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 132) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 133) 	/* now set the sibling and parent pointers on the new inode */
f068272cb2f13 (Bob Copeland      2008-09-06 17:51:53 -0400 134) 	bh = omfs_bread(dir->i_sb, inode->i_ino);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 135) 	if (!bh)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 136) 		goto out;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 137) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 138) 	oi = (struct omfs_inode *) bh->b_data;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 139) 	memcpy(oi->i_name, name, namelen);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 140) 	memset(oi->i_name + namelen, 0, OMFS_NAMELEN - namelen);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 141) 	oi->i_sibling = cpu_to_be64(block);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 142) 	oi->i_parent = cpu_to_be64(dir->i_ino);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 143) 	mark_buffer_dirty(bh);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 144) 	brelse(bh);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 145) 
02027d42c3f74 (Deepa Dinamani    2016-09-14 07:48:05 -0700 146) 	dir->i_ctime = current_time(dir);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 147) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 148) 	/* mark affected inodes dirty to rebuild checksums */
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 149) 	mark_inode_dirty(dir);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 150) 	mark_inode_dirty(inode);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 151) 	return 0;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 152) out:
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 153) 	return -ENOMEM;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 154) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 155) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 156) static int omfs_delete_entry(struct dentry *dentry)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 157) {
2b0143b5c986b (David Howells     2015-03-17 22:25:59 +0000 158) 	struct inode *dir = d_inode(dentry->d_parent);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 159) 	struct inode *dirty;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 160) 	const char *name = dentry->d_name.name;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 161) 	int namelen = dentry->d_name.len;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 162) 	struct omfs_inode *oi;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 163) 	struct buffer_head *bh, *bh2;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 164) 	__be64 *entry, next;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 165) 	u64 block, prev;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 166) 	int ofs;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 167) 	int err = -ENOMEM;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 168) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 169) 	/* delete the proper node in the bucket's linked list */
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 170) 	bh = omfs_get_bucket(dir, name, namelen, &ofs);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 171) 	if (!bh)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 172) 		goto out;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 173) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 174) 	entry = (__be64 *) &bh->b_data[ofs];
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 175) 	block = be64_to_cpu(*entry);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 176) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 177) 	bh2 = omfs_scan_list(dir, block, name, namelen, &prev);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 178) 	if (IS_ERR(bh2)) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 179) 		err = PTR_ERR(bh2);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 180) 		goto out_free_bh;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 181) 	}
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 182) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 183) 	oi = (struct omfs_inode *) bh2->b_data;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 184) 	next = oi->i_sibling;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 185) 	brelse(bh2);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 186) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 187) 	if (prev != ~0) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 188) 		/* found in middle of list, get list ptr */
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 189) 		brelse(bh);
f068272cb2f13 (Bob Copeland      2008-09-06 17:51:53 -0400 190) 		bh = omfs_bread(dir->i_sb, prev);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 191) 		if (!bh)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 192) 			goto out;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 193) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 194) 		oi = (struct omfs_inode *) bh->b_data;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 195) 		entry = &oi->i_sibling;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 196) 	}
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 197) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 198) 	*entry = next;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 199) 	mark_buffer_dirty(bh);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 200) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 201) 	if (prev != ~0) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 202) 		dirty = omfs_iget(dir->i_sb, prev);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 203) 		if (!IS_ERR(dirty)) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 204) 			mark_inode_dirty(dirty);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 205) 			iput(dirty);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 206) 		}
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 207) 	}
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 208) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 209) 	err = 0;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 210) out_free_bh:
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 211) 	brelse(bh);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 212) out:
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 213) 	return err;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 214) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 215) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 216) static int omfs_dir_is_empty(struct inode *inode)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 217) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 218) 	int nbuckets = (inode->i_size - OMFS_DIR_START) / 8;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 219) 	struct buffer_head *bh;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 220) 	u64 *ptr;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 221) 	int i;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 222) 
f068272cb2f13 (Bob Copeland      2008-09-06 17:51:53 -0400 223) 	bh = omfs_bread(inode->i_sb, inode->i_ino);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 224) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 225) 	if (!bh)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 226) 		return 0;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 227) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 228) 	ptr = (u64 *) &bh->b_data[OMFS_DIR_START];
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 229) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 230) 	for (i = 0; i < nbuckets; i++, ptr++)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 231) 		if (*ptr != ~0)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 232) 			break;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 233) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 234) 	brelse(bh);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 235) 	return *ptr != ~0;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 236) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 237) 
d932805b3dc8c (Al Viro           2011-03-04 01:31:03 -0500 238) static int omfs_remove(struct inode *dir, struct dentry *dentry)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 239) {
2b0143b5c986b (David Howells     2015-03-17 22:25:59 +0000 240) 	struct inode *inode = d_inode(dentry);
d932805b3dc8c (Al Viro           2011-03-04 01:31:03 -0500 241) 	int ret;
d932805b3dc8c (Al Viro           2011-03-04 01:31:03 -0500 242) 
79bf7c732b5ff (Sage Weil         2011-05-24 13:06:06 -0700 243) 
8aaa0f5431d8d (Sage Weil         2011-05-27 13:42:04 -0700 244) 	if (S_ISDIR(inode->i_mode) &&
8aaa0f5431d8d (Sage Weil         2011-05-27 13:42:04 -0700 245) 	    !omfs_dir_is_empty(inode))
8aaa0f5431d8d (Sage Weil         2011-05-27 13:42:04 -0700 246) 		return -ENOTEMPTY;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 247) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 248) 	ret = omfs_delete_entry(dentry);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 249) 	if (ret)
d932805b3dc8c (Al Viro           2011-03-04 01:31:03 -0500 250) 		return ret;
d932805b3dc8c (Al Viro           2011-03-04 01:31:03 -0500 251) 	
d932805b3dc8c (Al Viro           2011-03-04 01:31:03 -0500 252) 	clear_nlink(inode);
d932805b3dc8c (Al Viro           2011-03-04 01:31:03 -0500 253) 	mark_inode_dirty(inode);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 254) 	mark_inode_dirty(dir);
d932805b3dc8c (Al Viro           2011-03-04 01:31:03 -0500 255) 	return 0;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 256) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 257) 
587228be4a43c (Al Viro           2011-07-24 22:58:10 -0400 258) static int omfs_add_node(struct inode *dir, struct dentry *dentry, umode_t mode)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 259) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 260) 	int err;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 261) 	struct inode *inode = omfs_new_inode(dir, mode);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 262) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 263) 	if (IS_ERR(inode))
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 264) 		return PTR_ERR(inode);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 265) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 266) 	err = omfs_make_empty(inode, dir->i_sb);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 267) 	if (err)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 268) 		goto out_free_inode;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 269) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 270) 	err = omfs_add_link(dentry, inode);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 271) 	if (err)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 272) 		goto out_free_inode;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 273) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 274) 	d_instantiate(dentry, inode);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 275) 	return 0;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 276) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 277) out_free_inode:
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 278) 	iput(inode);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 279) 	return err;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 280) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 281) 
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 282) static int omfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 283) 		      struct dentry *dentry, umode_t mode)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 284) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 285) 	return omfs_add_node(dir, dentry, mode | S_IFDIR);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 286) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 287) 
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 288) static int omfs_create(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 289) 		       struct dentry *dentry, umode_t mode, bool excl)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 290) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 291) 	return omfs_add_node(dir, dentry, mode | S_IFREG);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 292) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 293) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 294) static struct dentry *omfs_lookup(struct inode *dir, struct dentry *dentry,
00cd8dd3bf95f (Al Viro           2012-06-10 17:13:09 -0400 295) 				  unsigned int flags)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 296) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 297) 	struct buffer_head *bh;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 298) 	struct inode *inode = NULL;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 299) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 300) 	if (dentry->d_name.len > OMFS_NAMELEN)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 301) 		return ERR_PTR(-ENAMETOOLONG);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 302) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 303) 	bh = omfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 304) 	if (!IS_ERR(bh)) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 305) 		struct omfs_inode *oi = (struct omfs_inode *)bh->b_data;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 306) 		ino_t ino = be64_to_cpu(oi->i_head.h_self);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 307) 		brelse(bh);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 308) 		inode = omfs_iget(dir->i_sb, ino);
18fbbfc2bfab4 (Al Viro           2018-04-30 20:00:22 -0400 309) 	} else if (bh != ERR_PTR(-ENOENT)) {
18fbbfc2bfab4 (Al Viro           2018-04-30 20:00:22 -0400 310) 		inode = ERR_CAST(bh);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 311) 	}
18fbbfc2bfab4 (Al Viro           2018-04-30 20:00:22 -0400 312) 	return d_splice_alias(inode, dentry);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 313) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 314) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 315) /* sanity check block's self pointer */
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 316) int omfs_is_bad(struct omfs_sb_info *sbi, struct omfs_header *header,
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 317) 	u64 fsblock)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 318) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 319) 	int is_bad;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 320) 	u64 ino = be64_to_cpu(header->h_self);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 321) 	is_bad = ((ino != fsblock) || (ino < sbi->s_root_ino) ||
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 322) 		(ino > sbi->s_num_blocks));
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 323) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 324) 	if (is_bad)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 325) 		printk(KERN_WARNING "omfs: bad hash chain detected\n");
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 326) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 327) 	return is_bad;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 328) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 329) 
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 330) static bool omfs_fill_chain(struct inode *dir, struct dir_context *ctx,
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 331) 		u64 fsblock, int hindex)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 332) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 333) 	/* follow chain in this bucket */
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 334) 	while (fsblock != ~0) {
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 335) 		struct buffer_head *bh = omfs_bread(dir->i_sb, fsblock);
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 336) 		struct omfs_inode *oi;
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 337) 		u64 self;
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 338) 		unsigned char d_type;
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 339) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 340) 		if (!bh)
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 341) 			return true;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 342) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 343) 		oi = (struct omfs_inode *) bh->b_data;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 344) 		if (omfs_is_bad(OMFS_SB(dir->i_sb), &oi->i_head, fsblock)) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 345) 			brelse(bh);
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 346) 			return true;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 347) 		}
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 348) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 349) 		self = fsblock;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 350) 		fsblock = be64_to_cpu(oi->i_sibling);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 351) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 352) 		/* skip visited nodes */
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 353) 		if (hindex) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 354) 			hindex--;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 355) 			brelse(bh);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 356) 			continue;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 357) 		}
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 358) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 359) 		d_type = (oi->i_type == OMFS_DIR) ? DT_DIR : DT_REG;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 360) 
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 361) 		if (!dir_emit(ctx, oi->i_name,
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 362) 			      strnlen(oi->i_name, OMFS_NAMELEN),
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 363) 			      self, d_type)) {
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 364) 			brelse(bh);
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 365) 			return false;
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 366) 		}
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 367) 		brelse(bh);
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 368) 		ctx->pos++;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 369) 	}
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 370) 	return true;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 371) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 372) 
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 373) static int omfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 374) 		       struct dentry *old_dentry, struct inode *new_dir,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 375) 		       struct dentry *new_dentry, unsigned int flags)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 376) {
2b0143b5c986b (David Howells     2015-03-17 22:25:59 +0000 377) 	struct inode *new_inode = d_inode(new_dentry);
2b0143b5c986b (David Howells     2015-03-17 22:25:59 +0000 378) 	struct inode *old_inode = d_inode(old_dentry);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 379) 	int err;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 380) 
f03b8ad8d3863 (Miklos Szeredi    2016-09-27 11:03:57 +0200 381) 	if (flags & ~RENAME_NOREPLACE)
f03b8ad8d3863 (Miklos Szeredi    2016-09-27 11:03:57 +0200 382) 		return -EINVAL;
f03b8ad8d3863 (Miklos Szeredi    2016-09-27 11:03:57 +0200 383) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 384) 	if (new_inode) {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 385) 		/* overwriting existing file/dir */
d932805b3dc8c (Al Viro           2011-03-04 01:31:03 -0500 386) 		err = omfs_remove(new_dir, new_dentry);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 387) 		if (err)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 388) 			goto out;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 389) 	}
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 390) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 391) 	/* since omfs locates files by name, we need to unlink _before_
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 392) 	 * adding the new link or we won't find the old one */
cdb26496dba00 (Al Viro           2011-03-04 01:18:19 -0500 393) 	err = omfs_delete_entry(old_dentry);
cdb26496dba00 (Al Viro           2011-03-04 01:18:19 -0500 394) 	if (err)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 395) 		goto out;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 396) 
cdb26496dba00 (Al Viro           2011-03-04 01:18:19 -0500 397) 	mark_inode_dirty(old_dir);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 398) 	err = omfs_add_link(new_dentry, old_inode);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 399) 	if (err)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 400) 		goto out;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 401) 
02027d42c3f74 (Deepa Dinamani    2016-09-14 07:48:05 -0700 402) 	old_inode->i_ctime = current_time(old_inode);
013e4f4a285d8 (Al Viro           2011-03-04 01:14:55 -0500 403) 	mark_inode_dirty(old_inode);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 404) out:
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 405) 	return err;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 406) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 407) 
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 408) static int omfs_readdir(struct file *file, struct dir_context *ctx)
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 409) {
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 410) 	struct inode *dir = file_inode(file);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 411) 	struct buffer_head *bh;
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 412) 	__be64 *p;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 413) 	unsigned int hchain, hindex;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 414) 	int nbuckets;
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 415) 
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 416) 	if (ctx->pos >> 32)
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 417) 		return -EINVAL;
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 418) 
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 419) 	if (ctx->pos < 1 << 20) {
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 420) 		if (!dir_emit_dots(file, ctx))
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 421) 			return 0;
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 422) 		ctx->pos = 1 << 20;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 423) 	}
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 424) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 425) 	nbuckets = (dir->i_size - OMFS_DIR_START) / 8;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 426) 
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 427) 	/* high 12 bits store bucket + 1 and low 20 bits store hash index */
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 428) 	hchain = (ctx->pos >> 20) - 1;
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 429) 	hindex = ctx->pos & 0xfffff;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 430) 
f068272cb2f13 (Bob Copeland      2008-09-06 17:51:53 -0400 431) 	bh = omfs_bread(dir->i_sb, dir->i_ino);
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 432) 	if (!bh)
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 433) 		return -EINVAL;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 434) 
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 435) 	p = (__be64 *)(bh->b_data + OMFS_DIR_START) + hchain;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 436) 
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 437) 	for (; hchain < nbuckets; hchain++) {
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 438) 		__u64 fsblock = be64_to_cpu(*p++);
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 439) 		if (!omfs_fill_chain(dir, ctx, fsblock, hindex))
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 440) 			break;
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 441) 		hindex = 0;
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 442) 		ctx->pos = (hchain+2) << 20;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 443) 	}
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 444) 	brelse(bh);
9fd4d05949d58 (Al Viro           2013-05-17 15:05:25 -0400 445) 	return 0;
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 446) }
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 447) 
6e1d5dcc2bbbe (Alexey Dobriyan   2009-09-21 17:01:11 -0700 448) const struct inode_operations omfs_dir_inops = {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 449) 	.lookup = omfs_lookup,
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 450) 	.mkdir = omfs_mkdir,
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 451) 	.rename = omfs_rename,
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 452) 	.create = omfs_create,
d932805b3dc8c (Al Viro           2011-03-04 01:31:03 -0500 453) 	.unlink = omfs_remove,
d932805b3dc8c (Al Viro           2011-03-04 01:31:03 -0500 454) 	.rmdir = omfs_remove,
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 455) };
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 456) 
828c09509b969 (Alexey Dobriyan   2009-10-01 15:43:56 -0700 457) const struct file_operations omfs_dir_operations = {
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 458) 	.read = generic_read_dir,
c51da20c48b76 (Al Viro           2016-04-30 22:37:34 -0400 459) 	.iterate_shared = omfs_readdir,
3222a3e55f402 (Christoph Hellwig 2008-09-03 21:53:01 +0200 460) 	.llseek = generic_file_llseek,
a3ab7155ea21a (Bob Copeland      2008-07-25 19:45:16 -0700 461) };