MFS: getdents fixes

.Use a bigger buffer to hold results
.Do not try to store more data than user buffer can hold
This commit is contained in:
Thomas Veerman 2012-07-26 12:42:55 +00:00
parent b6ea15115c
commit fa9199e049
2 changed files with 37 additions and 36 deletions

View File

@ -11,7 +11,6 @@
* should be more or less the same as * should be more or less the same as
* NR_VNODES in vfs * NR_VNODES in vfs
*/ */
#define GETDENTS_BUFSIZ 257
#define INODE_HASH_LOG2 7 /* 2 based logarithm of the inode hash size */ #define INODE_HASH_LOG2 7 /* 2 based logarithm of the inode hash size */
#define INODE_HASH_SIZE ((unsigned long)1<<INODE_HASH_LOG2) #define INODE_HASH_SIZE ((unsigned long)1<<INODE_HASH_LOG2)

View File

@ -17,7 +17,6 @@ static int rw_chunk(struct inode *rip, u64_t position, unsigned off,
size_t chunk, unsigned left, int rw_flag, cp_grant_id_t gid, unsigned size_t chunk, unsigned left, int rw_flag, cp_grant_id_t gid, unsigned
buf_off, unsigned int block_size, int *completed); buf_off, unsigned int block_size, int *completed);
static char getdents_buf[GETDENTS_BUFSIZ];
/*===========================================================================* /*===========================================================================*
* fs_readwrite * * fs_readwrite *
@ -538,6 +537,9 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */
*===========================================================================*/ *===========================================================================*/
int fs_getdents(void) int fs_getdents(void)
{ {
#define GETDENTS_BUFSIZE (sizeof(struct dirent) + MFS_NAME_MAX + 1)
#define GETDENTS_ENTRIES 8
static char getdents_buf[GETDENTS_BUFSIZE * GETDENTS_ENTRIES];
register struct inode *rip; register struct inode *rip;
int o, r, done; int o, r, done;
unsigned int block_size, len, reclen; unsigned int block_size, len, reclen;
@ -569,7 +571,7 @@ int fs_getdents(void)
done = FALSE; /* Stop processing directory blocks when done is set */ done = FALSE; /* Stop processing directory blocks when done is set */
tmpbuf_off = 0; /* Offset in getdents_buf */ tmpbuf_off = 0; /* Offset in getdents_buf */
memset(getdents_buf, '\0', GETDENTS_BUFSIZ); /* Avoid leaking any data */ memset(getdents_buf, '\0', sizeof(getdents_buf)); /* Avoid leaking any data */
userbuf_off = 0; /* Offset in the user's buffer */ userbuf_off = 0; /* Offset in the user's buffer */
/* The default position for the next request is EOF. If the user's buffer /* The default position for the next request is EOF. If the user's buffer
@ -609,7 +611,19 @@ int fs_getdents(void)
/* Need the position of this entry in the directory */ /* Need the position of this entry in the directory */
ent_pos = block_pos + ((char *) dp - (bp->b_data)); ent_pos = block_pos + ((char *) dp - (bp->b_data));
if(tmpbuf_off + reclen > GETDENTS_BUFSIZ) { 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_BUFSIZE*GETDENTS_ENTRIES) {
r = sys_safecopyto(VFS_PROC_NR, gid, r = sys_safecopyto(VFS_PROC_NR, gid,
(vir_bytes) userbuf_off, (vir_bytes) userbuf_off,
(vir_bytes) getdents_buf, (vir_bytes) getdents_buf,
@ -623,18 +637,6 @@ int fs_getdents(void)
tmpbuf_off = 0; tmpbuf_off = 0;
} }
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;
}
dep = (struct dirent *) &getdents_buf[tmpbuf_off]; dep = (struct dirent *) &getdents_buf[tmpbuf_off];
dep->d_ino = dp->mfs_d_ino; dep->d_ino = dp->mfs_d_ino;
dep->d_off = ent_pos; dep->d_off = ent_pos;