diff -urNX ../kernels/exclude ../kernels/linux-ac13/fs/lockd/clntlock.c linux-ac13+lock/fs/lockd/clntlock.c --- ../kernels/linux-ac13/fs/lockd/clntlock.c Sun Apr 2 18:31:32 2000 +++ linux-ac13+lock/fs/lockd/clntlock.c Sun Jun 11 02:06:57 2000 @@ -162,8 +162,7 @@ { struct nlm_host *host = (struct nlm_host *) ptr; struct nlm_wait *block; - struct file_lock *fl; - struct inode *inode; + struct list_head *tmp; /* This one ensures that our parent doesn't terminate while the * reclaim is in progress */ @@ -171,19 +170,21 @@ lockd_up(); /* First, reclaim all locks that have been granted previously. */ - do { - for (fl = file_lock_table; fl; fl = fl->fl_nextlink) { - inode = fl->fl_file->f_dentry->d_inode; - if (inode->i_sb->s_magic == NFS_SUPER_MAGIC - && nlm_cmp_addr(NFS_ADDR(inode), &host->h_addr) - && fl->fl_u.nfs_fl.state != host->h_state - && (fl->fl_u.nfs_fl.flags & NFS_LCK_GRANTED)) { - fl->fl_u.nfs_fl.flags &= ~ NFS_LCK_GRANTED; - nlmclnt_reclaim(host, fl); - break; - } +restart: + tmp = file_lock_list.next; + while (tmp != &file_lock_list) { + struct file_lock *fl = list_entry(tmp, struct file_lock, fl_link); + struct inode *inode = fl->fl_file->f_dentry->d_inode; + if (inode->i_sb->s_magic == NFS_SUPER_MAGIC && + nlm_cmp_addr(NFS_ADDR(inode), &host->h_addr) && + fl->fl_u.nfs_fl.state != host->h_state && + (fl->fl_u.nfs_fl.flags & NFS_LCK_GRANTED)) { + fl->fl_u.nfs_fl.flags &= ~ NFS_LCK_GRANTED; + nlmclnt_reclaim(host, fl); + goto restart; } - } while (fl); + tmp = tmp->next; + } host->h_reclaiming = 0; wake_up(&host->h_gracewait); diff -urNX ../kernels/exclude ../kernels/linux-ac13/fs/lockd/svclock.c linux-ac13+lock/fs/lockd/svclock.c --- ../kernels/linux-ac13/fs/lockd/svclock.c Sat May 13 12:43:55 2000 +++ linux-ac13+lock/fs/lockd/svclock.c Sun Jun 11 02:06:57 2000 @@ -347,7 +347,7 @@ /* Append to list of blocked */ nlmsvc_insert_block(block, NLM_NEVER); - if (!block->b_call.a_args.lock.fl.fl_prevblock) { + if (!list_empty(&block->b_call.a_args.lock.fl.fl_block)) { /* Now add block to block list of the conflicting lock if we haven't done so. */ dprintk("lockd: blocking on this lock.\n"); diff -urNX ../kernels/exclude ../kernels/linux-ac13/fs/locks.c linux-ac13+lock/fs/locks.c --- ../kernels/linux-ac13/fs/locks.c Sun Jun 11 01:45:30 2000 +++ linux-ac13+lock/fs/locks.c Sun Jun 11 05:14:29 2000 @@ -108,100 +108,97 @@ #include #include #include +#include #include -struct file_lock *file_lock_table = NULL; +LIST_HEAD(file_lock_list); +static LIST_HEAD(blocked_list); -/* - * Allocate an empty lock structure. We can use GFP_KERNEL now that - * all allocations are done in advance. - */ -static struct file_lock *locks_empty_lock(void) -{ - /* Okay, let's make a new file_lock structure... */ - return ((struct file_lock *) kmalloc(sizeof(struct file_lock), - GFP_KERNEL)); -} - -/* - * Initialize a new lock from an existing file_lock structure. - */ -static struct file_lock *locks_init_lock(struct file_lock *new, - struct file_lock *fl) -{ - if (new) { - memset(new, 0, sizeof(*new)); - new->fl_owner = fl->fl_owner; - new->fl_pid = fl->fl_pid; - init_waitqueue_head(&new->fl_wait); - new->fl_file = fl->fl_file; - new->fl_flags = fl->fl_flags; - new->fl_type = fl->fl_type; - new->fl_start = fl->fl_start; - new->fl_end = fl->fl_end; - new->fl_notify = fl->fl_notify; - new->fl_insert = fl->fl_insert; - new->fl_remove = fl->fl_remove; - new->fl_u = fl->fl_u; - } - return new; -} +static kmem_cache_t *filelock_cache; -/* Allocate a new lock, and initialize its fields from fl. - * The lock is not inserted into any lists until locks_insert_lock() or - * locks_insert_block() are called. - */ -static inline struct file_lock *locks_alloc_lock(struct file_lock *fl) +/* Allocate an empty lock structure. */ +static struct file_lock *locks_alloc_lock(void) { - return locks_init_lock(locks_empty_lock(), fl); + struct file_lock *fl; + fl = kmem_cache_alloc(filelock_cache, SLAB_KERNEL); + return fl; } -/* Free lock not inserted in any queue. - */ +/* Free a lock which is not in use. */ static inline void locks_free_lock(struct file_lock *fl) { + if (fl == NULL) { + BUG(); + return; + } + if (waitqueue_active(&fl->fl_wait)) panic("Attempting to free lock with active wait queue"); - if (fl->fl_nextblock != NULL || fl->fl_prevblock != NULL) + if (!list_empty(&fl->fl_block)) panic("Attempting to free lock with active block list"); - - kfree(fl); - return; + + if (!list_empty(&fl->fl_link)) + panic("Attempting to free lock on active lock list"); + + kmem_cache_free(filelock_cache, fl); } -/* Verify a call to flock() and fill in a file_lock structure with - * an appropriate FLOCK lock. +/* + * Initialises the fields of the file lock which are invariant for + * free file_locks. */ -static int flock_make_lock(struct file *filp, struct file_lock *fl, - unsigned int cmd) +static void init_once(void *foo, kmem_cache_t *cache, unsigned long flags) { - memset(fl, 0, sizeof(*fl)); + struct file_lock *lock = (struct file_lock *) foo; - init_waitqueue_head(&fl->fl_wait); + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) != + SLAB_CTOR_CONSTRUCTOR) + return; - switch (cmd & ~LOCK_NB) { - case LOCK_SH: - fl->fl_type = F_RDLCK; - break; - case LOCK_EX: - fl->fl_type = F_WRLCK; - break; - case LOCK_UN: - fl->fl_type = F_UNLCK; - break; - default: - return (0); - } + lock->fl_next = NULL; + INIT_LIST_HEAD(&lock->fl_link); + INIT_LIST_HEAD(&lock->fl_block); + init_waitqueue_head(&lock->fl_wait); +} +/* + * Initialize a new lock from an existing file_lock structure. + */ +static void locks_copy_lock(struct file_lock *new, struct file_lock *fl) +{ + new->fl_owner = fl->fl_owner; + new->fl_pid = fl->fl_pid; + new->fl_file = fl->fl_file; + new->fl_flags = fl->fl_flags; + new->fl_type = fl->fl_type; + new->fl_start = fl->fl_start; + new->fl_end = fl->fl_end; + new->fl_notify = fl->fl_notify; + new->fl_insert = fl->fl_insert; + new->fl_remove = fl->fl_remove; + new->fl_u = fl->fl_u; +} + +/* Fill in a file_lock structure with an appropriate FLOCK lock. */ +static struct file_lock *flock_make_lock(struct file *filp, unsigned int type) +{ + struct file_lock *fl = locks_alloc_lock(); + if (fl == NULL) + return NULL; + + fl->fl_owner = NULL; + fl->fl_file = filp; fl->fl_flags = FL_FLOCK; + fl->fl_type = type; fl->fl_start = 0; fl->fl_end = OFFSET_MAX; - fl->fl_file = filp; - fl->fl_owner = NULL; + fl->fl_notify = NULL; + fl->fl_insert = NULL; + fl->fl_remove = NULL; - return (1); + return fl; } /* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX @@ -212,21 +209,6 @@ { loff_t start; - memset(fl, 0, sizeof(*fl)); - - init_waitqueue_head(&fl->fl_wait); - fl->fl_flags = FL_POSIX; - - switch (l->l_type) { - case F_RDLCK: - case F_WRLCK: - case F_UNLCK: - fl->fl_type = l->l_type; - break; - default: - return (0); - } - switch (l->l_whence) { case 0: /*SEEK_SET*/ start = 0; @@ -250,9 +232,23 @@ if (l->l_len == 0) fl->fl_end = OFFSET_MAX; - fl->fl_file = filp; fl->fl_owner = current->files; fl->fl_pid = current->pid; + fl->fl_file = filp; + fl->fl_flags = FL_POSIX; + fl->fl_notify = NULL; + fl->fl_insert = NULL; + fl->fl_remove = NULL; + + switch (l->l_type) { + case F_RDLCK: + case F_WRLCK: + case F_UNLCK: + fl->fl_type = l->l_type; + break; + default: + return (0); + } return (1); } @@ -280,26 +276,12 @@ /* Remove waiter from blocker's block list. * When blocker ends up pointing to itself then the list is empty. */ -static void locks_delete_block(struct file_lock *blocker, - struct file_lock *waiter) +static void locks_delete_block(struct file_lock *waiter) { - struct file_lock *nextblock; - struct file_lock *prevblock; - - nextblock = waiter->fl_nextblock; - prevblock = waiter->fl_prevblock; - - if (nextblock == NULL) - return; - - nextblock->fl_prevblock = prevblock; - prevblock->fl_nextblock = nextblock; - - waiter->fl_prevblock = waiter->fl_nextblock = NULL; - if (blocker->fl_nextblock == blocker) - /* No more locks on blocker's blocked list */ - blocker->fl_prevblock = blocker->fl_nextblock = NULL; - return; + list_del(&waiter->fl_block); + INIT_LIST_HEAD(&waiter->fl_block); + list_del(&waiter->fl_link); + INIT_LIST_HEAD(&waiter->fl_link); } /* Insert waiter into blocker's block list. @@ -310,29 +292,15 @@ static void locks_insert_block(struct file_lock *blocker, struct file_lock *waiter) { - struct file_lock *prevblock; - - if (waiter->fl_prevblock) { - printk(KERN_ERR "locks_insert_block: remove duplicated lock " - "(pid=%d %Ld-%Ld type=%d)\n", - waiter->fl_pid, (long long)waiter->fl_start, - (long long)waiter->fl_end, waiter->fl_type); - locks_delete_block(waiter->fl_prevblock, waiter); - } - - if (blocker->fl_prevblock == NULL) - /* No previous waiters - list is empty */ - prevblock = blocker; - else - /* Previous waiters exist - add to end of list */ - prevblock = blocker->fl_prevblock; - - prevblock->fl_nextblock = waiter; - blocker->fl_prevblock = waiter; - waiter->fl_nextblock = blocker; - waiter->fl_prevblock = prevblock; - - return; + if (!list_empty(&waiter->fl_block)) { + printk(KERN_ERR "locks_insert_block: removing duplicated lock " + "(pid=%d %Ld-%Ld type=%d)\n", waiter->fl_pid, + waiter->fl_start, waiter->fl_end, waiter->fl_type); + locks_delete_block(waiter); + } + list_add_tail(&waiter->fl_block, &blocker->fl_block); +// list_add(&waiter->fl_link, &blocked_list); +// waiter->fl_next = blocker; } /* Wake up processes blocked waiting for blocker. @@ -341,9 +309,8 @@ */ static void locks_wake_up_blocks(struct file_lock *blocker, unsigned int wait) { - struct file_lock *waiter; - - while ((waiter = blocker->fl_nextblock) != NULL) { + while (!list_empty(&blocker->fl_block)) { + struct file_lock *waiter = list_entry(blocker->fl_block.next, struct file_lock, fl_block); /* N.B. Is it possible for the notify function to block?? */ if (waiter->fl_notify) waiter->fl_notify(waiter); @@ -358,10 +325,9 @@ /* Remove waiter from the block list, because by the * time it wakes up blocker won't exist any more. */ - locks_delete_block(blocker, waiter); + locks_delete_block(waiter); } } - return; } /* Insert file lock fl into an inode's lock list at the position indicated @@ -369,18 +335,14 @@ */ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl) { - fl->fl_nextlink = file_lock_table; - fl->fl_prevlink = NULL; - if (file_lock_table != NULL) - file_lock_table->fl_prevlink = fl; - file_lock_table = fl; - fl->fl_next = *pos; /* insert into file's list */ + list_add(&fl->fl_link, &file_lock_list); + + /* insert into file's list */ + fl->fl_next = *pos; *pos = fl; if (fl->fl_insert) fl->fl_insert(fl); - - return; } /* Delete a lock and free it. @@ -390,31 +352,25 @@ */ static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait) { - struct file_lock *thisfl; - struct file_lock *prevfl; - struct file_lock *nextfl; - - thisfl = *thisfl_p; - *thisfl_p = thisfl->fl_next; + int (*lock)(struct file *, int, struct file_lock *); + struct file_lock *fl = *thisfl_p; - prevfl = thisfl->fl_prevlink; - nextfl = thisfl->fl_nextlink; + *thisfl_p = fl->fl_next; + fl->fl_next = NULL; - if (nextfl != NULL) - nextfl->fl_prevlink = prevfl; + list_del(&fl->fl_link); + INIT_LIST_HEAD(&fl->fl_link); - if (prevfl != NULL) - prevfl->fl_nextlink = nextfl; - else - file_lock_table = nextfl; + if (fl->fl_remove) + fl->fl_remove(fl); - if (thisfl->fl_remove) - thisfl->fl_remove(thisfl); - - locks_wake_up_blocks(thisfl, wait); - locks_free_lock(thisfl); - - return; + locks_wake_up_blocks(fl, wait); + lock = fl->fl_file->f_op->lock; + if (lock) { + fl->fl_type = F_UNLCK; + lock(fl->fl_file, F_SETLK, fl); + } + locks_free_lock(fl); } /* Determine if lock sys_fl blocks lock caller_fl. Common functionality @@ -502,8 +458,7 @@ static int posix_locks_deadlock(struct file_lock *caller_fl, struct file_lock *block_fl) { - struct file_lock *fl; - struct file_lock *bfl; + struct list_head *tmp; void *caller_owner, *blocked_owner; unsigned int caller_pid, blocked_pid; @@ -514,11 +469,14 @@ next_task: if (caller_owner == blocked_owner && caller_pid == blocked_pid) - return (1); - for (fl = file_lock_table; fl != NULL; fl = fl->fl_nextlink) { - if (fl->fl_owner == NULL || fl->fl_nextblock == NULL) + return 1; + list_for_each(tmp, &file_lock_list) { + struct list_head *btmp; + struct file_lock *fl = list_entry(tmp, struct file_lock, fl_link); + if (fl->fl_owner == NULL || list_empty(&fl->fl_block)) continue; - for (bfl = fl->fl_nextblock; bfl != fl; bfl = bfl->fl_nextblock) { + list_for_each(btmp, &fl->fl_block) { + struct file_lock *bfl = list_entry(tmp, struct file_lock, fl_block); if (bfl->fl_owner == blocked_owner && bfl->fl_pid == blocked_pid) { if (fl->fl_owner == caller_owner && @@ -531,7 +489,7 @@ } } } - return (0); + return 0; } int locks_mandatory_locked(struct inode *inode) @@ -558,19 +516,16 @@ size_t count) { struct file_lock *fl; - struct file_lock tfl; + struct file_lock *new_fl = locks_alloc_lock(); int error; - memset(&tfl, 0, sizeof(tfl)); - - tfl.fl_file = filp; - tfl.fl_flags = FL_POSIX | FL_ACCESS; - tfl.fl_owner = current->files; - tfl.fl_pid = current->pid; - init_waitqueue_head(&tfl.fl_wait); - tfl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK; - tfl.fl_start = offset; - tfl.fl_end = offset + count - 1; + new_fl->fl_owner = current->files; + new_fl->fl_pid = current->pid; + new_fl->fl_file = filp; + new_fl->fl_flags = FL_POSIX | FL_ACCESS; + new_fl->fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK; + new_fl->fl_start = offset; + new_fl->fl_end = offset + count - 1; error = 0; lock_kernel(); @@ -588,7 +543,7 @@ /* Block for writes against a "read" lock, * and both reads and writes against a "write" lock. */ - if (posix_locks_conflict(&tfl, fl)) { + if (posix_locks_conflict(new_fl, fl)) { error = -EAGAIN; if (filp && (filp->f_flags & O_NONBLOCK)) break; @@ -596,12 +551,12 @@ if (signal_pending(current)) break; error = -EDEADLK; - if (posix_locks_deadlock(&tfl, fl)) + if (posix_locks_deadlock(new_fl, fl)) break; - locks_insert_block(fl, &tfl); - interruptible_sleep_on(&tfl.fl_wait); - locks_delete_block(fl, &tfl); + locks_insert_block(fl, new_fl); + interruptible_sleep_on(&new_fl->fl_wait); + locks_delete_block(new_fl); /* * If we've been sleeping someone might have @@ -613,6 +568,7 @@ } } unlock_kernel(); + locks_free_lock(new_fl); return error; } @@ -620,7 +576,7 @@ * the head of the list, but that's secret knowledge known only to the next * two functions. */ -static int flock_lock_file(struct file *filp, struct file_lock *caller, +static int flock_lock_file(struct file *filp, unsigned int lock_type, unsigned int wait) { struct file_lock *fl; @@ -628,14 +584,14 @@ struct file_lock **before; struct inode * inode = filp->f_dentry->d_inode; int error, change; - int unlock = (caller->fl_type == F_UNLCK); + int unlock = (lock_type == F_UNLCK); /* * If we need a new lock, get it in advance to avoid races. */ if (!unlock) { error = -ENOLCK; - new_fl = locks_alloc_lock(caller); + new_fl = flock_make_lock(filp, lock_type); if (!new_fl) goto out; } @@ -645,8 +601,8 @@ change = 0; before = &inode->i_flock; while (((fl = *before) != NULL) && (fl->fl_flags & FL_FLOCK)) { - if (caller->fl_file == fl->fl_file) { - if (caller->fl_type == fl->fl_type) + if (filp == fl->fl_file) { + if (lock_type == fl->fl_type) goto out; change = 1; break; @@ -682,7 +638,7 @@ goto out; locks_insert_block(fl, new_fl); interruptible_sleep_on(&new_fl->fl_wait); - locks_delete_block(fl, new_fl); + locks_delete_block(new_fl); goto repeat; } locks_insert_lock(&inode->i_flock, new_fl); @@ -722,8 +678,8 @@ * We may need two file_lock structures for this operation, * so we get them in advance to avoid races. */ - new_fl = locks_empty_lock(); - new_fl2 = locks_empty_lock(); + new_fl = locks_alloc_lock(); + new_fl2 = locks_alloc_lock(); error = -ENOLCK; /* "no luck" */ if (!(new_fl && new_fl2)) goto out; @@ -746,7 +702,7 @@ goto out; locks_insert_block(fl, caller); interruptible_sleep_on(&caller->fl_wait); - locks_delete_block(fl, caller); + locks_delete_block(caller); goto repeat; } } @@ -852,7 +808,7 @@ if (!added) { if (caller->fl_type == F_UNLCK) goto out; - locks_init_lock(new_fl, caller); + locks_copy_lock(new_fl, caller); locks_insert_lock(before, new_fl); new_fl = NULL; } @@ -862,8 +818,9 @@ * so we have to use the second new lock (in this * case, even F_UNLCK may fail!). */ - left = locks_init_lock(new_fl2, right); + locks_copy_lock(new_fl2, right); locks_insert_lock(before, left); + left = new_fl2; new_fl2 = NULL; } right->fl_start = caller->fl_end + 1; @@ -875,43 +832,58 @@ } out: /* - * Free any unused locks. (They haven't - * ever been used, so we use kfree().) + * Free any unused locks. */ if (new_fl) - kfree(new_fl); + locks_free_lock(new_fl); if (new_fl2) - kfree(new_fl2); + locks_free_lock(new_fl2); return error; } +static inline int flock_translate_cmd(int cmd) { + switch (cmd &~ LOCK_NB) { + case LOCK_SH: + return F_RDLCK; + case LOCK_EX: + return F_WRLCK; + case LOCK_UN: + return F_UNLCK; + } + return -EINVAL; +} + /* flock() system call entry point. Apply a FL_FLOCK style lock to * an open file descriptor. */ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd) { - struct file_lock file_lock; struct file *filp; - int error; + int error, type; - lock_kernel(); error = -EBADF; filp = fget(fd); if (!filp) goto out; - error = -EINVAL; - if (!flock_make_lock(filp, &file_lock, cmd)) + + error = flock_translate_cmd(cmd); + if (error < 0) goto out_putf; + type = error; + error = -EBADF; - if ((file_lock.fl_type != F_UNLCK) && !(filp->f_mode & 3)) + if ((type != F_UNLCK) && !(filp->f_mode & 3)) goto out_putf; - error = flock_lock_file(filp, &file_lock, + + lock_kernel(); + error = flock_lock_file(filp, type, (cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1); + unlock_kernel(); + out_putf: fput(filp); out: - unlock_kernel(); - return (error); + return error; } /* Report the first existing lock that would conflict with l. @@ -920,7 +892,7 @@ int fcntl_getlk(unsigned int fd, struct flock *l) { struct file *filp; - struct file_lock *fl,file_lock; + struct file_lock *fl, *file_lock = locks_alloc_lock(); struct flock flock; int error; @@ -936,20 +908,20 @@ if (!filp) goto out; - if (!posix_make_lock(filp, &file_lock, &flock)) + if (!posix_make_lock(filp, file_lock, &flock)) goto out_putf; if (filp->f_op->lock) { - error = filp->f_op->lock(filp, F_GETLK, &file_lock); + error = filp->f_op->lock(filp, F_GETLK, file_lock); if (error < 0) goto out_putf; else if (error == LOCK_USE_CLNT) /* Bypass for NFS with no locking - 2.0.36 compat */ - fl = posix_test_lock(filp, &file_lock); + fl = posix_test_lock(filp, file_lock); else - fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock); + fl = (file_lock->fl_type == F_UNLCK ? NULL : file_lock); } else { - fl = posix_test_lock(filp, &file_lock); + fl = posix_test_lock(filp, file_lock); } flock.l_type = F_UNLCK; @@ -968,6 +940,7 @@ out_putf: fput(filp); out: + locks_free_lock(file_lock); return error; } @@ -977,7 +950,7 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l) { struct file *filp; - struct file_lock file_lock; + struct file_lock *file_lock = locks_alloc_lock(); struct flock flock; struct inode *inode; int error; @@ -1019,7 +992,7 @@ } error = -EINVAL; - if (!posix_make_lock(filp, &file_lock, &flock)) + if (!posix_make_lock(filp, file_lock, &flock)) goto out_putf; error = -EBADF; @@ -1057,15 +1030,16 @@ } if (filp->f_op->lock != NULL) { - error = filp->f_op->lock(filp, cmd, &file_lock); + error = filp->f_op->lock(filp, cmd, file_lock); if (error < 0) goto out_putf; } - error = posix_lock_file(filp, &file_lock, cmd == F_SETLKW); + error = posix_lock_file(filp, file_lock, cmd == F_SETLKW); out_putf: fput(filp); out: + locks_free_lock(file_lock); return error; } @@ -1076,7 +1050,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner) { struct inode * inode = filp->f_dentry->d_inode; - struct file_lock file_lock, *fl; + struct file_lock *fl; struct file_lock **before; /* @@ -1086,19 +1060,8 @@ before = &inode->i_flock; while ((fl = *before) != NULL) { if ((fl->fl_flags & FL_POSIX) && fl->fl_owner == owner) { - int (*lock)(struct file *, int, struct file_lock *); - lock = filp->f_op->lock; - if (lock) { - file_lock = *fl; - file_lock.fl_type = F_UNLCK; - } locks_delete_lock(before, 0); - if (lock) { - lock(filp, F_SETLK, &file_lock); - /* List may have changed: */ - goto repeat; - } - continue; + goto repeat; } before = &fl->fl_next; } @@ -1142,15 +1105,15 @@ void posix_block_lock(struct file_lock *blocker, struct file_lock *waiter) { + lock_kernel(); locks_insert_block(blocker, waiter); - return; + unlock_kernel(); } void posix_unblock_lock(struct file_lock *waiter) { - if (waiter->fl_prevblock) - locks_delete_block(waiter->fl_prevblock, waiter); + locks_delete_block(waiter); return; } @@ -1177,8 +1140,8 @@ kdevname(inode->i_dev), inode->i_ino, (long long)fl->fl_start, (long long)fl->fl_end); sprintf(out, "%08lx %08lx %08lx %08lx %08lx\n", - (long)fl, (long)fl->fl_prevlink, (long)fl->fl_nextlink, - (long)fl->fl_next, (long)fl->fl_nextblock); + (long)fl, (long)fl->fl_link.prev, (long)fl->fl_link.next, + (long)fl->fl_next, (long)fl->fl_block.next); } static void move_lock_status(char **p, off_t* pos, off_t offset) @@ -1205,35 +1168,43 @@ int get_locks_status(char *buffer, char **start, off_t offset, int length) { - struct file_lock *fl; - struct file_lock *bfl; + struct list_head *tmp; char *q = buffer; off_t pos = 0; - int i; + int i = 0; - for (fl = file_lock_table, i = 1; fl != NULL; fl = fl->fl_nextlink, i++) { - lock_get_status(q, fl, i, ""); + lock_kernel(); + list_for_each(tmp, &file_lock_list) { + struct list_head *btmp; + struct file_lock *fl = list_entry(tmp, struct file_lock, fl_link); + lock_get_status(q, fl, ++i, ""); move_lock_status(&q, &pos, offset); if(pos >= offset+length) goto done; - if ((bfl = fl->fl_nextblock) == NULL) - continue; - do { + list_for_each(btmp, &fl->fl_block) { + struct file_lock *bfl = list_entry(btmp, + struct file_lock, fl_block); lock_get_status(q, bfl, i, " ->"); move_lock_status(&q, &pos, offset); if(pos >= offset+length) goto done; - } while ((bfl = bfl->fl_nextblock) != fl); + } } done: + unlock_kernel(); *start = buffer; if(q-buffer < length) return (q-buffer); return length; } - - +void __init filelock_init(void) +{ + filelock_cache = kmem_cache_create("file lock cache", + sizeof(struct file_lock), 0, 0, init_once, NULL); + if (!filelock_cache) + panic("cannot create file lock slab cache"); +} diff -urNX ../kernels/exclude ../kernels/linux-ac13/include/linux/fs.h linux-ac13+lock/include/linux/fs.h --- ../kernels/linux-ac13/include/linux/fs.h Sun Jun 11 01:45:35 2000 +++ linux-ac13+lock/include/linux/fs.h Sun Jun 11 02:13:19 2000 @@ -522,10 +522,8 @@ struct file_lock { struct file_lock *fl_next; /* singly linked list for this inode */ - struct file_lock *fl_nextlink; /* doubly linked list of all locks */ - struct file_lock *fl_prevlink; /* used to simplify lock removal */ - struct file_lock *fl_nextblock; /* circular list of blocked processes */ - struct file_lock *fl_prevblock; + struct list_head fl_link; /* doubly linked list of all locks */ + struct list_head fl_block; /* circular list of blocked processes */ fl_owner_t fl_owner; unsigned int fl_pid; wait_queue_head_t fl_wait; @@ -550,7 +548,7 @@ #define OFFSET_MAX INT_LIMIT(loff_t) #endif -extern struct file_lock *file_lock_table; +extern struct list_head file_lock_list; #include diff -urNX ../kernels/exclude ../kernels/linux-ac13/init/main.c linux-ac13+lock/init/main.c --- ../kernels/linux-ac13/init/main.c Sun Jun 11 01:45:43 2000 +++ linux-ac13+lock/init/main.c Sun Jun 11 05:50:13 2000 @@ -97,6 +97,7 @@ extern void bdev_init(void); extern int init_pcmcia_ds(void); extern int usb_init(void); +extern void filelock_init(void); extern void free_initmem(void); extern void filesystem_setup(void); @@ -588,6 +589,7 @@ bdev_init(); inode_init(mempages); file_table_init(); + filelock_init(); #if defined(CONFIG_SYSVIPC) ipc_init(); #endif diff -urNX ../kernels/exclude ../kernels/linux-ac13/kernel/ksyms.c linux-ac13+lock/kernel/ksyms.c --- ../kernels/linux-ac13/kernel/ksyms.c Sun Jun 11 01:45:43 2000 +++ linux-ac13+lock/kernel/ksyms.c Sun Jun 11 02:06:58 2000 @@ -207,7 +207,7 @@ EXPORT_SYMBOL(generic_buffer_fdatasync); EXPORT_SYMBOL(page_hash_bits); EXPORT_SYMBOL(page_hash_table); -EXPORT_SYMBOL(file_lock_table); +EXPORT_SYMBOL(file_lock_list); EXPORT_SYMBOL(posix_lock_file); EXPORT_SYMBOL(posix_test_lock); EXPORT_SYMBOL(posix_block_lock); .