Back to index

avfs  1.0.1
Classes | Defines | Enumerations | Functions | Variables
avfs_server.c File Reference
#include "server.h"
#include "cmd.h"
#include "send.h"
#include "internal.h"
#include "operutil.h"
#include "oper.h"
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <poll.h>
#include <assert.h>
#include <pthread.h>

Go to the source code of this file.

Classes

struct  file_holder
struct  cmdinfo

Defines

#define MULTITHREADED   1

Enumerations

enum  file_holder_state { FIH_DELETED = -1, FIH_UNUSED = 0, FIH_USED = 1 }

Functions

static AV_LOCK_DECL (file_holder_lock)
static void init_inmsg (struct avfs_in_message *inmsg)
static void free_inmsg (struct avfs_in_message *inmsg)
static int entry_local (ventry *ve)
static int getattr_entry (ventry *ve, struct avstat *stbuf, int attrmask, int flags)
static void send_error (int fd, int error)
static int do_readdir (int fd, struct avfs_direntry *de, char *name)
static void process_getattr (struct cmdinfo *ci)
static void register_holder (int holderfd, int serverfh)
static void process_open (struct cmdinfo *ci)
static void process_close (struct cmdinfo *ci)
static void process_fstat (struct cmdinfo *ci)
static void process_readdir (struct cmdinfo *ci)
static void process_lseek (struct cmdinfo *ci)
static void process_read (struct cmdinfo *ci)
static void process_write (struct cmdinfo *ci)
static void process_resolve (struct cmdinfo *ci)
static void process_readlink (struct cmdinfo *ci)
static void process_access (struct cmdinfo *ci)
static void * process_message (void *arg)
static void mark_file_holder (int holderfd)
static void unmark_file_holder (int serverfh)
static int wait_message (int sock)
int main ()

Variables

static struct file_holderfile_holders
static unsigned int file_holder_num

Class Documentation

struct file_holder

Definition at line 35 of file avfs_server.c.

struct cmdinfo

Definition at line 44 of file avfs_server.c.

Class Members
int fd

Define Documentation

#define MULTITHREADED   1

Definition at line 23 of file avfs_server.c.


Enumeration Type Documentation

Enumerator:
FIH_DELETED 
FIH_UNUSED 
FIH_USED 

Definition at line 29 of file avfs_server.c.

                       {
    FIH_DELETED = -1,
    FIH_UNUSED = 0,
    FIH_USED = 1,
};

Function Documentation

static AV_LOCK_DECL ( file_holder_lock  ) [static]
static int do_readdir ( int  fd,
struct avfs_direntry de,
char *  name 
) [static]

Definition at line 108 of file avfs_server.c.

{
    int res;
    struct avdirent buf;
    avoff_t n;
    
    res = av_fd_readdir(fd, &buf, &n);
    if(res > 0) {
        de->ino = buf.ino;
        de->type = buf.type;
        de->n = n;
        strncpy(name, buf.name, NAME_MAX);
        name[NAME_MAX] = '\0';
        av_free(buf.name);
    }

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int entry_local ( ventry *  ve) [static]

Definition at line 68 of file avfs_server.c.

{
    if(ve->mnt->base == NULL)
        return 1;
    else
        return 0;
}

Here is the caller graph for this function:

static void free_inmsg ( struct avfs_in_message inmsg) [static]

Definition at line 58 of file avfs_server.c.

{
    int i;

    for(i = 1; i < MAXSEG; i++) {
        if(inmsg->seg[i].buf)
            free(inmsg->seg[i].buf);
    }
}

Here is the caller graph for this function:

static int getattr_entry ( ventry *  ve,
struct avstat stbuf,
int  attrmask,
int  flags 
) [static]

Definition at line 77 of file avfs_server.c.

{
    int res;
    vfile vf;
    
    res = av_file_open(&vf, ve, AVO_NOPERM | flags, 0);
    if(res == 0) {
        res = av_file_getattr(&vf, stbuf, attrmask);
        av_file_close(&vf);
    }

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void init_inmsg ( struct avfs_in_message inmsg) [static]

Definition at line 50 of file avfs_server.c.

{
    int i;

    for(i = 1; i < MAXSEG; i++)
        inmsg->seg[i].buf = NULL;
}

Here is the caller graph for this function:

int main ( )

Definition at line 791 of file avfs_server.c.

{
    int sock;

#if MULTITHREADED
    pthread_attr_t attr;
    pthread_t thrid;

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
#endif

    sock = server_init();

    while(1) {
        int fd;
        int res;
        struct cmdinfo *ci;

        fd = wait_message(sock);
        
        AV_NEW(ci);
        init_inmsg(&ci->inmsg);
        ci->inmsg.seg[0].buf = &ci->cmd;

        res = __av_read_message(fd, &ci->inmsg);
        if(res == -1)
            av_log(AVLOG_ERROR, "Error reading message");
        else {
            ci->fd = fd;

            if(ci->cmd.type == CMD_OPEN)
                mark_file_holder(ci->fd);
            else if(ci->cmd.type == CMD_CLOSE)
                unmark_file_holder(ci->cmd.u.fdops.serverfh);
            
#if MULTITHREADED
            res = pthread_create(&thrid, &attr, process_message, ci);
            if(res != 0) 
                av_log(AVLOG_ERROR, "Error creating thread: %i",
                         res);
#else
            process_message(ci);
#endif
        }
    }
    
    return 0;
}

Here is the call graph for this function:

static void mark_file_holder ( int  holderfd) [static]

Definition at line 650 of file avfs_server.c.

{
    AV_LOCK(file_holder_lock);
    if(holderfd >= file_holder_num) {
        int i;
        unsigned int newnum = holderfd + 1;
        unsigned int newsize = newnum  * sizeof(struct file_holder);

        file_holders = realloc(file_holders, newsize);
        assert(file_holders != NULL);

        for(i = file_holder_num; i <= holderfd; i++)
            file_holders[i].state = FIH_UNUSED;

        file_holder_num = newnum;
    }
    
    if(file_holders[holderfd].state != FIH_UNUSED)
        av_log(AVLOG_ERROR, "Internal Error: file holder %i already used",
                 holderfd);

    file_holders[holderfd].state = FIH_USED;
    file_holders[holderfd].serverfh = -1;
    
    AV_UNLOCK(file_holder_lock);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void process_access ( struct cmdinfo ci) [static]

Definition at line 543 of file avfs_server.c.

{
    int res;
    char *path = ci->inmsg.seg[1].buf;
    int amode = ci->cmd.u.access.amode;
    ventry *ve;
    struct avfs_out_message outmsg;
    struct avfs_result result;

    av_log(AVLOG_SYSCALL, "access(\"%s\", 0%o)", path, amode);
    
    outmsg.num = 2;
    outmsg.seg[0].len = sizeof(result);
    outmsg.seg[0].buf = &result;
    outmsg.seg[1].len = 0;

    res = av_get_ventry(path, 1, &ve);
    if(res < 0)
        result.result = res;
    else {
        if(entry_local(ve)) {
            result.result = -EPERM;
            outmsg.seg[1].buf = (char *) ve->data;
            outmsg.seg[1].len = strlen(outmsg.seg[1].buf) + 1;
            if(outmsg.seg[1].len > PATHBUF_LEN) {
                outmsg.seg[1].len = 0;
                result.result = -ENAMETOOLONG;
            }
        }
        else
            result.result =  av_access(ve, amode);
    }

    av_log(AVLOG_SYSCALL, "   access(\"%s\", 0%o) = %i (%s)",
           path, amode, result.result, 
           outmsg.seg[1].len ? (char *) ve->data : "");

    res = __av_write_message(ci->fd, &outmsg);
    if(res == -1)
        av_log(AVLOG_ERROR, "Error sending message\n");

    av_free_ventry(ve);    
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void process_close ( struct cmdinfo ci) [static]

Definition at line 272 of file avfs_server.c.

{
    int res;
    int fh = ci->cmd.u.fdops.serverfh;
    struct avfs_out_message outmsg;
    struct avfs_result result;

    av_log(AVLOG_SYSCALL, "close(%i)", fh);
    
    outmsg.num = 1;
    outmsg.seg[0].len = sizeof(result);
    outmsg.seg[0].buf = &result;

    result.result = av_fd_close(fh);
    av_log(AVLOG_SYSCALL, "   close(%i) = %i", fh, result.result);

    res = __av_write_message(ci->fd, &outmsg);
    if(res == -1)
        av_log(AVLOG_ERROR, "Error sending message\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void process_fstat ( struct cmdinfo ci) [static]

Definition at line 293 of file avfs_server.c.

{
    int res;
    int fh = ci->cmd.u.fdops.serverfh;
    struct avfs_out_message outmsg;
    struct avfs_result result;
    struct avstat stbuf;

    av_log(AVLOG_SYSCALL, "fstat(%i)", fh);
    
    outmsg.num = 2;
    outmsg.seg[0].len = sizeof(result);
    outmsg.seg[0].buf = &result;
    outmsg.seg[1].len = 0;

    result.result = av_fd_getattr(fh, &stbuf, AVA_ALL);
    if(result.result == 0) {
        outmsg.seg[1].len = sizeof(stbuf);
        outmsg.seg[1].buf = &stbuf;
    }

    av_log(AVLOG_SYSCALL, "   fstat(%i) = %i", fh, result.result);

    res = __av_write_message(ci->fd, &outmsg);
    if(res == -1)
        av_log(AVLOG_ERROR, "Error sending message\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void process_getattr ( struct cmdinfo ci) [static]

Definition at line 127 of file avfs_server.c.

{
    int res;
    char *path = ci->inmsg.seg[1].buf;
    int flags = ci->cmd.u.getattr.flags;
    int attrmask = ci->cmd.u.getattr.attrmask;
    struct avstat stbuf;
    ventry *ve;
    struct avfs_out_message outmsg;
    struct avfs_result result;

    av_log(AVLOG_SYSCALL, "getattr(\"%s\", 0%o, 0%o)",
             path, flags, attrmask);
    
    outmsg.num = 3;
    outmsg.seg[0].len = sizeof(result);
    outmsg.seg[0].buf = &result;
    outmsg.seg[1].len = 0;
    outmsg.seg[2].len = 0;

    res = av_get_ventry(path, !(flags & AVO_NOFOLLOW), &ve);
    if(res < 0)
        result.result = res;
    else {
        if(entry_local(ve)) {
            result.result = -EPERM;
            outmsg.seg[1].buf = (char *) ve->data;
            outmsg.seg[1].len = strlen(outmsg.seg[1].buf) + 1;
            if(outmsg.seg[1].len > PATHBUF_LEN) {
                outmsg.seg[1].len = 0;
                result.result = -ENAMETOOLONG;
            }
        }
        else {
            res = getattr_entry(ve, &stbuf, attrmask, flags);
            result.result = res;
            if(res == 0) {
                outmsg.seg[2].buf = &stbuf;
                outmsg.seg[2].len = sizeof(stbuf);
            }
        }
    }

    av_log(AVLOG_SYSCALL, "   getattr(\"%s\", 0%o, 0%o) = %i (%s)",
             path, flags, attrmask, result.result,
             outmsg.seg[1].len ? (char *) ve->data : "");

    res = __av_write_message(ci->fd, &outmsg);
    if(res == -1)
        av_log(AVLOG_ERROR, "Error sending message\n");

    av_free_ventry(ve);    
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void process_lseek ( struct cmdinfo ci) [static]

Definition at line 354 of file avfs_server.c.

{
    int res;
    int fh = ci->cmd.u.lseek.serverfh;
    avoff_t offset = ci->cmd.u.lseek.offset;
    int whence = ci->cmd.u.lseek.whence;
    struct avfs_out_message outmsg;
    struct avfs_result result;

    av_log(AVLOG_SYSCALL, "lseek(%i, %lli, %i)", fh, offset, whence);
    
    outmsg.num = 1;
    outmsg.seg[0].len = sizeof(result);
    outmsg.seg[0].buf = &result;

    result.u.lseek.offset = av_fd_lseek(fh, offset, whence);

    av_log(AVLOG_SYSCALL, "   lseek(%i, %lli, %i) == %lli",
             fh, offset, whence, result.u.lseek.offset);

    res = __av_write_message(ci->fd, &outmsg);
    if(res == -1)
        av_log(AVLOG_ERROR, "Error sending message\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void* process_message ( void *  arg) [static]

Definition at line 588 of file avfs_server.c.

{
    struct cmdinfo *ci = (struct cmdinfo *) arg;
    
    switch(ci->cmd.type) {
    case CMD_GETATTR:
        process_getattr(ci);
        break;
        
    case CMD_OPEN:
        process_open(ci);
        break;
        
    case CMD_CLOSE:
        process_close(ci);
        break;
        
    case CMD_FSTAT:
        process_fstat(ci);
        break;
        
    case CMD_READDIR:
        process_readdir(ci);
        break;
        
    case CMD_LSEEK:
        process_lseek(ci);
        break;
        
    case CMD_READ:
        process_read(ci);
        break;

    case CMD_WRITE:
        process_write(ci);
        break;
        
    case CMD_RESOLVE:
        process_resolve(ci);
        break;
        
    case CMD_READLINK:
        process_readlink(ci);
        break;

    case CMD_ACCESS:
        process_access(ci);
        break;
        
    default:
        av_log(AVLOG_ERROR, "Unknown command: %i", ci->cmd.type);
        send_error(ci->fd, -ENOSYS);
    }

    if(ci->cmd.type != CMD_OPEN)
        close(ci->fd);
    free_inmsg(&ci->inmsg);
    av_free(ci);

    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void process_open ( struct cmdinfo ci) [static]

Definition at line 211 of file avfs_server.c.

{
    int res;
    char *path = ci->inmsg.seg[1].buf;
    int flags = ci->cmd.u.open.flags;
    mode_t mode = ci->cmd.u.open.mode;
    ventry *ve;
    struct avfs_out_message outmsg;
    struct avfs_result result;

    av_log(AVLOG_SYSCALL, "open(\"%s\", 0%o, 0%lo)", path, flags,
           (unsigned long) mode);
    
    outmsg.num = 2;
    outmsg.seg[0].len = sizeof(result);
    outmsg.seg[0].buf = &result;
    outmsg.seg[1].len = 0;

    res = av_get_ventry(path, 1, &ve);
    if(res < 0)
        result.result = res;
    else {
        if(entry_local(ve)) {
            result.result = -EPERM;
            outmsg.seg[1].buf = (char *) ve->data;
            outmsg.seg[1].len = strlen(outmsg.seg[1].buf) + 1;
            if(outmsg.seg[1].len > PATHBUF_LEN) {
                outmsg.seg[1].len = 0;
                result.result = -ENAMETOOLONG;
            }
        }
        else {
            struct avstat stbuf;

            res = getattr_entry(ve, &stbuf, AVA_MODE, 0);
            if(res == 0) {
                if(AV_ISDIR(stbuf.mode))
                    res = av_fd_open_entry(ve, flags | AVO_DIRECTORY, mode);
                else
                    res = av_fd_open_entry(ve, flags, mode);
            }
            else if(res == -ENOENT && (flags & AVO_CREAT) != 0)
                res = av_fd_open_entry(ve, flags, mode);

            result.result = res;
        }
    }
    av_log(AVLOG_SYSCALL, "   open(\"%s\", 0%o, 0%lo) = %i (%s)",
             path, flags, (unsigned long) mode, result.result,
             outmsg.seg[1].len ? (char *) ve->data : "");

    register_holder(ci->fd, result.result);

    res = __av_write_message(ci->fd, &outmsg);
    if(res == -1)
        av_log(AVLOG_ERROR, "Error sending message\n");

    av_free_ventry(ve);    
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void process_read ( struct cmdinfo ci) [static]

Definition at line 379 of file avfs_server.c.

{
    int res;
    int fh = ci->cmd.u.readwrite.serverfh;
    avsize_t nbyte = ci->cmd.u.readwrite.nbyte;
    struct avfs_out_message outmsg;
    struct avfs_result result;
    void *buf;
        
    outmsg.num = 2;
    outmsg.seg[0].len = sizeof(result);
    outmsg.seg[0].buf = &result;
    outmsg.seg[1].len = 0;
    
    buf = av_malloc(nbyte);

    result.result = av_fd_read(fh, buf, nbyte);
    if(result.result > 0) {
        outmsg.seg[1].len = result.result;
        outmsg.seg[1].buf = buf;
    }
   
    res = __av_write_message(ci->fd, &outmsg);
    if(res == -1)
        av_log(AVLOG_ERROR, "Error sending message\n");

    av_free(buf);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void process_readdir ( struct cmdinfo ci) [static]

Definition at line 321 of file avfs_server.c.

{
    int res;
    int fh = ci->cmd.u.fdops.serverfh;
    struct avfs_out_message outmsg;
    struct avfs_result result;
    char name[NAME_MAX + 1];
    struct avfs_direntry de;

    av_log(AVLOG_SYSCALL, "readdir(%i, ...)", fh);
    
    outmsg.num = 3;
    outmsg.seg[0].len = sizeof(result);
    outmsg.seg[0].buf = &result;
    outmsg.seg[1].len = 0;
    outmsg.seg[2].len = 0;

    result.result = do_readdir(fh, &de, name);
    if(result.result > 0) {
        outmsg.seg[1].len = sizeof(de);
        outmsg.seg[1].buf = &de;
        outmsg.seg[2].len = strlen(name) + 1;
        outmsg.seg[2].buf = name;
    }

    av_log(AVLOG_SYSCALL, "   readdir(%i, {%s, %lli, %i}) = %i",
             fh, result.result > 0 ? name : "", de.ino, de.n, result.result);

    res = __av_write_message(ci->fd, &outmsg);
    if(res == -1)
        av_log(AVLOG_ERROR, "Error sending message\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void process_readlink ( struct cmdinfo ci) [static]

Definition at line 484 of file avfs_server.c.

{
    int res;
    char *path = ci->inmsg.seg[1].buf;
    avsize_t bufsize = ci->cmd.u.readlink.bufsize;
    char *buf = NULL;
    ventry *ve;
    struct avfs_out_message outmsg;
    struct avfs_result result;

    av_log(AVLOG_SYSCALL, "readlink(\"%s\", ..., %u)", path, bufsize);
    
    outmsg.num = 3;
    outmsg.seg[0].len = sizeof(result);
    outmsg.seg[0].buf = &result;
    outmsg.seg[1].len = 0;
    outmsg.seg[2].len = 0;

    res = av_get_ventry(path, 0, &ve);
    if(res < 0)
        result.result = res;
    else {
        if(entry_local(ve)) {
            result.result = -EPERM;
            outmsg.seg[1].buf = (char *) ve->data;
            outmsg.seg[1].len = strlen(outmsg.seg[1].buf) + 1;
            if(outmsg.seg[1].len > PATHBUF_LEN) {
                outmsg.seg[1].len = 0;
                result.result = -ENAMETOOLONG;
            }
        }
        else {
            res = av_readlink(ve, &buf);
            if(res == 0) {
                avsize_t linklen = strlen(buf);

                result.result = AV_MIN(linklen, bufsize);
                outmsg.seg[2].len = AV_MIN(linklen + 1, bufsize);
                outmsg.seg[2].buf = buf;
            }
            else
                result.result = res;
        }
    }

    av_log(AVLOG_SYSCALL, "   readlink(\"%s\", \"%.*s\", %i) = %i (%s)",
             path, 
             result.result < 0 ? 0 : result.result, buf == NULL ? "" : buf,
             bufsize, result.result, 
             outmsg.seg[1].len ? (char *) ve->data : "");

    res = __av_write_message(ci->fd, &outmsg);
    if(res == -1)
        av_log(AVLOG_ERROR, "Error sending message\n");

    av_free_ventry(ve);    
    av_free(buf);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void process_resolve ( struct cmdinfo ci) [static]

Definition at line 435 of file avfs_server.c.

{
    int res;
    char *path = ci->inmsg.seg[1].buf;
    ventry *ve;
    struct avfs_out_message outmsg;
    struct avfs_result result;
    char *newpath = NULL;
    
    av_log(AVLOG_SYSCALL, "resolve(\"%s\")", path);
    
    outmsg.num = 2;
    outmsg.seg[0].len = sizeof(result);
    outmsg.seg[0].buf = &result;
    outmsg.seg[1].len = 0;

    res = av_get_ventry(path, 1, &ve);
    if(res < 0)
        result.result = res;
    else {
        if(entry_local(ve))
            result.u.resolve.isvirtual = 0;
        else
            result.u.resolve.isvirtual = 1;

        res = av_generate_path(ve, &newpath);
        result.result = res;
        if(res == 0) {
            outmsg.seg[1].buf = newpath;
            outmsg.seg[1].len = strlen(outmsg.seg[1].buf) + 1;
            if(outmsg.seg[1].len > PATHBUF_LEN) {
                outmsg.seg[1].len = 0;
                result.result = -ENAMETOOLONG;
            }
        }
        av_free_ventry(ve);    
    }

    av_log(AVLOG_SYSCALL, "   resolve(\"%s\", \"%s\", %i) = %i",
             path, outmsg.seg[1].len ? newpath : "", 
             result.u.resolve.isvirtual, result.result);

    res = __av_write_message(ci->fd, &outmsg);
    if(res == -1)
        av_log(AVLOG_ERROR, "Error sending message\n");
    
    av_free(newpath);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void process_write ( struct cmdinfo ci) [static]

Definition at line 408 of file avfs_server.c.

{
    int res;
    int fh = ci->cmd.u.readwrite.serverfh;
    avsize_t nbyte = ci->cmd.u.readwrite.nbyte;
    struct avfs_out_message outmsg;
    struct avfs_result result;
    const void *buf = ci->inmsg.seg[1].buf;

    av_log(AVLOG_SYSCALL, "write(%i, ..., %u)", fh, nbyte);
    
    outmsg.num = 1;
    outmsg.seg[0].len = sizeof(result);
    outmsg.seg[0].buf = &result;
    
    result.result = av_fd_write(fh, buf, nbyte);
   
    av_log(AVLOG_SYSCALL, "   write(%i, ..., %u) = %i",
             fh, nbyte, result.result);


    res = __av_write_message(ci->fd, &outmsg);
    if(res == -1)
        av_log(AVLOG_ERROR, "Error sending message\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void register_holder ( int  holderfd,
int  serverfh 
) [static]

Definition at line 181 of file avfs_server.c.

{
    int needclose = 0;
    int state;

    AV_LOCK(file_holder_lock);
    state = file_holders[holderfd].state;

    av_log(AVLOG_DEBUG, "register_holder: %i, state: %i/%i, serverfh: %i",
             holderfd, state,  file_holders[holderfd].serverfh, serverfh);
    
    if(state == FIH_USED) {
        if(serverfh < 0)
            file_holders[holderfd].state = FIH_UNUSED;
        else
            file_holders[holderfd].serverfh = serverfh;
    }
    else {
        if(serverfh >= 0)
            needclose = 1;

        file_holders[holderfd].state = FIH_UNUSED;
        close(holderfd);
    }
    AV_UNLOCK(file_holder_lock);

    if(needclose)
        av_fd_close(serverfh);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void send_error ( int  fd,
int  error 
) [static]

Definition at line 92 of file avfs_server.c.

{
    int res;
    struct avfs_out_message outmsg;
    struct avfs_result result;
    
    outmsg.num = 1;
    outmsg.seg[0].len = sizeof(result);
    outmsg.seg[0].buf = &result;
    
    result.result = error;
    res = __av_write_message(fd, &outmsg);
    if(res == -1)
        av_log(AVLOG_ERROR, "Error sending message\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void unmark_file_holder ( int  serverfh) [static]

Definition at line 677 of file avfs_server.c.

{
    int i;

    AV_LOCK(file_holder_lock);
    for(i = 0; i < file_holder_num; i++) {
        if(file_holders[i].state == FIH_USED &&
           file_holders[i].serverfh == serverfh) {
            file_holders[i].state = FIH_UNUSED;
            close(i);
            break;
        }
    }
    if(i == file_holder_num)
        av_log(AVLOG_DEBUG, "File holder not found for %i", serverfh);

    AV_UNLOCK(file_holder_lock);    
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int wait_message ( int  sock) [static]

Definition at line 696 of file avfs_server.c.

{
    int i;
    int nfds;
    struct pollfd *fds;
    int canaccept;
    int res;

    while(1) {
        AV_LOCK(file_holder_lock);
        nfds = 1;
        for(i = 0; i < file_holder_num; i++) {
            if(file_holders[i].state == FIH_USED)
                nfds++;
        }
        /* This is not av_malloc(), because exit will usually happen
           during poll(), and then there would be one unfreed memory. */
        fds = malloc(sizeof(struct pollfd) * nfds);
        nfds = 1;
        for(i = 0; i < file_holder_num; i++) {
            if(file_holders[i].state == FIH_USED) {
                fds[nfds].fd = i;
                fds[nfds].events = POLLIN;
                nfds++;
            }
        }
        AV_UNLOCK(file_holder_lock);
        fds[0].fd = sock;
        fds[0].events = POLLIN;
        
        do res = poll(fds, nfds, -1);
        while(res == -1 && (errno == EAGAIN || errno == EINTR));

        if(res == -1) {
            av_log(AVLOG_ERROR, "poll(): %s", strerror(errno));
            exit(1);
        }

        for(i = 1; i < nfds; i++) {
            if(fds[i].revents != 0) {
                int holderfd = fds[i].fd;
                int serverfh;

                AV_LOCK(file_holder_lock);
                serverfh = file_holders[holderfd].serverfh;

                {
                    char c;
                    av_log(AVLOG_DEBUG, "File holder closed: %i", holderfd);
                    av_log(AVLOG_DEBUG, "serverfh: %i", serverfh);
                    av_log(AVLOG_DEBUG, "state: %i",
                             file_holders[holderfd].state);
                    av_log(AVLOG_DEBUG, "revents: 0%o", fds[i].revents);
                    res = read(holderfd, &c, 1);
                    av_log(AVLOG_DEBUG, "read: %i, (%i)", res, c);
                }
                
                if(file_holders[holderfd].state == FIH_USED) {
                    if(serverfh == -1)
                        file_holders[holderfd].state = FIH_DELETED;
                    else {
                        close(holderfd);
                        file_holders[holderfd].state = FIH_UNUSED;
                    }
                }
                else 
                    close(holderfd);

                AV_UNLOCK(file_holder_lock);

                av_log(AVLOG_DEBUG, "File holder for %i closed", serverfh);
                                
                if(serverfh != -1)
                    av_fd_close(serverfh);
            }
        }

        canaccept = fds[0].revents;

        free(fds);
        
        if(canaccept) {
            int fd;

            fd = accept(sock, NULL, NULL);
            if(fd == -1) {
                av_log(AVLOG_ERROR, "accept(): %s", strerror(errno));
                exit(1);
            }

            return fd;
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

unsigned int file_holder_num [static]

Definition at line 41 of file avfs_server.c.

struct file_holder* file_holders [static]

Definition at line 40 of file avfs_server.c.