diff options
Diffstat (limited to 'libglusterfs/src/fd.c')
| -rw-r--r-- | libglusterfs/src/fd.c | 171 | 
1 files changed, 107 insertions, 64 deletions
diff --git a/libglusterfs/src/fd.c b/libglusterfs/src/fd.c index fc78acc7c..cfebf1489 100644 --- a/libglusterfs/src/fd.c +++ b/libglusterfs/src/fd.c @@ -77,10 +77,32 @@ gf_roundup_power_of_two (uint32_t nr)  	return result;  } +static int +gf_fd_chain_fd_entries (fdentry_t *entries, uint32_t startidx, +                        uint32_t endcount) +{ +        uint32_t        i = 0; + +        if (!entries) +                return -1; + +        /* Chain only till the second to last entry because we want to +         * ensure that the last entry has GF_FDTABLE_END. +         */ +        for (i = startidx; i < (endcount - 1); i++) +                entries[i].next_free = i + 1; + +        /* i has already been incremented upto the last entry. */ +        entries[i].next_free = GF_FDTABLE_END; + +        return 0; +} + +  static uint32_t   gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr)  { -	fd_t **oldfds = NULL; +	fdentry_t *oldfds = NULL;  	uint32_t oldmax_fds = -1;  	if (fdtable == NULL || nr < 0) @@ -89,22 +111,30 @@ gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr)  		return EINVAL;  	} -	nr /= (1024 / sizeof (fd_t *)); +	nr /= (1024 / sizeof (fdentry_t));  	nr = gf_roundup_power_of_two (nr + 1); -	nr *= (1024 / sizeof (fd_t *)); +	nr *= (1024 / sizeof (fdentry_t)); -	oldfds = fdtable->fds; +	oldfds = fdtable->fdentries;  	oldmax_fds = fdtable->max_fds; -	fdtable->fds = CALLOC (nr, sizeof (fd_t *)); -	ERR_ABORT (fdtable->fds); +	fdtable->fdentries = CALLOC (nr, sizeof (fdentry_t)); +	ERR_ABORT (fdtable->fdentries);  	fdtable->max_fds = nr;   	if (oldfds) { -		uint32_t cpy = oldmax_fds * sizeof (fd_t *); -		memcpy (fdtable->fds, oldfds, cpy); +		uint32_t cpy = oldmax_fds * sizeof (fdentry_t); +		memcpy (fdtable->fdentries, oldfds, cpy);  	} +        gf_fd_chain_fd_entries (fdtable->fdentries, oldmax_fds, +                                fdtable->max_fds); + +        /* Now that expansion is done, we must update the fd list +         * head pointer so that the fd allocation functions can continue +         * using the expanded table. +         */ +        fdtable->first_free = oldmax_fds;  	FREE (oldfds);  	return 0;  } @@ -129,36 +159,36 @@ gf_fd_fdtable_alloc (void)  	return fdtable;  } -fd_t ** +fdentry_t *  __gf_fd_fdtable_get_all_fds (fdtable_t *fdtable, uint32_t *count)  { -        fd_t **fds = NULL; +        fdentry_t       *fdentries = NULL;          if (count == NULL) {                  goto out;          } -        fds = fdtable->fds; -        fdtable->fds = calloc (fdtable->max_fds, sizeof (fd_t *)); +        fdentries = fdtable->fdentries; +        fdtable->fdentries = calloc (fdtable->max_fds, sizeof (fdentry_t));          *count = fdtable->max_fds;  out: -        return fds; +        return fdentries;  } -fd_t ** +fdentry_t *  gf_fd_fdtable_get_all_fds (fdtable_t *fdtable, uint32_t *count)  { -        fd_t **fds = NULL; +        fdentry_t       *entries = NULL;          if (fdtable) {                  pthread_mutex_lock (&fdtable->lock);                  { -                        fds = __gf_fd_fdtable_get_all_fds (fdtable, count); +                        entries = __gf_fd_fdtable_get_all_fds (fdtable, count);                  }                  pthread_mutex_unlock (&fdtable->lock);          } -        return fds; +        return entries;  }  void  @@ -166,31 +196,31 @@ gf_fd_fdtable_destroy (fdtable_t *fdtable)  {          struct list_head  list = {0, };          fd_t             *fd = NULL; -        fd_t            **fds = NULL; +        fdentry_t        *fdentries = NULL;          uint32_t          fd_count = 0;          int32_t           i = 0;           INIT_LIST_HEAD (&list); -	if (fdtable) { -		pthread_mutex_lock (&fdtable->lock); -		{ -                        fds = __gf_fd_fdtable_get_all_fds (fdtable, &fd_count); -			FREE (fdtable->fds); -		} -		pthread_mutex_unlock (&fdtable->lock); +	if (!fdtable) +                return; -                if (fds != NULL) { -                        for (i = 0; i < fd_count; i++) { -                                fd = fds[i]; -                                if (fd != NULL) { -                                        fd_unref (fd); -                                } -                        } +	pthread_mutex_lock (&fdtable->lock); +	{ +                fdentries = __gf_fd_fdtable_get_all_fds (fdtable, &fd_count); +		FREE (fdtable->fdentries); +	} +	pthread_mutex_unlock (&fdtable->lock); -                        FREE (fds); +        if (fdentries != NULL) { +                for (i = 0; i < fd_count; i++) { +                        fd = fdentries[i].fd; +                        if (fd != NULL) { +                                fd_unref (fd); +                        }                  } +                FREE (fdentries);  		pthread_mutex_destroy (&fdtable->lock);  		FREE (fdtable);  	} @@ -222,19 +252,10 @@ gf_fd_unused_get2 (fdtable_t *fdtable, fd_t *fdptr, int32_t fd)  			}  		} -		if (!fdtable->fds[fd])  -		{ -			fdtable->fds[fd] = fdptr; -			fd_ref (fdptr); -			ret = fd; -		}  -		else  -		{ -			gf_log ("fd.c", -				GF_LOG_ERROR, -				"Cannot allocate fd %d (slot not empty in fdtable)", fd); -		} -	} +		fdtable->fdentries[fd].fd = fdptr; +		fd_ref (fdptr); +		ret = fd; +        }  err:  	pthread_mutex_unlock (&fdtable->lock); @@ -245,7 +266,10 @@ err:  int32_t   gf_fd_unused_get (fdtable_t *fdtable, fd_t *fdptr)  { -	int32_t fd = -1, i = 0; +	int32_t         fd = -1; +        fdentry_t       *fde = NULL; +	int             error; +        int             alloc_attempts = 0;  	if (fdtable == NULL || fdptr == NULL)  	{ @@ -255,28 +279,42 @@ gf_fd_unused_get (fdtable_t *fdtable, fd_t *fdptr)  	pthread_mutex_lock (&fdtable->lock);  	{ -		for (i = 0; i<fdtable->max_fds; i++)  -		{ -			if (!fdtable->fds[i]) -				break; -		} - -		if (i < fdtable->max_fds) { -			fdtable->fds[i] = fdptr; -			fd = i; +fd_alloc_try_again: +                if (fdtable->first_free != GF_FDTABLE_END) { +                        fde = &fdtable->fdentries[fdtable->first_free]; +                        fd = fdtable->first_free; +                        fdtable->first_free = fde->next_free; +                        fde->next_free = GF_FDENTRY_ALLOCATED; +                        fde->fd = fdptr;  		} else { -			int32_t error; -			error = gf_fd_fdtable_expand (fdtable, fdtable->max_fds + 1); +                        /* If this is true, there is something +                         * seriously wrong with our data structures. +                         */ +                        if (alloc_attempts >= 2) { +                                gf_log ("server-protocol.c", GF_LOG_ERROR, +                                        "Multiple attempts to expand fd table" +                                        " have failed."); +                                goto out; +                        } +                        error = gf_fd_fdtable_expand (fdtable, +                                                      fdtable->max_fds + 1);  			if (error) {  				gf_log ("server-protocol.c",  					GF_LOG_ERROR,  					"Cannot expand fdtable:%s", strerror (error)); -			} else { -				fdtable->fds[i] = fdptr; -				fd = i; +                                goto out;  			} +                        ++alloc_attempts; +                        /* At this point, the table stands expanded +                         * with the first_free referring to the first +                         * free entry in the new set of fdentries that +                         * have just been allocated. That means, the +                         * above logic should just work. +                         */ +                        goto fd_alloc_try_again;  		}  	} +out:  	pthread_mutex_unlock (&fdtable->lock);  	return fd; @@ -287,6 +325,8 @@ inline void  gf_fd_put (fdtable_t *fdtable, int32_t fd)  {  	fd_t *fdptr = NULL; +        fdentry_t *fde = NULL; +  	if (fdtable == NULL || fd < 0)  	{  		gf_log ("fd", GF_LOG_ERROR, "invalid argument"); @@ -301,8 +341,11 @@ gf_fd_put (fdtable_t *fdtable, int32_t fd)  	pthread_mutex_lock (&fdtable->lock);  	{ -		fdptr = fdtable->fds[fd]; -		fdtable->fds[fd] = NULL; +                fde = &fdtable->fdentries[fd]; +		fdptr = fde->fd; +                fde->fd = NULL; +                fde->next_free = fdtable->first_free; +                fdtable->first_free = fd;  	}  	pthread_mutex_unlock (&fdtable->lock); @@ -333,7 +376,7 @@ gf_fd_fdptr_get (fdtable_t *fdtable, int64_t fd)  	pthread_mutex_lock (&fdtable->lock);  	{ -		fdptr = fdtable->fds[fd]; +		fdptr = fdtable->fdentries[fd].fd;  		if (fdptr) {  			fd_ref (fdptr);  		}  | 
