Re: [pnfs] [RFC 21/85] nfs41: find slot

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Nov. 10, 2008, 22:21 +0200, Benny Halevy <bhalevy@xxxxxxxxxxx> wrote:
> Find a free slot using bitmap-based allocation.
> Use the optimized ffz function to find a zero bit
> in the bitmap that indicates a free slot, starting
> the search from the 'lowest_free_slotid' position.
> 
> If found, mark the slot as used in the bitmap, get
> the slot's slotid and seqid, and update max_slotid
> to be used by the SEQUENCE operation.
> 
> Also, update lowest_free_slotid for next search.
> 
> If no free slot was found the caller has to wait
> for a free slot (outside the scope of this function)
> 
> Signed-off-by: Benny Halevy <bhalevy@xxxxxxxxxxx>
> ---
>  fs/nfs/nfs4proc.c            |   88 ++++++++++++++++++++++++++++++++++++++++++
>  include/linux/nfs4_session.h |    5 ++
>  2 files changed, 93 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 08e7129..4ded3a5 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -207,6 +207,94 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
>  	spin_unlock(&clp->cl_lock);
>  }
>  
> +#if defined(CONFIG_NFS_V4_1)
> +
> +/*
> + * idx2bmp - return pointer to bitmap word holding index "idx".
> + *
> + * inputs:
> + * @base	points to bitmap.
> + * @idx		slot index.
> + *
> + * output:
> + * @bit		optional, *bit set to bit index of "idx" in the returned
> + *		bitmap word.
> + */
> +static inline unsigned long *idx2bmp(unsigned long *base, int idx, int *bit)
> +{
> +	base += idx / BITS_PER_LONG;
> +	if (bit)
> +		*bit = idx & (BITS_PER_LONG - 1);
> +	return base;
> +}
> +
> +/*
> + * bmp2idx - return absolute index of bmp:bit in bitmap.
> + *
> + * inputs:
> + * @base	points to bitmap.
> + * @bmp		points to bitmap word.
> + * @bit		bit index in bitmap word.
> + */
> +static inline int bmp2idx(unsigned long *base, unsigned long *bmp,
> +			  int bit)
> +{
> +	return ((bmp - base) * BITS_PER_LONG) + bit;
> +}
> +
> +/*
> + * nfs4_find_slot - efficiently look for a free slot
> + *
> + * nfs4_find_slot uses the ffz cpu-optimized function to look for an unset
> + * bit in each word in the bitmap.
> + * Scan starts at lowest_free_slotid, which is a hint for the free slot,
> + * as all lower-numbered slots are known to be used.
> + * If found, we mark the slot as used, update the highest_used_slotid,
> + * and respectively set up the sequence operation args.
> + * The lowest_free_slotid is always set to the successive slotid.
> + * A pointer to the slot's seqid is returned if found, or NULL otherwise.
> + */
> +static struct nfs4_slot *
> +nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)
> +{
> +	int bit, slotid;
> +	struct nfs4_slot *slot = NULL;
> +	unsigned long *used, u;
> +
> +	spin_lock(&tbl->slot_tbl_lock);
> +	slotid = tbl->lowest_free_slotid;
> +	while (slotid < tbl->max_slots) {
> +		used = idx2bmp(tbl->used_slots, slotid, NULL);
> +		u = *used;
> +		if (u == ~0UL) {
> +			/* all slots marked used in this word */
> +			slotid += BITS_PER_LONG;
> +			continue;
> +		}
> +		/* find first slot marked free in word */
> +		bit = ffz(u);

review 11-14: look into using a bitmap_find_free_region function

> +		slotid = bmp2idx(tbl->used_slots, used, bit);
> +		/* mark slot used.  note that we don't do that if
> +		 * slotid >= tbl->max_slots so not to confuse
> +		 * highest_used_slotid algorithm */
> +		if (slotid < tbl->max_slots) {
> +			*used |= (1 << bit);
> +			if (slotid > tbl->highest_used_slotid)
> +				tbl->highest_used_slotid = slotid;
> +			slot = tbl->slots + slotid;
> +			slotid++;	/* for updating lowest_free_slot */
> +		}
> +		break;
> +	}
> +	tbl->lowest_free_slotid = slotid;
> +	spin_unlock(&tbl->slot_tbl_lock);
> +	dprintk("<-- %s slot %p slotid %d\n", __func__,
> +		slot, slot ? slot_idx(tbl, slot) : -1);
> +	return slot;
> +}
> +
> +#endif /* CONFIG_NFS_V4_1 */
> +
>  static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
>  {
>  	struct nfs_inode *nfsi = NFS_I(dir);
> diff --git a/include/linux/nfs4_session.h b/include/linux/nfs4_session.h
> index d534269..2960ba9 100644
> --- a/include/linux/nfs4_session.h
> +++ b/include/linux/nfs4_session.h
> @@ -33,6 +33,11 @@ struct nfs4_slot_table {
>  						 * op for dynamic resizing */
>  };
>  
> +static inline int slot_idx(struct nfs4_slot_table *tbl, struct nfs4_slot *sp)
> +{
> +	return sp - tbl->slots;
> +}
> +
>  struct nfs4_channel {
>  	struct nfs4_channel_attrs 	chan_attrs;
>  	struct rpc_clnt 		*rpc_client;
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux