Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
315e2d46
Commit
315e2d46
authored
Feb 28, 2004
by
Nathan Scott
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[XFS] Implement mrlocks on top of rwsems, instead of using our own mrlock code.
SGI Modid: xfs-linux:xfs-kern:167181a
parent
0a5e5d6b
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
60 additions
and
318 deletions
+60
-318
fs/xfs/Makefile
fs/xfs/Makefile
+0
-1
fs/xfs/linux/mrlock.c
fs/xfs/linux/mrlock.c
+0
-274
fs/xfs/linux/mrlock.h
fs/xfs/linux/mrlock.h
+60
-43
No files found.
fs/xfs/Makefile
View file @
315e2d46
...
...
@@ -130,7 +130,6 @@ xfs-$(CONFIG_XFS_TRACE) += xfs_dir2_trace.o
# Objects in linux/
xfs-y
+=
$(
addprefix
linux/,
\
mrlock.o
\
xfs_aops.o
\
xfs_buf.o
\
xfs_file.o
\
...
...
fs/xfs/linux/mrlock.c
deleted
100644 → 0
View file @
0a5e5d6b
/*
* Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#include <linux/time.h>
#include <linux/sched.h>
#include <asm/system.h>
#include <linux/interrupt.h>
#include <asm/current.h>
#include "mrlock.h"
#if USE_RW_WAIT_QUEUE_SPINLOCK
# define wq_write_lock write_lock
#else
# define wq_write_lock spin_lock
#endif
/*
* We don't seem to need lock_type (only one supported), name, or
* sequence. But, XFS will pass it so let's leave them here for now.
*/
/* ARGSUSED */
void
mrlock_init
(
mrlock_t
*
mrp
,
int
lock_type
,
char
*
name
,
long
sequence
)
{
mrp
->
mr_count
=
0
;
mrp
->
mr_reads_waiting
=
0
;
mrp
->
mr_writes_waiting
=
0
;
init_waitqueue_head
(
&
mrp
->
mr_readerq
);
init_waitqueue_head
(
&
mrp
->
mr_writerq
);
mrp
->
mr_lock
=
SPIN_LOCK_UNLOCKED
;
}
/*
* Macros to lock/unlock the mrlock_t.
*/
#define MRLOCK(m) spin_lock(&(m)->mr_lock);
#define MRUNLOCK(m) spin_unlock(&(m)->mr_lock);
/*
* lock_wait should never be called in an interrupt thread.
*
* mrlocks can sleep (i.e. call schedule) and so they can't ever
* be called from an interrupt thread.
*
* threads that wake-up should also never be invoked from interrupt threads.
*
* But, waitqueue_lock is locked from interrupt threads - and we are
* called with interrupts disabled, so it is all OK.
*/
/* ARGSUSED */
void
lock_wait
(
wait_queue_head_t
*
q
,
spinlock_t
*
lock
,
int
rw
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
__set_current_state
(
TASK_UNINTERRUPTIBLE
);
spin_lock
(
&
q
->
lock
);
if
(
rw
)
{
__add_wait_queue_tail
(
q
,
&
wait
);
}
else
{
__add_wait_queue
(
q
,
&
wait
);
}
spin_unlock
(
&
q
->
lock
);
spin_unlock
(
lock
);
schedule
();
spin_lock
(
&
q
->
lock
);
__remove_wait_queue
(
q
,
&
wait
);
spin_unlock
(
&
q
->
lock
);
spin_lock
(
lock
);
/* return with lock held */
}
/* ARGSUSED */
void
mrfree
(
mrlock_t
*
mrp
)
{
}
/* ARGSUSED */
void
mrlock
(
mrlock_t
*
mrp
,
int
type
,
int
flags
)
{
if
(
type
==
MR_ACCESS
)
mraccess
(
mrp
);
else
mrupdate
(
mrp
);
}
/* ARGSUSED */
void
mraccessf
(
mrlock_t
*
mrp
,
int
flags
)
{
MRLOCK
(
mrp
);
if
(
mrp
->
mr_writes_waiting
>
0
)
{
mrp
->
mr_reads_waiting
++
;
lock_wait
(
&
mrp
->
mr_readerq
,
&
mrp
->
mr_lock
,
0
);
mrp
->
mr_reads_waiting
--
;
}
while
(
mrp
->
mr_count
<
0
)
{
mrp
->
mr_reads_waiting
++
;
lock_wait
(
&
mrp
->
mr_readerq
,
&
mrp
->
mr_lock
,
0
);
mrp
->
mr_reads_waiting
--
;
}
mrp
->
mr_count
++
;
MRUNLOCK
(
mrp
);
}
/* ARGSUSED */
void
mrupdatef
(
mrlock_t
*
mrp
,
int
flags
)
{
MRLOCK
(
mrp
);
while
(
mrp
->
mr_count
)
{
mrp
->
mr_writes_waiting
++
;
lock_wait
(
&
mrp
->
mr_writerq
,
&
mrp
->
mr_lock
,
1
);
mrp
->
mr_writes_waiting
--
;
}
mrp
->
mr_count
=
-
1
;
/* writer on it */
MRUNLOCK
(
mrp
);
}
int
mrtryaccess
(
mrlock_t
*
mrp
)
{
MRLOCK
(
mrp
);
/*
* If anyone is waiting for update access or the lock is held for update
* fail the request.
*/
if
(
mrp
->
mr_writes_waiting
>
0
||
mrp
->
mr_count
<
0
)
{
MRUNLOCK
(
mrp
);
return
0
;
}
mrp
->
mr_count
++
;
MRUNLOCK
(
mrp
);
return
1
;
}
int
mrtrypromote
(
mrlock_t
*
mrp
)
{
MRLOCK
(
mrp
);
if
(
mrp
->
mr_count
==
1
)
{
/* We are the only thread with the lock */
mrp
->
mr_count
=
-
1
;
/* writer on it */
MRUNLOCK
(
mrp
);
return
1
;
}
MRUNLOCK
(
mrp
);
return
0
;
}
int
mrtryupdate
(
mrlock_t
*
mrp
)
{
MRLOCK
(
mrp
);
if
(
mrp
->
mr_count
)
{
MRUNLOCK
(
mrp
);
return
0
;
}
mrp
->
mr_count
=
-
1
;
/* writer on it */
MRUNLOCK
(
mrp
);
return
1
;
}
static
__inline__
void
mrwake
(
mrlock_t
*
mrp
)
{
/*
* First, if the count is now 0, we need to wake-up anyone waiting.
*/
if
(
!
mrp
->
mr_count
)
{
if
(
mrp
->
mr_writes_waiting
)
{
/* Wake-up first writer waiting */
wake_up
(
&
mrp
->
mr_writerq
);
}
else
if
(
mrp
->
mr_reads_waiting
)
{
/* Wakeup any readers waiting */
wake_up
(
&
mrp
->
mr_readerq
);
}
}
}
void
mraccunlock
(
mrlock_t
*
mrp
)
{
MRLOCK
(
mrp
);
mrp
->
mr_count
--
;
mrwake
(
mrp
);
MRUNLOCK
(
mrp
);
}
void
mrunlock
(
mrlock_t
*
mrp
)
{
MRLOCK
(
mrp
);
if
(
mrp
->
mr_count
<
0
)
{
mrp
->
mr_count
=
0
;
}
else
{
mrp
->
mr_count
--
;
}
mrwake
(
mrp
);
MRUNLOCK
(
mrp
);
}
int
ismrlocked
(
mrlock_t
*
mrp
,
int
type
)
/* No need to lock since info can change */
{
if
(
type
==
MR_ACCESS
)
return
(
mrp
->
mr_count
>
0
);
/* Read lock */
else
if
(
type
==
MR_UPDATE
)
return
(
mrp
->
mr_count
<
0
);
/* Write lock */
else
if
(
type
==
(
MR_UPDATE
|
MR_ACCESS
))
return
(
mrp
->
mr_count
);
/* Any type of lock held */
else
/* Any waiters */
return
(
mrp
->
mr_reads_waiting
|
mrp
->
mr_writes_waiting
);
}
/*
* Demote from update to access. We better be the only thread with the
* lock in update mode so it should be easy to set to 1.
* Wake-up any readers waiting.
*/
void
mrdemote
(
mrlock_t
*
mrp
)
{
MRLOCK
(
mrp
);
mrp
->
mr_count
=
1
;
if
(
mrp
->
mr_reads_waiting
)
{
/* Wakeup all readers waiting */
wake_up
(
&
mrp
->
mr_readerq
);
}
MRUNLOCK
(
mrp
);
}
fs/xfs/linux/mrlock.h
View file @
315e2d46
/*
* Copyright (c) 2000-200
3
Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2000-200
4
Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
...
...
@@ -32,56 +32,73 @@
#ifndef __XFS_SUPPORT_MRLOCK_H__
#define __XFS_SUPPORT_MRLOCK_H__
#include <linux/time.h>
#include <linux/wait.h>
#include <asm/atomic.h>
#include <asm/semaphore.h>
#include <linux/rwsem.h>
/*
* Implement mrlocks on Linux that work for XFS.
*
* These are sleep locks and not spinlocks. If one wants read/write spinlocks,
* use read_lock, write_lock, ... see spinlock.h.
*/
enum
{
MR_NONE
,
MR_ACCESS
,
MR_UPDATE
};
typedef
struct
mrlock_s
{
int
mr_count
;
unsigned
short
mr_reads_waiting
;
unsigned
short
mr_writes_waiting
;
wait_queue_head_t
mr_readerq
;
wait_queue_head_t
mr_writerq
;
spinlock_t
mr_lock
;
typedef
struct
{
struct
rw_semaphore
mr_lock
;
int
mr_writer
;
}
mrlock_t
;
#define MR_ACCESS 1
#define MR_UPDATE 2
#define mrinit(mrp, name) \
( (mrp)->mr_writer = 0, init_rwsem(&(mrp)->mr_lock) )
#define mrlock_init(mrp, t,n,s) mrinit(mrp, n)
#define mrfree(mrp) do { } while (0)
#define mraccess(mrp) mraccessf(mrp, 0)
#define mrupdate(mrp) mrupdatef(mrp, 0)
#define MRLOCK_BARRIER 0x1
#define MRLOCK_ALLOW_EQUAL_PRI 0x8
static
inline
void
mraccessf
(
mrlock_t
*
mrp
,
int
flags
)
{
down_read
(
&
mrp
->
mr_lock
);
}
/*
* mraccessf/mrupdatef take flags to be passed in while sleeping;
* only PLTWAIT is currently supported.
*/
static
inline
void
mrupdatef
(
mrlock_t
*
mrp
,
int
flags
)
{
down_write
(
&
mrp
->
mr_lock
);
mrp
->
mr_writer
=
1
;
}
extern
void
mraccessf
(
mrlock_t
*
,
int
);
extern
void
mrupdatef
(
mrlock_t
*
,
int
);
extern
void
mrlock
(
mrlock_t
*
,
int
,
int
);
extern
void
mrunlock
(
mrlock_t
*
);
extern
void
mraccunlock
(
mrlock_t
*
);
extern
int
mrtryupdate
(
mrlock_t
*
);
extern
int
mrtryaccess
(
mrlock_t
*
);
extern
int
mrtrypromote
(
mrlock_t
*
);
extern
void
mrdemote
(
mrlock_t
*
);
static
inline
int
mrtryaccess
(
mrlock_t
*
mrp
)
{
return
down_read_trylock
(
&
mrp
->
mr_lock
);
}
extern
int
ismrlocked
(
mrlock_t
*
,
int
);
extern
void
mrlock_init
(
mrlock_t
*
,
int
type
,
char
*
name
,
long
sequence
);
extern
void
mrfree
(
mrlock_t
*
);
static
inline
int
mrtryupdate
(
mrlock_t
*
mrp
)
{
if
(
!
down_write_trylock
(
&
mrp
->
mr_lock
))
return
0
;
mrp
->
mr_writer
=
1
;
return
1
;
}
#define mrinit(mrp, name) mrlock_init(mrp, MRLOCK_BARRIER, name, -1)
#define mraccess(mrp) mraccessf(mrp, 0)
/* grab for READ/ACCESS */
#define mrupdate(mrp) mrupdatef(mrp, 0)
/* grab for WRITE/UPDATE */
#define mrislocked_access(mrp) ((mrp)->mr_count > 0)
#define mrislocked_update(mrp) ((mrp)->mr_count < 0)
static
inline
void
mrunlock
(
mrlock_t
*
mrp
)
{
if
(
mrp
->
mr_writer
)
{
mrp
->
mr_writer
=
0
;
up_write
(
&
mrp
->
mr_lock
);
}
else
{
up_read
(
&
mrp
->
mr_lock
);
}
}
static
inline
void
mrdemote
(
mrlock_t
*
mrp
)
{
mrp
->
mr_writer
=
0
;
downgrade_write
(
&
mrp
->
mr_lock
);
}
/*
* Debug-only routine, without some platform-specific asm code, we can
* now only answer requests regarding whether we hold the lock for write
* (reader state is outside our visibility, we only track writer state).
* Note: means !ismrlocked would give false positivies, so don't do that.
*/
static
inline
int
ismrlocked
(
mrlock_t
*
mrp
,
int
type
)
{
if
(
type
==
MR_UPDATE
)
return
mrp
->
mr_writer
;
return
1
;
}
#endif
/* __XFS_SUPPORT_MRLOCK_H__ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment