Re: getdirentries_args and other kernel syscall structures

2005-11-23 Thread Daniel Rudy
At about the time of 11/23/2005 3:11 AM, Stefan Farfeleder stated the
following:

> On Tue, Nov 22, 2005 at 08:32:10PM -0800, Daniel Rudy wrote:
> 
>>Ok, I'va got a little question here.  In the structure
>>getdirentries_args, there seems to be duplicated fields that I'm not
>>entirely sure what they do.  Here's the definition of a structure
>>verbatim from sys/sysproto.h:
>>
>>struct getdirentries_args {
>>char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
>>char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)];
>>char count_l_[PADL_(u_int)]; u_int count; char
>>count_r_[PADR_(u_int)];
>>char basep_l_[PADL_(long *)]; long * basep; char
>>basep_r_[PADR_(long *)];
>>};
>>
>>Now my question is what does the l and r variables do?  It seems that
>>they do something with padding the data based on the endian of the
>>machine?  I look through this header file, and I see all the structures
>>have similar constructs.  Is it something that can be safely ignored?
> 
> 
> This file is automatically generated by makesyscalls.sh.  The l and r
> variables are a hack to correctly the member between them.  One of PADL_
> or PADR_ always evalutes to 0, the other one to the needed padding,
> depending on the passed type.  This is unfortunate because it relies on
> the GCC extension to accept 0-sized arrays.

The file is automatically generated?  Now that I think about it, I
remember seeing something to that effect in the header file...

> I'd love to fix that but couldn't come up with something that
> isn't very involved.

I have an idea about that...

Why not do something like this:

#define PAD_(t) (sizeof(register_t) <= sizeof(t) ? \
0 : sizeof(register_t) - sizeof(t))

struct getdirentries_args {
#if BYTE_ORDER == LITTLE_ENDIAN
int fd; char fd_r_[PAD_(int)];
char * buf; char buf_r_[PAD_(char *)];
u_int count; char count_r_[PAD_(u_int)];
long * basep; char basep_r_[PAD_(long *)];
#else
char fd_l_[PAD_(int)]; int fd;
char buf_l_[PAD_(char *)]; char * buf;
char count_l_[PAD_(u_int)]; u_int count;
char basep_l_[PAD_(long *)]; long * basep;
#endif
};

This way, you only pad what you need based on the endian of the machine,
and the one that isn't used is stripped out by the preprocessor.  And as
a bonus, it's pretty clear as to what is going on and not as confusing.
 I haven't looked at the script that generates this file, but I don't
see how hard it could be to modify the script to do something like this.
 Yes, the header file will be larger, but only half will be used.



Now, onto the actuall problem that I have been having with the
getdirentries syscall.  It has to do with the buf member.  The buffer
seems to be 4K, which we all know is the size of 1 page on IA32
hardware.  The problem is that I can only get data for the first struct
dirent record.  Subsequest records are null.  The first record
represents the '.' directory.  According to the man page, the d_reclen
member specifies the length of the current record, so the following code
should be able to walk from one record to another:

static int new_getdirentries(struct thread *t, struct getdirentries_args
*uap)
  {
unsigned int buffsize;
unsigned int n;
int flag;
struct dirent *dirp_start;
struct dirent *dirp_current;
struct dirent *dirp2;
struct dirent *dirp3;
int result;
int status;

/* issue the syscall */
result = getdirentries(t, uap);
printf("getdirentries result %d\n", result);
if (result != 0) return(result);

/* and check the buffer */
dirp_start = (struct dirent *)uap->buf;
if (dirp_start == NULL) return(result);

/* do we have work to do? */
if (dirp_start->d_namlen > 0)
  {
/* get our buffer size */
buffsize = uap->count;

/* allocate memory buffer in kernel space */
MALLOC(dirp2, struct dirent *, buffsize, M_DIRP2, M_NOWAIT);
if (dirp2 == NULL) return(result);

/* copy data into kernel space */
copyin(uap->buf, dirp2, buffsize);

/* setup pointers */
dirp_start = dirp2;
dirp_current = dirp_start;

/* set the flag */
flag = 0;
n = buffsize;
r = 0;

printf("buffsize %u; dirent size %d; getdirent %d\n", buffsize,
sizeof(struct dirent),
  sizeof(struct getdirentries_args));
/* now walk through the dirent structures */
while (flag == 0)
  {
/* decrement the used buffer length */
n -= dirp_current->d_reclen;

printf("**BEFORE\n");
printf("n %u; r %u\n", n, r);
printf("name %s; len %hhu; reclen %hu\n", dirp_current->d_name,
  dirp_current->d_namlen, dirp_current->d_reclen);
/* set next pointer */
dirp3 = dirp_current + dirp_current->d_reclen;
dirp_current = dirp3;
printf("**AFTER\n");
 

Re: getdirentries_args and other kernel syscall structures

2005-11-23 Thread Daniel Rudy
At about the time of 11/23/2005 3:23 AM, rookie stated the following:
> 2005/11/23, Daniel Rudy <[EMAIL PROTECTED]>:
> 
>>Ok, I'va got a little question here.  In the structure
>>getdirentries_args, there seems to be duplicated fields that I'm not
>>entirely sure what they do.  Here's the definition of a structure
>>verbatim from sys/sysproto.h:
>>
>>struct getdirentries_args {
>>char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
>>char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)];
>>char count_l_[PADL_(u_int)]; u_int count; char
>>count_r_[PADR_(u_int)];
>>char basep_l_[PADL_(long *)]; long * basep; char
>>basep_r_[PADR_(long *)];
>>};
>>
>>Now my question is what does the l and r variables do?  It seems that
>>they do something with padding the data based on the endian of the
>>machine?  I look through this header file, and I see all the structures
>>have similar constructs.  Is it something that can be safely ignored
> 
> 
> It just pads in the right way (according with endianism) the structure
> to the right word. For example, x86 gots sizeof(long *) == 4. If you
> want to have a syscall structure like that:
> 
> struct example_sys
> {
>char f;
>short p;
>int g;
> };
> 
> it is misaligned. In order to get a proper padded structure (all 32
> bits entries) to speed-up accesses to the members, this little trick
> is used.
> 
> Attilio
> 
> --
> Peace can only be achieved by understanding - A. Einstein
> 

Ah, a performance trick.  I get it now.  Thanks.

-- 
Daniel Rudy
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"


Re: getdirentries_args and other kernel syscall structures

2005-11-23 Thread rookie
2005/11/23, Daniel Rudy <[EMAIL PROTECTED]>:
>
> Ok, I'va got a little question here.  In the structure
> getdirentries_args, there seems to be duplicated fields that I'm not
> entirely sure what they do.  Here's the definition of a structure
> verbatim from sys/sysproto.h:
>
> struct getdirentries_args {
> char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
> char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)];
> char count_l_[PADL_(u_int)]; u_int count; char
> count_r_[PADR_(u_int)];
> char basep_l_[PADL_(long *)]; long * basep; char
> basep_r_[PADR_(long *)];
> };
>
> Now my question is what does the l and r variables do?  It seems that
> they do something with padding the data based on the endian of the
> machine?  I look through this header file, and I see all the structures
> have similar constructs.  Is it something that can be safely ignored

It just pads in the right way (according with endianism) the structure
to the right word. For example, x86 gots sizeof(long *) == 4. If you
want to have a syscall structure like that:

struct example_sys
{
   char f;
   short p;
   int g;
};

it is misaligned. In order to get a proper padded structure (all 32
bits entries) to speed-up accesses to the members, this little trick
is used.

Attilio

--
Peace can only be achieved by understanding - A. Einstein
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"


Re: getdirentries_args and other kernel syscall structures

2005-11-23 Thread Stefan Farfeleder
On Tue, Nov 22, 2005 at 08:32:10PM -0800, Daniel Rudy wrote:
> 
> Ok, I'va got a little question here.  In the structure
> getdirentries_args, there seems to be duplicated fields that I'm not
> entirely sure what they do.  Here's the definition of a structure
> verbatim from sys/sysproto.h:
> 
> struct getdirentries_args {
> char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
> char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)];
> char count_l_[PADL_(u_int)]; u_int count; char
> count_r_[PADR_(u_int)];
> char basep_l_[PADL_(long *)]; long * basep; char
> basep_r_[PADR_(long *)];
> };
> 
> Now my question is what does the l and r variables do?  It seems that
> they do something with padding the data based on the endian of the
> machine?  I look through this header file, and I see all the structures
> have similar constructs.  Is it something that can be safely ignored?

This file is automatically generated by makesyscalls.sh.  The l and r
variables are a hack to correctly the member between them.  One of PADL_
or PADR_ always evalutes to 0, the other one to the needed padding,
depending on the passed type.  This is unfortunate because it relies on
the GCC extension to accept 0-sized arrays.  I'd love to fix that but
couldn't come up with something that isn't very involved.

Stefan
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"


getdirentries_args and other kernel syscall structures

2005-11-22 Thread Daniel Rudy

Ok, I'va got a little question here.  In the structure
getdirentries_args, there seems to be duplicated fields that I'm not
entirely sure what they do.  Here's the definition of a structure
verbatim from sys/sysproto.h:

struct getdirentries_args {
char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)];
char count_l_[PADL_(u_int)]; u_int count; char
count_r_[PADR_(u_int)];
char basep_l_[PADL_(long *)]; long * basep; char
basep_r_[PADR_(long *)];
};

Now my question is what does the l and r variables do?  It seems that
they do something with padding the data based on the endian of the
machine?  I look through this header file, and I see all the structures
have similar constructs.  Is it something that can be safely ignored?


-- 
Daniel Rudy
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"