On Wed, Apr 20, 2011 at 12:07 PM, Jeff Layton <[email protected]> wrote:
> On Tue, 19 Apr 2011 08:21:09 -0500
> [email protected] wrote:
>
>> From: Shirish Pargaonkar <[email protected]>
>>
>>
>> rb tree search and insertion routines.
>>
>> A SID which needs to be mapped, is looked up in one of the rb trees
>> depending whether SID is either owner or group SID.
>> If found in the tree, a (mapped) id from that node is assigned to
>> uid or gid as appropriate. If unmapped, an upcall is attempted to
>> map the SID to an id. If upcall is successful, node is marked as
>> mapped. If upcall fails, node stays marked as unmapped and a mapping
>> is attempted again only after an arbitrary time period has passed.
>>
>> To map a SID, which can be either a Owner SID or a Group SID, key
>> description starts with the string "os" or "gs" followed by SID converted
>> to a string. Without "os" or "gs", cifs.upcall does not know whether
>> SID needs to be mapped to either an uid or a gid.
>>
>> Nodes in rb tree have fields to prevent multiple upcalls for
>> a SID. Adding and removing nodes is done within global locks.
>> Shrinker routine prunes a node if it has expired but does not prne
>> an expired node if its refcount is not zero (i.e. sid of that node
>> is being mapped via an upcall).
>> Every time an existing node is accessed, its timestamp is updated
>> to prevent it from getting erased.
>>
>> For now, cifs.upcall is only used to map a SID to an id (uid or gid) but
>> it would be used to obtain an SID for an id.
>>
>>
>> Signed-off-by: Shirish Pargaonkar <[email protected]>
>> ---
>> fs/cifs/cifsacl.c | 332
>> +++++++++++++++++++++++++++++++++++++++++++++++++----
>> fs/cifs/cifsacl.h | 25 ++++
>> 2 files changed, 333 insertions(+), 24 deletions(-)
>>
>> diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
>> index cad8d9b..bbc29b8 100644
>> --- a/fs/cifs/cifsacl.c
>> +++ b/fs/cifs/cifsacl.c
>
> [...]
>
>> + /*
>> + * Shrinker could be accessing this entry but it will not
>> + * get erased at this point in time and to make it stay further,
>> + * pretty soon we will take a reference on it only to
>> + * release the reference only after upcall returns (or we are
>> + * woken up), however longer that upcall may take to return.
>> + */
>> + if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) {
>> + /* paidid and its fields are being accessed sans spinlock */
>> + ++psidid->refcount;
> ^^^
> Huh? You're incrementing and decrementing the
> refcount without any locking at all? What prevents the
> shrinker from finding the entry just before you bump
> the refcount and wiping it out anyway?
>
Becaue we just updated the timestamp so shrinker will not evict the
entry at least for the duration of SID_MAP_EXPIRE.
The refcount is to account for an lenghty upcall.
>> +struct cifs_sid_id {
>> + unsigned int refcount;
>> + unsigned long id;
>> + unsigned long time;
>> + unsigned long retry;
>
> Why, exactly do we need "time" and "retry"? Wouldn't one timestamp
> field do here?
>
One timestamp is to make an entry eligible for eviction and the other
one is to attempt mapping again if previous attempt to map a sid had
failed.
>> + unsigned long state;
>> + char *sidstr;
>> + struct rb_node rbnode;
>> + struct cifs_sid sid;
>> +};
>> +
>
> --
> Jeff Layton <[email protected]>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html