Commit 3ba77f86 authored by Christoph Hellwig's avatar Christoph Hellwig

Replace BKL for chain locking with sysvfs-private rwlock.

parent d219d003
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
*/ */
#include <linux/locks.h> #include <linux/locks.h>
#include <linux/smp_lock.h>
#include "sysv.h" #include "sysv.h"
enum {DIRECT = 10, DEPTH = 4}; /* Have triple indirect */ enum {DIRECT = 10, DEPTH = 4}; /* Have triple indirect */
...@@ -62,6 +61,8 @@ typedef struct { ...@@ -62,6 +61,8 @@ typedef struct {
struct buffer_head *bh; struct buffer_head *bh;
} Indirect; } Indirect;
static rwlock_t pointers_lock = RW_LOCK_UNLOCKED;
static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v) static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v)
{ {
p->key = *(p->p = v); p->key = *(p->p = v);
...@@ -91,7 +92,7 @@ static Indirect *get_branch(struct inode *inode, ...@@ -91,7 +92,7 @@ static Indirect *get_branch(struct inode *inode,
struct buffer_head *bh; struct buffer_head *bh;
*err = 0; *err = 0;
add_chain (chain, NULL, SYSV_I(inode)->i_data + *offsets); add_chain(chain, NULL, SYSV_I(inode)->i_data + *offsets);
if (!p->key) if (!p->key)
goto no_block; goto no_block;
while (--depth) { while (--depth) {
...@@ -99,15 +100,18 @@ static Indirect *get_branch(struct inode *inode, ...@@ -99,15 +100,18 @@ static Indirect *get_branch(struct inode *inode,
bh = sb_bread(sb, block); bh = sb_bread(sb, block);
if (!bh) if (!bh)
goto failure; goto failure;
read_lock(&pointers_lock);
if (!verify_chain(chain, p)) if (!verify_chain(chain, p))
goto changed; goto changed;
add_chain(++p, bh, (u32*)bh->b_data + *++offsets); add_chain(++p, bh, (u32*)bh->b_data + *++offsets);
read_unlock(&pointers_lock);
if (!p->key) if (!p->key)
goto no_block; goto no_block;
} }
return NULL; return NULL;
changed: changed:
read_unlock(&pointers_lock);
*err = -EAGAIN; *err = -EAGAIN;
goto no_block; goto no_block;
failure: failure:
...@@ -165,12 +169,14 @@ static inline int splice_branch(struct inode *inode, ...@@ -165,12 +169,14 @@ static inline int splice_branch(struct inode *inode,
int num) int num)
{ {
int i; int i;
/* Verify that place we are splicing to is still there and vacant */
/* Verify that place we are splicing to is still there and vacant */
write_lock(&pointers_lock);
if (!verify_chain(chain, where-1) || *where->p) if (!verify_chain(chain, where-1) || *where->p)
goto changed; goto changed;
*where->p = where->key; *where->p = where->key;
write_unlock(&pointers_lock);
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
/* had we spliced it onto indirect block? */ /* had we spliced it onto indirect block? */
...@@ -184,6 +190,7 @@ static inline int splice_branch(struct inode *inode, ...@@ -184,6 +190,7 @@ static inline int splice_branch(struct inode *inode,
return 0; return 0;
changed: changed:
write_unlock(&pointers_lock);
for (i = 1; i < num; i++) for (i = 1; i < num; i++)
bforget(where[i].bh); bforget(where[i].bh);
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
...@@ -204,7 +211,6 @@ static int get_block(struct inode *inode, sector_t iblock, struct buffer_head *b ...@@ -204,7 +211,6 @@ static int get_block(struct inode *inode, sector_t iblock, struct buffer_head *b
if (depth == 0) if (depth == 0)
goto out; goto out;
lock_kernel();
reread: reread:
partial = get_branch(inode, depth, offsets, chain, &err); partial = get_branch(inode, depth, offsets, chain, &err);
...@@ -225,7 +231,6 @@ static int get_block(struct inode *inode, sector_t iblock, struct buffer_head *b ...@@ -225,7 +231,6 @@ static int get_block(struct inode *inode, sector_t iblock, struct buffer_head *b
brelse(partial->bh); brelse(partial->bh);
partial--; partial--;
} }
unlock_kernel();
out: out:
return err; return err;
} }
...@@ -277,6 +282,8 @@ static Indirect *find_shared(struct inode *inode, ...@@ -277,6 +282,8 @@ static Indirect *find_shared(struct inode *inode,
*top = 0; *top = 0;
for (k = depth; k > 1 && !offsets[k-1]; k--) for (k = depth; k > 1 && !offsets[k-1]; k--)
; ;
write_lock(&pointers_lock);
partial = get_branch(inode, k, offsets, chain, &err); partial = get_branch(inode, k, offsets, chain, &err);
if (!partial) if (!partial)
partial = chain + k-1; partial = chain + k-1;
...@@ -284,8 +291,10 @@ static Indirect *find_shared(struct inode *inode, ...@@ -284,8 +291,10 @@ static Indirect *find_shared(struct inode *inode,
* If the branch acquired continuation since we've looked at it - * If the branch acquired continuation since we've looked at it -
* fine, it should all survive and (new) top doesn't belong to us. * fine, it should all survive and (new) top doesn't belong to us.
*/ */
if (!partial->key && *partial->p) if (!partial->key && *partial->p) {
write_unlock(&pointers_lock);
goto no_top; goto no_top;
}
for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--) for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--)
; ;
/* /*
...@@ -300,8 +309,9 @@ static Indirect *find_shared(struct inode *inode, ...@@ -300,8 +309,9 @@ static Indirect *find_shared(struct inode *inode,
*top = *p->p; *top = *p->p;
*p->p = 0; *p->p = 0;
} }
write_unlock(&pointers_lock);
while(partial > p) { while (partial > p) {
brelse(partial->bh); brelse(partial->bh);
partial--; partial--;
} }
...@@ -372,8 +382,6 @@ void sysv_truncate (struct inode * inode) ...@@ -372,8 +382,6 @@ void sysv_truncate (struct inode * inode)
if (n == 0) if (n == 0)
return; return;
lock_kernel();
if (n == 1) { if (n == 1) {
free_data(inode, i_data+offsets[0], i_data + DIRECT); free_data(inode, i_data+offsets[0], i_data + DIRECT);
goto do_indirects; goto do_indirects;
...@@ -412,7 +420,6 @@ void sysv_truncate (struct inode * inode) ...@@ -412,7 +420,6 @@ void sysv_truncate (struct inode * inode)
sysv_sync_inode (inode); sysv_sync_inode (inode);
else else
mark_inode_dirty(inode); mark_inode_dirty(inode);
unlock_kernel();
} }
static int sysv_writepage(struct page *page) static int sysv_writepage(struct page *page)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment