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) };