#define REQ_TRC_START_LO m9_l3
#define REQ_UCRED_SIZE m9_s4
#define REQ_UID m9_s4
-#define REQ_PROTO m9_s4 /* For definition see RES_PROTO */
-
/* VFS/FS reply fields */
#define RES_DEV m9_l4
#define RES_SEEK_POS_LO m9_l4
#define RES_SYMLOOP m9_s3
#define RES_UID m9_s4
-
-#define RES_PROTO m9_s3
-/* RES_PROTO is defined as follows:
- * |--------------------------------|
- * 8O7 V 4 CR 0
- * 15 0
- * mentioned bits are inclusive
- * CR: bits 4-0 encode no. concurrent requests are supported by FS
- * V: bits 7-5 encode version of protocol
- * O: bit 8 encodes support for 64-bit file offsets
- */
-#define RES_PROTO_CR_SHIFT 0
-#define RES_PROTO_CR_MASK 0x1F
-#define VFS_FS_PROTO_CONREQS(b) (((b) & RES_PROTO_CR_MASK)>>RES_PROTO_CR_SHIFT)
-#define VFS_FS_PROTO_PUT_CONREQS(b,v) \
- ((b) |= (((v) << RES_PROTO_CR_SHIFT) & RES_PROTO_CR_MASK))
-#define RES_PROTO_V_SHIFT 5
-#define RES_PROTO_V_MASK 0x70
-#define VFS_FS_PROTO_VERSION(b) (((b) & RES_PROTO_V_MASK) >> RES_PROTO_V_SHIFT)
-#define VFS_FS_PROTO_PUT_VERSION(b,v) \
- ((b) |= (((v) << RES_PROTO_V_SHIFT) & RES_PROTO_V_MASK))
-#define VFS_FS_CURRENT_VERSION 1 /* Current version */
-#define RES_PROTO_BIGOFFT_SHIFT 8
-#define VFS_FS_PROTO_BIGOFFT(b) (b & RES_PROTO_BIGOFFT_SHIFT)
+#define RES_FLAGS m9_s3
/* VFS/FS flags */
-#define REQ_RDONLY 001
-#define REQ_ISROOT 002
-#define REQ_HASPROTO 004
+#define REQ_RDONLY 001 /* FS is mounted read-only */
+#define REQ_ISROOT 002 /* FS is root file system */
+
#define PATH_NOFLAGS 000
#define PATH_RET_SYMLINK 010 /* Return a symlink object (i.e.
* do not continue with the contents
* and struct ucred size in m9_s4 (as
* opposed to a REQ_UID). */
+#define RES_NOFLAGS 000
+#define RES_THREADED 001 /* FS supports multithreading */
+#define RES_HASPEEK 002 /* FS implements REQ_PEEK/REQ_BPEEK */
+#define RES_64BIT 004 /* FS can handle 64-bit file sizes */
+
/* VFS/FS error messages */
#define EENTERMOUNT (-301)
#define ELEAVEMOUNT (-302)
fs_m_out.RES_FILE_SIZE_LO = root_va->va_size;
fs_m_out.RES_UID = root_va->va_uid;
fs_m_out.RES_GID = root_va->va_gid;
- fs_m_out.RES_PROTO = 0;
- VFS_FS_PROTO_PUT_VERSION(fs_m_out.RES_PROTO, VFS_FS_CURRENT_VERSION);
- VFS_FS_PROTO_PUT_CONREQS(fs_m_out.RES_PROTO, 1);
+ fs_m_out.RES_FLAGS = RES_NOFLAGS;
return(OK);
}
m_out.RES_UID = sffs_params->p_uid;
m_out.RES_GID = sffs_params->p_gid;
m_out.RES_DEV = NO_DEV;
- m_out.RES_PROTO = 0;
- VFS_FS_PROTO_PUT_VERSION(m_out.RES_PROTO, VFS_FS_CURRENT_VERSION);
- VFS_FS_PROTO_PUT_CONREQS(m_out.RES_PROTO, 1);
+ m_out.RES_FLAGS = RES_64BIT;
state.s_mounted = TRUE;
EXTERN struct fs_hooks *vtreefs_hooks;
-EXTERN int proto_version;
EXTERN message fs_m_in;
EXTERN message fs_m_out;
if (fs_m_in.REQ_FLAGS & REQ_ISROOT)
return EINVAL;
- /* Get VFS-FS protocol version */
- if (!(fs_m_in.REQ_FLAGS & REQ_HASPROTO)) {
- proto_version = 0;
- } else {
- proto_version = VFS_FS_PROTO_VERSION(fs_m_in.REQ_PROTO);
- }
-
/* Get the root inode and increase its reference count. */
root = get_root_inode();
ref_inode(root);
fs_m_out.RES_UID = root->i_stat.uid;
fs_m_out.RES_GID = root->i_stat.gid;
fs_m_out.RES_DEV = NO_DEV;
-
- fs_m_out.RES_PROTO = 0;
- VFS_FS_PROTO_PUT_VERSION(fs_m_out.RES_PROTO, VFS_FS_CURRENT_VERSION);
- VFS_FS_PROTO_PUT_CONREQS(fs_m_out.RES_PROTO, 1);
+ fs_m_out.RES_FLAGS = RES_NOFLAGS;
fs_mounted = TRUE;
return r;
}
-/*===========================================================================*
- * fs_getdents_321 *
- *===========================================================================*/
-int fs_getdents_321(void)
-{
- /* Retrieve directory entries.
- */
- struct inode *node, *child = NULL;
- struct dirent_321 *dent;
- char *name;
- size_t len, off, user_off, user_left;
- off_t pos;
- int r, skip, get_next, indexed;
- static char buf[GETDENTS_BUFSIZ];
-
- if (fs_m_in.REQ_SEEK_POS_HI != 0)
- return EIO;
-
- if ((node = find_inode(fs_m_in.REQ_INODE_NR)) == NULL)
- return EINVAL;
-
- off = 0;
- user_off = 0;
- user_left = fs_m_in.REQ_MEM_SIZE;
- indexed = node->i_indexed;
- get_next = FALSE;
- child = NULL;
-
- /* Call the getdents hook, if any, to "refresh" the directory. */
- if (!is_inode_deleted(node) && vtreefs_hooks->getdents_hook != NULL) {
- r = vtreefs_hooks->getdents_hook(node, get_inode_cbdata(node));
- if (r != OK) return r;
- }
-
- for (pos = fs_m_in.REQ_SEEK_POS_LO; ; pos++) {
- /* Determine which inode and name to use for this entry. */
- if (pos == 0) {
- /* The "." entry. */
- child = node;
- name = ".";
- }
- else if (pos == 1) {
- /* The ".." entry. */
- child = get_parent_inode(node);
- if (child == NULL)
- child = node;
- name = "..";
- }
- else if (pos - 2 < indexed) {
- /* All indexed entries. */
- child = get_inode_by_index(node, pos - 2);
-
- /* If there is no inode with this particular index,
- * continue with the next index number.
- */
- if (child == NULL) continue;
-
- name = child->i_name;
- }
- else {
- /* All non-indexed entries. */
-
- /* If this is the first loop iteration, first get to
- * the non-indexed child identified by the current
- * position.
- */
- if (get_next == FALSE) {
- skip = pos - indexed - 2;
- child = get_first_inode(node);
-
- /* Skip indexed children. */
- while (child != NULL &&
- child->i_index != NO_INDEX)
- child = get_next_inode(child);
-
- /* Skip to the right position. */
- while (child != NULL && skip-- > 0)
- child = get_next_inode(child);
-
- get_next = TRUE;
- }
- else {
- child = get_next_inode(child);
- }
-
- /* No more children? Then stop. */
- if (child == NULL)
- break;
-
- assert(!is_inode_deleted(child));
-
- name = child->i_name;
- }
-
- len = DWORD_ALIGN(sizeof(struct dirent_321) + strlen(name));
-
- /* Is the user buffer too small to store another record? */
- if (user_off + off + len > user_left) {
- /* Is the user buffer too small for even a single
- * record?
- */
- if (user_off == 0 && off == 0)
- return EINVAL;
-
- break;
- }
-
- /* If our own buffer cannot contain the new record, copy out
- * first.
- */
- if (off + len > sizeof(buf)) {
- r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT,
- user_off, (vir_bytes) buf, off);
- if (r != OK) return r;
-
- user_off += off;
- user_left -= off;
- off = 0;
- }
-
- /* Fill in the actual directory entry. */
- dent = (struct dirent_321 *) &buf[off];
- dent->d_ino = (u32_t) get_inode_number(child);
- dent->d_off = (i32_t) pos;
- dent->d_reclen = len;
- strcpy(dent->d_name, name);
-
- off += len;
- }
-
- /* If there is anything left in our own buffer, copy that out now. */
- if (off > 0) {
- r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT,
- user_off, (vir_bytes) buf, off);
- if (r != OK)
- return r;
-
- user_off += off;
- }
-
- fs_m_out.RES_SEEK_POS_HI = 0;
- fs_m_out.RES_SEEK_POS_LO = pos;
- fs_m_out.RES_NBYTES = user_off;
-
- return OK;
-}
-
/*===========================================================================*
* fs_getdents *
*===========================================================================*/
int r, skip, get_next, indexed;
static char buf[GETDENTS_BUFSIZ];
- if (proto_version == 0)
- return fs_getdents_321();
-
if (fs_m_in.REQ_SEEK_POS_HI != 0)
return EIO;
extern int(*fs_call_vec[]) (void);
-EXTERN int proto_version;
-
EXTERN message fs_m_in;
EXTERN message fs_m_out;
EXTERN vfs_ucred_t credentials;
readonly = (fs_m_in.REQ_FLAGS & REQ_RDONLY) ? 1 : 0;
isroot = (fs_m_in.REQ_FLAGS & REQ_ISROOT) ? 1 : 0;
- if (!(fs_m_in.REQ_FLAGS & REQ_HASPROTO)) {
- proto_version = 0;
- } else {
- proto_version = VFS_FS_PROTO_VERSION(fs_m_in.REQ_PROTO);
- }
-
if (label_len > sizeof(fs_dev_label))
return(EINVAL);
fs_m_out.RES_FILE_SIZE_LO = root_ip->i_size;
fs_m_out.RES_UID = root_ip->i_uid;
fs_m_out.RES_GID = root_ip->i_gid;
- fs_m_out.RES_PROTO = 0;
- VFS_FS_PROTO_PUT_VERSION(fs_m_out.RES_PROTO, VFS_FS_CURRENT_VERSION);
- VFS_FS_PROTO_PUT_CONREQS(fs_m_out.RES_PROTO, 1);
+ fs_m_out.RES_FLAGS = RES_HASPEEK;
return(r);
}
}
-/*===========================================================================*
- * fs_getdents_321 *
- *===========================================================================*/
-static int fs_getdents_321(void)
-{
-#define GETDENTS_321_BUFSIZE (sizeof(struct dirent_321) + EXT2_NAME_MAX + 1)
-#define GETDENTS_321_ENTRIES 8
- static char getdents_buf[GETDENTS_321_BUFSIZE * GETDENTS_321_ENTRIES];
- struct inode *rip;
- int o, r, done;
- unsigned int block_size, len, reclen;
- pino_t ino;
- block_t b;
- cp_grant_id_t gid;
- size_t size, tmpbuf_off, userbuf_off;
- off_t pos, off, block_pos, new_pos, ent_pos;
- struct buf *bp;
- struct ext2_disk_dir_desc *d_desc;
- struct dirent *dep;
-
- ino = (pino_t) fs_m_in.REQ_INODE_NR;
- gid = (cp_grant_id_t) fs_m_in.REQ_GRANT;
- size = (size_t) fs_m_in.REQ_MEM_SIZE;
- pos = (off_t) fs_m_in.REQ_SEEK_POS_LO;
-
- /* Check whether the position is properly aligned */
- if ((unsigned int) pos % DIR_ENTRY_ALIGN)
- return(ENOENT);
-
- if ((rip = get_inode(fs_dev, ino)) == NULL)
- return(EINVAL);
-
- block_size = rip->i_sp->s_block_size;
- off = (pos % block_size); /* Offset in block */
- block_pos = pos - off;
- done = FALSE; /* Stop processing directory blocks when done is set */
-
- memset(getdents_buf, '\0', sizeof(getdents_buf)); /* Avoid leaking any data */
- tmpbuf_off = 0; /* Offset in getdents_buf */
- userbuf_off = 0; /* Offset in the user's buffer */
-
- /* The default position for the next request is EOF. If the user's buffer
- * fills up before EOF, new_pos will be modified. */
- new_pos = rip->i_size;
-
- for (; block_pos < rip->i_size; block_pos += block_size) {
- off_t temp_pos = block_pos;
- b = read_map(rip, block_pos, 0); /* get block number */
- /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */
- bp = get_block(rip->i_dev, b, NORMAL); /* get a dir block */
- assert(bp != NULL);
-
- /* Search a directory block. */
- d_desc = (struct ext2_disk_dir_desc*) &b_data(bp);
-
- /* we need to seek to entry at off bytes.
- * when NEXT_DISC_DIR_POS == block_size it's last dentry.
- */
- for (; temp_pos + conv2(le_CPU, d_desc->d_rec_len) <= pos
- && NEXT_DISC_DIR_POS(d_desc, &b_data(bp)) < block_size;
- d_desc = NEXT_DISC_DIR_DESC(d_desc)) {
- temp_pos += conv2(le_CPU, d_desc->d_rec_len);
- }
-
- for (; CUR_DISC_DIR_POS(d_desc, &b_data(bp)) < block_size;
- d_desc = NEXT_DISC_DIR_DESC(d_desc)) {
- if (d_desc->d_ino == 0)
- continue; /* Entry is not in use */
-
-#if 0 /* d_nam_len is a uint8_t, so the test is always false. */
- if (d_desc->d_name_len > NAME_MAX ||
- d_desc->d_name_len > EXT2_NAME_MAX) {
- len = min(NAME_MAX, EXT2_NAME_MAX);
- } else {
- len = d_desc->d_name_len;
- }
-#endif
- len = d_desc->d_name_len;
-
- /* Compute record length */
- reclen = offsetof(struct dirent_321, d_name) + len + 1;
- o = (reclen % sizeof(long));
- if (o != 0)
- reclen += sizeof(long) - o;
-
- /* Need the position of this entry in the directory */
- ent_pos = block_pos + ((char *)d_desc - b_data(bp));
-
- if (userbuf_off + tmpbuf_off + reclen >= size) {
- /* The user has no space for one more record */
- done = TRUE;
-
- /* Record the position of this entry, it is the
- * starting point of the next request (unless the
- * position is modified with lseek).
- */
- new_pos = ent_pos;
- break;
- }
-
- if (tmpbuf_off + reclen >=
- GETDENTS_321_BUFSIZE * GETDENTS_321_ENTRIES) {
- r = sys_safecopyto(VFS_PROC_NR, gid,
- (vir_bytes) userbuf_off,
- (vir_bytes) getdents_buf,
- (size_t) tmpbuf_off);
- if (r != OK) {
- put_inode(rip);
- return(r);
- }
- userbuf_off += tmpbuf_off;
- tmpbuf_off = 0;
- }
-
- dep = (struct dirent *) &getdents_buf[tmpbuf_off];
- dep->d_ino = (u32_t) conv4(le_CPU, d_desc->d_ino);
- dep->d_off = (i32_t) ent_pos;
- dep->d_reclen = (unsigned short) reclen;
- memcpy(dep->d_name, d_desc->d_name, len);
- dep->d_name[len] = '\0';
- tmpbuf_off += reclen;
- }
-
- put_block(bp, DIRECTORY_BLOCK);
- if (done)
- break;
- }
-
- if (tmpbuf_off != 0) {
- r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) userbuf_off,
- (vir_bytes) getdents_buf, (size_t) tmpbuf_off);
- if (r != OK) {
- put_inode(rip);
- return(r);
- }
-
- userbuf_off += tmpbuf_off;
- }
-
- if (done && userbuf_off == 0)
- r = EINVAL; /* The user's buffer is too small */
- else {
- fs_m_out.RES_NBYTES = userbuf_off;
- fs_m_out.RES_SEEK_POS_LO = new_pos;
- rip->i_update |= ATIME;
- rip->i_dirt = IN_DIRTY;
- r = OK;
- }
-
- put_inode(rip); /* release the inode */
- return(r);
-}
-
/*===========================================================================*
* fs_getdents *
*===========================================================================*/
struct ext2_disk_dir_desc *d_desc;
struct dirent *dep;
- if (proto_version == 0) {
- return fs_getdents_321();
- }
-
ino = (pino_t) fs_m_in.REQ_INODE_NR;
gid = (cp_grant_id_t) fs_m_in.REQ_GRANT;
size = (size_t) fs_m_in.REQ_MEM_SIZE;
EXTERN uid_t caller_uid;
EXTERN gid_t caller_gid;
-EXTERN int proto_version;
EXTERN int req_nr; /* request number to the server */
EXTERN int SELF_E; /* process number */
label_gid = fs_m_in.REQ_GRANT;
label_len = fs_m_in.REQ_PATH_LEN;
- if (!(fs_m_in.REQ_FLAGS & REQ_HASPROTO)) {
- proto_version = 0;
- } else {
- proto_version = VFS_FS_PROTO_VERSION(fs_m_in.REQ_PROTO);
- }
-
if (label_len > sizeof(fs_dev_label))
return(EINVAL);
fs_m_out.RES_FILE_SIZE_LO = v_pri.dir_rec_root->d_file_size;
fs_m_out.RES_UID = SYS_UID; /* Always root */
fs_m_out.RES_GID = SYS_GID; /* operator */
- fs_m_out.RES_PROTO = 0;
- VFS_FS_PROTO_PUT_VERSION(fs_m_out.RES_PROTO, VFS_FS_CURRENT_VERSION);
- VFS_FS_PROTO_PUT_CONREQS(fs_m_out.RES_PROTO, 1);
+ fs_m_out.RES_FLAGS = RES_NOFLAGS;
return(r);
}
}
-/*===========================================================================*
- * fs_getdents_321 *
- *===========================================================================*/
-int fs_getdents_321(void) {
- struct dir_record *dir;
- pino_t ino;
- cp_grant_id_t gid;
- size_t block_size;
- off_t pos, block_pos, block, cur_pos, tmpbuf_offset, userbuf_off;
- struct buf *bp;
- struct dir_record *dir_tmp;
- struct dirent *dirp;
- int r,done,o,len,reclen;
- char *cp;
- char name[NAME_MAX + 1];
- char name_old[NAME_MAX + 1];
-
- /* Initialize the tmp arrays */
- memset(name,'\0',NAME_MAX);
- memset(name_old,'\0',NAME_MAX);
-
- /* Get input parameters */
- ino = fs_m_in.REQ_INODE_NR;
- gid = fs_m_in.REQ_GRANT;
- pos = fs_m_in.REQ_SEEK_POS_LO;
-
- block_size = v_pri.logical_block_size_l;
- cur_pos = pos; /* The current position */
- tmpbuf_offset = 0;
- userbuf_off = 0;
- memset(getdents_buf, '\0', GETDENTS_BUFSIZ); /* Avoid leaking any data */
-
- if ((dir = get_dir_record(ino)) == NULL) return(EINVAL);
-
- block = dir->loc_extent_l; /* First block of the directory */
- block += pos / block_size; /* Shift to the block where start to read */
- done = FALSE;
-
- while (cur_pos<dir->d_file_size) {
- bp = get_block(block); /* Get physical block */
-
- if (bp == NULL) {
- release_dir_record(dir);
- return(EINVAL);
- }
-
- block_pos = cur_pos % block_size; /* Position where to start read */
-
- while (block_pos < block_size) {
- dir_tmp = get_free_dir_record();
- create_dir_record(dir_tmp,b_data(bp) + block_pos,
- block*block_size + block_pos);
- if (dir_tmp->length == 0) { /* EOF. I exit and return 0s */
- block_pos = block_size;
- done = TRUE;
- release_dir_record(dir_tmp);
- } else { /* The dir record is valid. Copy data... */
- if (dir_tmp->file_id[0] == 0)
- strlcpy(name, ".", NAME_MAX + 1);
- else if (dir_tmp->file_id[0] == 1)
- strlcpy(name, "..", NAME_MAX + 1);
- else {
- /* Extract the name from the field file_id */
- strncpy(name, dir_tmp->file_id,
- dir_tmp->length_file_id);
- name[dir_tmp->length_file_id] = 0;
-
- /* Tidy up file name */
- cp = memchr(name, ';', NAME_MAX);
- if (cp != NULL) name[cp - name] = 0;
-
- /*If no file extension, then remove final '.'*/
- if (name[strlen(name) - 1] == '.')
- name[strlen(name) - 1] = '\0';
- }
-
- if (strcmp(name_old, name) == 0) {
- cur_pos += dir_tmp->length;
- release_dir_record(dir_tmp);
- continue;
- }
-
- strlcpy(name_old, name, NAME_MAX + 1);
-
- /* Compute the length of the name */
- cp = memchr(name, '\0', NAME_MAX);
- if (cp == NULL) len = NAME_MAX;
- else len= cp - name;
-
- /* Compute record length */
- reclen = offsetof(struct dirent, d_name) + len + 1;
- o = (reclen % sizeof(long));
- if (o != 0)
- reclen += sizeof(long) - o;
-
- /* If the new record does not fit, then copy the buffer
- * and start from the beginning. */
- if (tmpbuf_offset + reclen > GETDENTS_BUFSIZ) {
- r = sys_safecopyto(VFS_PROC_NR, gid, userbuf_off,
- (vir_bytes)getdents_buf, tmpbuf_offset);
-
- if (r != OK)
- panic("fs_getdents: sys_safecopyto failed: %d", r);
- userbuf_off += tmpbuf_offset;
- tmpbuf_offset= 0;
- }
-
- /* The standard data structure is created using the
- * data in the buffer. */
- dirp = (struct dirent *) &getdents_buf[tmpbuf_offset];
- dirp->d_ino = (u32_t) (b_data(bp) + block_pos);
- dirp->d_off= (i32_t) cur_pos;
- dirp->d_reclen= reclen;
- memcpy(dirp->d_name, name, len);
- dirp->d_name[len]= '\0';
- tmpbuf_offset += reclen;
-
- cur_pos += dir_tmp->length;
- release_dir_record(dir_tmp);
- }
-
- block_pos += dir_tmp->length;
- }
-
- put_block(bp); /* release the block */
- if (done == TRUE) break;
-
- cur_pos += block_size - cur_pos;
- block++; /* read the next one */
- }
-
- if (tmpbuf_offset != 0) {
- r = sys_safecopyto(VFS_PROC_NR, gid, userbuf_off,
- (vir_bytes) getdents_buf, tmpbuf_offset);
- if (r != OK)
- panic("fs_getdents: sys_safecopyto failed: %d", r);
-
- userbuf_off += tmpbuf_offset;
- }
-
- fs_m_out.RES_NBYTES = userbuf_off;
- fs_m_out.RES_SEEK_POS_LO = cur_pos;
-
- release_dir_record(dir); /* release the inode */
- return(OK);
-}
-
/*===========================================================================*
* fs_getdents *
*===========================================================================*/
char name[NAME_MAX + 1];
char name_old[NAME_MAX + 1];
- if (proto_version == 0) {
- return fs_getdents_321();
- }
-
/* Initialize the tmp arrays */
memset(name,'\0',NAME_MAX);
memset(name_old,'\0',NAME_MAX);
EXTERN gid_t caller_gid;
EXTERN int req_nr;
-EXTERN int proto_version;
EXTERN endpoint_t SELF_E;
readonly = (fs_m_in.REQ_FLAGS & REQ_RDONLY) ? 1 : 0;
isroot = (fs_m_in.REQ_FLAGS & REQ_ISROOT) ? 1 : 0;
- if (!(fs_m_in.REQ_FLAGS & REQ_HASPROTO)) {
- proto_version = 0;
- } else {
- proto_version = VFS_FS_PROTO_VERSION(fs_m_in.REQ_PROTO);
- }
-
if (label_len > sizeof(fs_dev_label))
return(EINVAL);
fs_m_out.RES_FILE_SIZE_LO = root_ip->i_size;
fs_m_out.RES_UID = root_ip->i_uid;
fs_m_out.RES_GID = root_ip->i_gid;
- fs_m_out.RES_PROTO = 0;
- VFS_FS_PROTO_PUT_VERSION(fs_m_out.RES_PROTO, VFS_FS_CURRENT_VERSION);
- VFS_FS_PROTO_PUT_CONREQS(fs_m_out.RES_PROTO, 1);
+ fs_m_out.RES_FLAGS = RES_HASPEEK;
/* Mark it dirty */
if(!superblock.s_rd_only) {
int fs_chmod(void);
int fs_chown(void);
int fs_getdents(void);
-int fs_getdents_321(void);
int forbidden(struct inode *rip, pmode_t access_desired);
int read_only(struct inode *ip);
}
-/*===========================================================================*
- * fs_getdents_321 *
- *===========================================================================*/
-int fs_getdents_321(void)
-{
-#define GETDENTS_321_BUFSIZE (sizeof(struct dirent_321) + MFS_NAME_MAX + 1)
-#define GETDENTS_321_ENTRIES 8
- static char getdents_buf[GETDENTS_321_BUFSIZE * GETDENTS_321_ENTRIES];
- register struct inode *rip;
- int o, r, done;
- unsigned int block_size, len, reclen;
- pino_t ino;
- block_t b;
- cp_grant_id_t gid;
- size_t size, tmpbuf_off, userbuf_off;
- off_t pos, off, block_pos, new_pos, ent_pos;
- struct buf *bp;
- struct direct *dp;
- struct dirent_321 *dep;
- char *cp;
-
- ino = (pino_t) fs_m_in.REQ_INODE_NR;
- gid = (cp_grant_id_t) fs_m_in.REQ_GRANT;
- size = (size_t) fs_m_in.REQ_MEM_SIZE;
- pos = (off_t) fs_m_in.REQ_SEEK_POS_LO;
-
- /* Check whether the position is properly aligned */
- if ((unsigned int) pos % DIR_ENTRY_SIZE)
- return(ENOENT);
-
- if ((rip = get_inode(fs_dev, ino)) == NULL)
- return(EINVAL);
-
- block_size = rip->i_sp->s_block_size;
- off = (pos % block_size); /* Offset in block */
- block_pos = pos - off;
- done = FALSE; /* Stop processing directory blocks when done is set */
-
- tmpbuf_off = 0; /* Offset in getdents_buf */
- memset(getdents_buf, '\0', sizeof(getdents_buf)); /* Avoid leaking any data */
- userbuf_off = 0; /* Offset in the user's buffer */
-
- /* The default position for the next request is EOF. If the user's buffer
- * fills up before EOF, new_pos will be modified. */
- new_pos = rip->i_size;
-
- for(; block_pos < rip->i_size; block_pos += block_size) {
- b = read_map(rip, block_pos, 0); /* get block number */
-
- /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */
- bp = get_block(rip->i_dev, b, NORMAL); /* get a dir block */
-
- assert(bp != NULL);
-
- /* Search a directory block. */
- if (block_pos < pos)
- dp = &b_dir(bp)[off / DIR_ENTRY_SIZE];
- else
- dp = &b_dir(bp)[0];
- for (; dp < &b_dir(bp)[NR_DIR_ENTRIES(block_size)]; dp++) {
- if (dp->mfs_d_ino == 0)
- continue; /* Entry is not in use */
-
- /* Compute the length of the name */
- cp = memchr(dp->mfs_d_name, '\0', sizeof(dp->mfs_d_name));
- if (cp == NULL)
- len = sizeof(dp->mfs_d_name);
- else
- len = cp - (dp->mfs_d_name);
-
- /* Compute record length */
- reclen = offsetof(struct dirent_321, d_name) + len + 1;
- o = (reclen % sizeof(long));
- if (o != 0)
- reclen += sizeof(long) - o;
-
- /* Need the position of this entry in the directory */
- ent_pos = block_pos + ((char *) dp - (char *) bp->data);
-
- if (userbuf_off + tmpbuf_off + reclen >= size) {
- /* The user has no space for one more record */
- done = TRUE;
-
- /* Record the position of this entry, it is the
- * starting point of the next request (unless the
- * postion is modified with lseek).
- */
- new_pos = ent_pos;
- break;
- }
-
- if (tmpbuf_off + reclen >=
- GETDENTS_321_BUFSIZE * GETDENTS_321_ENTRIES) {
- r = sys_safecopyto(VFS_PROC_NR, gid,
- (vir_bytes) userbuf_off,
- (vir_bytes) getdents_buf,
- (size_t) tmpbuf_off);
- if (r != OK) {
- put_inode(rip);
- return(r);
- }
-
- userbuf_off += tmpbuf_off;
- tmpbuf_off = 0;
- }
-
- dep = (struct dirent_321 *) &getdents_buf[tmpbuf_off];
- dep->d_ino = (u32_t) dp->mfs_d_ino;
- dep->d_off = (i32_t) ent_pos;
- dep->d_reclen = (unsigned short) reclen;
- memcpy(dep->d_name, dp->mfs_d_name, len);
- dep->d_name[len] = '\0';
- tmpbuf_off += reclen;
- }
-
- put_block(bp, DIRECTORY_BLOCK);
- if (done)
- break;
- }
-
- if (tmpbuf_off != 0) {
- r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) userbuf_off,
- (vir_bytes) getdents_buf, (size_t) tmpbuf_off);
- if (r != OK) {
- put_inode(rip);
- return(r);
- }
-
- userbuf_off += tmpbuf_off;
- }
-
- if (done && userbuf_off == 0)
- r = EINVAL; /* The user's buffer is too small */
- else {
- fs_m_out.RES_NBYTES = userbuf_off;
- fs_m_out.RES_SEEK_POS_LO = new_pos;
- if(!rip->i_sp->s_rd_only) {
- rip->i_update |= ATIME;
- IN_MARKDIRTY(rip);
- }
- r = OK;
- }
-
- put_inode(rip); /* release the inode */
- return(r);
-}
-
/*===========================================================================*
* fs_getdents *
*===========================================================================*/
struct dirent *dep;
char *cp;
- if (proto_version == 0) {
- /* VFS-FS protocol version 0 uses 32-bits ino_t and off_t. We need to
- * use the binary compatible version of this routine */
- return fs_getdents_321();
- }
-
ino = (pino_t) fs_m_in.REQ_INODE_NR;
gid = (cp_grant_id_t) fs_m_in.REQ_GRANT;
size = (size_t) fs_m_in.REQ_MEM_SIZE;
{
struct vnode *vp = execi.vp;
assert(vp);
- if(vp->v_vmnt->m_haspeek && major(vp->v_dev) != MEMORY_MAJOR) {
+ if ((vp->v_vmnt->m_fs_flags & RES_HASPEEK) &&
+ major(vp->v_dev) != MEMORY_MAJOR) {
int newfd = -1;
if(get_fd(vmfp, 0, R_BIT, &newfd, &newfilp) == OK) {
assert(newfd >= 0 && newfd < OPEN_MAX);
return EBADF;
}
- if(!f->filp_vno->v_vmnt->m_haspeek) {
+ if(!(f->filp_vno->v_vmnt->m_fs_flags & RES_HASPEEK)) {
unlock_filp(f);
#if 0 /* Noisy diagnostic for mmap() by ld.so */
printf("VFS dupvm: no peek available\n");
struct node_details res;
struct lookup resolve;
struct statvfs statvfs_buf;
+ unsigned int fs_flags;
/* Look up block device driver label when dev is not a pseudo-device */
label = "";
/* Tell FS which device to mount */
new_vmp->m_flags |= VMNT_MOUNTING;
- r = req_readsuper(new_vmp, label, dev, !!(flags & MNT_RDONLY), isroot, &res);
+ r = req_readsuper(new_vmp, label, dev, !!(flags & MNT_RDONLY), isroot, &res,
+ &fs_flags);
new_vmp->m_flags &= ~VMNT_MOUNTING;
- if(req_peek(fs_e, 1, 0, PAGE_SIZE) != OK ||
- req_bpeek(fs_e, dev, 0, PAGE_SIZE) != OK) {
- new_vmp->m_haspeek = 0;
- } else {
- new_vmp->m_haspeek = 1;
- }
+ new_vmp->m_fs_flags = fs_flags;
/* Fill the statvfs cache with initial values. */
if (r == OK)
/* Root node is indeed on the partition */
root_node->v_vmnt = new_vmp;
root_node->v_dev = new_vmp->m_dev;
- if (VFS_FS_PROTO_CONREQS(new_vmp->m_proto) == 0)
- new_vmp->m_comm.c_max_reqs = 1; /* Default if FS doesn't tell us */
+ if (!(new_vmp->m_fs_flags & RES_THREADED))
+ new_vmp->m_comm.c_max_reqs = 1;
else
- new_vmp->m_comm.c_max_reqs = VFS_FS_PROTO_CONREQS(new_vmp->m_proto);
+ new_vmp->m_comm.c_max_reqs = NR_WTHREADS;
new_vmp->m_comm.c_cur_reqs = 0;
/* No more blocking operations, so we can now report on this file system. */
vmp->m_dev = dev;
vmp->m_fs_e = PFS_PROC_NR;
- vmp->m_proto = 0;
- VFS_FS_PROTO_PUT_CONREQS(vmp->m_proto, 1);
- VFS_FS_PROTO_PUT_VERSION(vmp->m_proto, VFS_FS_CURRENT_VERSION);
+ vmp->m_fs_flags = 0;
strlcpy(vmp->m_label, "pfs", LABEL_MAX);
strlcpy(vmp->m_mount_path, "pipe", PATH_MAX);
strlcpy(vmp->m_mount_dev, "none", PATH_MAX);
do {
r = req_getdents(dirp->v_fs_e, dirp->v_inode_nr, pos, buf, sizeof(buf),
- &new_pos, 1, 0 /* Not MINIX 3.2.1 format */);
+ &new_pos, 1);
if (r == 0) {
return(ENOENT); /* end of entries -- matching inode !found */
int req_statvfs(endpoint_t fs_e, struct statvfs *buf);
int req_ftrunc(endpoint_t fs_e, ino_t inode_nr, off_t start, off_t end);
int req_getdents(endpoint_t fs_e, ino_t inode_nr, off_t pos, char *buf,
- size_t size, off_t *new_pos, int direct, int getdents_321);
+ size_t size, off_t *new_pos, int direct);
int req_inhibread(endpoint_t fs_e, ino_t inode_nr);
int req_link(endpoint_t fs_e, ino_t link_parent, char *lastc,
ino_t linked_file);
int req_rdlink(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e,
vir_bytes buf, size_t len, int direct);
int req_readsuper(struct vmnt *vmp, char *driver_name, dev_t dev, int readonly,
- int isroot, struct node_details *res_nodep);
+ int isroot, struct node_details *res_nodep, unsigned int *fs_flags);
int req_readwrite(endpoint_t fs_e, ino_t inode_nr, off_t pos, int rw_flag,
endpoint_t user_e, vir_bytes user_addr, unsigned int num_of_bytes,
off_t *new_posp, unsigned int *cum_iop);
int do_getdents(message *UNUSED(m_out))
{
/* Perform the getdents(fd, buf, size) system call. */
- int r = OK, getdents_321 = 0;
+ int r = OK;
off_t new_pos;
register struct filp *rfilp;
- if (job_call_nr == GETDENTS_321) getdents_321 = 1;
scratch(fp).file.fd_nr = job_m_in.fd;
scratch(fp).io.io_buffer = job_m_in.buffer;
scratch(fp).io.io_nbytes = (size_t) job_m_in.nbytes;
if (r == OK) {
r = req_getdents(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
rfilp->filp_pos, scratch(fp).io.io_buffer,
- scratch(fp).io.io_nbytes, &new_pos, 0, getdents_321);
+ scratch(fp).io.io_nbytes, &new_pos, 0);
if (r > 0) rfilp->filp_pos = new_pos;
}
#include "vnode.h"
-static size_t translate_dents(char *src, size_t size, char *dst, int direction);
-
/*===========================================================================*
* req_breadwrite *
*===========================================================================*/
res->fs_e = m.m_source;
res->inode_nr = (ino_t) m.RES_INODE_NR;
res->fmode = (mode_t) m.RES_MODE;
- if (VFS_FS_PROTO_BIGOFFT(vmp->m_proto)) {
+ if (vmp->m_fs_flags & RES_64BIT) {
res->fsize = make64(m.RES_FILE_SIZE_LO, m.RES_FILE_SIZE_HI);
} else {
res->fsize = m.RES_FILE_SIZE_LO;
m.REQ_INODE_NR = (pino_t) inode_nr;
m.REQ_TRC_START_LO = ex64lo(start);
- if (VFS_FS_PROTO_BIGOFFT(vmp->m_proto)) {
+ if (vmp->m_fs_flags & RES_64BIT) {
m.REQ_TRC_START_HI = ex64hi(start);
} else if (start > INT_MAX) {
/* FS does not support 64-bit off_t and 32 bits is not enough */
}
m.REQ_TRC_END_LO = ex64lo(end);
- if (VFS_FS_PROTO_BIGOFFT(vmp->m_proto)) {
+ if (vmp->m_fs_flags & RES_64BIT) {
m.REQ_TRC_END_HI = ex64hi(end);
} else if (end > INT_MAX) {
/* FS does not support 64-bit off_t and 32 bits is not enough */
char *buf,
size_t size,
off_t *new_pos,
- int direct,
- int getdents_321 /* Set to 1 if user land expects old format */
+ int direct
)
{
int r;
- int fs_getdents_321 = 0, do_translation = 0;
message m;
cp_grant_id_t grant_id;
struct vmnt *vmp;
- char *indir_buf_src = NULL;
- char *indir_buf_dst = NULL;
vmp = find_vmnt(fs_e);
assert(vmp != NULL);
- if (VFS_FS_PROTO_VERSION(vmp->m_proto) == 0) {
- fs_getdents_321 = 1;
- }
-
- /* When we have to translate new struct dirent to the old format or vice
- * versa, we're going to have to ignore the user provided buffer and do only
- * one entry at a time. We have to do the translation here and allocate
- * space on the stack. This is a limited resource. Besides, we don't want to
- * be dependent on crazy buffer sizes provided by user space (i.e., we'd have
- * to allocate a similarly sized buffer here).
- *
- * We need to translate iff:
- * 1. userland expects old format and FS provides new format
- * 2. userland expects new format and FS provides old format
- * We don't need to translate iff
- * 3. userland expects old format and FS provides old format
- * 4. userland expects new format and FS provides new format
- *
- * Note: VFS expects new format (when doing 'direct'), covered by case 2.
- */
- if (getdents_321 && !fs_getdents_321) { /* case 1 */
- do_translation = 1;
- } else if (fs_getdents_321 && !getdents_321) {/* case 2 */
- do_translation = 1;
- }
-
- if (do_translation) {
- /* We're cutting down the buffer size in two so it's guaranteed we
- * have enough space for the translation (data structure has become
- * larger).
- */
- size = size / 2;
- indir_buf_src = malloc(size);
- indir_buf_dst = malloc(size * 2); /* dst buffer keeps original size */
- if (indir_buf_src == NULL || indir_buf_dst == NULL)
- panic("Couldn't allocate temp buf space\n");
-
- grant_id = cpf_grant_direct(fs_e, (vir_bytes) indir_buf_src, size,
- CPF_WRITE);
- } else if (direct) {
+ if (direct) {
grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, size, CPF_WRITE);
} else {
grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, size,
m.REQ_GRANT = grant_id;
m.REQ_MEM_SIZE = size;
m.REQ_SEEK_POS_LO = ex64lo(pos);
- if (VFS_FS_PROTO_BIGOFFT(vmp->m_proto)) {
+ if (vmp->m_fs_flags & RES_64BIT) {
m.REQ_SEEK_POS_HI = ex64hi(pos);
} else if (pos > INT_MAX) {
/* FS does not support 64-bit off_t and 32 bits is not enough */
- if (indir_buf_src != NULL) free(indir_buf_src);
- if (indir_buf_dst != NULL) free(indir_buf_dst);
return EINVAL;
} else {
m.REQ_SEEK_POS_HI = 0;
r = fs_sendrec(fs_e, &m);
cpf_revoke(grant_id);
- if (do_translation) {
- if (r == OK) {
- m.RES_NBYTES = translate_dents(indir_buf_src, m.RES_NBYTES,
- indir_buf_dst, getdents_321);
- if (direct) {
- memcpy(buf, indir_buf_dst, m.RES_NBYTES);
- } else {
- r = sys_vircopy(SELF, (vir_bytes) indir_buf_dst, who_e,
- (vir_bytes) buf, m.RES_NBYTES);
- }
- }
- free(indir_buf_src);
- free(indir_buf_dst);
- }
-
if (r == OK) {
- if (VFS_FS_PROTO_BIGOFFT(vmp->m_proto)) {
+ if (vmp->m_fs_flags & RES_64BIT) {
*new_pos = make64(m.RES_SEEK_POS_LO, m.RES_SEEK_POS_HI);
} else {
*new_pos = m.RES_SEEK_POS_LO;
return(r);
}
-/*===========================================================================*
- * translate_dents *
- *===========================================================================*/
-static size_t
-translate_dents(char *src, size_t size, char *dst, int to_getdents_321)
-{
-/* Convert between 'struct dirent' and 'struct dirent_321' both ways and
- * return the size of the new buffer.
- */
- int consumed = 0, newconsumed = 0;
- struct dirent *dent;
- struct dirent_321 *dent_321;
-#define DWORD_ALIGN(d) if((d) % sizeof(long)) (d)+=sizeof(long)-(d)%sizeof(long)
-
- if (to_getdents_321) {
- /* Provided format is struct dirent and has to be translated
- * to struct dirent_321 */
- dent_321 = (struct dirent_321 *) dst;
- dent = (struct dirent *) src;
-
- while (consumed < size && dent->d_reclen > 0) {
- dent_321->d_ino = (u32_t) dent->d_ino;
- dent_321->d_off = (i32_t) dent->d_off;
- dent_321->d_reclen = offsetof(struct dirent_321,d_name)+
- strlen(dent->d_name) + 1;
- DWORD_ALIGN(dent_321->d_reclen);
- strcpy(dent_321->d_name, dent->d_name);
- consumed += dent->d_reclen;
- newconsumed += dent_321->d_reclen;
- dent = (struct dirent *) &src[consumed];
- dent_321 = (struct dirent_321 *) &dst[newconsumed];
- }
- } else {
- /* Provided format is struct dirent_321 and has to be
- * translated to struct dirent */
- dent_321 = (struct dirent_321 *) src;
- dent = (struct dirent *) dst;
-
- while (consumed < size && dent_321->d_reclen > 0) {
- dent->d_ino = (ino_t) dent_321->d_ino;
- dent->d_off = (off_t) dent_321->d_off;
- dent->d_reclen = offsetof(struct dirent, d_name) +
- strlen(dent_321->d_name) + 1;
- DWORD_ALIGN(dent->d_reclen);
- strcpy(dent->d_name, dent_321->d_name);
- consumed += dent_321->d_reclen;
- newconsumed += dent->d_reclen;
- dent_321 = (struct dirent_321 *) &src[consumed];
- dent = (struct dirent *) &dst[newconsumed];
- }
- }
-
- return newconsumed;
-}
-
/*===========================================================================*
* req_inhibread *
*===========================================================================*/
case OK:
res->inode_nr = (ino_t) m.RES_INODE_NR;
res->fmode = (mode_t) m.RES_MODE;
- if (VFS_FS_PROTO_BIGOFFT(vmp->m_proto)) {
+ if (vmp->m_fs_flags & RES_64BIT) {
res->fsize = make64(m.RES_FILE_SIZE_LO, m.RES_FILE_SIZE_HI);
} else {
res->fsize = m.RES_FILE_SIZE_LO;
res->fs_e = m.m_source;
res->inode_nr = (ino_t) m.RES_INODE_NR;
res->fmode = (mode_t) m.RES_MODE;
- if (VFS_FS_PROTO_BIGOFFT(vmp->m_proto)) {
+ if (vmp->m_fs_flags & RES_64BIT) {
res->fsize = make64(m.RES_FILE_SIZE_LO, m.RES_FILE_SIZE_HI);
} else {
res->fsize = m.RES_FILE_SIZE_LO;
dev_t dev,
int readonly,
int isroot,
- struct node_details *res
+ struct node_details *res,
+ unsigned int *fs_flags
)
{
int r;
/* Fill in request message */
m.m_type = REQ_READSUPER;
m.REQ_FLAGS = 0;
- m.REQ_PROTO = 0;
- VFS_FS_PROTO_PUT_VERSION(m.REQ_PROTO, VFS_FS_CURRENT_VERSION);
- m.REQ_FLAGS |= REQ_HASPROTO;
if(readonly) m.REQ_FLAGS |= REQ_RDONLY;
if(isroot) m.REQ_FLAGS |= REQ_ISROOT;
m.REQ_GRANT = grant_id;
/* Fill in response structure */
res->fs_e = m.m_source;
res->inode_nr = (ino_t) m.RES_INODE_NR;
- vmp->m_proto = m.RES_PROTO;
res->fmode = (mode_t) m.RES_MODE;
- if (VFS_FS_PROTO_BIGOFFT(vmp->m_proto)) {
+ if (m.RES_FLAGS & RES_64BIT) {
res->fsize = make64(m.RES_FILE_SIZE_LO, m.RES_FILE_SIZE_HI);
} else {
res->fsize = m.RES_FILE_SIZE_LO;
}
res->uid = (uid_t) m.RES_UID;
res->gid = (gid_t) m.RES_GID;
+ *fs_flags = m.RES_FLAGS;
}
return(r);
m.REQ_INODE_NR = (pino_t) inode_nr;
m.REQ_GRANT = grant_id;
m.REQ_SEEK_POS_LO = ex64lo(pos);
- if (VFS_FS_PROTO_BIGOFFT(vmp->m_proto)) {
+ if (vmp->m_fs_flags & RES_64BIT) {
m.REQ_SEEK_POS_HI = ex64hi(pos);
} else if (pos > INT_MAX) {
return EINVAL;
if (r == OK) {
/* Fill in response structure */
- if (VFS_FS_PROTO_BIGOFFT(vmp->m_proto)) {
+ if (vmp->m_fs_flags & RES_64BIT) {
*new_posp = make64(m.RES_SEEK_POS_LO, m.RES_SEEK_POS_HI);
} else {
*new_posp = m.RES_SEEK_POS_LO;
comm_t m_comm;
dev_t m_dev; /* device number */
unsigned int m_flags; /* mount flags */
- unsigned int m_proto; /* vfs-fs protocol info */
+ unsigned int m_fs_flags; /* capability flags returned by FS */
struct vnode *m_mounted_on; /* vnode on which the partition is mounted */
struct vnode *m_root_node; /* root vnode */
char m_label[LABEL_MAX]; /* label of the file system process */
char m_mount_path[PATH_MAX]; /* path on which vmnt is mounted */
char m_mount_dev[PATH_MAX]; /* device from which vmnt is mounted */
char m_fstype[FSTYPE_MAX]; /* file system type */
- int m_haspeek; /* supports REQ_PEEK, REQ_BPEEK */
struct statvfs_cache m_stats; /* cached file system statistics */
} vmnt[NR_MNTS];