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
This commit is contained in:
Jérôme Duval
2006-08-27 22:04:34 +00:00
parent 49811b3ae3
commit f50c1ececf
20 changed files with 789 additions and 769 deletions
@@ -1,5 +1,9 @@
SubDir HAIKU_TOP src add-ons kernel file_systems dos ; SubDir HAIKU_TOP src add-ons kernel file_systems dos ;
UsePrivateHeaders kernel ;
SubDirCcFlags -DTRACK_FILENAME ;
KernelAddon dos : kernel file_systems : KernelAddon dos : kernel file_systems :
attr.c attr.c
dir.c dir.c
+80 -38
View File
@@ -18,13 +18,12 @@
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
#include <fsproto.h>
#include <lock.h>
#include "dosfs.h" #include "dosfs.h"
#include "attr.h" #include "attr.h"
#include "mime_table.h" #include "mime_table.h"
int32 kBeOSTypeCookie = 0x1234;
#define DPRINTF(a,b) if (debug_attr > (a)) dprintf b #define DPRINTF(a,b) if (debug_attr > (a)) dprintf b
status_t set_mime_type(vnode *node, const char *filename) 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; 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; nspace *vol = (nspace *)_vol;
@@ -82,7 +83,8 @@ int dosfs_open_attrdir(void *_vol, void *_node, void **_cookie)
return 0; 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; nspace *vol = (nspace *)_vol;
@@ -104,7 +106,9 @@ int dosfs_close_attrdir(void *_vol, void *_node, void *_cookie)
return 0; 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); TOUCH(_vol); TOUCH(_node);
@@ -121,7 +125,9 @@ int dosfs_free_attrcookie(void *_vol, void *_node, void *_cookie)
return 0; 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); TOUCH(_vol); TOUCH(_node);
@@ -136,8 +142,10 @@ int dosfs_rewind_attrdir(void *_vol, void *_node, void *_cookie)
return 0; 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; nspace *vol = (nspace *)_vol;
vnode *node = (vnode *)_node; vnode *node = (vnode *)_node;
@@ -173,20 +181,60 @@ int dosfs_read_attrdir(void *_vol, void *_node, void *_cookie, long *num,
return 0; 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; nspace *vol = (nspace *)_vol;
vnode *node = (vnode *)_node; vnode *node = (vnode *)_node;
DPRINTF(0, ("dosfs_stat_attr (%s)\n", name));
if (strcmp(name, "BEOS:TYPE")) if (strcmp(name, "BEOS:TYPE"))
return ENOENT; return ENOENT;
LOCK_VOL(vol); LOCK_VOL(vol);
if (check_nspace_magic(vol, "dosfs_read_attr") || if (node->mime == NULL) {
check_vnode_magic(node, "dosfs_read_attr")) { 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_stat") ||
check_vnode_magic(node, "dosfs_read_attr_stat")) {
UNLOCK_VOL(vol); UNLOCK_VOL(vol);
return EINVAL; return EINVAL;
} }
@@ -196,25 +244,24 @@ int dosfs_stat_attr(void *_vol, void *_node, const char *name, struct attr_info
return ENOENT; return ENOENT;
} }
buf->type = MIME_STRING_TYPE; stat->st_type = MIME_STRING_TYPE;
buf->size = strlen(node->mime) + 1; stat->st_size = strlen(node->mime) + 1;
UNLOCK_VOL(vol); UNLOCK_VOL(vol);
return 0; 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; nspace *vol = (nspace *)_vol;
vnode *node = (vnode *)_node; 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; return ENOENT;
LOCK_VOL(vol); LOCK_VOL(vol);
@@ -235,9 +282,9 @@ int dosfs_read_attr(void *_vol, void *_node, const char *name, int type, void *b
return EINVAL; return EINVAL;
} }
strncpy(buf, node->mime + pos, *len - 1); strncpy(buffer, node->mime + pos, *_length - 1);
((char *)buf)[*len - 1] = 0; ((char *)buffer)[*_length - 1] = 0;
*len = strlen(buf) + 1; *_length = strlen(buffer) + 1;
UNLOCK_VOL(vol); UNLOCK_VOL(vol);
return 0; 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 // suck up application attempts to set mime types; this hides an unsightly
// error message printed out by zip // error message printed out by zip
int dosfs_write_attr(void *_vol, void *_node, const char *name, int type, status_t
const void *buf, size_t *len, off_t pos) 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); DPRINTF(0, ("dosfs_write_attr\n"));
TOUCH(len); TOUCH(pos);
DPRINTF(0, ("dosfs_write_attr (%s)\n", name)); *_length = 0;
*len = 0; if (_cookie != &kBeOSTypeCookie)
if (strcmp(name, "BEOS:TYPE"))
return ENOSYS; return ENOSYS;
if (type != MIME_STRING_TYPE) return B_OK;
return ENOSYS;
return 0;
} }
+17 -11
View File
@@ -5,18 +5,24 @@
#ifndef _DOSFS_ATTR_H_ #ifndef _DOSFS_ATTR_H_
#define _DOSFS_ATTR_H_ #define _DOSFS_ATTR_H_
#include <fs_attr.h>
status_t set_mime_type(vnode *node, const char *filename); status_t set_mime_type(vnode *node, const char *filename);
int dosfs_open_attrdir(void *_vol, void *_node, void **_cookie); status_t dosfs_open_attrdir(void *_vol, void *_node, void **_cookie);
int dosfs_close_attrdir(void *_vol, void *_node, void *_cookie); status_t dosfs_close_attrdir(void *_vol, void *_node, void *_cookie);
int dosfs_free_attrcookie(void *_vol, void *_node, void *_cookie); status_t dosfs_free_attrdir_cookie(void *_vol, void *_node, void *_cookie);
int dosfs_rewind_attrdir(void *_vol, void *_node, void *_cookie); status_t dosfs_rewind_attrdir(void *_vol, void *_node, void *_cookie);
int dosfs_read_attrdir(void *_vol, void *_node, void *_cookie, long *num, status_t dosfs_read_attrdir(void *_vol, void *_node, void *_cookie,
struct dirent *buf, size_t bufsize); struct dirent *buf, size_t bufsize, uint32 *num);
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,
int dosfs_read_attr(void *_vol, void *_node, const char *name, int type, void *buf, fs_cookie *_cookie);
size_t *len, off_t pos); status_t dosfs_close_attr(void *_vol, void *_node, fs_cookie cookie);
int dosfs_write_attr(void *_vol, void *_node, const char *name, int type, status_t dosfs_free_attr_cookie(void *_vol, void *_node, fs_cookie cookie);
const void *buf, size_t *len, off_t pos); 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 #endif
-108
View File
@@ -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 <BeBuild.h>
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_ */
+33 -20
View File
@@ -4,12 +4,10 @@
*/ */
#include <KernelExport.h> #include <KernelExport.h>
#include <fsproto.h>
#include <lock.h>
#include <cache.h>
#include <stdlib.h> #include <stdlib.h>
#include <dirent.h> #include <dirent.h>
#include <fs_cache.h>
#include <fs_info.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
@@ -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); 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; nspace *vol = (nspace*)_vol;
int result = B_NO_ERROR; 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); entry->filename = malloc(sizeof(filename) + 1);
if (entry->filename) strcpy(entry->filename, filename); if (entry->filename) strcpy(entry->filename, filename);
#endif #endif
entry->cache = file_cache_create(vol->id, vnid, entry->st_size, vol->fd);
if(!(entry->mode & FAT_SUBDIR)) if(!(entry->mode & FAT_SUBDIR))
set_mime_type(entry, filename); set_mime_type(entry, filename);
@@ -969,17 +970,16 @@ bi: if (!reenter) UNLOCK_VOL(vol);
return result; 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 /* Starting at the base, find file in the subdir, and return path
string and vnode id of file. */ string and vnode id of file. */
nspace *vol = (nspace*)_vol; nspace *vol = (nspace*)_vol;
vnode *dir = (vnode*)_dir; vnode *dir = (vnode*)_dir;
vnode *vnode = NULL; vnode *vnode = NULL;
int result = ENOENT; status_t result = ENOENT;
/* we can ignore newpath since there are no symbolic links */
TOUCH(newpath);
LOCK_VOL(vol); 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)); 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) { if (result != B_OK) {
DPRINTF(0, ("dosfs_walk (%s)\n", strerror(result))); DPRINTF(0, ("dosfs_walk (%s)\n", strerror(result)));
} else { } else {
DPRINTF(0, ("dosfs_walk: found vnid %Lx\n", *vnid)); DPRINTF(0, ("dosfs_walk: found vnid %Lx\n", *_vnid));
} }
UNLOCK_VOL(vol); UNLOCK_VOL(vol);
@@ -1003,7 +1003,8 @@ int dosfs_walk(void *_vol, void *_dir, const char *file, char **newpath, vnode_i
return result; 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; status_t result = B_OK;
nspace *vol = (nspace *)_vol; nspace *vol = (nspace *)_vol;
@@ -1037,7 +1038,9 @@ int dosfs_access(void *_vol, void *_node, int mode)
return result; 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); 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; 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; nspace *vol = (nspace*)_vol;
vnode *node = (vnode*)_node; vnode *node = (vnode*)_node;
@@ -1102,8 +1107,10 @@ bi:
return result; 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; int result = ENOENT;
nspace* vol = (nspace*)_vol; nspace* vol = (nspace*)_vol;
@@ -1171,7 +1178,9 @@ bi:
return result; return result;
} }
int dosfs_rewinddir(void *_vol, void *_node, void* _cookie)
status_t
dosfs_rewinddir(void *_vol, void *_node, void* _cookie)
{ {
nspace *vol = _vol; nspace *vol = _vol;
vnode *node = _node; vnode *node = _node;
@@ -1195,7 +1204,9 @@ int dosfs_rewinddir(void *_vol, void *_node, void* _cookie)
return B_OK; 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); TOUCH(_vol); TOUCH(_node); TOUCH(_cookie);
@@ -1204,7 +1215,9 @@ int dosfs_closedir(void *_vol, void *_node, void *_cookie)
return 0; 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; nspace *vol = _vol;
dircookie *cookie = _cookie; dircookie *cookie = _cookie;
+11 -11
View File
@@ -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, status_t create_dir_entry(nspace *vol, vnode *dir, vnode *node,
const char *name, uint32 *ns, uint32 *ne); const char *name, uint32 *ns, uint32 *ne);
int dosfs_read_vnode(void *_vol, vnode_id vnid, char r, void **node); status_t dosfs_read_vnode(void *_vol, vnode_id vnid, void **node, bool reenter);
int dosfs_walk(void *_vol, void *_dir, const char *file, status_t dosfs_walk(void *_vol, void *_dir, const char *file,
char **newpath, vnode_id *vnid); vnode_id *_vnid, int *_type);
int dosfs_access(void *_vol, void *_node, int mode); status_t dosfs_access(void *_vol, void *_node, int mode);
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);
int dosfs_opendir(void *_vol, void *_node, void **cookie); status_t dosfs_opendir(void *_vol, void *_node, void **cookie);
int dosfs_readdir(void *_vol, void *_node, void *cookie, status_t dosfs_readdir(void *_vol, void *_node, void *cookie,
long *num, struct dirent *buf, size_t bufsize); struct dirent *buf, size_t bufsize, uint32 *num);
int dosfs_rewinddir(void *_vol, void *_node, void *cookie); status_t dosfs_rewinddir(void *_vol, void *_node, void *cookie);
int dosfs_closedir(void *_vol, void *_node, void *cookie); status_t dosfs_closedir(void *_vol, void *_node, void *cookie);
int dosfs_free_dircookie(void *_vol, void *_node, void *cookie); status_t dosfs_free_dircookie(void *_vol, void *_node, void *cookie);
#endif #endif
+1 -1
View File
@@ -20,8 +20,8 @@ TODO:
#define DPRINTF(a,b) if (debug_dlist > (a)) dprintf b #define DPRINTF(a,b) if (debug_dlist > (a)) dprintf b
#include <KernelExport.h> #include <KernelExport.h>
#include <fsproto.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "dosfs.h" #include "dosfs.h"
+217 -105
View File
@@ -14,12 +14,10 @@
#include <scsi.h> #include <scsi.h>
#include <fsproto.h> #include <fs_info.h>
#ifndef COMPILE_IN_BEOS #include <fs_interface.h>
#include <fs_cache.h>
#include <fs_volume.h> #include <fs_volume.h>
#endif
#include <lock.h>
#include <cache.h>
#include "dosfs.h" #include "dosfs.h"
#include "attr.h" #include "attr.h"
@@ -49,7 +47,7 @@ static status_t get_fsinfo(nspace *vol, uint32 *free_count, uint32 *last_allocat
int32 instances = 0; int32 instances = 0;
int debug_dos(int argc, char **argv) static int debug_dos(int argc, char **argv)
{ {
int i; int i;
for (i=1;i<argc;i++) { for (i=1;i<argc;i++) {
@@ -86,7 +84,7 @@ int debug_dos(int argc, char **argv)
return B_OK; return B_OK;
} }
int debug_dvnode(int argc, char **argv) static int debug_dvnode(int argc, char **argv)
{ {
int i; int i;
@@ -116,7 +114,7 @@ int debug_dvnode(int argc, char **argv)
return B_OK; return B_OK;
} }
int debug_dc2s(int argc, char **argv) static int debug_dc2s(int argc, char **argv)
{ {
int i; int i;
nspace *vol; nspace *vol;
@@ -146,7 +144,7 @@ static int lock_removable_device(int fd, bool state)
return ioctl(fd, B_SCSI_PREVENT_ALLOW, &state, sizeof(state)); return ioctl(fd, B_SCSI_PREVENT_ALLOW, &state, sizeof(state));
} }
static status_t mount_fat_disk(const char *path, nspace_id nsid, static status_t mount_fat_disk(const char *path, mount_id nsid,
const int flags, nspace** newVol, int fs_flags, int op_sync_mode) const int flags, nspace** newVol, int fs_flags, int op_sync_mode)
{ {
nspace *vol = NULL; nspace *vol = NULL;
@@ -438,7 +436,8 @@ static status_t mount_fat_disk(const char *path, nspace_id nsid,
} }
// initialize block cache // initialize block cache
if (init_cache_for_device(vol->fd, (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"); dprintf("error initializing block cache\n");
goto error; goto error;
} }
@@ -537,7 +536,7 @@ error3:
error2: error2:
uninit_vcache(vol); uninit_vcache(vol);
error1: error1:
remove_cached_device_blocks(vol->fd, NO_WRITES); block_cache_delete(vol->fBlockCache, false);
error: error:
if (!(vol->flags & B_FS_IS_READONLY) && (vol->flags & B_FS_IS_REMOVABLE) && (vol->fs_flags & FS_FLAGS_LOCK_DOOR)) 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); lock_removable_device(vol->fd, false);
@@ -547,8 +546,36 @@ error0:
return (err >= B_NO_ERROR) ? EINVAL : err; 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; int result;
nspace *vol; nspace *vol;
@@ -580,16 +607,16 @@ static int dosfs_mount(nspace_id nsid, const char *device, ulong flags, void *pa
unload_driver_settings(handle); 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 */ we can ignore these arguments */
TOUCH(parms); TOUCH(len); TOUCH(args);
#if __RO__ #if __RO__
// make it read-only // make it read-only
flags |= 1; flags |= 1;
#endif #endif
if (data == NULL) { if (_data == NULL) {
dprintf("dosfs_mount passed NULL data pointer\n"); dprintf("dosfs_mount passed NULL data pointer\n");
return EINVAL; 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; if (check_nspace_magic(vol, "dosfs_mount")) return EINVAL;
*vnid = vol->root_vnode.vnid; *_rootID = vol->root_vnode.vnid;
*data = (void*)vol; *_data = (void*)vol;
// You MUST do this. Create the vnode for the root. // 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) { if (result != B_NO_ERROR) {
dprintf("error creating new vnode (%s)\n", strerror(result)); dprintf("error creating new vnode (%s)\n", strerror(result));
goto error; goto error;
} }
sprintf(name, "fat lock %lx", vol->id); 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)); dprintf("error creating lock (%s)\n", strerror(result));
goto error; goto error;
} }
@@ -631,7 +658,7 @@ static int dosfs_mount(nspace_id nsid, const char *device, ulong flags, void *pa
return result; return result;
error: error:
remove_cached_device_blocks(vol->fd, NO_WRITES); block_cache_delete(vol->fBlockCache, false);
dlist_uninit(vol); dlist_uninit(vol);
uninit_vcache(vol); uninit_vcache(vol);
free(vol); free(vol);
@@ -643,7 +670,9 @@ static void update_fsinfo(nspace *vol)
if ((vol->fat_bits == 32) && (vol->fsinfo_sector != 0xffff) && if ((vol->fat_bits == 32) && (vol->fsinfo_sector != 0xffff) &&
((vol->flags & B_FS_IS_READONLY) == false)) { ((vol->flags & B_FS_IS_READONLY) == false)) {
uchar *buffer; 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)) { if ((read32(buffer,0) == 0x41615252) && (read32(buffer,0x1e4) == 0x61417272) && (read16(buffer,0x1fe) == 0xaa55)) {
//number of free clusters //number of free clusters
buffer[0x1e8] = (vol->free_clusters & 0xff); buffer[0x1e8] = (vol->free_clusters & 0xff);
@@ -655,12 +684,14 @@ static void update_fsinfo(nspace *vol)
buffer[0x1ed] = ((vol->last_allocated >> 8) & 0xff); buffer[0x1ed] = ((vol->last_allocated >> 8) & 0xff);
buffer[0x1ee] = ((vol->last_allocated >> 16) & 0xff); buffer[0x1ee] = ((vol->last_allocated >> 16) & 0xff);
buffer[0x1ef] = ((vol->last_allocated >> 24) & 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 { } else {
dprintf("update_fsinfo: fsinfo block has invalid magic number\n"); 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 { } else {
cache_end_transaction(vol->fBlockCache, tid, NULL, NULL);
dprintf("update_fsinfo: error getting fsinfo sector %x\n", vol->fsinfo_sector); 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)) if ((vol->fat_bits != 32) || (vol->fsinfo_sector == 0xffff))
return B_ERROR; 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); dprintf("get_fsinfo: error getting fsinfo sector %x\n", vol->fsinfo_sector);
return EIO; return EIO;
} }
@@ -688,11 +719,13 @@ static status_t get_fsinfo(nspace *vol, uint32 *free_count, uint32 *last_allocat
result = B_ERROR; result = B_ERROR;
} }
release_block(vol->fd, vol->fsinfo_sector); block_cache_put(vol->fBlockCache, vol->fsinfo_sector);
return result; return result;
} }
static int dosfs_unmount(void *_vol)
static status_t
dosfs_unmount(void *_vol)
{ {
int result = B_NO_ERROR; int result = B_NO_ERROR;
@@ -708,8 +741,7 @@ static int dosfs_unmount(void *_vol)
DPRINTF(0, ("dosfs_unmount volume %lx\n", vol->id)); DPRINTF(0, ("dosfs_unmount volume %lx\n", vol->id));
update_fsinfo(vol); update_fsinfo(vol);
flush_device(vol->fd, 0); block_cache_delete(vol->fBlockCache, true);
remove_cached_device_blocks(vol->fd, ALLOW_WRITES);
#if DEBUG #if DEBUG
if (atomic_add(&instances, -1) == 1) { 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)) 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); lock_removable_device(vol->fd, false);
result = close(vol->fd); result = close(vol->fd);
free_lock(&(vol->vlock)); recursive_lock_destroy(&(vol->vlock));
vol->magic = ~VNODE_MAGIC; vol->magic = ~VNODE_MAGIC;
free(vol); free(vol);
@@ -738,20 +770,21 @@ static int dosfs_unmount(void *_vol)
return result; return result;
} }
// dosfs_rfsstat - Fill in fs_info struct for device. // dosfs_read_fs_stat - Fill in fs_info struct for device.
static int dosfs_rfsstat(void *_vol, struct fs_info * fss) static status_t
dosfs_read_fs_stat(void *_vol, struct fs_info * fss)
{ {
nspace* vol = (nspace*)_vol; nspace* vol = (nspace*)_vol;
int i; int i;
LOCK_VOL(vol); LOCK_VOL(vol);
if (check_nspace_magic(vol, "dosfs_rfsstat")) { if (check_nspace_magic(vol, "dosfs_read_fs_stat")) {
UNLOCK_VOL(vol); UNLOCK_VOL(vol);
return EINVAL; 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 // 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); 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; nspace* vol = (nspace*)_vol;
LOCK_VOL(vol); LOCK_VOL(vol);
if (check_nspace_magic(vol, "dosfs_wfsstat")) { if (check_nspace_magic(vol, "dosfs_write_fs_stat")) {
UNLOCK_VOL(vol); UNLOCK_VOL(vol);
return EINVAL; 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 /* if it's a r/o file system and not the special hack, then don't allow
* volume renaming */ * volume renaming */
@@ -817,7 +851,7 @@ static int dosfs_wfsstat(void *_vol, struct fs_info * fss, long mask)
return EROFS; return EROFS;
} }
if (mask & WFSSTAT_NAME) { if (mask & FS_WRITE_FSINFO_NAME) {
// sanitize name // sanitize name
char name[11]; char name[11];
int i,j; int i,j;
@@ -840,7 +874,9 @@ static int dosfs_wfsstat(void *_vol, struct fs_info * fss, long mask)
if (vol->vol_entry == -1) { if (vol->vol_entry == -1) {
// stored in the bpb // stored in the bpb
uchar *buffer; 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; result = EIO;
goto bi; goto bi;
} }
@@ -849,10 +885,11 @@ static int dosfs_wfsstat(void *_vol, struct fs_info * fss, long mask)
result = B_ERROR; result = B_ERROR;
} else { } else {
memcpy(buffer + 0x2b, name, 11); memcpy(buffer + 0x2b, name, 11);
mark_blocks_dirty(vol->fd, 0, 1); block_cache_set_dirty(vol->fBlockCache, 0, true, tid);
result = 0; 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) { } else if (vol->vol_entry >= 0) {
struct diri diri; struct diri diri;
uint8 *buffer; uint8 *buffer;
@@ -887,7 +924,9 @@ bi: UNLOCK_VOL(vol);
return result; 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) void *buf, size_t len)
{ {
status_t result = B_OK; 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; if (buf) *(bigtime_t *)buf = node->st_time;
break; break;
case 69666 : /*case 69666 :
result = fragment(vol, buf); result = fragment(vol, buf);
break; break;
*/
case 100000 : case 100000 :
dprintf("built at %s on %s\n", build_time, build_date); 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; break;
default : 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; result = EINVAL;
break; break;
} }
@@ -980,21 +1020,25 @@ static int dosfs_ioctl(void *_vol, void *_node, void *cookie, int code,
return result; return result;
} }
int _dosfs_sync(nspace *vol)
status_t
_dosfs_sync(nspace *vol)
{ {
if (check_nspace_magic(vol, "dosfs_sync")) if (check_nspace_magic(vol, "dosfs_sync"))
return EINVAL; return EINVAL;
update_fsinfo(vol); 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; nspace *vol = (nspace *)_vol;
int err; status_t err;
DPRINTF(0, ("dosfs_sync called on volume %lx\n", vol->id)); DPRINTF(0, ("dosfs_sync called on volume %lx\n", vol->id));
@@ -1005,76 +1049,144 @@ static int dosfs_sync(void *_vol)
return err; return err;
} }
static int dosfs_fsync(void *vol, void *node)
static status_t
dosfs_fsync(void *vol, void *node)
{ {
TOUCH(node); TOUCH(node);
return dosfs_sync(vol); return dosfs_sync(vol);
} }
vnode_ops fs_entry = {
&dosfs_read_vnode, // #pragma mark -
&dosfs_write_vnode,
&dosfs_remove_vnode,
NULL, 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_walk,
&dosfs_access, &dosfs_get_vnode_name,
&dosfs_create, &dosfs_read_vnode,
&dosfs_mkdir, &dosfs_release_vnode,
NULL, &dosfs_remove_vnode,
NULL,
&dosfs_rename, /* VM file access */
&dosfs_unlink, NULL, //&fs_can_page,
&dosfs_rmdir, 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_readlink,
&dosfs_opendir, NULL, // write link
&dosfs_closedir, NULL, //&fs_create_symlink,
&dosfs_free_dircookie,
&dosfs_rewinddir, NULL, //&fs_link,
&dosfs_readdir, &dosfs_unlink,
&dosfs_rename,
&dosfs_access,
&dosfs_rstat,
&dosfs_wstat,
/* file operations */
&dosfs_create,
&dosfs_open, &dosfs_open,
&dosfs_close, &dosfs_close,
&dosfs_free_cookie, &dosfs_free_cookie,
&dosfs_read, &dosfs_read,
&dosfs_write, &dosfs_write,
NULL,
NULL, /* directory operations */
&dosfs_ioctl, &dosfs_mkdir,
NULL, &dosfs_rmdir,
&dosfs_rstat, &dosfs_opendir,
&dosfs_wstat, &dosfs_closedir,
&dosfs_fsync, &dosfs_free_dircookie,
NULL, &dosfs_readdir,
&dosfs_mount, &dosfs_rewinddir,
&dosfs_unmount,
&dosfs_sync, /* attribute directory operations */
&dosfs_rfsstat,
&dosfs_wfsstat,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
&dosfs_open_attrdir, &dosfs_open_attrdir,
&dosfs_close_attrdir, &dosfs_close_attrdir,
&dosfs_free_attrcookie, &dosfs_free_attrdir_cookie,
&dosfs_rewind_attrdir,
&dosfs_read_attrdir, &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, &dosfs_read_attr,
NULL, &dosfs_write_attr,
NULL,
&dosfs_stat_attr, &dosfs_read_attr_stat,
NULL, NULL, //&fs_write_attr_stat,
NULL, NULL, //&fs_rename_attr,
NULL, NULL, //&fs_remove_attr,
NULL
/* 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,
};
+13 -18
View File
@@ -5,21 +5,16 @@
#ifndef _DOSFS_H_ #ifndef _DOSFS_H_
#define _DOSFS_H_ #define _DOSFS_H_
#if USE_DMALLOC
#include <dmalloc.h>
#else
/* allocate memory from swappable heap */
#define malloc smalloc
#define free sfree
#define calloc scalloc
#define realloc srealloc
#include <kalloc.h>
#endif
#include <KernelExport.h> #include <KernelExport.h>
#include <fs_interface.h>
#include <lock.h>
//#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 */ /* for multiple reader/single writer locks */
#define READERS 100000 #define READERS 100000
@@ -68,8 +63,6 @@
#define VNODE_PARENT_DIR_CLUSTER(vnode) \ #define VNODE_PARENT_DIR_CLUSTER(vnode) \
CLUSTER_OF_DIR_CLUSTER_VNID((vnode)->dir_vnid) CLUSTER_OF_DIR_CLUSTER_VNID((vnode)->dir_vnid)
#include <lock.h>
#define VNODE_MAGIC 'treB' #define VNODE_MAGIC 'treB'
typedef struct vnode typedef struct vnode
@@ -77,6 +70,7 @@ typedef struct vnode
uint32 magic; uint32 magic;
vnode_id vnid; // self id vnode_id vnid; // self id
vnode_id dir_vnid; // parent vnode id (directory containing entry) 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 uint32 disk_image; // 0 = no, 1 = BEOS, 2 = IMAGE.BE
@@ -122,10 +116,11 @@ struct vcache_entry;
typedef struct _nspace typedef struct _nspace
{ {
uint32 magic; uint32 magic;
nspace_id id; // ID passed in to fs_mount mount_id id; // ID passed in to fs_mount
int fd; // File descriptor int fd; // File descriptor
char device[256]; char device[256];
uint32 flags; // see <fcntl.be.h> for modes uint32 flags; // see <fcntl.be.h> for modes
void *fBlockCache;
// info from bpb // info from bpb
uint32 bytes_per_sector; 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, extern int debug_attr, debug_dir, debug_dlist, debug_dosfs, debug_encodings,
debug_fat, debug_file, debug_iter, debug_vcache; debug_fat, debug_file, debug_iter, debug_vcache;
int _dosfs_sync(nspace *vol); status_t _dosfs_sync(nspace *vol);
#endif #endif
+55 -27
View File
@@ -4,10 +4,7 @@
*/ */
#include <KernelExport.h> #include <KernelExport.h>
#include <fsproto.h> #include <fs_cache.h>
#include <lock.h>
#include <cache.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ByteOrder.h> #include <ByteOrder.h>
@@ -24,9 +21,10 @@
#define DPRINTF(a,b) if (debug_fat > (a)) dprintf b #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; uint32 i;
char *buf = buffer;
if (!vol->fat_mirrored) if (!vol->fat_mirrored)
return B_OK; return B_OK;
@@ -34,9 +32,13 @@ static status_t mirror_fats(nspace *vol, uint32 sector, uint8 *buffer)
sector -= vol->active_fat * vol->sectors_per_fat; sector -= vol->active_fat * vol->sectors_per_fat;
for (i=0;i<vol->fat_count;i++) { for (i=0;i<vol->fat_count;i++) {
char *blockData;
if (i == vol->active_fat) if (i == vol->active_fat)
continue; 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; return B_OK;
@@ -45,7 +47,7 @@ static status_t mirror_fats(nspace *vol, uint32 sector, uint8 *buffer)
static int32 _count_free_clusters_fat32(nspace *vol) static int32 _count_free_clusters_fat32(nspace *vol)
{ {
int32 count = 0; int32 count = 0;
uint8 *block; const uint8 *block;
uint32 fat_sector; uint32 fat_sector;
uint32 i; uint32 i;
uint32 cur_sector; 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; cur_sector = vol->reserved_sectors + vol->active_fat * vol->sectors_per_fat;
for(fat_sector = 0; fat_sector < vol->sectors_per_fat; fat_sector++) { 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) { if(block == NULL) {
return EIO; return EIO;
} }
@@ -63,7 +65,7 @@ static int32 _count_free_clusters_fat32(nspace *vol)
if(val == 0) count++; if(val == 0) count++;
} }
release_block(vol->fd, cur_sector); block_cache_put(vol->fBlockCache, cur_sector);
cur_sector++; cur_sector++;
} }
@@ -85,6 +87,7 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N)
uint32 sector; uint32 sector;
uint32 off, val = 0; /* quiet warning */ uint32 off, val = 0; /* quiet warning */
uint8 *block1, *block2 = NULL; /* quiet warning */ uint8 *block1, *block2 = NULL; /* quiet warning */
int32 tid = -1;
// mark end of chain for allocations // mark end of chain for allocations
uint32 V = (action == _IOCTL_SET_ENTRY_) ? N : 0x0fffffff; uint32 V = (action == _IOCTL_SET_ENTRY_) ? N : 0x0fffffff;
@@ -95,7 +98,6 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N)
DPRINTF(3, ("_fat_ioctl_: action %lx, cluster %lx, N %lx\n", action, cluster, N)); DPRINTF(3, ("_fat_ioctl_: action %lx, cluster %lx, N %lx\n", action, cluster, N));
if (action == _IOCTL_COUNT_FREE_) { if (action == _IOCTL_COUNT_FREE_) {
if(vol->fat_bits == 32) if(vol->fat_bits == 32)
// use a optimized version of the cluster counting algorithms // use a optimized version of the cluster counting algorithms
@@ -119,7 +121,14 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N)
off / vol->bytes_per_sector; off / vol->bytes_per_sector;
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)); DPRINTF(0, ("_fat_ioctl_: error reading fat (sector %lx)\n", sector));
return EIO; return EIO;
} }
@@ -130,7 +139,12 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N)
if (vol->fat_bits == 12) { if (vol->fat_bits == 12) {
if (off == vol->bytes_per_sector - 1) { 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)); DPRINTF(0, ("_fat_ioctl_: error reading fat (sector %lx)\n", sector));
result = EIO; result = EIO;
sector--; sector--;
@@ -162,8 +176,8 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N)
block1[off] &= (andmask & 0xff); block1[off] &= (andmask & 0xff);
block1[off] |= (ormask & 0xff); block1[off] |= (ormask & 0xff);
if (off == vol->bytes_per_sector - 1) { if (off == vol->bytes_per_sector - 1) {
mark_blocks_dirty(vol->fd, sector - 1, 1); //mark_blocks_dirty(vol->fd, sector - 1, 1);
mirror_fats(vol, sector - 1, block1); mirror_fats(vol, sector - 1, block1, tid);
block2[0] &= (andmask >> 8); block2[0] &= (andmask >> 8);
block2[0] |= (ormask >> 8); block2[0] |= (ormask >> 8);
} else { } else {
@@ -174,7 +188,7 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N)
if (off == vol->bytes_per_sector - 1) { if (off == vol->bytes_per_sector - 1) {
off = (cluster & 1) ? 1 : 0; off = (cluster & 1) ? 1 : 0;
release_block(vol->fd, sector - 1); block_cache_put(vol->fBlockCache, sector - 1);
block1 = block2; block1 = block2;
} else { } else {
off += (cluster & 1) ? 2 : 1; off += (cluster & 1) ? 2 : 1;
@@ -220,13 +234,13 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N)
result = val; result = val;
goto bi; goto bi;
} else if (action == _IOCTL_SET_ENTRY_) { } else if (action == _IOCTL_SET_ENTRY_) {
mark_blocks_dirty(vol->fd, sector, 1); //mark_blocks_dirty(vol->fd, sector, 1);
mirror_fats(vol, sector, block1); mirror_fats(vol, sector, block1, tid);
goto bi; goto bi;
} else if ((action == _IOCTL_ALLOCATE_N_ENTRIES_) && (val == 0)) { } else if ((action == _IOCTL_ALLOCATE_N_ENTRIES_) && (val == 0)) {
vol->free_clusters--; vol->free_clusters--;
mark_blocks_dirty(vol->fd, sector, 1); //mark_blocks_dirty(vol->fd, sector, 1);
mirror_fats(vol, sector, block1); mirror_fats(vol, sector, block1, tid);
if (n == 0) { if (n == 0) {
ASSERT(first == 0); ASSERT(first == 0);
first = last = cluster; 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 // iterate cluster and sector if needed
if (++cluster == vol->total_clusters + 2) { if (++cluster == vol->total_clusters + 2) {
release_block(vol->fd, sector); block_cache_put(vol->fBlockCache, sector);
cluster = 2; cluster = 2;
off = 2 * vol->fat_bits / 8; off = 2 * vol->fat_bits / 8;
sector = vol->reserved_sectors + vol->active_fat * vol->sectors_per_fat; 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) { if (off >= vol->bytes_per_sector) {
release_block(vol->fd, sector); block_cache_put(vol->fBlockCache, sector);
off -= vol->bytes_per_sector; sector++;
off -= vol->bytes_per_sector;
sector++;
ASSERT(sector < vol->reserved_sectors + (vol->active_fat + 1) * vol->sectors_per_fat); 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) { if (block1 == NULL) {
@@ -273,7 +296,10 @@ static int32 _fat_ioctl_(nspace *vol, uint32 action, uint32 cluster, int32 N)
} }
bi: 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 (action == _IOCTL_ALLOCATE_N_ENTRIES_) {
if (result < 0) { 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))); DPRINTF(0, ("_fat_ioctl_ error: action = %lx cluster = %lx N = %lx (%s)\n", action, cluster, N, strerror(result)));
}
return result; return result;
} }
@@ -553,6 +579,7 @@ void dump_fat_chain(nspace *vol, uint32 cluster)
dprintf("\n"); dprintf("\n");
} }
/*
status_t fragment(nspace *vol, uint32 *pattern) status_t fragment(nspace *vol, uint32 *pattern)
{ {
uint32 sector, offset, previous_entry, i, val; uint32 sector, offset, previous_entry, i, val;
@@ -642,3 +669,4 @@ status_t fragment(nspace *vol, uint32 *pattern)
return B_OK; return B_OK;
} }
*/
+258 -48
View File
@@ -2,15 +2,16 @@
Copyright 1999-2001, Be Incorporated. All Rights Reserved. Copyright 1999-2001, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License. This file may be used under the terms of the Be Sample Code License.
*/ */
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <KernelExport.h> #include <fs_cache.h>
#include <fs_info.h>
#include <Drivers.h> #include <Drivers.h>
#include <KernelExport.h>
#include <NodeMonitor.h>
#include <fsproto.h>
#include <lock.h>
#include <cache.h>
#include <time.h> #include <time.h>
#include "iter.h" #include "iter.h"
@@ -44,14 +45,26 @@ typedef struct filecookie
static CHECK_MAGIC(filecookie,struct filecookie, FILECOOKIE_MAGIC) 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) status_t write_vnode_entry(nspace *vol, vnode *node)
{ {
uint32 i; uint32 i;
struct diri diri; struct diri diri;
uint8 *buffer; uint8 *buffer;
// TODO : is it needed ? vfs job ?
// don't update entries of deleted files // 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 // XXX: should check if directory position is still valid even
// though we do the is_vnode_removed check above // 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; return B_OK;
} }
// called when fs is done with vnode // called when fs is done with vnode
// after close, etc. free vnode resources here // 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; nspace *vol = (nspace *)_vol;
vnode *node = (vnode *)_node; vnode *node = (vnode *)_node;
@@ -122,8 +137,11 @@ int dosfs_write_vnode(void *_vol, void *_node, char reenter)
#if TRACK_FILENAME #if TRACK_FILENAME
if (node->filename) free(node->filename); if (node->filename) free(node->filename);
#endif #endif
if (node->vnid != vol->root_vnode.vnid) { if (node->vnid != vol->root_vnode.vnid) {
node->magic = ~VNODE_MAGIC; // munge magic number to be safe node->magic = ~VNODE_MAGIC; // munge magic number to be safe
if (node->cache != NULL)
file_cache_delete(node->cache);
free(node); free(node);
} }
} }
@@ -131,7 +149,9 @@ int dosfs_write_vnode(void *_vol, void *_node, char reenter)
return 0; 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; nspace *vol = (nspace*)_vol;
vnode *node = (vnode*)_node; vnode *node = (vnode*)_node;
@@ -168,7 +188,9 @@ int dosfs_rstat(void *_vol, void *_node, struct stat *st)
return B_NO_ERROR; 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; int err = B_OK;
nspace *vol = (nspace*)_vol; nspace *vol = (nspace*)_vol;
@@ -197,7 +219,7 @@ int dosfs_wstat(void *_vol, void *_node, struct stat *st, long mask)
return EPERM; return EPERM;
} }
if (mask & WSTAT_MODE) { if (mask & FS_WRITE_STAT_MODE) {
DPRINTF(0, ("setting file mode to %o\n", st->st_mode)); DPRINTF(0, ("setting file mode to %o\n", st->st_mode));
if (st->st_mode & S_IWUSR) if (st->st_mode & S_IWUSR)
node->mode &= ~FAT_READ_ONLY; node->mode &= ~FAT_READ_ONLY;
@@ -206,7 +228,7 @@ int dosfs_wstat(void *_vol, void *_node, struct stat *st, long mask)
dirty = true; dirty = true;
} }
if (mask & WSTAT_SIZE) { if (mask & FS_WRITE_STAT_SIZE) {
DPRINTF(0, ("setting file size to %Lx\n", st->st_size)); DPRINTF(0, ("setting file size to %Lx\n", st->st_size));
if (node->mode & FAT_SUBDIR) { if (node->mode & FAT_SUBDIR) {
dprintf("dosfs_wstat: can't set file size of directory!\n"); 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->st_size = st->st_size;
node->iteration++; node->iteration++;
dirty = true; 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")); DPRINTF(0, ("setting modification time\n"));
node->st_time = st->st_mtime; node->st_time = st->st_mtime;
dirty = true; dirty = true;
@@ -249,9 +272,11 @@ int dosfs_wstat(void *_vol, void *_node, struct stat *st, long mask)
return err; 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; nspace *vol = (nspace *)_vol;
vnode* node = (vnode*)_node; vnode* node = (vnode*)_node;
filecookie *cookie; filecookie *cookie;
@@ -320,18 +345,20 @@ error:
return result; 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) void *buf, size_t *len)
{ {
nspace *vol = (nspace *)_vol; nspace *vol = (nspace *)_vol;
vnode *node = (vnode *)_node; vnode *node = (vnode *)_node;
filecookie *cookie = (filecookie *)_cookie; filecookie *cookie = (filecookie *)_cookie;
uint8 *buffer; //uint8 *buffer;
struct csi iter; //struct csi iter;
int result = B_OK; int result = B_OK;
size_t bytes_read = 0; //size_t bytes_read = 0;
uint32 cluster1; //uint32 cluster1;
off_t diff; //off_t diff;
LOCK_VOL(vol); LOCK_VOL(vol);
@@ -343,6 +370,7 @@ int dosfs_read(void *_vol, void *_node, void *_cookie, off_t pos,
return EINVAL; return EINVAL;
} }
if (node->mode & FAT_SUBDIR) { if (node->mode & FAT_SUBDIR) {
DPRINTF(0, ("dosfs_read called on subdirectory %Lx\n", node->vnid)); DPRINTF(0, ("dosfs_read called on subdirectory %Lx\n", node->vnid));
*len = 0; *len = 0;
@@ -355,7 +383,8 @@ int dosfs_read(void *_vol, void *_node, void *_cookie, off_t pos,
if (pos < 0) pos = 0; if (pos < 0) pos = 0;
if ((node->st_size == 0) || (*len == 0) || (pos >= node->st_size)) { if ((node->st_size == 0) || (*len == 0) || (pos >= node->st_size)) {
bytes_read = 0; //bytes_read = 0;
*len = 0;
goto bi; goto bi;
} }
@@ -363,6 +392,10 @@ int dosfs_read(void *_vol, void *_node, void *_cookie, off_t pos,
if (pos + *len >= node->st_size) if (pos + *len >= node->st_size)
*len = node->st_size - pos; *len = node->st_size - pos;
result = file_cache_read(node->cache, pos, buf, len);
#if 0
if ((cookie->ccache.iteration == node->iteration) && if ((cookie->ccache.iteration == node->iteration) &&
(pos >= cookie->ccache.index * vol->bytes_per_sector * vol->sectors_per_cluster)) { (pos >= cookie->ccache.index * vol->bytes_per_sector * vol->sectors_per_cluster)) {
/* the cached fat value is both valid and helpful */ /* the cached fat value is both valid and helpful */
@@ -455,9 +488,9 @@ int dosfs_read(void *_vol, void *_node, void *_cookie, off_t pos,
} }
result = B_OK; result = B_OK;
bi: #endif
*len = bytes_read;
bi:
if (result != B_OK) { if (result != B_OK) {
DPRINTF(0, ("dosfs_read (%s)\n", strerror(result))); DPRINTF(0, ("dosfs_read (%s)\n", strerror(result)));
} else { } else {
@@ -468,18 +501,21 @@ bi:
return result; 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) const void *buf, size_t *len)
{ {
nspace *vol = (nspace *)_vol; nspace *vol = (nspace *)_vol;
vnode *node = (vnode *)_node; vnode *node = (vnode *)_node;
filecookie *cookie = (filecookie *)_cookie; filecookie *cookie = (filecookie *)_cookie;
uint8 *buffer; //uint8 *buffer;
struct csi iter; //struct csi iter;
int result = B_OK; int result = B_OK;
size_t bytes_written = 0; //size_t bytes_written = 0;
uint32 cluster1; //uint32 cluster1;
off_t diff; //off_t diff;
LOCK_VOL(vol); LOCK_VOL(vol);
@@ -503,6 +539,7 @@ int dosfs_write(void *_vol, void *_node, void *_cookie, off_t pos,
if ((cookie->mode & O_RWMASK) == O_RDONLY) { if ((cookie->mode & O_RWMASK) == O_RDONLY) {
dprintf("dosfs_write: called on file opened as read-only\n"); dprintf("dosfs_write: called on file opened as read-only\n");
*len = 0;
result = EPERM; result = EPERM;
goto bi; goto bi;
} }
@@ -515,6 +552,7 @@ int dosfs_write(void *_vol, void *_node, void *_cookie, off_t pos,
if (pos >= MAX_FILE_SIZE) { if (pos >= MAX_FILE_SIZE) {
dprintf("dosfs_write: write position exceeds fat limits\n"); dprintf("dosfs_write: write position exceeds fat limits\n");
*len = 0;
result = E2BIG; result = E2BIG;
goto bi; goto bi;
} }
@@ -523,6 +561,8 @@ int dosfs_write(void *_vol, void *_node, void *_cookie, off_t pos,
*len = (size_t)(MAX_FILE_SIZE - pos); *len = (size_t)(MAX_FILE_SIZE - pos);
} }
#if 0
if (node->st_size && if (node->st_size &&
(cookie->ccache.iteration == node->iteration) && (cookie->ccache.iteration == node->iteration) &&
(pos >= cookie->ccache.index * vol->bytes_per_sector * vol->sectors_per_cluster)) { (pos >= cookie->ccache.index * vol->bytes_per_sector * vol->sectors_per_cluster)) {
@@ -534,6 +574,7 @@ int dosfs_write(void *_vol, void *_node, void *_cookie, off_t pos,
cluster1 = 0xffffffff; cluster1 = 0xffffffff;
diff = 0; diff = 0;
} }
#endif
// extend file size if needed // extend file size if needed
if (pos + *len > node->st_size) { 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)); DPRINTF(0, ("setting file size to %Lx (%lx clusters)\n", node->st_size, clusters));
node->dirty = true; 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) { if (cluster1 == 0xffffffff) {
cluster1 = node->cluster; cluster1 = node->cluster;
diff = pos; diff = pos;
@@ -643,10 +688,9 @@ int dosfs_write(void *_vol, void *_node, void *_cookie, off_t pos,
} }
result = B_OK; result = B_OK;
#endif
bi: bi:
*len = bytes_written;
if (result != B_OK) { if (result != B_OK) {
DPRINTF(0, ("dosfs_write (%s)\n", strerror(result))); DPRINTF(0, ("dosfs_write (%s)\n", strerror(result)));
} else { } else {
@@ -657,7 +701,9 @@ bi:
return result; 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; nspace *vol = (nspace *)_vol;
vnode *node = (vnode *)_node; vnode *node = (vnode *)_node;
@@ -683,7 +729,9 @@ int dosfs_close(void *_vol, void *_node, void *_cookie)
return 0; 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; nspace *vol = _vol;
vnode *node = _node; vnode *node = _node;
@@ -707,8 +755,10 @@ int dosfs_free_cookie(void *_vol, void *_node, void *_cookie)
return 0; 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; nspace *vol = (nspace *)_vol;
vnode *dir = (vnode *)_dir, *file; vnode *dir = (vnode *)_dir, *file;
@@ -739,11 +789,12 @@ int dosfs_create(void *_vol, void *_dir, const char *name, int omode,
return EROFS; 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"); dprintf("dosfs_create() called in removed directory. disallowed.\n");
UNLOCK_VOL(vol); UNLOCK_VOL(vol);
return EPERM; return EPERM;
} }*/
if ((omode & O_RWMASK) == O_RDONLY) { if ((omode & O_RWMASK) == O_RDONLY) {
dprintf("invalid permissions used in creating file\n"); dprintf("invalid permissions used in creating file\n");
@@ -854,7 +905,9 @@ bi: if (result != B_OK) free(cookie);
return result; 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; nspace *vol = (nspace *)_vol;
vnode *dir = (vnode *)_dir, dummy; vnode *dir = (vnode *)_dir, dummy;
@@ -871,11 +924,12 @@ int dosfs_mkdir(void *_vol, void *_dir, const char *name, int perms)
return EINVAL; 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"); dprintf("dosfs_mkdir() called in removed directory. disallowed.\n");
UNLOCK_VOL(vol); UNLOCK_VOL(vol);
return EPERM; return EPERM;
} }*/
DPRINTF(0, ("dosfs_mkdir called: %Lx/%s (perm %o)\n", dir->vnid, name, perms)); 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; 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) void *_ndir, const char *newname)
{ {
status_t result = EINVAL; status_t result = EINVAL;
@@ -1230,7 +1286,9 @@ bi:
return result; 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; nspace *vol = (nspace *)_vol;
vnode *node = (vnode *)_node; vnode *node = (vnode *)_node;
@@ -1279,13 +1337,14 @@ int dosfs_remove_vnode(void *_vol, void *_node, char reenter)
UNLOCK_VOL(vol); UNLOCK_VOL(vol);
} }
return 0; return B_OK;
} }
// get rid of node or directory // 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; nspace *vol = (nspace *)_vol;
vnode *dir = (vnode *)_dir, *file; vnode *dir = (vnode *)_dir, *file;
vnode_id vnid; vnode_id vnid;
@@ -1391,16 +1450,167 @@ bi: UNLOCK_VOL(vol);
return result; 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")); 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")); 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;
} }
+18 -15
View File
@@ -7,24 +7,27 @@
status_t write_vnode_entry(nspace *vol, vnode *node); status_t write_vnode_entry(nspace *vol, vnode *node);
int dosfs_write_vnode(void *_vol, void *_node, char r); status_t dosfs_get_vnode_name(void *_ns, void *_node, char *buffer, size_t bufferSize);
int dosfs_rstat(void *_vol, void *_node, struct stat *st); status_t dosfs_release_vnode(void *_vol, void *_node, bool reenter);
int dosfs_open(void *_vol, void *_node, int omode, void **cookie); status_t dosfs_rstat(void *_vol, void *_node, struct stat *st);
int dosfs_read(void *_vol, void *_node, void *cookie, off_t pos, 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); void *buf, size_t *len);
int dosfs_free_cookie(void *vol, void *node, void *cookie); status_t dosfs_free_cookie(void *vol, void *node, void *cookie);
int dosfs_close(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); status_t dosfs_remove_vnode(void *vol, void *node, bool reenter);
int dosfs_create(void *vol, void *dir, const char *name, status_t dosfs_create(void *vol, void *dir, const char *name,
int perms, int omode, vnode_id *vnid, void **cookie); int omode, int perms, void **cookie, vnode_id *vnid);
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);
int dosfs_rename(void *vol, void *olddir, const char *oldname, status_t dosfs_rename(void *vol, void *olddir, const char *oldname,
void *newdir, const char *newname); void *newdir, const char *newname);
int dosfs_unlink(void *vol, void *dir, const char *name); status_t dosfs_unlink(void *vol, void *dir, const char *name);
int dosfs_rmdir(void *vol, void *dir, const char *name); status_t dosfs_rmdir(void *vol, void *dir, const char *name);
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 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); 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 #endif
@@ -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 <sys/dirent.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <unistd.h>
#include <iovec.h>
#include <OS.h>
#include <fs_attr.h>
#include <fs_info.h>
#include <BeBuild.h>
#include <Drivers.h>
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
+56 -32
View File
@@ -4,9 +4,8 @@
*/ */
#include <KernelExport.h> #include <KernelExport.h>
#include <fsproto.h> #include <fs_cache.h>
#include <lock.h> #include <string.h>
#include <cache.h>
#include "iter.h" #include "iter.h"
#include "dosfs.h" #include "dosfs.h"
@@ -34,7 +33,7 @@ static int _validate_cs_(nspace *vol, uint32 cluster, uint32 sector)
return 0; 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 // presumes the caller has already called _validate_cs_ on the argument
ASSERT(_validate_cs_(csi->vol, csi->cluster, csi->sector) == 0); ASSERT(_validate_cs_(csi->vol, csi->cluster, csi->sector) == 0);
@@ -97,37 +96,34 @@ int iter_csi(struct csi *csi, int sectors)
return -1; 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) if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0)
return NULL; 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 csi_release_block(struct csi *csi)
{ {
status_t err;
if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0) if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0)
return EINVAL; return EINVAL;
err = release_block(csi->vol->fd, _csi_to_block_(csi)); block_cache_put(csi->vol->fBlockCache, csi_to_block(csi));
ASSERT(err == B_OK); return B_OK;
return err;
} }
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); ASSERT(_validate_cs_(csi->vol, csi->cluster, csi->sector) == 0);
if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0) if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0)
return EINVAL; return EINVAL;
err = mark_blocks_dirty(csi->vol->fd, _csi_to_block_(csi), 1); // TODO : block_cache doesn't implement this
ASSERT(err == B_OK); //block_cache_set_dirty(csi->vol->fBlockCache, csi_to_block(csi), true, tid);
return err;
return B_OK;
} }
/* XXX: not the most efficient implementation, but it gets the job done */ /* XXX: not the most efficient implementation, but it gets the job done */
@@ -137,6 +133,8 @@ status_t csi_read_blocks(struct csi *csi, uint8 *buffer, ssize_t len)
uint32 sectors; uint32 sectors;
off_t block; off_t block;
status_t err; status_t err;
char *buf = buffer;
int32 i;
ASSERT(len >= csi->vol->bytes_per_sector); ASSERT(len >= csi->vol->bytes_per_sector);
@@ -144,21 +142,24 @@ status_t csi_read_blocks(struct csi *csi, uint8 *buffer, ssize_t len)
return EINVAL; return EINVAL;
sectors = 1; sectors = 1;
block = _csi_to_block_(csi); block = csi_to_block(csi);
while (1) { while (1) {
old_csi = *csi; old_csi = *csi;
err = iter_csi(csi, 1); err = iter_csi(csi, 1);
if (len < (sectors + 1) * csi->vol->bytes_per_sector) if (len < (sectors + 1) * csi->vol->bytes_per_sector)
break; break;
if ((err < B_OK) || (block + sectors != _csi_to_block_(csi))) if ((err < B_OK) || (block + sectors != csi_to_block(csi)))
break; break;
sectors++; sectors++;
} }
err = cached_read(csi->vol->fd, block, buffer, sectors, csi->vol->bytes_per_sector); for (i=block; i<block+sectors; i++) {
if (err < B_OK) char *blockData = (char *)block_cache_get(csi->vol->fBlockCache, i);
return err; memcpy(buf, blockData, csi->vol->bytes_per_sector);
buf += csi->vol->bytes_per_sector;
block_cache_put(csi->vol->fBlockCache, i);
}
*csi = old_csi; *csi = old_csi;
@@ -171,6 +172,8 @@ status_t csi_write_blocks(struct csi *csi, uint8 *buffer, ssize_t len)
uint32 sectors; uint32 sectors;
off_t block; off_t block;
status_t err; status_t err;
char *buf = buffer;
int32 i, tid;
ASSERT(len >= csi->vol->bytes_per_sector); 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; return EINVAL;
sectors = 1; sectors = 1;
block = _csi_to_block_(csi); block = csi_to_block(csi);
while (1) { while (1) {
old_csi = *csi; old_csi = *csi;
err = iter_csi(csi, 1); err = iter_csi(csi, 1);
if (len < (sectors + 1) * csi->vol->bytes_per_sector) if (len < (sectors + 1) * csi->vol->bytes_per_sector)
break; break;
if ((err < B_OK) || (block + sectors != _csi_to_block_(csi))) if ((err < B_OK) || (block + sectors != csi_to_block(csi)))
break; break;
sectors++; sectors++;
} }
err = cached_write(csi->vol->fd, block, buffer, sectors, csi->vol->bytes_per_sector); tid = cache_start_transaction(csi->vol->fBlockCache);
if (err < B_OK) for(i=block; i<block+sectors; i++) {
return err; char *blockData = block_cache_get_writable_etc(csi->vol->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 /* 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 * 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) 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); ASSERT(_validate_cs_(csi->vol, csi->cluster, csi->sector) == 0);
if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0) if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0)
return EINVAL; return EINVAL;
return cached_write(csi->vol->fd, _csi_to_block_(csi), buffer, 1, csi->vol->bytes_per_sector); 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 B_OK;
} }
static void _diri_release_current_block_(struct diri *diri) static void _diri_release_current_block_(struct diri *diri)
@@ -239,8 +259,10 @@ uint8 *diri_init(nspace *vol, uint32 cluster, uint32 index, struct diri *diri)
return NULL; return NULL;
} }
diri->tid = cache_start_transaction(diri->csi.vol->fBlockCache);
// get current sector // 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) if (diri->current_block == NULL)
return NULL; return NULL;
@@ -257,6 +279,8 @@ int diri_free(struct diri *diri)
if (diri->current_block) if (diri->current_block)
_diri_release_current_block_(diri); _diri_release_current_block_(diri);
cache_end_transaction(diri->csi.vol->fBlockCache, diri->tid, NULL, NULL);
return 0; return 0;
} }
@@ -281,7 +305,7 @@ uint8 *diri_next_entry(struct diri *diri)
_diri_release_current_block_(diri); _diri_release_current_block_(diri);
if (iter_csi(&(diri->csi), 1) != 0) if (iter_csi(&(diri->csi), 1) != 0)
return NULL; 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) if (diri->current_block == NULL)
return NULL; return NULL;
} }
@@ -298,7 +322,7 @@ uint8 *diri_rewind(struct diri *diri)
_diri_release_current_block_(diri); _diri_release_current_block_(diri);
if (init_csi(diri->csi.vol, diri->starting_cluster, 0, &(diri->csi)) != 0) if (init_csi(diri->csi.vol, diri->starting_cluster, 0, &(diri->csi)) != 0)
return NULL; return NULL;
diri->current_block = csi_get_block(&(diri->csi)); diri->current_block = csi_get_block(&(diri->csi), diri->tid);
} }
diri->current_index = 0; diri->current_index = 0;
return diri->current_block; return diri->current_block;
@@ -306,5 +330,5 @@ uint8 *diri_rewind(struct diri *diri)
void diri_mark_dirty(struct diri *diri) void diri_mark_dirty(struct diri *diri)
{ {
csi_mark_block_dirty(&(diri->csi)); csi_mark_block_dirty(&(diri->csi), diri->tid);
} }
+4 -2
View File
@@ -15,11 +15,12 @@ struct csi
uint32 sector; uint32 sector;
}; };
off_t csi_to_block(struct csi *csi);
int init_csi(struct _nspace *vol, uint32 cluster, uint32 sector, struct csi *csi); int init_csi(struct _nspace *vol, uint32 cluster, uint32 sector, struct csi *csi);
int iter_csi(struct csi *csi, int sectors); 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_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_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_blocks(struct csi *csi, uint8 *buffer, ssize_t len);
status_t csi_write_block(struct csi *csi, uint8 *buffer); status_t csi_write_block(struct csi *csi, uint8 *buffer);
@@ -33,6 +34,7 @@ struct diri
uint32 starting_cluster; uint32 starting_cluster;
uint32 current_index; uint32 current_index;
uint8 *current_block; uint8 *current_block;
int32 tid;
}; };
uint8 *diri_init(struct _nspace *vol, uint32 cluster, uint32 index, struct diri *diri); uint8 *diri_init(struct _nspace *vol, uint32 cluster, uint32 index, struct diri *diri);
@@ -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 <SupportDefs.h>
#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
@@ -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 <BeBuild.h>
#include <OS.h>
#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
+5 -2
View File
@@ -9,8 +9,7 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <fsproto.h> #include "rtc_info.h"
#include <rtc_info.h>
#include "dosfs.h" #include "dosfs.h"
#include "fat.h" #include "fat.h"
@@ -18,6 +17,8 @@
static int32 tzoffset = -1; /* in minutes */ static int32 tzoffset = -1; /* in minutes */
#ifdef DEBUG
int _assert_(char *a, int b, char *c) int _assert_(char *a, int b, char *c)
{ {
dprintf("tripped assertion in %s/%d (%s)\n", a, b, 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; return 0;
} }
#endif
static void print_byte(uint8 c) static void print_byte(uint8 c)
{ {
dprintf("%c", ((c >= ' ') && (c <= '~')) ? c : '.'); dprintf("%c", ((c >= ' ') && (c <= '~')) ? c : '.');
+2 -1
View File
@@ -8,13 +8,14 @@
#include <ByteOrder.h> #include <ByteOrder.h>
// debugging functions // debugging functions
#ifndef ASSERT
#ifndef DEBUG #ifndef DEBUG
#define ASSERT(c) ((void)0) #define ASSERT(c) ((void)0)
#else #else
int _assert_(char *,int,char *); int _assert_(char *,int,char *);
#define ASSERT(c) (!(c) ? _assert_(__FILE__,__LINE__,#c) : 0) #define ASSERT(c) (!(c) ? _assert_(__FILE__,__LINE__,#c) : 0)
#endif #endif
#endif
void dump_bytes(uint8 *buffer, uint32 count); void dump_bytes(uint8 *buffer, uint32 count);
void dump_directory(uint8 *buffer); void dump_directory(uint8 *buffer);
+2 -3
View File
@@ -50,7 +50,6 @@ purpose.
#define UNLOCK_CACHE_W \ #define UNLOCK_CACHE_W \
release_sem_etc(vol->vcache.vc_sem, READERS, 0) release_sem_etc(vol->vcache.vc_sem, READERS, 0)
#include <fsproto.h>
#include <KernelExport.h> #include <KernelExport.h>
#include <stdio.h> #include <stdio.h>
@@ -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)); 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)) if (!IS_ARTIFICIAL_VNID(loc))
return B_OK; return B_OK;
} else { } else {
ASSERT(is_vnode_removed(vol->id, vnid) == 0); ASSERT(is_vnode_removed(vol->id, vnid) == 0);
} }*/
LOCK_CACHE_W; LOCK_CACHE_W;