aboutsummaryrefslogtreecommitdiffstats
path: root/fs/minix/dir.c
diff options
context:
space:
mode:
authorAndries Brouwer <aeb@cwi.nl>2007-02-12 03:52:49 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-12 12:48:31 -0500
commit939b00df0306bc4b5cd25c3c3c78e89b91e72fc8 (patch)
treec251dca9f3ebbebfa1f40f39716423842b247742 /fs/minix/dir.c
parentb587b13a4f670ebae79ae6259cf44328455e4e69 (diff)
[PATCH] Minix V3 support
This morning I needed to read a Minix V3 filesystem, but unfortunately my 2.6.19 did not support that, and neither did the downloaded 2.6.20rc4. Fortunately, google told me that Daniel Aragones had already done the work, patch found at http://www.terra.es/personal2/danarag/ Unfortunaly, looking at the patch was painful to my eyes, so I polished it a bit before applying. The resulting kernel boots, and reads the filesystem it needed to read. Signed-off-by: Daniel Aragones <danarag@gmail.com> Signed-off-by: Andries Brouwer <aeb@cwi.nl> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/minix/dir.c')
-rw-r--r--fs/minix/dir.c162
1 files changed, 111 insertions, 51 deletions
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index ab782c4086f5..cb4cb571fddf 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -4,6 +4,8 @@
4 * Copyright (C) 1991, 1992 Linus Torvalds 4 * Copyright (C) 1991, 1992 Linus Torvalds
5 * 5 *
6 * minix directory handling functions 6 * minix directory handling functions
7 *
8 * Updated to filesystem version 3 by Daniel Aragones
7 */ 9 */
8 10
9#include "minix.h" 11#include "minix.h"
@@ -11,6 +13,7 @@
11#include <linux/smp_lock.h> 13#include <linux/smp_lock.h>
12 14
13typedef struct minix_dir_entry minix_dirent; 15typedef struct minix_dir_entry minix_dirent;
16typedef struct minix3_dir_entry minix3_dirent;
14 17
15static int minix_readdir(struct file *, void *, filldir_t); 18static int minix_readdir(struct file *, void *, filldir_t);
16 19
@@ -89,6 +92,8 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
89 unsigned long npages = dir_pages(inode); 92 unsigned long npages = dir_pages(inode);
90 struct minix_sb_info *sbi = minix_sb(sb); 93 struct minix_sb_info *sbi = minix_sb(sb);
91 unsigned chunk_size = sbi->s_dirsize; 94 unsigned chunk_size = sbi->s_dirsize;
95 char *name;
96 __u32 inumber;
92 97
93 lock_kernel(); 98 lock_kernel();
94 99
@@ -105,16 +110,24 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
105 kaddr = (char *)page_address(page); 110 kaddr = (char *)page_address(page);
106 p = kaddr+offset; 111 p = kaddr+offset;
107 limit = kaddr + minix_last_byte(inode, n) - chunk_size; 112 limit = kaddr + minix_last_byte(inode, n) - chunk_size;
108 for ( ; p <= limit ; p = minix_next_entry(p, sbi)) { 113 for ( ; p <= limit; p = minix_next_entry(p, sbi)) {
109 minix_dirent *de = (minix_dirent *)p; 114 if (sbi->s_version == MINIX_V3) {
110 if (de->inode) { 115 minix3_dirent *de3 = (minix3_dirent *)p;
116 name = de3->name;
117 inumber = de3->inode;
118 } else {
119 minix_dirent *de = (minix_dirent *)p;
120 name = de->name;
121 inumber = de->inode;
122 }
123 if (inumber) {
111 int over; 124 int over;
112 unsigned l = strnlen(de->name,sbi->s_namelen);
113 125
126 unsigned l = strnlen(name, sbi->s_namelen);
114 offset = p - kaddr; 127 offset = p - kaddr;
115 over = filldir(dirent, de->name, l, 128 over = filldir(dirent, name, l,
116 (n<<PAGE_CACHE_SHIFT) | offset, 129 (n << PAGE_CACHE_SHIFT) | offset,
117 de->inode, DT_UNKNOWN); 130 inumber, DT_UNKNOWN);
118 if (over) { 131 if (over) {
119 dir_put_page(page); 132 dir_put_page(page);
120 goto done; 133 goto done;
@@ -156,23 +169,34 @@ minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page)
156 unsigned long n; 169 unsigned long n;
157 unsigned long npages = dir_pages(dir); 170 unsigned long npages = dir_pages(dir);
158 struct page *page = NULL; 171 struct page *page = NULL;
159 struct minix_dir_entry *de; 172 char *p;
160 173
174 char *namx;
175 __u32 inumber;
161 *res_page = NULL; 176 *res_page = NULL;
162 177
163 for (n = 0; n < npages; n++) { 178 for (n = 0; n < npages; n++) {
164 char *kaddr; 179 char *kaddr, *limit;
180
165 page = dir_get_page(dir, n); 181 page = dir_get_page(dir, n);
166 if (IS_ERR(page)) 182 if (IS_ERR(page))
167 continue; 183 continue;
168 184
169 kaddr = (char*)page_address(page); 185 kaddr = (char*)page_address(page);
170 de = (struct minix_dir_entry *) kaddr; 186 limit = kaddr + minix_last_byte(dir, n) - sbi->s_dirsize;
171 kaddr += minix_last_byte(dir, n) - sbi->s_dirsize; 187 for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
172 for ( ; (char *) de <= kaddr ; de = minix_next_entry(de,sbi)) { 188 if (sbi->s_version == MINIX_V3) {
173 if (!de->inode) 189 minix3_dirent *de3 = (minix3_dirent *)p;
190 namx = de3->name;
191 inumber = de3->inode;
192 } else {
193 minix_dirent *de = (minix_dirent *)p;
194 namx = de->name;
195 inumber = de->inode;
196 }
197 if (!inumber)
174 continue; 198 continue;
175 if (namecompare(namelen,sbi->s_namelen,name,de->name)) 199 if (namecompare(namelen, sbi->s_namelen, name, namx))
176 goto found; 200 goto found;
177 } 201 }
178 dir_put_page(page); 202 dir_put_page(page);
@@ -181,7 +205,7 @@ minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page)
181 205
182found: 206found:
183 *res_page = page; 207 *res_page = page;
184 return de; 208 return (minix_dirent *)p;
185} 209}
186 210
187int minix_add_link(struct dentry *dentry, struct inode *inode) 211int minix_add_link(struct dentry *dentry, struct inode *inode)
@@ -192,12 +216,15 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
192 struct super_block * sb = dir->i_sb; 216 struct super_block * sb = dir->i_sb;
193 struct minix_sb_info * sbi = minix_sb(sb); 217 struct minix_sb_info * sbi = minix_sb(sb);
194 struct page *page = NULL; 218 struct page *page = NULL;
195 struct minix_dir_entry * de;
196 unsigned long npages = dir_pages(dir); 219 unsigned long npages = dir_pages(dir);
197 unsigned long n; 220 unsigned long n;
198 char *kaddr; 221 char *kaddr, *p;
222 minix_dirent *de;
223 minix3_dirent *de3;
199 unsigned from, to; 224 unsigned from, to;
200 int err; 225 int err;
226 char *namx = NULL;
227 __u32 inumber;
201 228
202 /* 229 /*
203 * We take care of directory expansion in the same loop 230 * We take care of directory expansion in the same loop
@@ -205,7 +232,7 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
205 * to protect that region. 232 * to protect that region.
206 */ 233 */
207 for (n = 0; n <= npages; n++) { 234 for (n = 0; n <= npages; n++) {
208 char *dir_end; 235 char *limit, *dir_end;
209 236
210 page = dir_get_page(dir, n); 237 page = dir_get_page(dir, n);
211 err = PTR_ERR(page); 238 err = PTR_ERR(page);
@@ -214,20 +241,30 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
214 lock_page(page); 241 lock_page(page);
215 kaddr = (char*)page_address(page); 242 kaddr = (char*)page_address(page);
216 dir_end = kaddr + minix_last_byte(dir, n); 243 dir_end = kaddr + minix_last_byte(dir, n);
217 de = (minix_dirent *)kaddr; 244 limit = kaddr + PAGE_CACHE_SIZE - sbi->s_dirsize;
218 kaddr += PAGE_CACHE_SIZE - sbi->s_dirsize; 245 for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
219 while ((char *)de <= kaddr) { 246 de = (minix_dirent *)p;
220 if ((char *)de == dir_end) { 247 de3 = (minix3_dirent *)p;
248 if (sbi->s_version == MINIX_V3) {
249 namx = de3->name;
250 inumber = de3->inode;
251 } else {
252 namx = de->name;
253 inumber = de->inode;
254 }
255 if (p == dir_end) {
221 /* We hit i_size */ 256 /* We hit i_size */
222 de->inode = 0; 257 if (sbi->s_version == MINIX_V3)
258 de3->inode = 0;
259 else
260 de->inode = 0;
223 goto got_it; 261 goto got_it;
224 } 262 }
225 if (!de->inode) 263 if (!inumber)
226 goto got_it; 264 goto got_it;
227 err = -EEXIST; 265 err = -EEXIST;
228 if (namecompare(namelen,sbi->s_namelen,name,de->name)) 266 if (namecompare(namelen, sbi->s_namelen, name, namx))
229 goto out_unlock; 267 goto out_unlock;
230 de = minix_next_entry(de, sbi);
231 } 268 }
232 unlock_page(page); 269 unlock_page(page);
233 dir_put_page(page); 270 dir_put_page(page);
@@ -236,14 +273,19 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
236 return -EINVAL; 273 return -EINVAL;
237 274
238got_it: 275got_it:
239 from = (char*)de - (char*)page_address(page); 276 from = p - (char*)page_address(page);
240 to = from + sbi->s_dirsize; 277 to = from + sbi->s_dirsize;
241 err = page->mapping->a_ops->prepare_write(NULL, page, from, to); 278 err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
242 if (err) 279 if (err)
243 goto out_unlock; 280 goto out_unlock;
244 memcpy (de->name, name, namelen); 281 memcpy (namx, name, namelen);
245 memset (de->name + namelen, 0, sbi->s_dirsize - namelen - 2); 282 if (sbi->s_version == MINIX_V3) {
246 de->inode = inode->i_ino; 283 memset (namx + namelen, 0, sbi->s_dirsize - namelen - 4);
284 de3->inode = inode->i_ino;
285 } else {
286 memset (namx + namelen, 0, sbi->s_dirsize - namelen - 2);
287 de->inode = inode->i_ino;
288 }
247 err = dir_commit_chunk(page, from, to); 289 err = dir_commit_chunk(page, from, to);
248 dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; 290 dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
249 mark_inode_dirty(dir); 291 mark_inode_dirty(dir);
@@ -283,8 +325,7 @@ int minix_make_empty(struct inode *inode, struct inode *dir)
283{ 325{
284 struct address_space *mapping = inode->i_mapping; 326 struct address_space *mapping = inode->i_mapping;
285 struct page *page = grab_cache_page(mapping, 0); 327 struct page *page = grab_cache_page(mapping, 0);
286 struct minix_sb_info * sbi = minix_sb(inode->i_sb); 328 struct minix_sb_info *sbi = minix_sb(inode->i_sb);
287 struct minix_dir_entry * de;
288 char *kaddr; 329 char *kaddr;
289 int err; 330 int err;
290 331
@@ -299,12 +340,23 @@ int minix_make_empty(struct inode *inode, struct inode *dir)
299 kaddr = kmap_atomic(page, KM_USER0); 340 kaddr = kmap_atomic(page, KM_USER0);
300 memset(kaddr, 0, PAGE_CACHE_SIZE); 341 memset(kaddr, 0, PAGE_CACHE_SIZE);
301 342
302 de = (struct minix_dir_entry *)kaddr; 343 if (sbi->s_version == MINIX_V3) {
303 de->inode = inode->i_ino; 344 minix3_dirent *de3 = (minix3_dirent *)kaddr;
304 strcpy(de->name,"."); 345
305 de = minix_next_entry(de, sbi); 346 de3->inode = inode->i_ino;
306 de->inode = dir->i_ino; 347 strcpy(de3->name, ".");
307 strcpy(de->name,".."); 348 de3 = minix_next_entry(de3, sbi);
349 de3->inode = dir->i_ino;
350 strcpy(de3->name, "..");
351 } else {
352 minix_dirent *de = (minix_dirent *)kaddr;
353
354 de->inode = inode->i_ino;
355 strcpy(de->name, ".");
356 de = minix_next_entry(de, sbi);
357 de->inode = dir->i_ino;
358 strcpy(de->name, "..");
359 }
308 kunmap_atomic(kaddr, KM_USER0); 360 kunmap_atomic(kaddr, KM_USER0);
309 361
310 err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize); 362 err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize);
@@ -321,33 +373,41 @@ int minix_empty_dir(struct inode * inode)
321 struct page *page = NULL; 373 struct page *page = NULL;
322 unsigned long i, npages = dir_pages(inode); 374 unsigned long i, npages = dir_pages(inode);
323 struct minix_sb_info *sbi = minix_sb(inode->i_sb); 375 struct minix_sb_info *sbi = minix_sb(inode->i_sb);
376 char *name;
377 __u32 inumber;
324 378
325 for (i = 0; i < npages; i++) { 379 for (i = 0; i < npages; i++) {
326 char *kaddr; 380 char *p, *kaddr, *limit;
327 minix_dirent * de;
328 page = dir_get_page(inode, i);
329 381
382 page = dir_get_page(inode, i);
330 if (IS_ERR(page)) 383 if (IS_ERR(page))
331 continue; 384 continue;
332 385
333 kaddr = (char *)page_address(page); 386 kaddr = (char *)page_address(page);
334 de = (minix_dirent *)kaddr; 387 limit = kaddr + minix_last_byte(inode, i) - sbi->s_dirsize;
335 kaddr += minix_last_byte(inode, i) - sbi->s_dirsize; 388 for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
389 if (sbi->s_version == MINIX_V3) {
390 minix3_dirent *de3 = (minix3_dirent *)p;
391 name = de3->name;
392 inumber = de3->inode;
393 } else {
394 minix_dirent *de = (minix_dirent *)p;
395 name = de->name;
396 inumber = de->inode;
397 }
336 398
337 while ((char *)de <= kaddr) { 399 if (inumber != 0) {
338 if (de->inode != 0) {
339 /* check for . and .. */ 400 /* check for . and .. */
340 if (de->name[0] != '.') 401 if (name[0] != '.')
341 goto not_empty; 402 goto not_empty;
342 if (!de->name[1]) { 403 if (!name[1]) {
343 if (de->inode != inode->i_ino) 404 if (inumber != inode->i_ino)
344 goto not_empty; 405 goto not_empty;
345 } else if (de->name[1] != '.') 406 } else if (name[1] != '.')
346 goto not_empty; 407 goto not_empty;
347 else if (de->name[2]) 408 else if (name[2])
348 goto not_empty; 409 goto not_empty;
349 } 410 }
350 de = minix_next_entry(de, sbi);
351 } 411 }
352 dir_put_page(page); 412 dir_put_page(page);
353 } 413 }