Merge branch 'md-fixes' of https://git.kernel.org/pub/scm/linux/kernel/git/song/md...
[linux-2.6-block.git] / fs / minix / dir.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
1da177e4
LT
2/*
3 * linux/fs/minix/dir.c
4 *
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 *
7 * minix directory handling functions
939b00df
AB
8 *
9 * Updated to filesystem version 3 by Daniel Aragones
1da177e4
LT
10 */
11
12#include "minix.h"
4a66af9e 13#include <linux/buffer_head.h>
1da177e4 14#include <linux/highmem.h>
4a66af9e 15#include <linux/swap.h>
1da177e4
LT
16
17typedef struct minix_dir_entry minix_dirent;
939b00df 18typedef struct minix3_dir_entry minix3_dirent;
1da177e4 19
80886298 20static int minix_readdir(struct file *, struct dir_context *);
1da177e4 21
4b6f5d20 22const struct file_operations minix_dir_operations = {
cc46759a 23 .llseek = generic_file_llseek,
1da177e4 24 .read = generic_read_dir,
3b0a3c1a 25 .iterate_shared = minix_readdir,
1b061d92 26 .fsync = generic_file_fsync,
1da177e4
LT
27};
28
29static inline void dir_put_page(struct page *page)
30{
31 kunmap(page);
09cbfeaf 32 put_page(page);
1da177e4
LT
33}
34
35/*
36 * Return the offset into page `page_nr' of the last valid
37 * byte in that page, plus one.
38 */
39static unsigned
40minix_last_byte(struct inode *inode, unsigned long page_nr)
41{
09cbfeaf 42 unsigned last_byte = PAGE_SIZE;
1da177e4 43
09cbfeaf
KS
44 if (page_nr == (inode->i_size >> PAGE_SHIFT))
45 last_byte = inode->i_size & (PAGE_SIZE - 1);
1da177e4
LT
46 return last_byte;
47}
48
f556e776 49static void dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
1da177e4 50{
4a66af9e
NP
51 struct address_space *mapping = page->mapping;
52 struct inode *dir = mapping->host;
f556e776 53
4a66af9e
NP
54 block_write_end(NULL, mapping, pos, len, len, page, NULL);
55
56 if (pos+len > dir->i_size) {
57 i_size_write(dir, pos+len);
58 mark_inode_dirty(dir);
59 }
f556e776
CH
60 unlock_page(page);
61}
62
63static int minix_handle_dirsync(struct inode *dir)
64{
65 int err;
66
67 err = filemap_write_and_wait(dir->i_mapping);
68 if (!err)
69 err = sync_inode_metadata(dir, 1);
1da177e4
LT
70 return err;
71}
72
73static struct page * dir_get_page(struct inode *dir, unsigned long n)
74{
75 struct address_space *mapping = dir->i_mapping;
090d2b18 76 struct page *page = read_mapping_page(mapping, n, NULL);
49837a80 77 if (!IS_ERR(page))
1da177e4 78 kmap(page);
1da177e4 79 return page;
1da177e4
LT
80}
81
82static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi)
83{
84 return (void*)((char*)de + sbi->s_dirsize);
85}
86
80886298 87static int minix_readdir(struct file *file, struct dir_context *ctx)
1da177e4 88{
80886298 89 struct inode *inode = file_inode(file);
1da177e4 90 struct super_block *sb = inode->i_sb;
1da177e4
LT
91 struct minix_sb_info *sbi = minix_sb(sb);
92 unsigned chunk_size = sbi->s_dirsize;
80886298
AV
93 unsigned long npages = dir_pages(inode);
94 unsigned long pos = ctx->pos;
95 unsigned offset;
96 unsigned long n;
1da177e4 97
642b704c 98 ctx->pos = pos = ALIGN(pos, chunk_size);
1da177e4 99 if (pos >= inode->i_size)
80886298
AV
100 return 0;
101
09cbfeaf
KS
102 offset = pos & ~PAGE_MASK;
103 n = pos >> PAGE_SHIFT;
1da177e4
LT
104
105 for ( ; n < npages; n++, offset = 0) {
106 char *p, *kaddr, *limit;
107 struct page *page = dir_get_page(inode, n);
108
109 if (IS_ERR(page))
110 continue;
111 kaddr = (char *)page_address(page);
112 p = kaddr+offset;
113 limit = kaddr + minix_last_byte(inode, n) - chunk_size;
939b00df 114 for ( ; p <= limit; p = minix_next_entry(p, sbi)) {
80886298
AV
115 const char *name;
116 __u32 inumber;
939b00df
AB
117 if (sbi->s_version == MINIX_V3) {
118 minix3_dirent *de3 = (minix3_dirent *)p;
119 name = de3->name;
120 inumber = de3->inode;
121 } else {
122 minix_dirent *de = (minix_dirent *)p;
123 name = de->name;
124 inumber = de->inode;
125 }
126 if (inumber) {
939b00df 127 unsigned l = strnlen(name, sbi->s_namelen);
80886298
AV
128 if (!dir_emit(ctx, name, l,
129 inumber, DT_UNKNOWN)) {
1da177e4 130 dir_put_page(page);
80886298 131 return 0;
1da177e4
LT
132 }
133 }
80886298 134 ctx->pos += chunk_size;
1da177e4
LT
135 }
136 dir_put_page(page);
137 }
1da177e4
LT
138 return 0;
139}
140
141static inline int namecompare(int len, int maxlen,
142 const char * name, const char * buffer)
143{
144 if (len < maxlen && buffer[len])
145 return 0;
146 return !memcmp(name, buffer, len);
147}
148
149/*
150 * minix_find_entry()
151 *
152 * finds an entry in the specified directory with the wanted name. It
153 * returns the cache buffer in which the entry was found, and the entry
154 * itself (as a parameter - res_dir). It does NOT read the inode of the
155 * entry - you'll have to do that yourself if you want to.
156 */
157minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page)
158{
159 const char * name = dentry->d_name.name;
160 int namelen = dentry->d_name.len;
2b0143b5 161 struct inode * dir = d_inode(dentry->d_parent);
1da177e4
LT
162 struct super_block * sb = dir->i_sb;
163 struct minix_sb_info * sbi = minix_sb(sb);
164 unsigned long n;
165 unsigned long npages = dir_pages(dir);
166 struct page *page = NULL;
939b00df 167 char *p;
1da177e4 168
939b00df
AB
169 char *namx;
170 __u32 inumber;
1da177e4
LT
171 *res_page = NULL;
172
173 for (n = 0; n < npages; n++) {
939b00df
AB
174 char *kaddr, *limit;
175
1da177e4
LT
176 page = dir_get_page(dir, n);
177 if (IS_ERR(page))
178 continue;
179
180 kaddr = (char*)page_address(page);
939b00df
AB
181 limit = kaddr + minix_last_byte(dir, n) - sbi->s_dirsize;
182 for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
183 if (sbi->s_version == MINIX_V3) {
184 minix3_dirent *de3 = (minix3_dirent *)p;
185 namx = de3->name;
186 inumber = de3->inode;
187 } else {
188 minix_dirent *de = (minix_dirent *)p;
189 namx = de->name;
190 inumber = de->inode;
191 }
192 if (!inumber)
1da177e4 193 continue;
939b00df 194 if (namecompare(namelen, sbi->s_namelen, name, namx))
1da177e4
LT
195 goto found;
196 }
197 dir_put_page(page);
198 }
199 return NULL;
200
201found:
202 *res_page = page;
939b00df 203 return (minix_dirent *)p;
1da177e4
LT
204}
205
206int minix_add_link(struct dentry *dentry, struct inode *inode)
207{
2b0143b5 208 struct inode *dir = d_inode(dentry->d_parent);
1da177e4
LT
209 const char * name = dentry->d_name.name;
210 int namelen = dentry->d_name.len;
211 struct super_block * sb = dir->i_sb;
212 struct minix_sb_info * sbi = minix_sb(sb);
213 struct page *page = NULL;
1da177e4
LT
214 unsigned long npages = dir_pages(dir);
215 unsigned long n;
939b00df
AB
216 char *kaddr, *p;
217 minix_dirent *de;
218 minix3_dirent *de3;
4a66af9e 219 loff_t pos;
1da177e4 220 int err;
939b00df
AB
221 char *namx = NULL;
222 __u32 inumber;
1da177e4
LT
223
224 /*
225 * We take care of directory expansion in the same loop
226 * This code plays outside i_size, so it locks the page
227 * to protect that region.
228 */
229 for (n = 0; n <= npages; n++) {
939b00df 230 char *limit, *dir_end;
1da177e4
LT
231
232 page = dir_get_page(dir, n);
233 err = PTR_ERR(page);
234 if (IS_ERR(page))
235 goto out;
236 lock_page(page);
237 kaddr = (char*)page_address(page);
238 dir_end = kaddr + minix_last_byte(dir, n);
09cbfeaf 239 limit = kaddr + PAGE_SIZE - sbi->s_dirsize;
939b00df
AB
240 for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
241 de = (minix_dirent *)p;
242 de3 = (minix3_dirent *)p;
243 if (sbi->s_version == MINIX_V3) {
244 namx = de3->name;
245 inumber = de3->inode;
246 } else {
247 namx = de->name;
248 inumber = de->inode;
249 }
250 if (p == dir_end) {
1da177e4 251 /* We hit i_size */
939b00df
AB
252 if (sbi->s_version == MINIX_V3)
253 de3->inode = 0;
254 else
255 de->inode = 0;
1da177e4
LT
256 goto got_it;
257 }
939b00df 258 if (!inumber)
1da177e4
LT
259 goto got_it;
260 err = -EEXIST;
939b00df 261 if (namecompare(namelen, sbi->s_namelen, name, namx))
1da177e4 262 goto out_unlock;
1da177e4
LT
263 }
264 unlock_page(page);
265 dir_put_page(page);
266 }
267 BUG();
268 return -EINVAL;
269
270got_it:
d6b54841 271 pos = page_offset(page) + p - (char *)page_address(page);
f4e420dc 272 err = minix_prepare_chunk(page, pos, sbi->s_dirsize);
1da177e4
LT
273 if (err)
274 goto out_unlock;
939b00df
AB
275 memcpy (namx, name, namelen);
276 if (sbi->s_version == MINIX_V3) {
277 memset (namx + namelen, 0, sbi->s_dirsize - namelen - 4);
278 de3->inode = inode->i_ino;
279 } else {
280 memset (namx + namelen, 0, sbi->s_dirsize - namelen - 2);
281 de->inode = inode->i_ino;
282 }
f556e776 283 dir_commit_chunk(page, pos, sbi->s_dirsize);
02027d42 284 dir->i_mtime = dir->i_ctime = current_time(dir);
1da177e4 285 mark_inode_dirty(dir);
f556e776 286 err = minix_handle_dirsync(dir);
1da177e4
LT
287out_put:
288 dir_put_page(page);
289out:
290 return err;
291out_unlock:
292 unlock_page(page);
293 goto out_put;
294}
295
296int minix_delete_entry(struct minix_dir_entry *de, struct page *page)
297{
f4e420dc 298 struct inode *inode = page->mapping->host;
1da177e4 299 char *kaddr = page_address(page);
4a66af9e 300 loff_t pos = page_offset(page) + (char*)de - kaddr;
9f6c1333
DG
301 struct minix_sb_info *sbi = minix_sb(inode->i_sb);
302 unsigned len = sbi->s_dirsize;
1da177e4
LT
303 int err;
304
305 lock_page(page);
f4e420dc 306 err = minix_prepare_chunk(page, pos, len);
b61d15d5 307 if (err) {
1da177e4 308 unlock_page(page);
b61d15d5 309 return err;
1da177e4 310 }
b61d15d5
CH
311 if (sbi->s_version == MINIX_V3)
312 ((minix3_dirent *)de)->inode = 0;
313 else
314 de->inode = 0;
f556e776 315 dir_commit_chunk(page, pos, len);
02027d42 316 inode->i_ctime = inode->i_mtime = current_time(inode);
1da177e4 317 mark_inode_dirty(inode);
f556e776 318 return minix_handle_dirsync(inode);
1da177e4
LT
319}
320
321int minix_make_empty(struct inode *inode, struct inode *dir)
322{
f4e420dc 323 struct page *page = grab_cache_page(inode->i_mapping, 0);
939b00df 324 struct minix_sb_info *sbi = minix_sb(inode->i_sb);
1da177e4
LT
325 char *kaddr;
326 int err;
327
328 if (!page)
329 return -ENOMEM;
f4e420dc 330 err = minix_prepare_chunk(page, 0, 2 * sbi->s_dirsize);
1da177e4
LT
331 if (err) {
332 unlock_page(page);
333 goto fail;
334 }
335
27a6d5c7 336 kaddr = kmap_atomic(page);
09cbfeaf 337 memset(kaddr, 0, PAGE_SIZE);
1da177e4 338
939b00df
AB
339 if (sbi->s_version == MINIX_V3) {
340 minix3_dirent *de3 = (minix3_dirent *)kaddr;
341
342 de3->inode = inode->i_ino;
343 strcpy(de3->name, ".");
344 de3 = minix_next_entry(de3, sbi);
345 de3->inode = dir->i_ino;
346 strcpy(de3->name, "..");
347 } else {
348 minix_dirent *de = (minix_dirent *)kaddr;
349
350 de->inode = inode->i_ino;
351 strcpy(de->name, ".");
352 de = minix_next_entry(de, sbi);
353 de->inode = dir->i_ino;
354 strcpy(de->name, "..");
355 }
27a6d5c7 356 kunmap_atomic(kaddr);
1da177e4 357
f556e776
CH
358 dir_commit_chunk(page, 0, 2 * sbi->s_dirsize);
359 err = minix_handle_dirsync(inode);
1da177e4 360fail:
09cbfeaf 361 put_page(page);
1da177e4
LT
362 return err;
363}
364
365/*
366 * routine to check that the specified directory is empty (for rmdir)
367 */
368int minix_empty_dir(struct inode * inode)
369{
370 struct page *page = NULL;
371 unsigned long i, npages = dir_pages(inode);
372 struct minix_sb_info *sbi = minix_sb(inode->i_sb);
939b00df
AB
373 char *name;
374 __u32 inumber;
1da177e4
LT
375
376 for (i = 0; i < npages; i++) {
939b00df 377 char *p, *kaddr, *limit;
1da177e4 378
939b00df 379 page = dir_get_page(inode, i);
1da177e4
LT
380 if (IS_ERR(page))
381 continue;
382
383 kaddr = (char *)page_address(page);
939b00df
AB
384 limit = kaddr + minix_last_byte(inode, i) - sbi->s_dirsize;
385 for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
386 if (sbi->s_version == MINIX_V3) {
387 minix3_dirent *de3 = (minix3_dirent *)p;
388 name = de3->name;
389 inumber = de3->inode;
390 } else {
391 minix_dirent *de = (minix_dirent *)p;
392 name = de->name;
393 inumber = de->inode;
394 }
1da177e4 395
939b00df 396 if (inumber != 0) {
1da177e4 397 /* check for . and .. */
939b00df 398 if (name[0] != '.')
1da177e4 399 goto not_empty;
939b00df
AB
400 if (!name[1]) {
401 if (inumber != inode->i_ino)
1da177e4 402 goto not_empty;
939b00df 403 } else if (name[1] != '.')
1da177e4 404 goto not_empty;
939b00df 405 else if (name[2])
1da177e4
LT
406 goto not_empty;
407 }
1da177e4
LT
408 }
409 dir_put_page(page);
410 }
411 return 1;
412
413not_empty:
414 dir_put_page(page);
415 return 0;
416}
417
418/* Releases the page */
2d1a9d59
CH
419int minix_set_link(struct minix_dir_entry *de, struct page *page,
420 struct inode *inode)
1da177e4 421{
f4e420dc 422 struct inode *dir = page->mapping->host;
1da177e4 423 struct minix_sb_info *sbi = minix_sb(dir->i_sb);
4a66af9e
NP
424 loff_t pos = page_offset(page) +
425 (char *)de-(char*)page_address(page);
1da177e4
LT
426 int err;
427
428 lock_page(page);
f4e420dc 429 err = minix_prepare_chunk(page, pos, sbi->s_dirsize);
2d1a9d59 430 if (err) {
1da177e4 431 unlock_page(page);
2d1a9d59 432 return err;
1da177e4 433 }
2d1a9d59
CH
434 if (sbi->s_version == MINIX_V3)
435 ((minix3_dirent *)de)->inode = inode->i_ino;
436 else
437 de->inode = inode->i_ino;
f556e776 438 dir_commit_chunk(page, pos, sbi->s_dirsize);
02027d42 439 dir->i_mtime = dir->i_ctime = current_time(dir);
1da177e4 440 mark_inode_dirty(dir);
f556e776 441 return minix_handle_dirsync(dir);
1da177e4
LT
442}
443
444struct minix_dir_entry * minix_dotdot (struct inode *dir, struct page **p)
445{
446 struct page *page = dir_get_page(dir, 0);
447 struct minix_sb_info *sbi = minix_sb(dir->i_sb);
448 struct minix_dir_entry *de = NULL;
449
450 if (!IS_ERR(page)) {
451 de = minix_next_entry(page_address(page), sbi);
452 *p = page;
453 }
454 return de;
455}
456
457ino_t minix_inode_by_name(struct dentry *dentry)
458{
459 struct page *page;
460 struct minix_dir_entry *de = minix_find_entry(dentry, &page);
461 ino_t res = 0;
462
463 if (de) {
9f6c1333
DG
464 struct address_space *mapping = page->mapping;
465 struct inode *inode = mapping->host;
466 struct minix_sb_info *sbi = minix_sb(inode->i_sb);
467
468 if (sbi->s_version == MINIX_V3)
469 res = ((minix3_dirent *) de)->inode;
470 else
471 res = de->inode;
1da177e4
LT
472 dir_put_page(page);
473 }
474 return res;
475}