Re: [PATCH 2/2] cifs: Invoke id mapping functions (try #10)

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

 



On Thu, 24 Mar 2011 12:00:24 -0500
shirishpargaonkar@xxxxxxxxx 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 <jlayton@xxxxxxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux