From f50c1ececf8477b20e5c0263ff60134f86c17067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Sun, 27 Aug 2006 22:04:34 +0000 Subject: [PATCH] initial port of dosfs to Haiku, read is working, write not yet please use carefully! git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18655 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/file_systems/dos/Jamfile | 4 + src/add-ons/kernel/file_systems/dos/attr.c | 118 +++++-- src/add-ons/kernel/file_systems/dos/attr.h | 28 +- src/add-ons/kernel/file_systems/dos/cache.h | 108 ------ src/add-ons/kernel/file_systems/dos/dir.c | 53 +-- src/add-ons/kernel/file_systems/dos/dir.h | 22 +- src/add-ons/kernel/file_systems/dos/dlist.c | 2 +- src/add-ons/kernel/file_systems/dos/dosfs.c | 324 ++++++++++++------ src/add-ons/kernel/file_systems/dos/dosfs.h | 33 +- src/add-ons/kernel/file_systems/dos/fat.c | 90 +++-- src/add-ons/kernel/file_systems/dos/file.c | 314 ++++++++++++++--- src/add-ons/kernel/file_systems/dos/file.h | 33 +- src/add-ons/kernel/file_systems/dos/fsproto.h | 245 ------------- src/add-ons/kernel/file_systems/dos/iter.c | 94 +++-- src/add-ons/kernel/file_systems/dos/iter.h | 6 +- src/add-ons/kernel/file_systems/dos/kalloc.h | 23 -- src/add-ons/kernel/file_systems/dos/lock.h | 46 --- src/add-ons/kernel/file_systems/dos/util.c | 7 +- src/add-ons/kernel/file_systems/dos/util.h | 3 +- src/add-ons/kernel/file_systems/dos/vcache.c | 5 +- 20 files changed, 789 insertions(+), 769 deletions(-) delete mode 100644 src/add-ons/kernel/file_systems/dos/cache.h delete mode 100644 src/add-ons/kernel/file_systems/dos/fsproto.h delete mode 100644 src/add-ons/kernel/file_systems/dos/kalloc.h delete mode 100644 src/add-ons/kernel/file_systems/dos/lock.h diff --git a/src/add-ons/kernel/file_systems/dos/Jamfile b/src/add-ons/kernel/file_systems/dos/Jamfile index 2939121ed0..9a34bf2b9b 100644 --- a/src/add-ons/kernel/file_systems/dos/Jamfile +++ b/src/add-ons/kernel/file_systems/dos/Jamfile @@ -1,5 +1,9 @@ SubDir HAIKU_TOP src add-ons kernel file_systems dos ; +UsePrivateHeaders kernel ; + +SubDirCcFlags -DTRACK_FILENAME ; + KernelAddon dos : kernel file_systems : attr.c dir.c diff --git a/src/add-ons/kernel/file_systems/dos/attr.c b/src/add-ons/kernel/file_systems/dos/attr.c index f394910946..7c63218d27 100644 --- a/src/add-ons/kernel/file_systems/dos/attr.c +++ b/src/add-ons/kernel/file_systems/dos/attr.c @@ -18,13 +18,12 @@ #include #include -#include -#include - #include "dosfs.h" #include "attr.h" #include "mime_table.h" +int32 kBeOSTypeCookie = 0x1234; + #define DPRINTF(a,b) if (debug_attr > (a)) dprintf b status_t set_mime_type(vnode *node, const char *filename) @@ -56,7 +55,9 @@ status_t set_mime_type(vnode *node, const char *filename) return B_OK; } -int dosfs_open_attrdir(void *_vol, void *_node, void **_cookie) + +status_t +dosfs_open_attrdir(void *_vol, void *_node, void **_cookie) { nspace *vol = (nspace *)_vol; @@ -82,7 +83,8 @@ int dosfs_open_attrdir(void *_vol, void *_node, void **_cookie) return 0; } -int dosfs_close_attrdir(void *_vol, void *_node, void *_cookie) +status_t +dosfs_close_attrdir(void *_vol, void *_node, void *_cookie) { nspace *vol = (nspace *)_vol; @@ -104,7 +106,9 @@ int dosfs_close_attrdir(void *_vol, void *_node, void *_cookie) return 0; } -int dosfs_free_attrcookie(void *_vol, void *_node, void *_cookie) + +status_t +dosfs_free_attrdir_cookie(void *_vol, void *_node, void *_cookie) { TOUCH(_vol); TOUCH(_node); @@ -121,7 +125,9 @@ int dosfs_free_attrcookie(void *_vol, void *_node, void *_cookie) return 0; } -int dosfs_rewind_attrdir(void *_vol, void *_node, void *_cookie) + +status_t +dosfs_rewind_attrdir(void *_vol, void *_node, void *_cookie) { TOUCH(_vol); TOUCH(_node); @@ -136,8 +142,10 @@ int dosfs_rewind_attrdir(void *_vol, void *_node, void *_cookie) return 0; } -int dosfs_read_attrdir(void *_vol, void *_node, void *_cookie, long *num, - struct dirent *entry, size_t bufsize) + +status_t +dosfs_read_attrdir(void *_vol, void *_node, void *_cookie, + struct dirent *entry, size_t bufsize, uint32 *num) { nspace *vol = (nspace *)_vol; vnode *node = (vnode *)_node; @@ -173,20 +181,60 @@ int dosfs_read_attrdir(void *_vol, void *_node, void *_cookie, long *num, return 0; } -int dosfs_stat_attr(void *_vol, void *_node, const char *name, struct attr_info *buf) + +status_t +dosfs_open_attr(void *_vol, void *_node, const char *name, int openMode, + fs_cookie *_cookie) { nspace *vol = (nspace *)_vol; vnode *node = (vnode *)_node; - DPRINTF(0, ("dosfs_stat_attr (%s)\n", name)); - if (strcmp(name, "BEOS:TYPE")) return ENOENT; + + LOCK_VOL(vol); + + if (node->mime == NULL) { + UNLOCK_VOL(vol); + return ENOENT; + } + + UNLOCK_VOL(vol); + + *_cookie = &kBeOSTypeCookie; + return B_OK; +} + + +status_t +dosfs_close_attr(void *_vol, void *_node, fs_cookie cookie) +{ + return B_OK; +} + + +status_t +dosfs_free_attr_cookie(void *_vol, void *_node, fs_cookie cookie) +{ + return B_OK; +} + + +status_t +dosfs_read_attr_stat(void *_vol, void *_node, fs_cookie _cookie, struct stat *stat) +{ + nspace *vol = (nspace *)_vol; + vnode *node = (vnode *)_node; + + DPRINTF(0, ("dosfs_read_attr_stat\n")); + + if (_cookie != &kBeOSTypeCookie) + return ENOENT; LOCK_VOL(vol); - if (check_nspace_magic(vol, "dosfs_read_attr") || - check_vnode_magic(node, "dosfs_read_attr")) { + if (check_nspace_magic(vol, "dosfs_read_attr_stat") || + check_vnode_magic(node, "dosfs_read_attr_stat")) { UNLOCK_VOL(vol); return EINVAL; } @@ -196,27 +244,26 @@ int dosfs_stat_attr(void *_vol, void *_node, const char *name, struct attr_info return ENOENT; } - buf->type = MIME_STRING_TYPE; - buf->size = strlen(node->mime) + 1; + stat->st_type = MIME_STRING_TYPE; + stat->st_size = strlen(node->mime) + 1; UNLOCK_VOL(vol); return 0; } -int dosfs_read_attr(void *_vol, void *_node, const char *name, int type, void *buf, - size_t *len, off_t pos) + +status_t +dosfs_read_attr(void *_vol, void *_node, fs_cookie _cookie, off_t pos, + void *buffer, size_t *_length) { nspace *vol = (nspace *)_vol; vnode *node = (vnode *)_node; - DPRINTF(0, ("dosfs_read_attr (%s)\n", name)); + DPRINTF(0, ("dosfs_read_attr\n")); - if (strcmp(name, "BEOS:TYPE")) + if (_cookie != &kBeOSTypeCookie) return ENOENT; - if (type != MIME_STRING_TYPE) - return ENOENT; - LOCK_VOL(vol); if (check_nspace_magic(vol, "dosfs_read_attr") || @@ -235,9 +282,9 @@ int dosfs_read_attr(void *_vol, void *_node, const char *name, int type, void *b return EINVAL; } - strncpy(buf, node->mime + pos, *len - 1); - ((char *)buf)[*len - 1] = 0; - *len = strlen(buf) + 1; + strncpy(buffer, node->mime + pos, *_length - 1); + ((char *)buffer)[*_length - 1] = 0; + *_length = strlen(buffer) + 1; UNLOCK_VOL(vol); return 0; @@ -245,21 +292,16 @@ int dosfs_read_attr(void *_vol, void *_node, const char *name, int type, void *b // suck up application attempts to set mime types; this hides an unsightly // error message printed out by zip -int dosfs_write_attr(void *_vol, void *_node, const char *name, int type, - const void *buf, size_t *len, off_t pos) +status_t +dosfs_write_attr(void *_vol, void *_node, fs_cookie _cookie, off_t pos, + const void *buffer, size_t *_length) { - TOUCH(_vol); TOUCH(_node); TOUCH(name); TOUCH(type); TOUCH(buf); - TOUCH(len); TOUCH(pos); + DPRINTF(0, ("dosfs_write_attr\n")); - DPRINTF(0, ("dosfs_write_attr (%s)\n", name)); + *_length = 0; - *len = 0; - - if (strcmp(name, "BEOS:TYPE")) + if (_cookie != &kBeOSTypeCookie) return ENOSYS; - if (type != MIME_STRING_TYPE) - return ENOSYS; - - return 0; + return B_OK; } diff --git a/src/add-ons/kernel/file_systems/dos/attr.h b/src/add-ons/kernel/file_systems/dos/attr.h index 6f9c60dcb3..61037c7c7f 100644 --- a/src/add-ons/kernel/file_systems/dos/attr.h +++ b/src/add-ons/kernel/file_systems/dos/attr.h @@ -5,18 +5,24 @@ #ifndef _DOSFS_ATTR_H_ #define _DOSFS_ATTR_H_ +#include + status_t set_mime_type(vnode *node, const char *filename); -int dosfs_open_attrdir(void *_vol, void *_node, void **_cookie); -int dosfs_close_attrdir(void *_vol, void *_node, void *_cookie); -int dosfs_free_attrcookie(void *_vol, void *_node, void *_cookie); -int dosfs_rewind_attrdir(void *_vol, void *_node, void *_cookie); -int dosfs_read_attrdir(void *_vol, void *_node, void *_cookie, long *num, - struct dirent *buf, size_t bufsize); -int dosfs_stat_attr(void *_vol, void *_node, const char *name, struct attr_info *buf); -int dosfs_read_attr(void *_vol, void *_node, const char *name, int type, void *buf, - size_t *len, off_t pos); -int dosfs_write_attr(void *_vol, void *_node, const char *name, int type, - const void *buf, size_t *len, off_t pos); +status_t dosfs_open_attrdir(void *_vol, void *_node, void **_cookie); +status_t dosfs_close_attrdir(void *_vol, void *_node, void *_cookie); +status_t dosfs_free_attrdir_cookie(void *_vol, void *_node, void *_cookie); +status_t dosfs_rewind_attrdir(void *_vol, void *_node, void *_cookie); +status_t dosfs_read_attrdir(void *_vol, void *_node, void *_cookie, + struct dirent *buf, size_t bufsize, uint32 *num); +status_t dosfs_open_attr(void *_vol, void *_node, const char *name, int openMode, + fs_cookie *_cookie); +status_t dosfs_close_attr(void *_vol, void *_node, fs_cookie cookie); +status_t dosfs_free_attr_cookie(void *_vol, void *_node, fs_cookie cookie); +status_t dosfs_read_attr_stat(void *_vol, void *_node, fs_cookie _cookie, struct stat *stat); +status_t dosfs_read_attr(void *_vol, void *_node, fs_cookie _cookie, off_t pos, + void *buffer, size_t *_length); +status_t dosfs_write_attr(void *_vol, void *_node, fs_cookie _cookie, off_t pos, + const void *buffer, size_t *_length); #endif diff --git a/src/add-ons/kernel/file_systems/dos/cache.h b/src/add-ons/kernel/file_systems/dos/cache.h deleted file mode 100644 index 19e5c9f6f5..0000000000 --- a/src/add-ons/kernel/file_systems/dos/cache.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - Copyright 1999-2001, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ - -#ifndef _CACHE_H_ -#define _CACHE_H_ - -#include - -typedef struct hash_ent { - int dev; - off_t bnum; - off_t hash_val; - void *data; - struct hash_ent *next; -} hash_ent; - - -typedef struct hash_table { - hash_ent **table; - int max; - int mask; /* == max - 1 */ - int num_elements; -} hash_table; - - -#define HT_DEFAULT_MAX 128 - - -typedef struct cache_ent { - int dev; - off_t block_num; - int bsize; - volatile int flags; - - void *data; - void *clone; /* copy of data by set_block_info() */ - int lock; - - void (*func)(off_t bnum, size_t num_blocks, void *arg); - off_t logged_bnum; - void *arg; - - struct cache_ent *next, /* points toward mru end of list */ - *prev; /* points toward lru end of list */ - -} cache_ent; - -#define CE_NORMAL 0x0000 /* a nice clean pristine page */ -#define CE_DIRTY 0x0002 /* needs to be written to disk */ -#define CE_BUSY 0x0004 /* this block has i/o happening, don't touch it */ - - -typedef struct cache_ent_list { - cache_ent *lru; /* tail of the list */ - cache_ent *mru; /* head of the list */ -} cache_ent_list; - - -typedef struct block_cache { - lock lock; - int flags; - int cur_blocks; - int max_blocks; - hash_table ht; - - cache_ent_list normal, /* list of "normal" blocks (clean & dirty) */ - locked; /* list of clean and locked blocks */ -} block_cache; - -#if 0 /* XXXdbg -- need to deal with write through caches */ -#define DC_WRITE_THROUGH 0x0001 /* cache is write-through (for floppies) */ -#endif - -#define ALLOW_WRITES 1 -#define NO_WRITES 0 - -extern _IMPEXP_KERNEL int init_block_cache(int max_blocks, int flags); -extern _IMPEXP_KERNEL void shutdown_block_cache(void); - -extern _IMPEXP_KERNEL void force_cache_flush(int dev, int prefer_log_blocks); -extern _IMPEXP_KERNEL int flush_blocks(int dev, off_t bnum, int nblocks); -extern _IMPEXP_KERNEL int flush_device(int dev, int warn_locked); - -extern _IMPEXP_KERNEL int init_cache_for_device(int fd, off_t max_blocks); -extern _IMPEXP_KERNEL int remove_cached_device_blocks(int dev, int allow_write); - -extern _IMPEXP_KERNEL void *get_block(int dev, off_t bnum, int bsize); -extern _IMPEXP_KERNEL void *get_empty_block(int dev, off_t bnum, int bsize); -extern _IMPEXP_KERNEL int release_block(int dev, off_t bnum); -extern _IMPEXP_KERNEL int mark_blocks_dirty(int dev, off_t bnum, int nblocks); - - -extern _IMPEXP_KERNEL int cached_read(int dev, off_t bnum, void *data, off_t num_blocks, int bsize); -extern _IMPEXP_KERNEL int cached_write(int dev, off_t bnum, const void *data, - off_t num_blocks, int bsize); -extern _IMPEXP_KERNEL int cached_write_locked(int dev, off_t bnum, const void *data, - off_t num_blocks, int bsize); -extern _IMPEXP_KERNEL int set_blocks_info(int dev, off_t *blocks, int nblocks, - void (*func)(off_t bnum, size_t nblocks, void *arg), - void *arg); - - -extern _IMPEXP_KERNEL size_t read_phys_blocks (int fd, off_t bnum, void *data, uint num_blocks, int bsize); -extern _IMPEXP_KERNEL size_t write_phys_blocks(int fd, off_t bnum, void *data, uint num_blocks, int bsize); - -#endif /* _CACHE_H_ */ diff --git a/src/add-ons/kernel/file_systems/dos/dir.c b/src/add-ons/kernel/file_systems/dos/dir.c index 875ce35be5..c209547a59 100644 --- a/src/add-ons/kernel/file_systems/dos/dir.c +++ b/src/add-ons/kernel/file_systems/dos/dir.c @@ -4,12 +4,10 @@ */ #include -#include -#include -#include - #include #include +#include +#include #include #include #include @@ -846,7 +844,9 @@ status_t create_dir_entry(nspace *vol, vnode *dir, vnode *node, return _create_dir_entry_(vol, dir, &info, (char *)nshort, (char *)nlong, len, ns, ne); } -int dosfs_read_vnode(void *_vol, vnode_id vnid, char reenter, void **_node) + +status_t +dosfs_read_vnode(void *_vol, vnode_id vnid, void **_node, bool reenter) { nspace *vol = (nspace*)_vol; int result = B_NO_ERROR; @@ -956,6 +956,7 @@ int dosfs_read_vnode(void *_vol, vnode_id vnid, char reenter, void **_node) entry->filename = malloc(sizeof(filename) + 1); if (entry->filename) strcpy(entry->filename, filename); #endif + entry->cache = file_cache_create(vol->id, vnid, entry->st_size, vol->fd); if(!(entry->mode & FAT_SUBDIR)) set_mime_type(entry, filename); @@ -969,17 +970,16 @@ bi: if (!reenter) UNLOCK_VOL(vol); return result; } -int dosfs_walk(void *_vol, void *_dir, const char *file, char **newpath, vnode_id *vnid) + +status_t +dosfs_walk(void *_vol, void *_dir, const char *file, vnode_id *_vnid, int *_type) { /* Starting at the base, find file in the subdir, and return path string and vnode id of file. */ nspace *vol = (nspace*)_vol; vnode *dir = (vnode*)_dir; vnode *vnode = NULL; - int result = ENOENT; - - /* we can ignore newpath since there are no symbolic links */ - TOUCH(newpath); + status_t result = ENOENT; LOCK_VOL(vol); @@ -991,11 +991,11 @@ int dosfs_walk(void *_vol, void *_dir, const char *file, char **newpath, vnode_i DPRINTF(0, ("dosfs_walk: find %Lx/%s\n", dir->vnid, file)); - result = findfile_case(vol, dir, file, vnid, &vnode); + result = findfile_case(vol, dir, file, _vnid, &vnode); if (result != B_OK) { DPRINTF(0, ("dosfs_walk (%s)\n", strerror(result))); } else { - DPRINTF(0, ("dosfs_walk: found vnid %Lx\n", *vnid)); + DPRINTF(0, ("dosfs_walk: found vnid %Lx\n", *_vnid)); } UNLOCK_VOL(vol); @@ -1003,7 +1003,8 @@ int dosfs_walk(void *_vol, void *_dir, const char *file, char **newpath, vnode_i return result; } -int dosfs_access(void *_vol, void *_node, int mode) +status_t +dosfs_access(void *_vol, void *_node, int mode) { status_t result = B_OK; nspace *vol = (nspace *)_vol; @@ -1037,7 +1038,9 @@ int dosfs_access(void *_vol, void *_node, int mode) return result; } -int dosfs_readlink(void *_vol, void *_node, char *buf, size_t *bufsize) + +status_t +dosfs_readlink(void *_vol, void *_node, char *buf, size_t *bufsize) { TOUCH(_vol); TOUCH(_node); TOUCH(buf); TOUCH(bufsize); @@ -1047,7 +1050,9 @@ int dosfs_readlink(void *_vol, void *_node, char *buf, size_t *bufsize) return EINVAL; } -int dosfs_opendir(void *_vol, void *_node, void **_cookie) + +status_t +dosfs_opendir(void *_vol, void *_node, void **_cookie) { nspace *vol = (nspace*)_vol; vnode *node = (vnode*)_node; @@ -1102,8 +1107,10 @@ bi: return result; } -int dosfs_readdir(void *_vol, void *_dir, void *_cookie, long *num, - struct dirent *entry, size_t bufsize) + +status_t +dosfs_readdir(void *_vol, void *_dir, void *_cookie, + struct dirent *entry, size_t bufsize, uint32 *num) { int result = ENOENT; nspace* vol = (nspace*)_vol; @@ -1171,7 +1178,9 @@ bi: return result; } -int dosfs_rewinddir(void *_vol, void *_node, void* _cookie) + +status_t +dosfs_rewinddir(void *_vol, void *_node, void* _cookie) { nspace *vol = _vol; vnode *node = _node; @@ -1195,7 +1204,9 @@ int dosfs_rewinddir(void *_vol, void *_node, void* _cookie) return B_OK; } -int dosfs_closedir(void *_vol, void *_node, void *_cookie) + +status_t +dosfs_closedir(void *_vol, void *_node, void *_cookie) { TOUCH(_vol); TOUCH(_node); TOUCH(_cookie); @@ -1204,7 +1215,9 @@ int dosfs_closedir(void *_vol, void *_node, void *_cookie) return 0; } -int dosfs_free_dircookie(void *_vol, void *node, void *_cookie) + +status_t +dosfs_free_dircookie(void *_vol, void *node, void *_cookie) { nspace *vol = _vol; dircookie *cookie = _cookie; diff --git a/src/add-ons/kernel/file_systems/dos/dir.h b/src/add-ons/kernel/file_systems/dos/dir.h index 5683c7b398..361530049f 100644 --- a/src/add-ons/kernel/file_systems/dos/dir.h +++ b/src/add-ons/kernel/file_systems/dos/dir.h @@ -21,16 +21,16 @@ status_t create_volume_label(nspace *vol, const char name[11], uint32 *index); status_t create_dir_entry(nspace *vol, vnode *dir, vnode *node, const char *name, uint32 *ns, uint32 *ne); -int dosfs_read_vnode(void *_vol, vnode_id vnid, char r, void **node); -int dosfs_walk(void *_vol, void *_dir, const char *file, - char **newpath, vnode_id *vnid); -int dosfs_access(void *_vol, void *_node, int mode); -int dosfs_readlink(void *_vol, void *_node, char *buf, size_t *bufsize); -int dosfs_opendir(void *_vol, void *_node, void **cookie); -int dosfs_readdir(void *_vol, void *_node, void *cookie, - long *num, struct dirent *buf, size_t bufsize); -int dosfs_rewinddir(void *_vol, void *_node, void *cookie); -int dosfs_closedir(void *_vol, void *_node, void *cookie); -int dosfs_free_dircookie(void *_vol, void *_node, void *cookie); +status_t dosfs_read_vnode(void *_vol, vnode_id vnid, void **node, bool reenter); +status_t dosfs_walk(void *_vol, void *_dir, const char *file, + vnode_id *_vnid, int *_type); +status_t dosfs_access(void *_vol, void *_node, int mode); +status_t dosfs_readlink(void *_vol, void *_node, char *buf, size_t *bufsize); +status_t dosfs_opendir(void *_vol, void *_node, void **cookie); +status_t dosfs_readdir(void *_vol, void *_node, void *cookie, + struct dirent *buf, size_t bufsize, uint32 *num); +status_t dosfs_rewinddir(void *_vol, void *_node, void *cookie); +status_t dosfs_closedir(void *_vol, void *_node, void *cookie); +status_t dosfs_free_dircookie(void *_vol, void *_node, void *cookie); #endif diff --git a/src/add-ons/kernel/file_systems/dos/dlist.c b/src/add-ons/kernel/file_systems/dos/dlist.c index c9a4512970..0a09d4e9eb 100644 --- a/src/add-ons/kernel/file_systems/dos/dlist.c +++ b/src/add-ons/kernel/file_systems/dos/dlist.c @@ -20,8 +20,8 @@ TODO: #define DPRINTF(a,b) if (debug_dlist > (a)) dprintf b #include -#include +#include #include #include "dosfs.h" diff --git a/src/add-ons/kernel/file_systems/dos/dosfs.c b/src/add-ons/kernel/file_systems/dos/dosfs.c index f08da2345c..83e2bd7259 100644 --- a/src/add-ons/kernel/file_systems/dos/dosfs.c +++ b/src/add-ons/kernel/file_systems/dos/dosfs.c @@ -14,12 +14,10 @@ #include -#include -#ifndef COMPILE_IN_BEOS +#include +#include +#include #include -#endif -#include -#include #include "dosfs.h" #include "attr.h" @@ -49,7 +47,7 @@ static status_t get_fsinfo(nspace *vol, uint32 *free_count, uint32 *last_allocat int32 instances = 0; -int debug_dos(int argc, char **argv) +static int debug_dos(int argc, char **argv) { int i; for (i=1;ifd, (off_t)vol->total_sectors) < 0) { + vol->fBlockCache = block_cache_create(vol->fd, vol->total_sectors, vol->bytes_per_sector); + if (vol->fBlockCache == NULL) { dprintf("error initializing block cache\n"); goto error; } @@ -537,7 +536,7 @@ error3: error2: uninit_vcache(vol); error1: - remove_cached_device_blocks(vol->fd, NO_WRITES); + block_cache_delete(vol->fBlockCache, false); error: if (!(vol->flags & B_FS_IS_READONLY) && (vol->flags & B_FS_IS_REMOVABLE) && (vol->fs_flags & FS_FLAGS_LOCK_DOOR)) lock_removable_device(vol->fd, false); @@ -547,8 +546,36 @@ error0: return (err >= B_NO_ERROR) ? EINVAL : err; } -static int dosfs_mount(nspace_id nsid, const char *device, ulong flags, void *parms, - size_t len, void **data, vnode_id *vnid) + +// #pragma mark - Scanning + + +static float +dosfs_identify_partition(int fd, partition_data *partition, void **_cookie) +{ + return 0.0f; +} + + +static status_t +dosfs_scan_partition(int fd, partition_data *partition, void *_cookie) +{ + return B_OK; +} + + +static void +dosfs_free_identify_partition_cookie(partition_data *partition, void *_cookie) +{ +} + + +// #pragma mark - + + +static status_t +dosfs_mount(mount_id nsid, const char *device, uint32 flags, + const char *args, void **_data, vnode_id *_rootID) { int result; nspace *vol; @@ -579,17 +606,17 @@ static int dosfs_mount(nspace_id nsid, const char *device, ulong flags, void *pa } unload_driver_settings(handle); - - /* parms and len are command line options; dosfs doesn't use any so + + /* args is a command line option; dosfs doesn't use any so we can ignore these arguments */ - TOUCH(parms); TOUCH(len); + TOUCH(args); #if __RO__ // make it read-only flags |= 1; #endif - if (data == NULL) { + if (_data == NULL) { dprintf("dosfs_mount passed NULL data pointer\n"); return EINVAL; } @@ -600,17 +627,17 @@ static int dosfs_mount(nspace_id nsid, const char *device, ulong flags, void *pa if (check_nspace_magic(vol, "dosfs_mount")) return EINVAL; - *vnid = vol->root_vnode.vnid; - *data = (void*)vol; + *_rootID = vol->root_vnode.vnid; + *_data = (void*)vol; // You MUST do this. Create the vnode for the root. - result = new_vnode(nsid, *vnid, (void*)&(vol->root_vnode)); + result = publish_vnode(nsid, *_rootID, (void*)&(vol->root_vnode)); if (result != B_NO_ERROR) { dprintf("error creating new vnode (%s)\n", strerror(result)); goto error; } sprintf(name, "fat lock %lx", vol->id); - if ((result = new_lock(&(vol->vlock), name)) != 0) { + if ((result = recursive_lock_init(&(vol->vlock), name)) != 0) { dprintf("error creating lock (%s)\n", strerror(result)); goto error; } @@ -631,7 +658,7 @@ static int dosfs_mount(nspace_id nsid, const char *device, ulong flags, void *pa return result; error: - remove_cached_device_blocks(vol->fd, NO_WRITES); + block_cache_delete(vol->fBlockCache, false); dlist_uninit(vol); uninit_vcache(vol); free(vol); @@ -643,7 +670,9 @@ static void update_fsinfo(nspace *vol) if ((vol->fat_bits == 32) && (vol->fsinfo_sector != 0xffff) && ((vol->flags & B_FS_IS_READONLY) == false)) { uchar *buffer; - if ((buffer = (uchar *)get_block(vol->fd, vol->fsinfo_sector, vol->bytes_per_sector)) != NULL) { + int32 tid = cache_start_transaction(vol->fBlockCache); + if ((buffer = (uchar *)block_cache_get_writable_etc(vol->fBlockCache, + vol->fsinfo_sector, 0, vol->bytes_per_sector, tid)) != NULL) { if ((read32(buffer,0) == 0x41615252) && (read32(buffer,0x1e4) == 0x61417272) && (read16(buffer,0x1fe) == 0xaa55)) { //number of free clusters buffer[0x1e8] = (vol->free_clusters & 0xff); @@ -655,12 +684,14 @@ static void update_fsinfo(nspace *vol) buffer[0x1ed] = ((vol->last_allocated >> 8) & 0xff); buffer[0x1ee] = ((vol->last_allocated >> 16) & 0xff); buffer[0x1ef] = ((vol->last_allocated >> 24) & 0xff); - mark_blocks_dirty(vol->fd, vol->fsinfo_sector, 1); + block_cache_set_dirty(vol->fBlockCache, vol->fsinfo_sector, true, tid); } else { dprintf("update_fsinfo: fsinfo block has invalid magic number\n"); } - release_block(vol->fd, vol->fsinfo_sector); + block_cache_put(vol->fBlockCache, vol->fsinfo_sector); + cache_end_transaction(vol->fBlockCache, tid, NULL, NULL); } else { + cache_end_transaction(vol->fBlockCache, tid, NULL, NULL); dprintf("update_fsinfo: error getting fsinfo sector %x\n", vol->fsinfo_sector); } } @@ -674,7 +705,7 @@ static status_t get_fsinfo(nspace *vol, uint32 *free_count, uint32 *last_allocat if ((vol->fat_bits != 32) || (vol->fsinfo_sector == 0xffff)) return B_ERROR; - if ((buffer = (uchar *)get_block(vol->fd, vol->fsinfo_sector, vol->bytes_per_sector)) == NULL) { + if ((buffer = (uchar *)block_cache_get_etc(vol->fBlockCache, vol->fsinfo_sector, 0, vol->bytes_per_sector)) == NULL) { dprintf("get_fsinfo: error getting fsinfo sector %x\n", vol->fsinfo_sector); return EIO; } @@ -688,11 +719,13 @@ static status_t get_fsinfo(nspace *vol, uint32 *free_count, uint32 *last_allocat result = B_ERROR; } - release_block(vol->fd, vol->fsinfo_sector); + block_cache_put(vol->fBlockCache, vol->fsinfo_sector); return result; } -static int dosfs_unmount(void *_vol) + +static status_t +dosfs_unmount(void *_vol) { int result = B_NO_ERROR; @@ -708,8 +741,7 @@ static int dosfs_unmount(void *_vol) DPRINTF(0, ("dosfs_unmount volume %lx\n", vol->id)); update_fsinfo(vol); - flush_device(vol->fd, 0); - remove_cached_device_blocks(vol->fd, ALLOW_WRITES); + block_cache_delete(vol->fBlockCache, true); #if DEBUG if (atomic_add(&instances, -1) == 1) { @@ -727,7 +759,7 @@ static int dosfs_unmount(void *_vol) if (!(vol->flags & B_FS_IS_READONLY) && (vol->flags & B_FS_IS_REMOVABLE) && (vol->fs_flags & FS_FLAGS_LOCK_DOOR)) lock_removable_device(vol->fd, false); result = close(vol->fd); - free_lock(&(vol->vlock)); + recursive_lock_destroy(&(vol->vlock)); vol->magic = ~VNODE_MAGIC; free(vol); @@ -738,20 +770,21 @@ static int dosfs_unmount(void *_vol) return result; } -// dosfs_rfsstat - Fill in fs_info struct for device. -static int dosfs_rfsstat(void *_vol, struct fs_info * fss) +// dosfs_read_fs_stat - Fill in fs_info struct for device. +static status_t +dosfs_read_fs_stat(void *_vol, struct fs_info * fss) { nspace* vol = (nspace*)_vol; int i; LOCK_VOL(vol); - if (check_nspace_magic(vol, "dosfs_rfsstat")) { + if (check_nspace_magic(vol, "dosfs_read_fs_stat")) { UNLOCK_VOL(vol); return EINVAL; } - DPRINTF(1, ("dosfs_rfsstat called\n")); + DPRINTF(1, ("dosfs_read_fs_stat called\n")); // fss->dev and fss->root filled in by kernel @@ -793,22 +826,23 @@ static int dosfs_rfsstat(void *_vol, struct fs_info * fss) UNLOCK_VOL(vol); - return 0; + return B_OK; } -static int dosfs_wfsstat(void *_vol, struct fs_info * fss, long mask) +static status_t +dosfs_write_fs_stat(void *_vol, const struct fs_info * fss, uint32 mask) { - int result = B_ERROR; + status_t result = B_ERROR; nspace* vol = (nspace*)_vol; LOCK_VOL(vol); - if (check_nspace_magic(vol, "dosfs_wfsstat")) { + if (check_nspace_magic(vol, "dosfs_write_fs_stat")) { UNLOCK_VOL(vol); return EINVAL; } - DPRINTF(0, ("dosfs_wfsstat called\n")); + DPRINTF(0, ("dosfs_write_fs_stat called\n")); /* if it's a r/o file system and not the special hack, then don't allow * volume renaming */ @@ -817,7 +851,7 @@ static int dosfs_wfsstat(void *_vol, struct fs_info * fss, long mask) return EROFS; } - if (mask & WFSSTAT_NAME) { + if (mask & FS_WRITE_FSINFO_NAME) { // sanitize name char name[11]; int i,j; @@ -840,7 +874,9 @@ static int dosfs_wfsstat(void *_vol, struct fs_info * fss, long mask) if (vol->vol_entry == -1) { // stored in the bpb uchar *buffer; - if ((buffer = get_block(vol->fd, 0, vol->bytes_per_sector)) == NULL) { + int32 tid = cache_start_transaction(vol->fBlockCache); + if ((buffer = block_cache_get_writable_etc(vol->fBlockCache, 0, 0, vol->bytes_per_sector, tid)) == NULL) { + cache_end_transaction(vol->fBlockCache, tid, NULL, NULL); result = EIO; goto bi; } @@ -849,10 +885,11 @@ static int dosfs_wfsstat(void *_vol, struct fs_info * fss, long mask) result = B_ERROR; } else { memcpy(buffer + 0x2b, name, 11); - mark_blocks_dirty(vol->fd, 0, 1); + block_cache_set_dirty(vol->fBlockCache, 0, true, tid); result = 0; } - release_block(vol->fd, 0); + block_cache_put(vol->fBlockCache, 0); + cache_end_transaction(vol->fBlockCache, tid, NULL, NULL); } else if (vol->vol_entry >= 0) { struct diri diri; uint8 *buffer; @@ -887,7 +924,9 @@ bi: UNLOCK_VOL(vol); return result; } -static int dosfs_ioctl(void *_vol, void *_node, void *cookie, int code, + +static status_t +dosfs_ioctl(void *_vol, void *_node, void *cookie, ulong code, void *buf, size_t len) { status_t result = B_OK; @@ -912,9 +951,10 @@ static int dosfs_ioctl(void *_vol, void *_node, void *cookie, int code, if (buf) *(bigtime_t *)buf = node->st_time; break; - case 69666 : + /*case 69666 : result = fragment(vol, buf); break; + */ case 100000 : dprintf("built at %s on %s\n", build_time, build_date); @@ -970,7 +1010,7 @@ static int dosfs_ioctl(void *_vol, void *_node, void *cookie, int code, break; default : - dprintf("dosfs_ioctl: vol %lx, vnode %Lx code = %d\n", vol->id, node->vnid, code); + dprintf("dosfs_ioctl: vol %lx, vnode %Lx code = %ld\n", vol->id, node->vnid, code); result = EINVAL; break; } @@ -980,21 +1020,25 @@ static int dosfs_ioctl(void *_vol, void *_node, void *cookie, int code, return result; } -int _dosfs_sync(nspace *vol) + +status_t +_dosfs_sync(nspace *vol) { if (check_nspace_magic(vol, "dosfs_sync")) return EINVAL; update_fsinfo(vol); - flush_device(vol->fd, 0); + block_cache_sync(vol->fBlockCache); - return 0; + return B_OK; } -static int dosfs_sync(void *_vol) + +static status_t +dosfs_sync(void *_vol) { nspace *vol = (nspace *)_vol; - int err; + status_t err; DPRINTF(0, ("dosfs_sync called on volume %lx\n", vol->id)); @@ -1005,76 +1049,144 @@ static int dosfs_sync(void *_vol) return err; } -static int dosfs_fsync(void *vol, void *node) + +static status_t +dosfs_fsync(void *vol, void *node) { TOUCH(node); return dosfs_sync(vol); } -vnode_ops fs_entry = { - &dosfs_read_vnode, - &dosfs_write_vnode, - &dosfs_remove_vnode, - NULL, + +// #pragma mark - + + +static status_t +dos_std_ops(int32 op, ...) +{ + switch (op) { + case B_MODULE_INIT: + return B_OK; + case B_MODULE_UNINIT: + return B_OK; + + default: + return B_ERROR; + } +} + + +static file_system_module_info sDosFileSystem = { + { + "file_systems/dos" B_CURRENT_FS_API_VERSION, + 0, + dos_std_ops, + }, + + "FAT32 File System", + + // scanning + dosfs_identify_partition, + dosfs_scan_partition, + dosfs_free_identify_partition_cookie, + NULL, // free_partition_content_cookie() + + &dosfs_mount, + &dosfs_unmount, + &dosfs_read_fs_stat, + &dosfs_write_fs_stat, + &dosfs_sync, + + /* vnode operations */ &dosfs_walk, - &dosfs_access, - &dosfs_create, - &dosfs_mkdir, - NULL, - NULL, - &dosfs_rename, - &dosfs_unlink, - &dosfs_rmdir, + &dosfs_get_vnode_name, + &dosfs_read_vnode, + &dosfs_release_vnode, + &dosfs_remove_vnode, + + /* VM file access */ + NULL, //&fs_can_page, + NULL, //&fs_read_pages, + NULL, //&fs_write_pages, + + &dosfs_get_file_map, + + &dosfs_ioctl, + NULL, //&fs_set_flags, + NULL, //&fs_select + NULL, //&fs_deselect + &dosfs_fsync, + &dosfs_readlink, - &dosfs_opendir, - &dosfs_closedir, - &dosfs_free_dircookie, - &dosfs_rewinddir, - &dosfs_readdir, + NULL, // write link + NULL, //&fs_create_symlink, + + NULL, //&fs_link, + &dosfs_unlink, + &dosfs_rename, + + &dosfs_access, + &dosfs_rstat, + &dosfs_wstat, + + /* file operations */ + &dosfs_create, &dosfs_open, &dosfs_close, &dosfs_free_cookie, &dosfs_read, &dosfs_write, - NULL, - NULL, - &dosfs_ioctl, - NULL, - &dosfs_rstat, - &dosfs_wstat, - &dosfs_fsync, - NULL, - &dosfs_mount, - &dosfs_unmount, - &dosfs_sync, - &dosfs_rfsstat, - &dosfs_wfsstat, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, + + /* directory operations */ + &dosfs_mkdir, + &dosfs_rmdir, + &dosfs_opendir, + &dosfs_closedir, + &dosfs_free_dircookie, + &dosfs_readdir, + &dosfs_rewinddir, + + /* attribute directory operations */ &dosfs_open_attrdir, &dosfs_close_attrdir, - &dosfs_free_attrcookie, - &dosfs_rewind_attrdir, + &dosfs_free_attrdir_cookie, &dosfs_read_attrdir, - &dosfs_write_attr, + &dosfs_rewind_attrdir, + + /* attribute operations */ + NULL, //&fs_create_attr, + &dosfs_open_attr, + &dosfs_close_attr, + &dosfs_free_attr_cookie, &dosfs_read_attr, - NULL, - NULL, - &dosfs_stat_attr, - NULL, - NULL, - NULL, - NULL + &dosfs_write_attr, + + &dosfs_read_attr_stat, + NULL, //&fs_write_attr_stat, + NULL, //&fs_rename_attr, + NULL, //&fs_remove_attr, + + /* index directory & index operations */ + NULL, //&fs_open_index_dir, + NULL, //&fs_close_index_dir, + NULL, //&fs_free_index_dir_cookie, + NULL, //&fs_read_index_dir, + NULL, //&fs_rewind_index_dir, + + NULL, //&fs_create_index, + NULL, //&fs_remove_index, + NULL, //&fs_stat_index, + + /* query operations */ + NULL, //&fs_open_query, + NULL, //&fs_close_query, + NULL, //&fs_free_query_cookie, + NULL, //&fs_read_query, + NULL, //&fs_rewind_query, }; -int32 api_version = B_CUR_FS_API_VERSION; +module_info *modules[] = { + (module_info *)&sDosFileSystem, + NULL, +}; diff --git a/src/add-ons/kernel/file_systems/dos/dosfs.h b/src/add-ons/kernel/file_systems/dos/dosfs.h index 8dcba9b644..eabbf2702f 100644 --- a/src/add-ons/kernel/file_systems/dos/dosfs.h +++ b/src/add-ons/kernel/file_systems/dos/dosfs.h @@ -5,21 +5,16 @@ #ifndef _DOSFS_H_ #define _DOSFS_H_ -#if USE_DMALLOC - #include -#else - -/* allocate memory from swappable heap */ -#define malloc smalloc -#define free sfree -#define calloc scalloc -#define realloc srealloc - -#include - -#endif - #include +#include +#include + +//#define DEBUG 1 + +typedef recursive_lock lock; +#define LOCK(l) recursive_lock_lock(&l); +#define UNLOCK(l) recursive_lock_unlock(&l); + /* for multiple reader/single writer locks */ #define READERS 100000 @@ -68,8 +63,6 @@ #define VNODE_PARENT_DIR_CLUSTER(vnode) \ CLUSTER_OF_DIR_CLUSTER_VNID((vnode)->dir_vnid) -#include - #define VNODE_MAGIC 'treB' typedef struct vnode @@ -77,6 +70,7 @@ typedef struct vnode uint32 magic; vnode_id vnid; // self id vnode_id dir_vnid; // parent vnode id (directory containing entry) + void *cache; // for file cache uint32 disk_image; // 0 = no, 1 = BEOS, 2 = IMAGE.BE @@ -104,7 +98,7 @@ typedef struct vnode #if TRACK_FILENAME char *filename; -#endif +#endif } vnode; // mode bits @@ -122,10 +116,11 @@ struct vcache_entry; typedef struct _nspace { uint32 magic; - nspace_id id; // ID passed in to fs_mount + mount_id id; // ID passed in to fs_mount int fd; // File descriptor char device[256]; uint32 flags; // see for modes + void *fBlockCache; // info from bpb uint32 bytes_per_sector; @@ -206,6 +201,6 @@ int check_nspace_magic(struct _nspace *t, char *funcname); extern int debug_attr, debug_dir, debug_dlist, debug_dosfs, debug_encodings, debug_fat, debug_file, debug_iter, debug_vcache; -int _dosfs_sync(nspace *vol); +status_t _dosfs_sync(nspace *vol); #endif diff --git a/src/add-ons/kernel/file_systems/dos/fat.c b/src/add-ons/kernel/file_systems/dos/fat.c index 90aaaf5068..7fb1182f2e 100644 --- a/src/add-ons/kernel/file_systems/dos/fat.c +++ b/src/add-ons/kernel/file_systems/dos/fat.c @@ -4,10 +4,7 @@ */ #include -#include -#include -#include - +#include #include #include #include @@ -24,9 +21,10 @@ #define DPRINTF(a,b) if (debug_fat > (a)) dprintf b -static status_t mirror_fats(nspace *vol, uint32 sector, uint8 *buffer) +static status_t mirror_fats(nspace *vol, uint32 sector, uint8 *buffer, int32 tid) { uint32 i; + char *buf = buffer; if (!vol->fat_mirrored) return B_OK; @@ -34,18 +32,22 @@ static status_t mirror_fats(nspace *vol, uint32 sector, uint8 *buffer) sector -= vol->active_fat * vol->sectors_per_fat; for (i=0;ifat_count;i++) { + char *blockData; if (i == vol->active_fat) continue; - cached_write(vol->fd, sector + i*vol->sectors_per_fat, buffer, 1, vol->bytes_per_sector); + blockData = block_cache_get_writable_etc(vol->fBlockCache, sector + i*vol->sectors_per_fat, 0, 1, tid); + memcpy(blockData, buf, vol->bytes_per_sector); + buf += vol->bytes_per_sector; + block_cache_put(vol->fBlockCache, sector + i*vol->sectors_per_fat); } - + return B_OK; } static int32 _count_free_clusters_fat32(nspace *vol) { int32 count = 0; - uint8 *block; + const uint8 *block; uint32 fat_sector; uint32 i; uint32 cur_sector; @@ -53,7 +55,7 @@ static int32 _count_free_clusters_fat32(nspace *vol) cur_sector = vol->reserved_sectors + vol->active_fat * vol->sectors_per_fat; for(fat_sector = 0; fat_sector < vol->sectors_per_fat; fat_sector++) { - block = (uint8 *)get_block(vol->fd, cur_sector, vol->bytes_per_sector); + block = (uint8 *)block_cache_get(vol->fBlockCache, cur_sector); if(block == NULL) { return EIO; } @@ -63,7 +65,7 @@ static int32 _count_free_clusters_fat32(nspace *vol) if(val == 0) count++; } - release_block(vol->fd, cur_sector); + block_cache_put(vol->fBlockCache, cur_sector); cur_sector++; } @@ -85,6 +87,7 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N) uint32 sector; uint32 off, val = 0; /* quiet warning */ uint8 *block1, *block2 = NULL; /* quiet warning */ + int32 tid = -1; // mark end of chain for allocations uint32 V = (action == _IOCTL_SET_ENTRY_) ? N : 0x0fffffff; @@ -94,8 +97,7 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N) if (check_nspace_magic(vol, "_fat_ioctl_")) return EINVAL; DPRINTF(3, ("_fat_ioctl_: action %lx, cluster %lx, N %lx\n", action, cluster, N)); - - + if (action == _IOCTL_COUNT_FREE_) { if(vol->fat_bits == 32) // use a optimized version of the cluster counting algorithms @@ -118,19 +120,31 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N) sector = vol->reserved_sectors + vol->active_fat * vol->sectors_per_fat + off / vol->bytes_per_sector; off %= vol->bytes_per_sector; - - if ((block1 = (uint8 *)get_block(vol->fd, sector, vol->bytes_per_sector)) == NULL) { + + if (action != _IOCTL_SET_ENTRY_ && action != _IOCTL_ALLOCATE_N_ENTRIES_) { + block1 = (uint8 *)block_cache_get(vol->fBlockCache, sector); + } else { + tid = cache_start_transaction(vol->fBlockCache); + block1 = (uint8 *)block_cache_get_writable(vol->fBlockCache, sector, tid); + } + + if (block1 == NULL) { DPRINTF(0, ("_fat_ioctl_: error reading fat (sector %lx)\n", sector)); return EIO; } - + for (i=0;itotal_clusters;i++) { ASSERT(IS_DATA_CLUSTER(cluster)); ASSERT(off == ((cluster * vol->fat_bits / 8) % vol->bytes_per_sector)); if (vol->fat_bits == 12) { if (off == vol->bytes_per_sector - 1) { - if ((block2 = (uint8 *)get_block(vol->fd, ++sector, vol->bytes_per_sector)) == NULL) { + if (action != _IOCTL_SET_ENTRY_ && action != _IOCTL_ALLOCATE_N_ENTRIES_) + block2 = (uint8 *)block_cache_get(vol->fBlockCache, ++sector); + else + block2 = (uint8 *)block_cache_get_writable(vol->fBlockCache, ++sector, tid); + + if (block2 == NULL) { DPRINTF(0, ("_fat_ioctl_: error reading fat (sector %lx)\n", sector)); result = EIO; sector--; @@ -162,8 +176,8 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N) block1[off] &= (andmask & 0xff); block1[off] |= (ormask & 0xff); if (off == vol->bytes_per_sector - 1) { - mark_blocks_dirty(vol->fd, sector - 1, 1); - mirror_fats(vol, sector - 1, block1); + //mark_blocks_dirty(vol->fd, sector - 1, 1); + mirror_fats(vol, sector - 1, block1, tid); block2[0] &= (andmask >> 8); block2[0] |= (ormask >> 8); } else { @@ -174,7 +188,7 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N) if (off == vol->bytes_per_sector - 1) { off = (cluster & 1) ? 1 : 0; - release_block(vol->fd, sector - 1); + block_cache_put(vol->fBlockCache, sector - 1); block1 = block2; } else { off += (cluster & 1) ? 2 : 1; @@ -220,13 +234,13 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N) result = val; goto bi; } else if (action == _IOCTL_SET_ENTRY_) { - mark_blocks_dirty(vol->fd, sector, 1); - mirror_fats(vol, sector, block1); + //mark_blocks_dirty(vol->fd, sector, 1); + mirror_fats(vol, sector, block1, tid); goto bi; } else if ((action == _IOCTL_ALLOCATE_N_ENTRIES_) && (val == 0)) { vol->free_clusters--; - mark_blocks_dirty(vol->fd, sector, 1); - mirror_fats(vol, sector, block1); + //mark_blocks_dirty(vol->fd, sector, 1); + mirror_fats(vol, sector, block1, tid); if (n == 0) { ASSERT(first == 0); first = last = cluster; @@ -249,20 +263,29 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N) // iterate cluster and sector if needed if (++cluster == vol->total_clusters + 2) { - release_block(vol->fd, sector); + block_cache_put(vol->fBlockCache, sector); cluster = 2; off = 2 * vol->fat_bits / 8; sector = vol->reserved_sectors + vol->active_fat * vol->sectors_per_fat; - block1 = (uint8 *)get_block(vol->fd, sector, vol->bytes_per_sector); + if (action != _IOCTL_SET_ENTRY_ && action != _IOCTL_ALLOCATE_N_ENTRIES_) + block1 = (uint8 *)block_cache_get(vol->fBlockCache, sector); + else + block1 = (uint8 *)block_cache_get_writable(vol->fBlockCache, sector, tid); } if (off >= vol->bytes_per_sector) { - release_block(vol->fd, sector); - off -= vol->bytes_per_sector; sector++; + block_cache_put(vol->fBlockCache, sector); + + off -= vol->bytes_per_sector; + sector++; ASSERT(sector < vol->reserved_sectors + (vol->active_fat + 1) * vol->sectors_per_fat); - block1 = (uint8 *)get_block(vol->fd, sector, vol->bytes_per_sector); + + if (action != _IOCTL_SET_ENTRY_ && action != _IOCTL_ALLOCATE_N_ENTRIES_) + block1 = (uint8 *)block_cache_get(vol->fBlockCache, sector); + else + block1 = (uint8 *)block_cache_get_writable(vol->fBlockCache, sector, tid); } if (block1 == NULL) { @@ -273,7 +296,10 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N) } bi: - if (block1) release_block(vol->fd, sector); + if (block1) + block_cache_put(vol->fBlockCache, sector); + if (tid >= 0) + cache_end_transaction(vol->fBlockCache, tid, NULL, NULL); if (action == _IOCTL_ALLOCATE_N_ENTRIES_) { if (result < 0) { @@ -290,9 +316,9 @@ bi: } } - if (result < B_OK) + if (result < B_OK) { DPRINTF(0, ("_fat_ioctl_ error: action = %lx cluster = %lx N = %lx (%s)\n", action, cluster, N, strerror(result))); - + } return result; } @@ -553,6 +579,7 @@ void dump_fat_chain(nspace *vol, uint32 cluster) dprintf("\n"); } +/* status_t fragment(nspace *vol, uint32 *pattern) { uint32 sector, offset, previous_entry, i, val; @@ -642,3 +669,4 @@ status_t fragment(nspace *vol, uint32 *pattern) return B_OK; } +*/ \ No newline at end of file diff --git a/src/add-ons/kernel/file_systems/dos/file.c b/src/add-ons/kernel/file_systems/dos/file.c index b3bda2526f..130cc1af9b 100644 --- a/src/add-ons/kernel/file_systems/dos/file.c +++ b/src/add-ons/kernel/file_systems/dos/file.c @@ -2,15 +2,16 @@ Copyright 1999-2001, Be Incorporated. All Rights Reserved. This file may be used under the terms of the Be Sample Code License. */ +#include #include #include -#include +#include +#include #include +#include +#include -#include -#include -#include #include #include "iter.h" @@ -44,14 +45,26 @@ typedef struct filecookie static CHECK_MAGIC(filecookie,struct filecookie, FILECOOKIE_MAGIC) + +status_t +dosfs_get_vnode_name(void *_ns, void *_node, char *buffer, size_t bufferSize) +{ + vnode *node = (vnode*)_node; + strlcpy(buffer, node->filename, bufferSize); + return B_OK; +} + + status_t write_vnode_entry(nspace *vol, vnode *node) { uint32 i; struct diri diri; uint8 *buffer; + + // TODO : is it needed ? vfs job ? // don't update entries of deleted files - if (is_vnode_removed(vol->id, node->vnid) > 0) return 0; + //if (is_vnode_removed(vol->id, node->vnid) > 0) return 0; // XXX: should check if directory position is still valid even // though we do the is_vnode_removed check above @@ -96,9 +109,11 @@ status_t write_vnode_entry(nspace *vol, vnode *node) return B_OK; } + // called when fs is done with vnode // after close, etc. free vnode resources here -int dosfs_write_vnode(void *_vol, void *_node, char reenter) +status_t +dosfs_release_vnode(void *_vol, void *_node, bool reenter) { nspace *vol = (nspace *)_vol; vnode *node = (vnode *)_node; @@ -122,8 +137,11 @@ int dosfs_write_vnode(void *_vol, void *_node, char reenter) #if TRACK_FILENAME if (node->filename) free(node->filename); #endif + if (node->vnid != vol->root_vnode.vnid) { node->magic = ~VNODE_MAGIC; // munge magic number to be safe + if (node->cache != NULL) + file_cache_delete(node->cache); free(node); } } @@ -131,7 +149,9 @@ int dosfs_write_vnode(void *_vol, void *_node, char reenter) return 0; } -int dosfs_rstat(void *_vol, void *_node, struct stat *st) + +status_t +dosfs_rstat(void *_vol, void *_node, struct stat *st) { nspace *vol = (nspace*)_vol; vnode *node = (vnode*)_node; @@ -168,7 +188,9 @@ int dosfs_rstat(void *_vol, void *_node, struct stat *st) return B_NO_ERROR; } -int dosfs_wstat(void *_vol, void *_node, struct stat *st, long mask) + +status_t +dosfs_wstat(void *_vol, void *_node, const struct stat *st, uint32 mask) { int err = B_OK; nspace *vol = (nspace*)_vol; @@ -197,7 +219,7 @@ int dosfs_wstat(void *_vol, void *_node, struct stat *st, long mask) return EPERM; } - if (mask & WSTAT_MODE) { + if (mask & FS_WRITE_STAT_MODE) { DPRINTF(0, ("setting file mode to %o\n", st->st_mode)); if (st->st_mode & S_IWUSR) node->mode &= ~FAT_READ_ONLY; @@ -206,7 +228,7 @@ int dosfs_wstat(void *_vol, void *_node, struct stat *st, long mask) dirty = true; } - if (mask & WSTAT_SIZE) { + if (mask & FS_WRITE_STAT_SIZE) { DPRINTF(0, ("setting file size to %Lx\n", st->st_size)); if (node->mode & FAT_SUBDIR) { dprintf("dosfs_wstat: can't set file size of directory!\n"); @@ -221,11 +243,12 @@ int dosfs_wstat(void *_vol, void *_node, struct stat *st, long mask) node->st_size = st->st_size; node->iteration++; dirty = true; + file_cache_set_size(node->cache, node->st_size); } } } - if (mask & WSTAT_MTIME) { + if (mask & FS_WRITE_STAT_MTIME) { DPRINTF(0, ("setting modification time\n")); node->st_time = st->st_mtime; dirty = true; @@ -249,9 +272,11 @@ int dosfs_wstat(void *_vol, void *_node, struct stat *st, long mask) return err; } -int dosfs_open(void *_vol, void *_node, int omode, void **_cookie) + +status_t +dosfs_open(void *_vol, void *_node, int omode, void **_cookie) { - int result = EINVAL; + status_t result = EINVAL; nspace *vol = (nspace *)_vol; vnode* node = (vnode*)_node; filecookie *cookie; @@ -320,18 +345,20 @@ error: return result; } -int dosfs_read(void *_vol, void *_node, void *_cookie, off_t pos, + +status_t +dosfs_read(void *_vol, void *_node, void *_cookie, off_t pos, void *buf, size_t *len) { nspace *vol = (nspace *)_vol; vnode *node = (vnode *)_node; filecookie *cookie = (filecookie *)_cookie; - uint8 *buffer; - struct csi iter; + //uint8 *buffer; + //struct csi iter; int result = B_OK; - size_t bytes_read = 0; - uint32 cluster1; - off_t diff; + //size_t bytes_read = 0; + //uint32 cluster1; + //off_t diff; LOCK_VOL(vol); @@ -343,6 +370,7 @@ int dosfs_read(void *_vol, void *_node, void *_cookie, off_t pos, return EINVAL; } + if (node->mode & FAT_SUBDIR) { DPRINTF(0, ("dosfs_read called on subdirectory %Lx\n", node->vnid)); *len = 0; @@ -355,13 +383,18 @@ int dosfs_read(void *_vol, void *_node, void *_cookie, off_t pos, if (pos < 0) pos = 0; if ((node->st_size == 0) || (*len == 0) || (pos >= node->st_size)) { - bytes_read = 0; + //bytes_read = 0; + *len = 0; goto bi; } // truncate bytes to read to file size if (pos + *len >= node->st_size) *len = node->st_size - pos; + + result = file_cache_read(node->cache, pos, buf, len); + +#if 0 if ((cookie->ccache.iteration == node->iteration) && (pos >= cookie->ccache.index * vol->bytes_per_sector * vol->sectors_per_cluster)) { @@ -455,9 +488,9 @@ int dosfs_read(void *_vol, void *_node, void *_cookie, off_t pos, } result = B_OK; +#endif + bi: - *len = bytes_read; - if (result != B_OK) { DPRINTF(0, ("dosfs_read (%s)\n", strerror(result))); } else { @@ -468,18 +501,21 @@ bi: return result; } -int dosfs_write(void *_vol, void *_node, void *_cookie, off_t pos, + +status_t +dosfs_write(void *_vol, void *_node, void *_cookie, off_t pos, const void *buf, size_t *len) { nspace *vol = (nspace *)_vol; vnode *node = (vnode *)_node; filecookie *cookie = (filecookie *)_cookie; - uint8 *buffer; - struct csi iter; + //uint8 *buffer; + //struct csi iter; int result = B_OK; - size_t bytes_written = 0; - uint32 cluster1; - off_t diff; + //size_t bytes_written = 0; + //uint32 cluster1; + //off_t diff; + LOCK_VOL(vol); @@ -500,9 +536,10 @@ int dosfs_write(void *_vol, void *_node, void *_cookie, off_t pos, } DPRINTF(0, ("dosfs_write called %lx bytes at %Lx from buffer at %lx (vnode id %Lx)\n", *len, pos, (uint32)buf, node->vnid)); - + if ((cookie->mode & O_RWMASK) == O_RDONLY) { dprintf("dosfs_write: called on file opened as read-only\n"); + *len = 0; result = EPERM; goto bi; } @@ -515,6 +552,7 @@ int dosfs_write(void *_vol, void *_node, void *_cookie, off_t pos, if (pos >= MAX_FILE_SIZE) { dprintf("dosfs_write: write position exceeds fat limits\n"); + *len = 0; result = E2BIG; goto bi; } @@ -522,6 +560,8 @@ int dosfs_write(void *_vol, void *_node, void *_cookie, off_t pos, if (pos + *len >= MAX_FILE_SIZE) { *len = (size_t)(MAX_FILE_SIZE - pos); } + +#if 0 if (node->st_size && (cookie->ccache.iteration == node->iteration) && @@ -534,6 +574,7 @@ int dosfs_write(void *_vol, void *_node, void *_cookie, off_t pos, cluster1 = 0xffffffff; diff = 0; } +#endif // extend file size if needed if (pos + *len > node->st_size) { @@ -552,8 +593,12 @@ int dosfs_write(void *_vol, void *_node, void *_cookie, off_t pos, DPRINTF(0, ("setting file size to %Lx (%lx clusters)\n", node->st_size, clusters)); node->dirty = true; + file_cache_set_size(node->cache, node->st_size); } - + + result = file_cache_write(node->cache, pos, buf, len); + +#if 0 if (cluster1 == 0xffffffff) { cluster1 = node->cluster; diff = pos; @@ -643,10 +688,9 @@ int dosfs_write(void *_vol, void *_node, void *_cookie, off_t pos, } result = B_OK; - +#endif + bi: - *len = bytes_written; - if (result != B_OK) { DPRINTF(0, ("dosfs_write (%s)\n", strerror(result))); } else { @@ -657,7 +701,9 @@ bi: return result; } -int dosfs_close(void *_vol, void *_node, void *_cookie) + +status_t +dosfs_close(void *_vol, void *_node, void *_cookie) { nspace *vol = (nspace *)_vol; vnode *node = (vnode *)_node; @@ -683,7 +729,9 @@ int dosfs_close(void *_vol, void *_node, void *_cookie) return 0; } -int dosfs_free_cookie(void *_vol, void *_node, void *_cookie) + +status_t +dosfs_free_cookie(void *_vol, void *_node, void *_cookie) { nspace *vol = _vol; vnode *node = _node; @@ -707,8 +755,10 @@ int dosfs_free_cookie(void *_vol, void *_node, void *_cookie) return 0; } -int dosfs_create(void *_vol, void *_dir, const char *name, int omode, - int perms, vnode_id *vnid, void **_cookie) + +status_t +dosfs_create(void *_vol, void *_dir, const char *name, int omode, + int perms, void **_cookie, vnode_id *vnid) { nspace *vol = (nspace *)_vol; vnode *dir = (vnode *)_dir, *file; @@ -732,18 +782,19 @@ int dosfs_create(void *_vol, void *_dir, const char *name, int omode, } DPRINTF(0, ("dosfs_create called: %Lx/%s perms=%o omode=%o\n", dir->vnid, name, perms, omode)); - + if (vol->flags & B_FS_IS_READONLY) { dprintf("dosfs_create called on read-only volume\n"); UNLOCK_VOL(vol); return EROFS; } - if (is_vnode_removed(vol->id, dir->vnid) > 0) { + // TODO : is it needed ? vfs job ? + /*if (is_vnode_removed(vol->id, dir->vnid) > 0) { dprintf("dosfs_create() called in removed directory. disallowed.\n"); UNLOCK_VOL(vol); return EPERM; - } + }*/ if ((omode & O_RWMASK) == O_RDONLY) { dprintf("invalid permissions used in creating file\n"); @@ -854,7 +905,9 @@ bi: if (result != B_OK) free(cookie); return result; } -int dosfs_mkdir(void *_vol, void *_dir, const char *name, int perms) + +status_t +dosfs_mkdir(void *_vol, void *_dir, const char *name, int perms, vnode_id *_vnid) { nspace *vol = (nspace *)_vol; vnode *dir = (vnode *)_dir, dummy; @@ -871,11 +924,12 @@ int dosfs_mkdir(void *_vol, void *_dir, const char *name, int perms) return EINVAL; } - if (is_vnode_removed(vol->id, dir->vnid) > 0) { + // TODO : is it needed ? vfs job ? + /*if (is_vnode_removed(vol->id, dir->vnid) > 0) { dprintf("dosfs_mkdir() called in removed directory. disallowed.\n"); UNLOCK_VOL(vol); return EPERM; - } + }*/ DPRINTF(0, ("dosfs_mkdir called: %Lx/%s (perm %o)\n", dir->vnid, name, perms)); @@ -1003,7 +1057,9 @@ bi: dummy.magic = ~VNODE_MAGIC; return result; } -int dosfs_rename(void *_vol, void *_odir, const char *oldname, + +status_t +dosfs_rename(void *_vol, void *_odir, const char *oldname, void *_ndir, const char *newname) { status_t result = EINVAL; @@ -1230,7 +1286,9 @@ bi: return result; } -int dosfs_remove_vnode(void *_vol, void *_node, char reenter) + +status_t +dosfs_remove_vnode(void *_vol, void *_node, bool reenter) { nspace *vol = (nspace *)_vol; vnode *node = (vnode *)_node; @@ -1279,13 +1337,14 @@ int dosfs_remove_vnode(void *_vol, void *_node, char reenter) UNLOCK_VOL(vol); } - return 0; + return B_OK; } // get rid of node or directory -static int do_unlink(void *_vol, void *_dir, const char *name, bool is_file) +static status_t +do_unlink(void *_vol, void *_dir, const char *name, bool is_file) { - int result = EINVAL; + status_t result = EINVAL; nspace *vol = (nspace *)_vol; vnode *dir = (vnode *)_dir, *file; vnode_id vnid; @@ -1391,16 +1450,167 @@ bi: UNLOCK_VOL(vol); return result; } -int dosfs_unlink(void *vol, void *dir, const char *name) +status_t +dosfs_unlink(void *vol, void *dir, const char *name) { DPRINTF(1, ("dosfs_unlink called\n")); - return do_unlink(vol,dir,name,true); + return do_unlink(vol, dir, name, true); } -int dosfs_rmdir(void *vol, void *dir, const char *name) + +status_t +dosfs_rmdir(void *vol, void *dir, const char *name) { DPRINTF(1, ("dosfs_rmdir called\n")); - return do_unlink(vol,dir,name,false); + return do_unlink(vol, dir, name, false); +} + + +status_t +dosfs_get_file_map(void *_fs, void *_node, off_t pos, size_t len, + struct file_io_vec *vecs, size_t *_count) +{ + nspace *vol = (nspace *)_fs; + vnode *node = (vnode *)_node; + struct csi iter; + int result = B_OK; + size_t bytes_read = 0; + uint32 cluster1; + off_t diff; + size_t index = 0, max = *_count; + + LOCK_VOL(vol); + *_count = 0; + + if (check_nspace_magic((nspace *)vol, "dosfs_get_file_map") || + check_vnode_magic(node, "dosfs_get_file_map")) { + UNLOCK_VOL(vol); + return EINVAL; + } + + if (node->mode & FAT_SUBDIR) { + DPRINTF(0, ("dosfs_get_file_map called on subdirectory %Lx\n", node->vnid)); + UNLOCK_VOL(vol); + return EISDIR; + } + + DPRINTF(0, ("dosfs_get_file_map called %lx bytes at %Lx (vnode id %Lx)\n", len, pos, node->vnid)); + + if (pos < 0) pos = 0; + + if ((node->st_size == 0) || (len == 0) || (pos >= node->st_size)) { + bytes_read = 0; + goto bi; + } + + // truncate bytes to read to file size + if (pos + len >= node->st_size) + len = node->st_size - pos; + + /* the fat chain changed, so we have to start from the beginning */ + cluster1 = node->cluster; + diff = pos; + diff /= vol->bytes_per_sector; /* convert to sectors */ + + if ((result = init_csi(vol, cluster1, 0, &iter)) != B_OK) { + dprintf("dosfs_get_file_map: invalid starting cluster (%lx)\n", cluster1); + goto bi; + } + + if (diff && ((result = iter_csi(&iter, diff)) != B_OK)) { + dprintf("dosfs_get_file_map: end of file reached (init)\n"); + result = EIO; + goto bi; + } + + ASSERT(iter.cluster == get_nth_fat_entry(vol, node->cluster, pos / vol->bytes_per_sector / vol->sectors_per_cluster)); + + if ((pos % vol->bytes_per_sector) != 0) { + // read in partial first sector if necessary + size_t amt = vol->bytes_per_sector - (pos % vol->bytes_per_sector); + if (amt > len) + amt = len; + vecs[index].offset = csi_to_block(&iter) * vol->bytes_per_sector + (pos % vol->bytes_per_sector); + vecs[index].length = amt; + index++; + if (index >= max) { + // we're out of file_io_vecs; let's bail out + result = B_BUFFER_OVERFLOW; + goto bi; + } + + bytes_read += amt; + + if (bytes_read < len) + if ((result = iter_csi(&iter, 1)) != B_OK) { + dprintf("dosfs_get_file_map: end of file reached\n"); + result = EIO; + goto bi; + } + } + + // read middle sectors + while (bytes_read + vol->bytes_per_sector <= len) { + struct csi old_csi; + uint32 sectors = 1; + off_t block = csi_to_block(&iter); + status_t err; + + while (1) { + old_csi = iter; + err = iter_csi(&iter, 1); + if ((len - bytes_read) < (sectors + 1) * iter.vol->bytes_per_sector) + break; + if ((err < B_OK) || (block + sectors != csi_to_block(&iter))) + break; + sectors++; + } + + vecs[index].offset = block * vol->bytes_per_sector; + vecs[index].length = sectors * vol->bytes_per_sector; + bytes_read += sectors * vol->bytes_per_sector; + index++; + iter = old_csi; + + if (index >= max) { + // we're out of file_io_vecs; let's bail out + result = B_BUFFER_OVERFLOW; + goto bi; + } + + if (bytes_read < len) + if ((result = iter_csi(&iter, 1)) != B_OK) { + dprintf("dosfs_get_file_map: end of file reached\n"); + result = EIO; + goto bi; + } + } + + // read part of remaining sector if needed + if (bytes_read < len) { + size_t amt = len - bytes_read; + vecs[index].offset = csi_to_block(&iter) * vol->bytes_per_sector; + vecs[index].length = amt; + index++; + bytes_read += amt; + + if (index >= max) { + // we're out of file_io_vecs; let's bail out + result = B_BUFFER_OVERFLOW; + goto bi; + } + } + + result = B_OK; +bi: + *_count = index; + + if (result != B_OK) { + DPRINTF(0, ("dosfs_get_file_map (%s)\n", strerror(result))); + } + UNLOCK_VOL(vol); + + return result; } diff --git a/src/add-ons/kernel/file_systems/dos/file.h b/src/add-ons/kernel/file_systems/dos/file.h index 44d278f94d..5b188fabb1 100644 --- a/src/add-ons/kernel/file_systems/dos/file.h +++ b/src/add-ons/kernel/file_systems/dos/file.h @@ -7,24 +7,27 @@ status_t write_vnode_entry(nspace *vol, vnode *node); -int dosfs_write_vnode(void *_vol, void *_node, char r); -int dosfs_rstat(void *_vol, void *_node, struct stat *st); -int dosfs_open(void *_vol, void *_node, int omode, void **cookie); -int dosfs_read(void *_vol, void *_node, void *cookie, off_t pos, +status_t dosfs_get_vnode_name(void *_ns, void *_node, char *buffer, size_t bufferSize); +status_t dosfs_release_vnode(void *_vol, void *_node, bool reenter); +status_t dosfs_rstat(void *_vol, void *_node, struct stat *st); +status_t dosfs_open(void *_vol, void *_node, int omode, void **cookie); +status_t dosfs_read(void *_vol, void *_node, void *cookie, off_t pos, void *buf, size_t *len); -int dosfs_free_cookie(void *vol, void *node, void *cookie); -int dosfs_close(void *vol, void *node, void *cookie); +status_t dosfs_free_cookie(void *vol, void *node, void *cookie); +status_t dosfs_close(void *vol, void *node, void *cookie); -int dosfs_remove_vnode(void *vol, void *node, char r); -int dosfs_create(void *vol, void *dir, const char *name, - int perms, int omode, vnode_id *vnid, void **cookie); -int dosfs_mkdir(void *vol, void *dir, const char *name, int perms); -int dosfs_rename(void *vol, void *olddir, const char *oldname, +status_t dosfs_remove_vnode(void *vol, void *node, bool reenter); +status_t dosfs_create(void *vol, void *dir, const char *name, + int omode, int perms, void **cookie, vnode_id *vnid); +status_t dosfs_mkdir(void *vol, void *dir, const char *name, int perms, vnode_id *_vnid); +status_t dosfs_rename(void *vol, void *olddir, const char *oldname, void *newdir, const char *newname); -int dosfs_unlink(void *vol, void *dir, const char *name); -int dosfs_rmdir(void *vol, void *dir, const char *name); -int dosfs_wstat(void *vol, void *node, struct stat *st, long mask); -int dosfs_write(void *vol, void *node, void *cookie, off_t pos, +status_t dosfs_unlink(void *vol, void *dir, const char *name); +status_t dosfs_rmdir(void *vol, void *dir, const char *name); +status_t dosfs_wstat(void *vol, void *node, const struct stat *st, uint32 mask); +status_t dosfs_write(void *vol, void *node, void *cookie, off_t pos, const void *buf, size_t *len); +status_t dosfs_get_file_map(void *fs, void *node, off_t pos, size_t reqLen, + struct file_io_vec *vecs, size_t *_count); #endif diff --git a/src/add-ons/kernel/file_systems/dos/fsproto.h b/src/add-ons/kernel/file_systems/dos/fsproto.h deleted file mode 100644 index afa16d61b3..0000000000 --- a/src/add-ons/kernel/file_systems/dos/fsproto.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - Copyright 1999-2001, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ - -#ifndef _FSPROTO_H -#define _FSPROTO_H - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -typedef dev_t nspace_id; -typedef ino_t vnode_id; - -/* - * PUBLIC PART OF THE FILE SYSTEM PROTOCOL - */ - -#define WSTAT_MODE 0x0001 -#define WSTAT_UID 0x0002 -#define WSTAT_GID 0x0004 -#define WSTAT_SIZE 0x0008 -#define WSTAT_ATIME 0x0010 -#define WSTAT_MTIME 0x0020 -#define WSTAT_CRTIME 0x0040 - -#define WFSSTAT_NAME 0x0001 - -#define B_ENTRY_CREATED 1 -#define B_ENTRY_REMOVED 2 -#define B_ENTRY_MOVED 3 -#define B_STAT_CHANGED 4 -#define B_ATTR_CHANGED 5 -#define B_DEVICE_MOUNTED 6 -#define B_DEVICE_UNMOUNTED 7 - -#define B_STOP_WATCHING 0x0000 -#define B_WATCH_NAME 0x0001 -#define B_WATCH_STAT 0x0002 -#define B_WATCH_ATTR 0x0004 -#define B_WATCH_DIRECTORY 0x0008 - -#define SELECT_READ 1 -#define SELECT_WRITE 2 -#define SELECT_EXCEPTION 3 - -#define B_CUR_FS_API_VERSION 2 - -struct attr_info; -struct index_info; - -typedef int op_read_vnode(void *ns, vnode_id vnid, char r, void **node); -typedef int op_write_vnode(void *ns, void *node, char r); -typedef int op_remove_vnode(void *ns, void *node, char r); -typedef int op_secure_vnode(void *ns, void *node); - -typedef int op_walk(void *ns, void *base, const char *file, char **newpath, - vnode_id *vnid); - -typedef int op_access(void *ns, void *node, int mode); - -typedef int op_create(void *ns, void *dir, const char *name, - int omode, int perms, vnode_id *vnid, void **cookie); -typedef int op_mkdir(void *ns, void *dir, const char *name, int perms); -typedef int op_symlink(void *ns, void *dir, const char *name, - const char *path); -typedef int op_link(void *ns, void *dir, const char *name, void *node); - -typedef int op_rename(void *ns, void *olddir, const char *oldname, - void *newdir, const char *newname); -typedef int op_unlink(void *ns, void *dir, const char *name); -typedef int op_rmdir(void *ns, void *dir, const char *name); - -typedef int op_readlink(void *ns, void *node, char *buf, size_t *bufsize); - -typedef int op_opendir(void *ns, void *node, void **cookie); -typedef int op_closedir(void *ns, void *node, void *cookie); -typedef int op_rewinddir(void *ns, void *node, void *cookie); -typedef int op_readdir(void *ns, void *node, void *cookie, long *num, - struct dirent *buf, size_t bufsize); - -typedef int op_open(void *ns, void *node, int omode, void **cookie); -typedef int op_close(void *ns, void *node, void *cookie); -typedef int op_free_cookie(void *ns, void *node, void *cookie); -typedef int op_read(void *ns, void *node, void *cookie, off_t pos, void *buf, - size_t *len); -typedef int op_write(void *ns, void *node, void *cookie, off_t pos, - const void *buf, size_t *len); -typedef int op_readv(void *ns, void *node, void *cookie, off_t pos, const iovec *vec, - size_t count, size_t *len); -typedef int op_writev(void *ns, void *node, void *cookie, off_t pos, const iovec *vec, - size_t count, size_t *len); -typedef int op_ioctl(void *ns, void *node, void *cookie, int cmd, void *buf, - size_t len); -typedef int op_setflags(void *ns, void *node, void *cookie, int flags); - -typedef int op_rstat(void *ns, void *node, struct stat *); -typedef int op_wstat(void *ns, void *node, struct stat *, long mask); -typedef int op_fsync(void *ns, void *node); - -typedef int op_select(void *ns, void *node, void *cookie, uint8 event, - uint32 ref, selectsync *sync); -typedef int op_deselect(void *ns, void *node, void *cookie, uint8 event, - selectsync *sync); - -typedef int op_initialize(const char *devname, void *parms, size_t len); -typedef int op_mount(nspace_id nsid, const char *devname, ulong flags, - void *parms, size_t len, void **data, vnode_id *vnid); -typedef int op_unmount(void *ns); -typedef int op_sync(void *ns); -typedef int op_rfsstat(void *ns, struct fs_info *); -typedef int op_wfsstat(void *ns, struct fs_info *, long mask); - - -typedef int op_open_attrdir(void *ns, void *node, void **cookie); -typedef int op_close_attrdir(void *ns, void *node, void *cookie); -typedef int op_rewind_attrdir(void *ns, void *node, void *cookie); -typedef int op_read_attrdir(void *ns, void *node, void *cookie, long *num, - struct dirent *buf, size_t bufsize); -typedef int op_remove_attr(void *ns, void *node, const char *name); -typedef int op_rename_attr(void *ns, void *node, const char *oldname, - const char *newname); -typedef int op_stat_attr(void *ns, void *node, const char *name, - struct attr_info *buf); - -typedef int op_write_attr(void *ns, void *node, const char *name, int type, - const void *buf, size_t *len, off_t pos); -typedef int op_read_attr(void *ns, void *node, const char *name, int type, - void *buf, size_t *len, off_t pos); - -typedef int op_open_indexdir(void *ns, void **cookie); -typedef int op_close_indexdir(void *ns, void *cookie); -typedef int op_rewind_indexdir(void *ns, void *cookie); -typedef int op_read_indexdir(void *ns, void *cookie, long *num, - struct dirent *buf, size_t bufsize); -typedef int op_create_index(void *ns, const char *name, int type, int flags); -typedef int op_remove_index(void *ns, const char *name); -typedef int op_rename_index(void *ns, const char *oldname, - const char *newname); -typedef int op_stat_index(void *ns, const char *name, struct index_info *buf); - -typedef int op_open_query(void *ns, const char *query, ulong flags, - port_id port, long token, void **cookie); -typedef int op_close_query(void *ns, void *cookie); -typedef int op_read_query(void *ns, void *cookie, long *num, - struct dirent *buf, size_t bufsize); - -typedef struct vnode_ops { - op_read_vnode (*read_vnode); - op_write_vnode (*write_vnode); - op_remove_vnode (*remove_vnode); - op_secure_vnode (*secure_vnode); - op_walk (*walk); - op_access (*access); - op_create (*create); - op_mkdir (*mkdir); - op_symlink (*symlink); - op_link (*link); - op_rename (*rename); - op_unlink (*unlink); - op_rmdir (*rmdir); - op_readlink (*readlink); - op_opendir (*opendir); - op_closedir (*closedir); - op_free_cookie (*free_dircookie); - op_rewinddir (*rewinddir); - op_readdir (*readdir); - op_open (*open); - op_close (*close); - op_free_cookie (*free_cookie); - op_read (*read); - op_write (*write); - op_readv (*readv); - op_writev (*writev); - op_ioctl (*ioctl); - op_setflags (*setflags); - op_rstat (*rstat); - op_wstat (*wstat); - op_fsync (*fsync); - op_initialize (*initialize); - op_mount (*mount); - op_unmount (*unmount); - op_sync (*sync); - op_rfsstat (*rfsstat); - op_wfsstat (*wfsstat); - op_select (*select); - op_deselect (*deselect); - op_open_indexdir (*open_indexdir); - op_close_indexdir (*close_indexdir); - op_free_cookie (*free_indexdircookie); - op_rewind_indexdir (*rewind_indexdir); - op_read_indexdir (*read_indexdir); - op_create_index (*create_index); - op_remove_index (*remove_index); - op_rename_index (*rename_index); - op_stat_index (*stat_index); - op_open_attrdir (*open_attrdir); - op_close_attrdir (*close_attrdir); - op_free_cookie (*free_attrdircookie); - op_rewind_attrdir (*rewind_attrdir); - op_read_attrdir (*read_attrdir); - op_write_attr (*write_attr); - op_read_attr (*read_attr); - op_remove_attr (*remove_attr); - op_rename_attr (*rename_attr); - op_stat_attr (*stat_attr); - op_open_query (*open_query); - op_close_query (*close_query); - op_free_cookie (*free_querycookie); - op_read_query (*read_query); -} vnode_ops; - -extern _IMPEXP_KERNEL int new_path(const char *path, char **copy); -extern _IMPEXP_KERNEL void free_path(char *p); - -extern _IMPEXP_KERNEL int notify_listener(int op, nspace_id nsid, - vnode_id vnida, vnode_id vnidb, - vnode_id vnidc, const char *name); -extern _IMPEXP_KERNEL int send_notification(port_id port, long token, - ulong what, long op, nspace_id nsida, - nspace_id nsidb, vnode_id vnida, - vnode_id vnidb, vnode_id vnidc, - const char *name); -extern _IMPEXP_KERNEL int get_vnode(nspace_id nsid, vnode_id vnid, void **data); -extern _IMPEXP_KERNEL int put_vnode(nspace_id nsid, vnode_id vnid); -extern _IMPEXP_KERNEL int new_vnode(nspace_id nsid, vnode_id vnid, void *data); -extern _IMPEXP_KERNEL int remove_vnode(nspace_id nsid, vnode_id vnid); -extern _IMPEXP_KERNEL int unremove_vnode(nspace_id nsid, vnode_id vnid); -extern _IMPEXP_KERNEL int is_vnode_removed(nspace_id nsid, vnode_id vnid); - - -extern _EXPORT vnode_ops fs_entry; -extern _EXPORT int32 api_version; - -#endif diff --git a/src/add-ons/kernel/file_systems/dos/iter.c b/src/add-ons/kernel/file_systems/dos/iter.c index 6563ce9bd8..bc06070278 100644 --- a/src/add-ons/kernel/file_systems/dos/iter.c +++ b/src/add-ons/kernel/file_systems/dos/iter.c @@ -2,11 +2,10 @@ Copyright 1999-2001, Be Incorporated. All Rights Reserved. This file may be used under the terms of the Be Sample Code License. */ -#include +#include -#include -#include -#include +#include +#include #include "iter.h" #include "dosfs.h" @@ -34,7 +33,7 @@ static int _validate_cs_(nspace *vol, uint32 cluster, uint32 sector) return 0; } -static off_t _csi_to_block_(struct csi *csi) +off_t csi_to_block(struct csi *csi) { // presumes the caller has already called _validate_cs_ on the argument ASSERT(_validate_cs_(csi->vol, csi->cluster, csi->sector) == 0); @@ -97,37 +96,34 @@ int iter_csi(struct csi *csi, int sectors) return -1; } -uint8 *csi_get_block(struct csi *csi) +uint8 *csi_get_block(struct csi *csi, int32 tid) { if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0) return NULL; - return get_block(csi->vol->fd, _csi_to_block_(csi), csi->vol->bytes_per_sector); + return block_cache_get_writable_etc(csi->vol->fBlockCache, csi_to_block(csi), + 1, csi->vol->bytes_per_sector, tid); } status_t csi_release_block(struct csi *csi) { - status_t err; - if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0) return EINVAL; - err = release_block(csi->vol->fd, _csi_to_block_(csi)); - ASSERT(err == B_OK); - return err; + block_cache_put(csi->vol->fBlockCache, csi_to_block(csi)); + return B_OK; } -status_t csi_mark_block_dirty(struct csi *csi) +status_t csi_mark_block_dirty(struct csi *csi, int32 tid) { - status_t err; - ASSERT(_validate_cs_(csi->vol, csi->cluster, csi->sector) == 0); if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0) return EINVAL; - err = mark_blocks_dirty(csi->vol->fd, _csi_to_block_(csi), 1); - ASSERT(err == B_OK); - return err; + // TODO : block_cache doesn't implement this + //block_cache_set_dirty(csi->vol->fBlockCache, csi_to_block(csi), true, tid); + + return B_OK; } /* XXX: not the most efficient implementation, but it gets the job done */ @@ -137,28 +133,33 @@ status_t csi_read_blocks(struct csi *csi, uint8 *buffer, ssize_t len) uint32 sectors; off_t block; status_t err; - + char *buf = buffer; + int32 i; + ASSERT(len >= csi->vol->bytes_per_sector); if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0) return EINVAL; sectors = 1; - block = _csi_to_block_(csi); + block = csi_to_block(csi); while (1) { old_csi = *csi; err = iter_csi(csi, 1); if (len < (sectors + 1) * csi->vol->bytes_per_sector) break; - if ((err < B_OK) || (block + sectors != _csi_to_block_(csi))) + if ((err < B_OK) || (block + sectors != csi_to_block(csi))) break; sectors++; } - err = cached_read(csi->vol->fd, block, buffer, sectors, csi->vol->bytes_per_sector); - if (err < B_OK) - return err; + for (i=block; ivol->fBlockCache, i); + memcpy(buf, blockData, csi->vol->bytes_per_sector); + buf += csi->vol->bytes_per_sector; + block_cache_put(csi->vol->fBlockCache, i); + } *csi = old_csi; @@ -171,6 +172,8 @@ status_t csi_write_blocks(struct csi *csi, uint8 *buffer, ssize_t len) uint32 sectors; off_t block; status_t err; + char *buf = buffer; + int32 i, tid; ASSERT(len >= csi->vol->bytes_per_sector); @@ -179,21 +182,26 @@ status_t csi_write_blocks(struct csi *csi, uint8 *buffer, ssize_t len) return EINVAL; sectors = 1; - block = _csi_to_block_(csi); + block = csi_to_block(csi); while (1) { old_csi = *csi; err = iter_csi(csi, 1); if (len < (sectors + 1) * csi->vol->bytes_per_sector) break; - if ((err < B_OK) || (block + sectors != _csi_to_block_(csi))) + if ((err < B_OK) || (block + sectors != csi_to_block(csi))) break; sectors++; } - - err = cached_write(csi->vol->fd, block, buffer, sectors, csi->vol->bytes_per_sector); - if (err < B_OK) - return err; + + tid = cache_start_transaction(csi->vol->fBlockCache); + for(i=block; ivol->fBlockCache, i, 0, 1, tid); + memcpy(blockData, buf, csi->vol->bytes_per_sector); + buf += csi->vol->bytes_per_sector; + block_cache_put(csi->vol->fBlockCache, i); + } + cache_end_transaction(csi->vol->fBlockCache, tid, NULL, NULL); /* return the last state of the iterator because that's what dosfs_write * expects. this lets it meaningfully cache the state even when it's @@ -205,11 +213,23 @@ status_t csi_write_blocks(struct csi *csi, uint8 *buffer, ssize_t len) status_t csi_write_block(struct csi *csi, uint8 *buffer) { + off_t block; + int32 tid; + char *blockData; + + block = csi_to_block(csi); + ASSERT(_validate_cs_(csi->vol, csi->cluster, csi->sector) == 0); if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0) return EINVAL; + + tid = cache_start_transaction(csi->vol->fBlockCache); + blockData = block_cache_get_writable_etc(csi->vol->fBlockCache, block, 0, 1, tid); + memcpy(blockData, buffer, csi->vol->bytes_per_sector); + block_cache_put(csi->vol->fBlockCache, block); + cache_end_transaction(csi->vol->fBlockCache, tid, NULL, NULL); - return cached_write(csi->vol->fd, _csi_to_block_(csi), buffer, 1, csi->vol->bytes_per_sector); + return B_OK; } static void _diri_release_current_block_(struct diri *diri) @@ -238,9 +258,11 @@ uint8 *diri_init(nspace *vol, uint32 cluster, uint32 index, struct diri *diri) if (iter_csi(&(diri->csi), diri->current_index / (vol->bytes_per_sector / 0x20)) != 0) return NULL; } + + diri->tid = cache_start_transaction(diri->csi.vol->fBlockCache); // get current sector - diri->current_block = csi_get_block(&(diri->csi)); + diri->current_block = csi_get_block(&(diri->csi), diri->tid); if (diri->current_block == NULL) return NULL; @@ -256,6 +278,8 @@ int diri_free(struct diri *diri) if (diri->current_block) _diri_release_current_block_(diri); + + cache_end_transaction(diri->csi.vol->fBlockCache, diri->tid, NULL, NULL); return 0; } @@ -281,7 +305,7 @@ uint8 *diri_next_entry(struct diri *diri) _diri_release_current_block_(diri); if (iter_csi(&(diri->csi), 1) != 0) return NULL; - diri->current_block = csi_get_block(&(diri->csi)); + diri->current_block = csi_get_block(&(diri->csi), diri->tid); if (diri->current_block == NULL) return NULL; } @@ -298,7 +322,7 @@ uint8 *diri_rewind(struct diri *diri) _diri_release_current_block_(diri); if (init_csi(diri->csi.vol, diri->starting_cluster, 0, &(diri->csi)) != 0) return NULL; - diri->current_block = csi_get_block(&(diri->csi)); + diri->current_block = csi_get_block(&(diri->csi), diri->tid); } diri->current_index = 0; return diri->current_block; @@ -306,5 +330,5 @@ uint8 *diri_rewind(struct diri *diri) void diri_mark_dirty(struct diri *diri) { - csi_mark_block_dirty(&(diri->csi)); + csi_mark_block_dirty(&(diri->csi), diri->tid); } diff --git a/src/add-ons/kernel/file_systems/dos/iter.h b/src/add-ons/kernel/file_systems/dos/iter.h index ec6dafb0de..a277ee6bc7 100644 --- a/src/add-ons/kernel/file_systems/dos/iter.h +++ b/src/add-ons/kernel/file_systems/dos/iter.h @@ -15,11 +15,12 @@ struct csi uint32 sector; }; +off_t csi_to_block(struct csi *csi); int init_csi(struct _nspace *vol, uint32 cluster, uint32 sector, struct csi *csi); int iter_csi(struct csi *csi, int sectors); -uint8 *csi_get_block(struct csi *csi); +uint8 *csi_get_block(struct csi *csi, int32 tid); status_t csi_release_block(struct csi *csi); -status_t csi_mark_block_dirty(struct csi *csi); +status_t csi_mark_block_dirty(struct csi *csi, int32 tid); status_t csi_read_blocks(struct csi *csi, uint8 *buffer, ssize_t len); status_t csi_write_blocks(struct csi *csi, uint8 *buffer, ssize_t len); status_t csi_write_block(struct csi *csi, uint8 *buffer); @@ -33,6 +34,7 @@ struct diri uint32 starting_cluster; uint32 current_index; uint8 *current_block; + int32 tid; }; uint8 *diri_init(struct _nspace *vol, uint32 cluster, uint32 index, struct diri *diri); diff --git a/src/add-ons/kernel/file_systems/dos/kalloc.h b/src/add-ons/kernel/file_systems/dos/kalloc.h deleted file mode 100644 index 43c5bdfdef..0000000000 --- a/src/add-ons/kernel/file_systems/dos/kalloc.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - Copyright 1999-2001, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ - -#ifndef _ALLOC_H -#define _ALLOC_H - -#include - -#if KMALLOC_TRACKING -extern bool kmalloc_tracking_enabled; -#endif - -extern void init_malloc(void); -extern void init_smalloc(void); - -extern void * smalloc(unsigned int nbytes); -extern void sfree(void *ptr); -extern void * scalloc(unsigned int nobj, unsigned int size); -extern void * srealloc(void *p, unsigned int newsize); - -#endif diff --git a/src/add-ons/kernel/file_systems/dos/lock.h b/src/add-ons/kernel/file_systems/dos/lock.h deleted file mode 100644 index 4014b752d4..0000000000 --- a/src/add-ons/kernel/file_systems/dos/lock.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright 1999-2001, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ - -#ifndef _LOCK_H -#define _LOCK_H - -#include - -#include - -#ifdef __cplusplus - extern "C" { -#endif - -typedef struct lock lock; -typedef struct mlock mlock; - -struct lock { - sem_id s; - long c; -}; - -struct mlock { - sem_id s; -}; - -extern _IMPEXP_KERNEL int new_lock(lock *l, const char *name); -extern _IMPEXP_KERNEL int free_lock(lock *l); - -#define LOCK(l) if (atomic_add(&l.c, -1) <= 0) acquire_sem(l.s); -#define UNLOCK(l) if (atomic_add(&l.c, 1) < 0) release_sem(l.s); - -extern _IMPEXP_KERNEL int new_mlock(mlock *l, long c, const char *name); -extern _IMPEXP_KERNEL int free_mlock(mlock *l); - -#define LOCKM(l,cnt) acquire_sem_etc(l.s, cnt, 0, 0) -#define UNLOCKM(l,cnt) release_sem_etc(l.s, cnt, 0) - - -#ifdef __cplusplus - } // extern "C" -#endif - -#endif diff --git a/src/add-ons/kernel/file_systems/dos/util.c b/src/add-ons/kernel/file_systems/dos/util.c index 86cf91e2e9..3d1825cd24 100644 --- a/src/add-ons/kernel/file_systems/dos/util.c +++ b/src/add-ons/kernel/file_systems/dos/util.c @@ -9,8 +9,7 @@ #include #include -#include -#include +#include "rtc_info.h" #include "dosfs.h" #include "fat.h" @@ -18,6 +17,8 @@ static int32 tzoffset = -1; /* in minutes */ +#ifdef DEBUG + int _assert_(char *a, int b, char *c) { dprintf("tripped assertion in %s/%d (%s)\n", a, b, c); @@ -25,6 +26,8 @@ int _assert_(char *a, int b, char *c) return 0; } +#endif + static void print_byte(uint8 c) { dprintf("%c", ((c >= ' ') && (c <= '~')) ? c : '.'); diff --git a/src/add-ons/kernel/file_systems/dos/util.h b/src/add-ons/kernel/file_systems/dos/util.h index 7ff13912f3..00d400b19d 100644 --- a/src/add-ons/kernel/file_systems/dos/util.h +++ b/src/add-ons/kernel/file_systems/dos/util.h @@ -8,13 +8,14 @@ #include // debugging functions - +#ifndef ASSERT #ifndef DEBUG #define ASSERT(c) ((void)0) #else int _assert_(char *,int,char *); #define ASSERT(c) (!(c) ? _assert_(__FILE__,__LINE__,#c) : 0) #endif +#endif void dump_bytes(uint8 *buffer, uint32 count); void dump_directory(uint8 *buffer); diff --git a/src/add-ons/kernel/file_systems/dos/vcache.c b/src/add-ons/kernel/file_systems/dos/vcache.c index 8bb1ac0517..8fa9934ee4 100644 --- a/src/add-ons/kernel/file_systems/dos/vcache.c +++ b/src/add-ons/kernel/file_systems/dos/vcache.c @@ -50,7 +50,6 @@ purpose. #define UNLOCK_CACHE_W \ release_sem_etc(vol->vcache.vc_sem, READERS, 0) -#include #include #include @@ -358,12 +357,12 @@ status_t vcache_set_entry(nspace *vol, vnode_id vnid, vnode_id loc) DPRINTF(0, ("vcache_set_entry: %Lx -> %Lx\n", vnid, loc)); - if (is_vnode_removed(vol->id, vnid) > 0) { + /*if (is_vnode_removed(vol->id, vnid) > 0) { if (!IS_ARTIFICIAL_VNID(loc)) return B_OK; } else { ASSERT(is_vnode_removed(vol->id, vnid) == 0); - } + }*/ LOCK_CACHE_W;