^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * fs/bfs/dir.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * BFS directory operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1999-2018 Tigran Aivazian <aivazian.tigran@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Made endianness-clean by Andrew Stribblehill <ads@wompom.org> 2005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/buffer_head.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "bfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #undef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define dprintf(x...) printf(x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define dprintf(x...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static int bfs_add_entry(struct inode *dir, const struct qstr *child, int ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static struct buffer_head *bfs_find_entry(struct inode *dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) const struct qstr *child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct bfs_dirent **res_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static int bfs_readdir(struct file *f, struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct inode *dir = file_inode(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct buffer_head *bh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct bfs_dirent *de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) unsigned int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) int block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (ctx->pos & (BFS_DIRENT_SIZE - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) printf("Bad f_pos=%08lx for %s:%08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) (unsigned long)ctx->pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) dir->i_sb->s_id, dir->i_ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) while (ctx->pos < dir->i_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) offset = ctx->pos & (BFS_BSIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) block = BFS_I(dir)->i_sblock + (ctx->pos >> BFS_BSIZE_BITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) bh = sb_bread(dir->i_sb, block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (!bh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) ctx->pos += BFS_BSIZE - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) de = (struct bfs_dirent *)(bh->b_data + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (de->ino) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int size = strnlen(de->name, BFS_NAMELEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (!dir_emit(ctx, de->name, size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) le16_to_cpu(de->ino),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) DT_UNKNOWN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) offset += BFS_DIRENT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) ctx->pos += BFS_DIRENT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) } while ((offset < BFS_BSIZE) && (ctx->pos < dir->i_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) const struct file_operations bfs_dir_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .read = generic_read_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .iterate_shared = bfs_readdir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .fsync = generic_file_fsync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .llseek = generic_file_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) bool excl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct super_block *s = dir->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct bfs_sb_info *info = BFS_SB(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) unsigned long ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) inode = new_inode(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) mutex_lock(&info->bfs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) ino = find_first_zero_bit(info->si_imap, info->si_lasti + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (ino > info->si_lasti) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) mutex_unlock(&info->bfs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) iput(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) set_bit(ino, info->si_imap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) info->si_freei--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) inode_init_owner(inode, dir, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) inode->i_blocks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) inode->i_op = &bfs_file_inops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) inode->i_fop = &bfs_file_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) inode->i_mapping->a_ops = &bfs_aops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) inode->i_ino = ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) BFS_I(inode)->i_dsk_ino = ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) BFS_I(inode)->i_sblock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) BFS_I(inode)->i_eblock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) insert_inode_hash(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) mark_inode_dirty(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) bfs_dump_imap("create", s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) err = bfs_add_entry(dir, &dentry->d_name, inode->i_ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) inode_dec_link_count(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) mutex_unlock(&info->bfs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) iput(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) mutex_unlock(&info->bfs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) d_instantiate(dentry, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct inode *inode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct buffer_head *bh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct bfs_dirent *de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct bfs_sb_info *info = BFS_SB(dir->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (dentry->d_name.len > BFS_NAMELEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return ERR_PTR(-ENAMETOOLONG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) mutex_lock(&info->bfs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) bh = bfs_find_entry(dir, &dentry->d_name, &de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (bh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) unsigned long ino = (unsigned long)le16_to_cpu(de->ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) inode = bfs_iget(dir->i_sb, ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) mutex_unlock(&info->bfs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return d_splice_alias(inode, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static int bfs_link(struct dentry *old, struct inode *dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct dentry *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct inode *inode = d_inode(old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct bfs_sb_info *info = BFS_SB(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) mutex_lock(&info->bfs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) err = bfs_add_entry(dir, &new->d_name, inode->i_ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) mutex_unlock(&info->bfs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) inc_nlink(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) inode->i_ctime = current_time(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) mark_inode_dirty(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ihold(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) d_instantiate(new, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) mutex_unlock(&info->bfs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static int bfs_unlink(struct inode *dir, struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) int error = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct inode *inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct buffer_head *bh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct bfs_dirent *de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct bfs_sb_info *info = BFS_SB(inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) mutex_lock(&info->bfs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) bh = bfs_find_entry(dir, &dentry->d_name, &de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (!bh || (le16_to_cpu(de->ino) != inode->i_ino))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) goto out_brelse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (!inode->i_nlink) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) printf("unlinking non-existent file %s:%lu (nlink=%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) inode->i_sb->s_id, inode->i_ino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) inode->i_nlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) set_nlink(inode, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) de->ino = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) mark_buffer_dirty_inode(bh, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) dir->i_ctime = dir->i_mtime = current_time(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) mark_inode_dirty(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) inode->i_ctime = dir->i_ctime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) inode_dec_link_count(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) out_brelse:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) mutex_unlock(&info->bfs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct inode *new_dir, struct dentry *new_dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct inode *old_inode, *new_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct buffer_head *old_bh, *new_bh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct bfs_dirent *old_de, *new_de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct bfs_sb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) int error = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (flags & ~RENAME_NOREPLACE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) old_bh = new_bh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) old_inode = d_inode(old_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (S_ISDIR(old_inode->i_mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) info = BFS_SB(old_inode->i_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) mutex_lock(&info->bfs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) old_bh = bfs_find_entry(old_dir, &old_dentry->d_name, &old_de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (!old_bh || (le16_to_cpu(old_de->ino) != old_inode->i_ino))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) goto end_rename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) new_inode = d_inode(new_dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) new_bh = bfs_find_entry(new_dir, &new_dentry->d_name, &new_de);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (new_bh && !new_inode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) brelse(new_bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) new_bh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (!new_bh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) error = bfs_add_entry(new_dir, &new_dentry->d_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) old_inode->i_ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) goto end_rename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) old_de->ino = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) mark_inode_dirty(old_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (new_inode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) new_inode->i_ctime = current_time(new_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) inode_dec_link_count(new_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) mark_buffer_dirty_inode(old_bh, old_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) end_rename:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) mutex_unlock(&info->bfs_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) brelse(old_bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) brelse(new_bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) const struct inode_operations bfs_dir_inops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .create = bfs_create,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) .lookup = bfs_lookup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .link = bfs_link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .unlink = bfs_unlink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .rename = bfs_rename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static int bfs_add_entry(struct inode *dir, const struct qstr *child, int ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) const unsigned char *name = child->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) int namelen = child->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct buffer_head *bh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct bfs_dirent *de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) int block, sblock, eblock, off, pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) dprintf("name=%s, namelen=%d\n", name, namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (!namelen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (namelen > BFS_NAMELEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return -ENAMETOOLONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) sblock = BFS_I(dir)->i_sblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) eblock = BFS_I(dir)->i_eblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) for (block = sblock; block <= eblock; block++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) bh = sb_bread(dir->i_sb, block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (!bh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) for (off = 0; off < BFS_BSIZE; off += BFS_DIRENT_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) de = (struct bfs_dirent *)(bh->b_data + off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (!de->ino) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) pos = (block - sblock) * BFS_BSIZE + off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (pos >= dir->i_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) dir->i_size += BFS_DIRENT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) dir->i_ctime = current_time(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) dir->i_mtime = current_time(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) mark_inode_dirty(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) de->ino = cpu_to_le16((u16)ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) for (i = 0; i < BFS_NAMELEN; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) de->name[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) (i < namelen) ? name[i] : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) mark_buffer_dirty_inode(bh, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static inline int bfs_namecmp(int len, const unsigned char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) const char *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if ((len < BFS_NAMELEN) && buffer[len])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return !memcmp(name, buffer, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static struct buffer_head *bfs_find_entry(struct inode *dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) const struct qstr *child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct bfs_dirent **res_dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) unsigned long block = 0, offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct buffer_head *bh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct bfs_dirent *de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) const unsigned char *name = child->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) int namelen = child->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) *res_dir = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (namelen > BFS_NAMELEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) while (block * BFS_BSIZE + offset < dir->i_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (!bh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) bh = sb_bread(dir->i_sb, BFS_I(dir)->i_sblock + block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (!bh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) block++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) de = (struct bfs_dirent *)(bh->b_data + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) offset += BFS_DIRENT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (le16_to_cpu(de->ino) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) bfs_namecmp(namelen, name, de->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) *res_dir = de;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return bh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (offset < bh->b_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) bh = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) block++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }