3 * BFS directory operations.
4 * Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
5 * Made endianness-clean by Andrew Stribblehill <ads@wompom.org> 2005
8 #include <linux/time.h>
9 #include <linux/string.h>
11 #include <linux/smp_lock.h>
12 #include <linux/buffer_head.h>
13 #include <linux/sched.h>
19 #define dprintf(x...) printf(x)
24 static int bfs_add_entry(struct inode
*dir
, const unsigned char *name
,
25 int namelen
, int ino
);
26 static struct buffer_head
*bfs_find_entry(struct inode
*dir
,
27 const unsigned char *name
, int namelen
,
28 struct bfs_dirent
**res_dir
);
30 static int bfs_readdir(struct file
*f
, void *dirent
, filldir_t filldir
)
32 struct inode
*dir
= f
->f_path
.dentry
->d_inode
;
33 struct buffer_head
*bh
;
34 struct bfs_dirent
*de
;
35 struct bfs_sb_info
*info
= BFS_SB(dir
->i_sb
);
39 mutex_lock(&info
->bfs_lock
);
41 if (f
->f_pos
& (BFS_DIRENT_SIZE
- 1)) {
42 printf("Bad f_pos=%08lx for %s:%08lx\n",
43 (unsigned long)f
->f_pos
,
44 dir
->i_sb
->s_id
, dir
->i_ino
);
45 mutex_unlock(&info
->bfs_lock
);
49 while (f
->f_pos
< dir
->i_size
) {
50 offset
= f
->f_pos
& (BFS_BSIZE
- 1);
51 block
= BFS_I(dir
)->i_sblock
+ (f
->f_pos
>> BFS_BSIZE_BITS
);
52 bh
= sb_bread(dir
->i_sb
, block
);
54 f
->f_pos
+= BFS_BSIZE
- offset
;
58 de
= (struct bfs_dirent
*)(bh
->b_data
+ offset
);
60 int size
= strnlen(de
->name
, BFS_NAMELEN
);
61 if (filldir(dirent
, de
->name
, size
, f
->f_pos
,
65 mutex_unlock(&info
->bfs_lock
);
69 offset
+= BFS_DIRENT_SIZE
;
70 f
->f_pos
+= BFS_DIRENT_SIZE
;
71 } while ((offset
< BFS_BSIZE
) && (f
->f_pos
< dir
->i_size
));
75 mutex_unlock(&info
->bfs_lock
);
79 const struct file_operations bfs_dir_operations
= {
80 .read
= generic_read_dir
,
81 .readdir
= bfs_readdir
,
82 .fsync
= simple_fsync
,
83 .llseek
= generic_file_llseek
,
86 extern void dump_imap(const char *, struct super_block
*);
88 static int bfs_create(struct inode
*dir
, struct dentry
*dentry
, int mode
,
93 struct super_block
*s
= dir
->i_sb
;
94 struct bfs_sb_info
*info
= BFS_SB(s
);
100 mutex_lock(&info
->bfs_lock
);
101 ino
= find_first_zero_bit(info
->si_imap
, info
->si_lasti
);
102 if (ino
> info
->si_lasti
) {
103 mutex_unlock(&info
->bfs_lock
);
107 set_bit(ino
, info
->si_imap
);
109 inode
->i_uid
= current_fsuid();
110 inode
->i_gid
= (dir
->i_mode
& S_ISGID
) ? dir
->i_gid
: current_fsgid();
111 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME_SEC
;
113 inode
->i_op
= &bfs_file_inops
;
114 inode
->i_fop
= &bfs_file_operations
;
115 inode
->i_mapping
->a_ops
= &bfs_aops
;
116 inode
->i_mode
= mode
;
118 BFS_I(inode
)->i_dsk_ino
= ino
;
119 BFS_I(inode
)->i_sblock
= 0;
120 BFS_I(inode
)->i_eblock
= 0;
121 insert_inode_hash(inode
);
122 mark_inode_dirty(inode
);
123 dump_imap("create", s
);
125 err
= bfs_add_entry(dir
, dentry
->d_name
.name
, dentry
->d_name
.len
,
128 inode_dec_link_count(inode
);
129 mutex_unlock(&info
->bfs_lock
);
133 mutex_unlock(&info
->bfs_lock
);
134 d_instantiate(dentry
, inode
);
138 static struct dentry
*bfs_lookup(struct inode
*dir
, struct dentry
*dentry
,
139 struct nameidata
*nd
)
141 struct inode
*inode
= NULL
;
142 struct buffer_head
*bh
;
143 struct bfs_dirent
*de
;
144 struct bfs_sb_info
*info
= BFS_SB(dir
->i_sb
);
146 if (dentry
->d_name
.len
> BFS_NAMELEN
)
147 return ERR_PTR(-ENAMETOOLONG
);
149 mutex_lock(&info
->bfs_lock
);
150 bh
= bfs_find_entry(dir
, dentry
->d_name
.name
, dentry
->d_name
.len
, &de
);
152 unsigned long ino
= (unsigned long)le16_to_cpu(de
->ino
);
154 inode
= bfs_iget(dir
->i_sb
, ino
);
156 mutex_unlock(&info
->bfs_lock
);
157 return ERR_CAST(inode
);
160 mutex_unlock(&info
->bfs_lock
);
161 d_add(dentry
, inode
);
165 static int bfs_link(struct dentry
*old
, struct inode
*dir
,
168 struct inode
*inode
= old
->d_inode
;
169 struct bfs_sb_info
*info
= BFS_SB(inode
->i_sb
);
172 mutex_lock(&info
->bfs_lock
);
173 err
= bfs_add_entry(dir
, new->d_name
.name
, new->d_name
.len
,
176 mutex_unlock(&info
->bfs_lock
);
180 inode
->i_ctime
= CURRENT_TIME_SEC
;
181 mark_inode_dirty(inode
);
182 atomic_inc(&inode
->i_count
);
183 d_instantiate(new, inode
);
184 mutex_unlock(&info
->bfs_lock
);
188 static int bfs_unlink(struct inode
*dir
, struct dentry
*dentry
)
191 struct inode
*inode
= dentry
->d_inode
;
192 struct buffer_head
*bh
;
193 struct bfs_dirent
*de
;
194 struct bfs_sb_info
*info
= BFS_SB(inode
->i_sb
);
196 mutex_lock(&info
->bfs_lock
);
197 bh
= bfs_find_entry(dir
, dentry
->d_name
.name
, dentry
->d_name
.len
, &de
);
198 if (!bh
|| (le16_to_cpu(de
->ino
) != inode
->i_ino
))
201 if (!inode
->i_nlink
) {
202 printf("unlinking non-existent file %s:%lu (nlink=%d)\n",
203 inode
->i_sb
->s_id
, inode
->i_ino
,
208 mark_buffer_dirty_inode(bh
, dir
);
209 dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME_SEC
;
210 mark_inode_dirty(dir
);
211 inode
->i_ctime
= dir
->i_ctime
;
212 inode_dec_link_count(inode
);
217 mutex_unlock(&info
->bfs_lock
);
221 static int bfs_rename(struct inode
*old_dir
, struct dentry
*old_dentry
,
222 struct inode
*new_dir
, struct dentry
*new_dentry
)
224 struct inode
*old_inode
, *new_inode
;
225 struct buffer_head
*old_bh
, *new_bh
;
226 struct bfs_dirent
*old_de
, *new_de
;
227 struct bfs_sb_info
*info
;
230 old_bh
= new_bh
= NULL
;
231 old_inode
= old_dentry
->d_inode
;
232 if (S_ISDIR(old_inode
->i_mode
))
235 info
= BFS_SB(old_inode
->i_sb
);
237 mutex_lock(&info
->bfs_lock
);
238 old_bh
= bfs_find_entry(old_dir
,
239 old_dentry
->d_name
.name
,
240 old_dentry
->d_name
.len
, &old_de
);
242 if (!old_bh
|| (le16_to_cpu(old_de
->ino
) != old_inode
->i_ino
))
246 new_inode
= new_dentry
->d_inode
;
247 new_bh
= bfs_find_entry(new_dir
,
248 new_dentry
->d_name
.name
,
249 new_dentry
->d_name
.len
, &new_de
);
251 if (new_bh
&& !new_inode
) {
256 error
= bfs_add_entry(new_dir
,
257 new_dentry
->d_name
.name
,
258 new_dentry
->d_name
.len
,
264 old_dir
->i_ctime
= old_dir
->i_mtime
= CURRENT_TIME_SEC
;
265 mark_inode_dirty(old_dir
);
267 new_inode
->i_ctime
= CURRENT_TIME_SEC
;
268 inode_dec_link_count(new_inode
);
270 mark_buffer_dirty_inode(old_bh
, old_dir
);
274 mutex_unlock(&info
->bfs_lock
);
280 const struct inode_operations bfs_dir_inops
= {
281 .create
= bfs_create
,
282 .lookup
= bfs_lookup
,
284 .unlink
= bfs_unlink
,
285 .rename
= bfs_rename
,
288 static int bfs_add_entry(struct inode
*dir
, const unsigned char *name
,
289 int namelen
, int ino
)
291 struct buffer_head
*bh
;
292 struct bfs_dirent
*de
;
293 int block
, sblock
, eblock
, off
, pos
;
296 dprintf("name=%s, namelen=%d\n", name
, namelen
);
300 if (namelen
> BFS_NAMELEN
)
301 return -ENAMETOOLONG
;
303 sblock
= BFS_I(dir
)->i_sblock
;
304 eblock
= BFS_I(dir
)->i_eblock
;
305 for (block
= sblock
; block
<= eblock
; block
++) {
306 bh
= sb_bread(dir
->i_sb
, block
);
309 for (off
= 0; off
< BFS_BSIZE
; off
+= BFS_DIRENT_SIZE
) {
310 de
= (struct bfs_dirent
*)(bh
->b_data
+ off
);
312 pos
= (block
- sblock
) * BFS_BSIZE
+ off
;
313 if (pos
>= dir
->i_size
) {
314 dir
->i_size
+= BFS_DIRENT_SIZE
;
315 dir
->i_ctime
= CURRENT_TIME_SEC
;
317 dir
->i_mtime
= CURRENT_TIME_SEC
;
318 mark_inode_dirty(dir
);
319 de
->ino
= cpu_to_le16((u16
)ino
);
320 for (i
= 0; i
< BFS_NAMELEN
; i
++)
322 (i
< namelen
) ? name
[i
] : 0;
323 mark_buffer_dirty_inode(bh
, dir
);
333 static inline int bfs_namecmp(int len
, const unsigned char *name
,
336 if ((len
< BFS_NAMELEN
) && buffer
[len
])
338 return !memcmp(name
, buffer
, len
);
341 static struct buffer_head
*bfs_find_entry(struct inode
*dir
,
342 const unsigned char *name
, int namelen
,
343 struct bfs_dirent
**res_dir
)
345 unsigned long block
= 0, offset
= 0;
346 struct buffer_head
*bh
= NULL
;
347 struct bfs_dirent
*de
;
350 if (namelen
> BFS_NAMELEN
)
353 while (block
* BFS_BSIZE
+ offset
< dir
->i_size
) {
355 bh
= sb_bread(dir
->i_sb
, BFS_I(dir
)->i_sblock
+ block
);
361 de
= (struct bfs_dirent
*)(bh
->b_data
+ offset
);
362 offset
+= BFS_DIRENT_SIZE
;
363 if (le16_to_cpu(de
->ino
) &&
364 bfs_namecmp(namelen
, name
, de
->name
)) {
368 if (offset
< bh
->b_size
)