Mercurial > illumos > illumos-gate
changeset 5005:452acb289ff1
6581372 specfs module accesses s_flag when not holding the lock.
author | cg13442 |
---|---|
date | Thu, 06 Sep 2007 07:13:46 -0700 |
parents | ed80345a3522 |
children | 304eb1332eef |
files | usr/src/uts/common/fs/specfs/specvnops.c |
diffstat | 1 files changed, 26 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fs/specfs/specvnops.c Thu Sep 06 03:56:01 2007 -0700 +++ b/usr/src/uts/common/fs/specfs/specvnops.c Thu Sep 06 07:13:46 2007 -0700 @@ -219,25 +219,37 @@ #define LOCKHOLD_CSP_SIG(csp) spec_lockcsp(csp, 1, 1, 1) #define SYNCHOLD_CSP_SIG(csp, intr) spec_lockcsp(csp, intr, 0, 1) +typedef enum { + LOOP, + INTR, + SUCCESS +} slock_ret_t; + /* - * Synchronize with active SLOCKED, optionally checking for a signal and + * Synchronize with active SLOCKED snode, optionally checking for a signal and * optionally returning with SLOCKED set and SN_HOLD done. The 'intr' * argument determines if the thread is interruptible by a signal while - * waiting, the function returns 0 if interrupted. When 1 is returned - * the 'hold' argument determines if the open count (SN_HOLD) has been - * incremented and the 'setlock' argument determines if the function - * returns with SLOCKED set. + * waiting, the function returns INTR if interrupted while there is another + * thread closing this snonde and LOOP if interrupted otherwise. + * When SUCCESS is returned the 'hold' argument determines if the open + * count (SN_HOLD) has been incremented and the 'setlock' argument + * determines if the function returns with SLOCKED set. */ -static int +static slock_ret_t spec_lockcsp(struct snode *csp, int intr, int setlock, int hold) { + slock_ret_t ret = SUCCESS; mutex_enter(&csp->s_lock); while (csp->s_flag & SLOCKED) { csp->s_flag |= SWANT; if (intr) { if (!cv_wait_sig(&csp->s_cv, &csp->s_lock)) { + if (csp->s_flag & SCLOSING) + ret = INTR; + else + ret = LOOP; mutex_exit(&csp->s_lock); - return (0); /* interrupted */ + return (ret); /* interrupted */ } } else { cv_wait(&csp->s_cv, &csp->s_lock); @@ -248,7 +260,7 @@ if (hold) csp->s_count++; /* one more open reference : SN_HOLD */ mutex_exit(&csp->s_lock); - return (1); /* serialized/locked */ + return (ret); /* serialized/locked */ } /* @@ -548,6 +560,8 @@ int error, type; contract_t *ct = NULL; int open_returns_eintr; + slock_ret_t spec_locksp_ret; + flag &= ~FCREAT; /* paranoia */ @@ -627,8 +641,9 @@ open_returns_eintr = 1; else open_returns_eintr = 0; - while (SYNCHOLD_CSP_SIG(csp, open_returns_eintr) == 0) { - if (csp->s_flag & SCLOSING) + while ((spec_locksp_ret = SYNCHOLD_CSP_SIG(csp, open_returns_eintr)) != + SUCCESS) { + if (spec_locksp_ret == INTR) return (EINTR); } @@ -738,7 +753,7 @@ * D_OPEN_RETURNS_EINTR. Open count already incremented (SN_HOLD) * on non-zero return. */ - if (LOCKHOLD_CSP_SIG(csp) == 0) + if (LOCKHOLD_CSP_SIG(csp) != SUCCESS) return (EINTR); error = stropen(cvp, &newdev, flag, cr);