static struct buffer_head * affs_find_entry(struct inode *dir, struct dentry *dentry) { struct super_block *sb = dir->i_sb; struct buffer_head *bh; toupper_t toupper = affs_get_toupper(sb); u32 key; pr_debug("AFFS: find_entry(\"%.*s\")\n", (int)dentry->d_name.len, dentry->d_name.name); bh = affs_bread(sb, dir->i_ino); if (!bh) return ERR_PTR(-EIO); key = be32_to_cpu(AFFS_HEAD(bh)->table[affs_hash_name(sb, dentry->d_name.name, dentry->d_name.len)]); for (;;) { affs_brelse(bh); if (key == 0) return NULL; bh = affs_bread(sb, key); if (!bh) return ERR_PTR(-EIO); if (affs_match(dentry, AFFS_TAIL(sb, bh)->name, toupper)) return bh; key = be32_to_cpu(AFFS_TAIL(sb, bh)->hash_chain); } }
int affs_remove_hash(struct inode *dir, struct buffer_head *rem_bh) { struct super_block *sb; struct buffer_head *bh; u32 rem_ino, hash_ino; __be32 ino; int offset, retval; sb = dir->i_sb; rem_ino = rem_bh->b_blocknr; offset = affs_hash_name(sb, AFFS_TAIL(sb, rem_bh)->name+1, AFFS_TAIL(sb, rem_bh)->name[0]); pr_debug("AFFS: remove_hash(dir=%d, ino=%d, hashval=%d)\n", (u32)dir->i_ino, rem_ino, offset); bh = affs_bread(sb, dir->i_ino); if (!bh) return -EIO; retval = -ENOENT; hash_ino = be32_to_cpu(AFFS_HEAD(bh)->table[offset]); while (hash_ino) { if (hash_ino == rem_ino) { ino = AFFS_TAIL(sb, rem_bh)->hash_chain; if (dir->i_ino == bh->b_blocknr) AFFS_HEAD(bh)->table[offset] = ino; else AFFS_TAIL(sb, bh)->hash_chain = ino; affs_adjust_checksum(bh, be32_to_cpu(ino) - hash_ino); mark_buffer_dirty_inode(bh, dir); AFFS_TAIL(sb, rem_bh)->parent = 0; retval = 0; break; } affs_brelse(bh); bh = affs_bread(sb, hash_ino); if (!bh) return -EIO; hash_ino = be32_to_cpu(AFFS_TAIL(sb, bh)->hash_chain); } affs_brelse(bh); dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; dir->i_version++; mark_inode_dirty(dir); return retval; }
static struct buffer_head * affs_find_entry(struct inode *dir, struct dentry *dentry, unsigned long *ino) { struct buffer_head *bh; int intl = AFFS_I2FSTYPE(dir); s32 key; const char *name = dentry->d_name.name; int namelen = dentry->d_name.len; pr_debug("AFFS: find_entry(\"%.*s\")\n",namelen,name); bh = affs_bread(dir->i_dev,dir->i_ino,AFFS_I2BSIZE(dir)); if (!bh) return NULL; if (namelen == 1 && name[0] == '.') { *ino = dir->i_ino; return bh; } if (namelen == 2 && name[0] == '.' && name[1] == '.') { *ino = affs_parent_ino(dir); return bh; } key = AFFS_GET_HASHENTRY(bh->b_data,affs_hash_name(name,namelen,intl,AFFS_I2HSIZE(dir))); for (;;) { unsigned char *cname; int cnamelen; affs_brelse(bh); bh = NULL; if (key == 0) break; bh = affs_bread(dir->i_dev,key,AFFS_I2BSIZE(dir)); if (!bh) break; cnamelen = affs_get_file_name(AFFS_I2BSIZE(dir),bh->b_data,&cname); if (affs_match(name,namelen,cname,cnamelen,intl)) break; key = be32_to_cpu(FILE_END(bh->b_data,dir)->hash_chain); } *ino = key; return bh; }
int affs_insert_hash(struct inode *dir, struct buffer_head *bh) { struct super_block *sb = dir->i_sb; struct buffer_head *dir_bh; u32 ino, hash_ino; int offset; ino = bh->b_blocknr; offset = affs_hash_name(sb, AFFS_TAIL(sb, bh)->name + 1, AFFS_TAIL(sb, bh)->name[0]); pr_debug("AFFS: insert_hash(dir=%u, ino=%d)\n", (u32)dir->i_ino, ino); dir_bh = affs_bread(sb, dir->i_ino); if (!dir_bh) return -EIO; hash_ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[offset]); while (hash_ino) { affs_brelse(dir_bh); dir_bh = affs_bread(sb, hash_ino); if (!dir_bh) return -EIO; hash_ino = be32_to_cpu(AFFS_TAIL(sb, dir_bh)->hash_chain); } AFFS_TAIL(sb, bh)->parent = cpu_to_be32(dir->i_ino); AFFS_TAIL(sb, bh)->hash_chain = 0; affs_fix_checksum(sb, bh); if (dir->i_ino == dir_bh->b_blocknr) AFFS_HEAD(dir_bh)->table[offset] = cpu_to_be32(ino); else AFFS_TAIL(sb, dir_bh)->hash_chain = cpu_to_be32(ino); affs_adjust_checksum(dir_bh, ino); mark_buffer_dirty_inode(dir_bh, dir); affs_brelse(dir_bh); dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; dir->i_version++; mark_inode_dirty(dir); return 0; }