aboutsummaryrefslogtreecommitdiffstats
path: root/fs/bfs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/bfs/dir.c')
-rw-r--r--fs/bfs/dir.c146
1 files changed, 78 insertions, 68 deletions
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 097f1497f743..1fd056d0fc3d 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -21,29 +21,32 @@
21#define dprintf(x...) 21#define dprintf(x...)
22#endif 22#endif
23 23
24static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino); 24static int bfs_add_entry(struct inode *dir, const unsigned char *name,
25static struct buffer_head * bfs_find_entry(struct inode * dir, 25 int namelen, int ino);
26 const unsigned char * name, int namelen, struct bfs_dirent ** res_dir); 26static struct buffer_head *bfs_find_entry(struct inode *dir,
27 const unsigned char *name, int namelen,
28 struct bfs_dirent **res_dir);
27 29
28static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir) 30static int bfs_readdir(struct file *f, void *dirent, filldir_t filldir)
29{ 31{
30 struct inode * dir = f->f_path.dentry->d_inode; 32 struct inode *dir = f->f_path.dentry->d_inode;
31 struct buffer_head * bh; 33 struct buffer_head *bh;
32 struct bfs_dirent * de; 34 struct bfs_dirent *de;
33 unsigned int offset; 35 unsigned int offset;
34 int block; 36 int block;
35 37
36 lock_kernel(); 38 lock_kernel();
37 39
38 if (f->f_pos & (BFS_DIRENT_SIZE-1)) { 40 if (f->f_pos & (BFS_DIRENT_SIZE - 1)) {
39 printf("Bad f_pos=%08lx for %s:%08lx\n", (unsigned long)f->f_pos, 41 printf("Bad f_pos=%08lx for %s:%08lx\n",
40 dir->i_sb->s_id, dir->i_ino); 42 (unsigned long)f->f_pos,
43 dir->i_sb->s_id, dir->i_ino);
41 unlock_kernel(); 44 unlock_kernel();
42 return -EBADF; 45 return -EBADF;
43 } 46 }
44 47
45 while (f->f_pos < dir->i_size) { 48 while (f->f_pos < dir->i_size) {
46 offset = f->f_pos & (BFS_BSIZE-1); 49 offset = f->f_pos & (BFS_BSIZE - 1);
47 block = BFS_I(dir)->i_sblock + (f->f_pos >> BFS_BSIZE_BITS); 50 block = BFS_I(dir)->i_sblock + (f->f_pos >> BFS_BSIZE_BITS);
48 bh = sb_bread(dir->i_sb, block); 51 bh = sb_bread(dir->i_sb, block);
49 if (!bh) { 52 if (!bh) {
@@ -54,7 +57,9 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
54 de = (struct bfs_dirent *)(bh->b_data + offset); 57 de = (struct bfs_dirent *)(bh->b_data + offset);
55 if (de->ino) { 58 if (de->ino) {
56 int size = strnlen(de->name, BFS_NAMELEN); 59 int size = strnlen(de->name, BFS_NAMELEN);
57 if (filldir(dirent, de->name, size, f->f_pos, le16_to_cpu(de->ino), DT_UNKNOWN) < 0) { 60 if (filldir(dirent, de->name, size, f->f_pos,
61 le16_to_cpu(de->ino),
62 DT_UNKNOWN) < 0) {
58 brelse(bh); 63 brelse(bh);
59 unlock_kernel(); 64 unlock_kernel();
60 return 0; 65 return 0;
@@ -62,7 +67,7 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
62 } 67 }
63 offset += BFS_DIRENT_SIZE; 68 offset += BFS_DIRENT_SIZE;
64 f->f_pos += BFS_DIRENT_SIZE; 69 f->f_pos += BFS_DIRENT_SIZE;
65 } while (offset < BFS_BSIZE && f->f_pos < dir->i_size); 70 } while ((offset < BFS_BSIZE) && (f->f_pos < dir->i_size));
66 brelse(bh); 71 brelse(bh);
67 } 72 }
68 73
@@ -78,13 +83,13 @@ const struct file_operations bfs_dir_operations = {
78 83
79extern void dump_imap(const char *, struct super_block *); 84extern void dump_imap(const char *, struct super_block *);
80 85
81static int bfs_create(struct inode * dir, struct dentry * dentry, int mode, 86static int bfs_create(struct inode *dir, struct dentry *dentry, int mode,
82 struct nameidata *nd) 87 struct nameidata *nd)
83{ 88{
84 int err; 89 int err;
85 struct inode * inode; 90 struct inode *inode;
86 struct super_block * s = dir->i_sb; 91 struct super_block *s = dir->i_sb;
87 struct bfs_sb_info * info = BFS_SB(s); 92 struct bfs_sb_info *info = BFS_SB(s);
88 unsigned long ino; 93 unsigned long ino;
89 94
90 inode = new_inode(s); 95 inode = new_inode(s);
@@ -97,7 +102,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
97 iput(inode); 102 iput(inode);
98 return -ENOSPC; 103 return -ENOSPC;
99 } 104 }
100 set_bit(ino, info->si_imap); 105 set_bit(ino, info->si_imap);
101 info->si_freei--; 106 info->si_freei--;
102 inode->i_uid = current->fsuid; 107 inode->i_uid = current->fsuid;
103 inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; 108 inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
@@ -113,9 +118,10 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
113 BFS_I(inode)->i_eblock = 0; 118 BFS_I(inode)->i_eblock = 0;
114 insert_inode_hash(inode); 119 insert_inode_hash(inode);
115 mark_inode_dirty(inode); 120 mark_inode_dirty(inode);
116 dump_imap("create",s); 121 dump_imap("create", s);
117 122
118 err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, inode->i_ino); 123 err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len,
124 inode->i_ino);
119 if (err) { 125 if (err) {
120 inode_dec_link_count(inode); 126 inode_dec_link_count(inode);
121 iput(inode); 127 iput(inode);
@@ -127,11 +133,12 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
127 return 0; 133 return 0;
128} 134}
129 135
130static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd) 136static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry,
137 struct nameidata *nd)
131{ 138{
132 struct inode * inode = NULL; 139 struct inode *inode = NULL;
133 struct buffer_head * bh; 140 struct buffer_head *bh;
134 struct bfs_dirent * de; 141 struct bfs_dirent *de;
135 142
136 if (dentry->d_name.len > BFS_NAMELEN) 143 if (dentry->d_name.len > BFS_NAMELEN)
137 return ERR_PTR(-ENAMETOOLONG); 144 return ERR_PTR(-ENAMETOOLONG);
@@ -152,13 +159,15 @@ static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry, st
152 return NULL; 159 return NULL;
153} 160}
154 161
155static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new) 162static int bfs_link(struct dentry *old, struct inode *dir,
163 struct dentry *new)
156{ 164{
157 struct inode * inode = old->d_inode; 165 struct inode *inode = old->d_inode;
158 int err; 166 int err;
159 167
160 lock_kernel(); 168 lock_kernel();
161 err = bfs_add_entry(dir, new->d_name.name, new->d_name.len, inode->i_ino); 169 err = bfs_add_entry(dir, new->d_name.name, new->d_name.len,
170 inode->i_ino);
162 if (err) { 171 if (err) {
163 unlock_kernel(); 172 unlock_kernel();
164 return err; 173 return err;
@@ -172,23 +181,23 @@ static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new
172 return 0; 181 return 0;
173} 182}
174 183
175 184static int bfs_unlink(struct inode *dir, struct dentry *dentry)
176static int bfs_unlink(struct inode * dir, struct dentry * dentry)
177{ 185{
178 int error = -ENOENT; 186 int error = -ENOENT;
179 struct inode * inode; 187 struct inode *inode;
180 struct buffer_head * bh; 188 struct buffer_head *bh;
181 struct bfs_dirent * de; 189 struct bfs_dirent *de;
182 190
183 inode = dentry->d_inode; 191 inode = dentry->d_inode;
184 lock_kernel(); 192 lock_kernel();
185 bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); 193 bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
186 if (!bh || le16_to_cpu(de->ino) != inode->i_ino) 194 if (!bh || (le16_to_cpu(de->ino) != inode->i_ino))
187 goto out_brelse; 195 goto out_brelse;
188 196
189 if (!inode->i_nlink) { 197 if (!inode->i_nlink) {
190 printf("unlinking non-existent file %s:%lu (nlink=%d)\n", inode->i_sb->s_id, 198 printf("unlinking non-existent file %s:%lu (nlink=%d)\n",
191 inode->i_ino, inode->i_nlink); 199 inode->i_sb->s_id, inode->i_ino,
200 inode->i_nlink);
192 inode->i_nlink = 1; 201 inode->i_nlink = 1;
193 } 202 }
194 de->ino = 0; 203 de->ino = 0;
@@ -205,12 +214,12 @@ out_brelse:
205 return error; 214 return error;
206} 215}
207 216
208static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry, 217static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
209 struct inode * new_dir, struct dentry * new_dentry) 218 struct inode *new_dir, struct dentry *new_dentry)
210{ 219{
211 struct inode * old_inode, * new_inode; 220 struct inode *old_inode, *new_inode;
212 struct buffer_head * old_bh, * new_bh; 221 struct buffer_head *old_bh, *new_bh;
213 struct bfs_dirent * old_de, * new_de; 222 struct bfs_dirent *old_de, *new_de;
214 int error = -ENOENT; 223 int error = -ENOENT;
215 224
216 old_bh = new_bh = NULL; 225 old_bh = new_bh = NULL;
@@ -223,7 +232,7 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
223 old_dentry->d_name.name, 232 old_dentry->d_name.name,
224 old_dentry->d_name.len, &old_de); 233 old_dentry->d_name.len, &old_de);
225 234
226 if (!old_bh || le16_to_cpu(old_de->ino) != old_inode->i_ino) 235 if (!old_bh || (le16_to_cpu(old_de->ino) != old_inode->i_ino))
227 goto end_rename; 236 goto end_rename;
228 237
229 error = -EPERM; 238 error = -EPERM;
@@ -239,7 +248,8 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
239 if (!new_bh) { 248 if (!new_bh) {
240 error = bfs_add_entry(new_dir, 249 error = bfs_add_entry(new_dir,
241 new_dentry->d_name.name, 250 new_dentry->d_name.name,
242 new_dentry->d_name.len, old_inode->i_ino); 251 new_dentry->d_name.len,
252 old_inode->i_ino);
243 if (error) 253 if (error)
244 goto end_rename; 254 goto end_rename;
245 } 255 }
@@ -268,11 +278,12 @@ const struct inode_operations bfs_dir_inops = {
268 .rename = bfs_rename, 278 .rename = bfs_rename,
269}; 279};
270 280
271static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino) 281static int bfs_add_entry(struct inode *dir, const unsigned char *name,
282 int namelen, int ino)
272{ 283{
273 struct buffer_head * bh; 284 struct buffer_head *bh;
274 struct bfs_dirent * de; 285 struct bfs_dirent *de;
275 int block, sblock, eblock, off, eoff; 286 int block, sblock, eblock, off, pos;
276 int i; 287 int i;
277 288
278 dprintf("name=%s, namelen=%d\n", name, namelen); 289 dprintf("name=%s, namelen=%d\n", name, namelen);
@@ -284,27 +295,24 @@ static int bfs_add_entry(struct inode * dir, const unsigned char * name, int nam
284 295
285 sblock = BFS_I(dir)->i_sblock; 296 sblock = BFS_I(dir)->i_sblock;
286 eblock = BFS_I(dir)->i_eblock; 297 eblock = BFS_I(dir)->i_eblock;
287 eoff = dir->i_size % BFS_BSIZE; 298 for (block = sblock; block <= eblock; block++) {
288 for (block=sblock; block<=eblock; block++) {
289 bh = sb_bread(dir->i_sb, block); 299 bh = sb_bread(dir->i_sb, block);
290 if(!bh) 300 if (!bh)
291 return -ENOSPC; 301 return -ENOSPC;
292 for (off=0; off<BFS_BSIZE; off+=BFS_DIRENT_SIZE) { 302 for (off = 0; off < BFS_BSIZE; off += BFS_DIRENT_SIZE) {
293 de = (struct bfs_dirent *)(bh->b_data + off); 303 de = (struct bfs_dirent *)(bh->b_data + off);
294 if (block==eblock && off>=eoff) {
295 /* Do not read/interpret the garbage in the end of eblock. */
296 de->ino = 0;
297 }
298 if (!de->ino) { 304 if (!de->ino) {
299 if ((block-sblock)*BFS_BSIZE + off >= dir->i_size) { 305 pos = (block - sblock) * BFS_BSIZE + off;
306 if (pos >= dir->i_size) {
300 dir->i_size += BFS_DIRENT_SIZE; 307 dir->i_size += BFS_DIRENT_SIZE;
301 dir->i_ctime = CURRENT_TIME_SEC; 308 dir->i_ctime = CURRENT_TIME_SEC;
302 } 309 }
303 dir->i_mtime = CURRENT_TIME_SEC; 310 dir->i_mtime = CURRENT_TIME_SEC;
304 mark_inode_dirty(dir); 311 mark_inode_dirty(dir);
305 de->ino = cpu_to_le16((u16)ino); 312 de->ino = cpu_to_le16((u16)ino);
306 for (i=0; i<BFS_NAMELEN; i++) 313 for (i = 0; i < BFS_NAMELEN; i++)
307 de->name[i] = (i < namelen) ? name[i] : 0; 314 de->name[i] =
315 (i < namelen) ? name[i] : 0;
308 mark_buffer_dirty(bh); 316 mark_buffer_dirty(bh);
309 brelse(bh); 317 brelse(bh);
310 return 0; 318 return 0;
@@ -315,25 +323,26 @@ static int bfs_add_entry(struct inode * dir, const unsigned char * name, int nam
315 return -ENOSPC; 323 return -ENOSPC;
316} 324}
317 325
318static inline int bfs_namecmp(int len, const unsigned char * name, const char * buffer) 326static inline int bfs_namecmp(int len, const unsigned char *name,
327 const char *buffer)
319{ 328{
320 if (len < BFS_NAMELEN && buffer[len]) 329 if ((len < BFS_NAMELEN) && buffer[len])
321 return 0; 330 return 0;
322 return !memcmp(name, buffer, len); 331 return !memcmp(name, buffer, len);
323} 332}
324 333
325static struct buffer_head * bfs_find_entry(struct inode * dir, 334static struct buffer_head *bfs_find_entry(struct inode *dir,
326 const unsigned char * name, int namelen, struct bfs_dirent ** res_dir) 335 const unsigned char *name, int namelen,
336 struct bfs_dirent **res_dir)
327{ 337{
328 unsigned long block, offset; 338 unsigned long block = 0, offset = 0;
329 struct buffer_head * bh; 339 struct buffer_head *bh = NULL;
330 struct bfs_dirent * de; 340 struct bfs_dirent *de;
331 341
332 *res_dir = NULL; 342 *res_dir = NULL;
333 if (namelen > BFS_NAMELEN) 343 if (namelen > BFS_NAMELEN)
334 return NULL; 344 return NULL;
335 bh = NULL; 345
336 block = offset = 0;
337 while (block * BFS_BSIZE + offset < dir->i_size) { 346 while (block * BFS_BSIZE + offset < dir->i_size) {
338 if (!bh) { 347 if (!bh) {
339 bh = sb_bread(dir->i_sb, BFS_I(dir)->i_sblock + block); 348 bh = sb_bread(dir->i_sb, BFS_I(dir)->i_sblock + block);
@@ -344,7 +353,8 @@ static struct buffer_head * bfs_find_entry(struct inode * dir,
344 } 353 }
345 de = (struct bfs_dirent *)(bh->b_data + offset); 354 de = (struct bfs_dirent *)(bh->b_data + offset);
346 offset += BFS_DIRENT_SIZE; 355 offset += BFS_DIRENT_SIZE;
347 if (le16_to_cpu(de->ino) && bfs_namecmp(namelen, name, de->name)) { 356 if (le16_to_cpu(de->ino) &&
357 bfs_namecmp(namelen, name, de->name)) {
348 *res_dir = de; 358 *res_dir = de;
349 return bh; 359 return bh;
350 } 360 }