On Thu, 24 Mar 2011 12:00:24 -0500
[email protected] wrote:

> +static int
> +sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
> +             struct cifs_fattr *fattr, uint sidtype)
> +{
> +     int rc;
> +     unsigned long cid;
> +     char *strptr;
> +     struct key *idkey;
> +     const struct cred *saved_cred;
> +     struct cifs_sid_id *psidid, *npsidid;
> +     struct rb_root *cidtree;
> +     spinlock_t *cidlock;
> +
> +     if (sidtype == SIDOWNER) {
> +             cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */
> +             cidlock = &siduidlock;
> +             cidtree = &uidtree;
> +     } else if (sidtype == SIDGROUP) {
> +             cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */
> +             cidlock = &sidgidlock;
> +             cidtree = &gidtree;
> +     } else
> +             return -ENOENT;
> +

That default seems reasonable, I think...

> +     spin_lock(cidlock);
> +     psidid = id_rb_search(cidtree, psid);
> +     spin_unlock(cidlock);
> +
> +     if (!psidid) { /* node does not exist, allocate one & attempt adding */
> +             npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL);
> +             if (!npsidid)
> +                     return -ENOMEM;
> +
> +             spin_lock(cidlock);
> +             psidid = id_rb_search(cidtree, psid);
> +             if (psidid) { /* node happened to get inserted meanwhile */
> +                     spin_unlock(cidlock);
> +                     kfree(npsidid);
> +             } else {
> +                     psidid = npsidid;
> +                     id_rb_insert(cidtree, psid, &psidid);
> +                     spin_unlock(cidlock);
> +             }
> +     }
> +
> +     if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) {
> +             if (!test_bit(SID_ID_MAPPED, &psidid->state)) {

Overall this looks a lot better. The above however is a bit
questionable. Every time you find an entry in the tree, you then mark
it PENDING and check to see if it's MAPPED.

These entries are never going to go from being MAPPED to not. Would it
instead make more sense to check whether it's MAPPED first, and only
then try to set the PENDING bit?

if (!test_bit(SID_ID_MAPPED, &psidid->state) &&
    !test_and_set_bit(SID_ID_PENDING, &psidid->state)) {
        /* construct the entry */
} else {
    /* wait on the PENDING bit */
}

The reason for this would be to minimize the times that you're going to
set the PENDING bit, and force other threads to serialize behind it.

> +                     /* node with unmapped SID */
> +                     memset(psidid->sidstr, '\0', SIDLEN);
> +                     if (sidtype == SIDOWNER)
> +                             sprintf(psidid->sidstr, "%s", "os:");
> +                     else
> +                             sprintf(psidid->sidstr, "%s", "gs:");
> +
> +                     strptr = psidid->sidstr + strlen(psidid->sidstr);
> +                     sid_to_str(psid, strptr);
> +
> +                     saved_cred = override_creds(root_cred);
> +                     idkey = request_key(&cifs_idmap_key_type,
> +                                             psidid->sidstr, "");
> +                     if (IS_ERR(idkey)) {
> +                             psidid->id = cid;
> +                             cFYI(1, "%s: Can't map SID to an id", __func__);
> +                     } else {
> +                             psidid->id =
> +                                     *(unsigned long *)idkey->payload.value;
> +                             psidid->time = jiffies;
> +                             set_bit(SID_ID_MAPPED, &psidid->state);
> +                             key_put(idkey);
> +                     }
> +                     revert_creds(saved_cred);
> +             }
> +             clear_bit(SID_ID_PENDING, &psidid->state);
> +             wake_up_bit(&psidid->state, SID_ID_PENDING);
> +     } else {
> +             /*
> +              * either an existing node with SID mapped (in which case
> +              * we would not wait) or a node whose SID is being mapped by
> +              * somebody else (in which case, we would end up waiting).
> +              */
> +             rc = wait_on_bit(&psidid->state, SID_ID_PENDING,
> +                             sidid_pending_wait, TASK_INTERRUPTIBLE);
> +             if (rc) {
> +                     cFYI(1, "%s: sidid_pending_wait interrupted %d",
> +                             __func__, rc);
> +                     return rc;
> +             }
> +     }
> +
> +
-- 
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

Reply via email to