X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=fs%2Flocks.c;h=e0b6a80649a01ff79c26206c039ece3d4faebd0c;hb=c7cf0c68ea4e2020db7204eb0ed4412b2cbb167d;hp=1ad29c9b6252b28cc0e306fb893400293b598608;hpb=b0904e147f7cbe4be3b4dae49ddccd627bb66f16;p=linux-2.6-omap-h63xx.git diff --git a/fs/locks.c b/fs/locks.c index 1ad29c9b625..e0b6a80649a 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -314,13 +314,13 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl, off_t start, end; switch (l->l_whence) { - case 0: /*SEEK_SET*/ + case SEEK_SET: start = 0; break; - case 1: /*SEEK_CUR*/ + case SEEK_CUR: start = filp->f_pos; break; - case 2: /*SEEK_END*/ + case SEEK_END: start = i_size_read(filp->f_dentry->d_inode); break; default: @@ -364,13 +364,13 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, loff_t start; switch (l->l_whence) { - case 0: /*SEEK_SET*/ + case SEEK_SET: start = 0; break; - case 1: /*SEEK_CUR*/ + case SEEK_CUR: start = filp->f_pos; break; - case 2: /*SEEK_END*/ + case SEEK_END: start = i_size_read(filp->f_dentry->d_inode); break; default: @@ -725,6 +725,10 @@ next_task: /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks * at the head of the list, but that's secret knowledge known only to * flock_lock_file and posix_lock_file. + * + * Note that if called with an FL_EXISTS argument, the caller may determine + * whether or not a lock was successfully freed by testing the return + * value for -ENOENT. */ static int flock_lock_file(struct file *filp, struct file_lock *request) { @@ -735,6 +739,8 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) int found = 0; lock_kernel(); + if (request->fl_flags & FL_ACCESS) + goto find_conflict; for_each_lock(inode, before) { struct file_lock *fl = *before; if (IS_POSIX(fl)) @@ -750,8 +756,11 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) break; } - if (request->fl_type == F_UNLCK) + if (request->fl_type == F_UNLCK) { + if ((request->fl_flags & FL_EXISTS) && !found) + error = -ENOENT; goto out; + } error = -ENOMEM; new_fl = locks_alloc_lock(); @@ -764,6 +773,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) if (found) cond_resched(); +find_conflict: for_each_lock(inode, before) { struct file_lock *fl = *before; if (IS_POSIX(fl)) @@ -777,6 +787,8 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) locks_insert_block(fl, request); goto out; } + if (request->fl_flags & FL_ACCESS) + goto out; locks_copy_lock(new_fl, request); locks_insert_lock(&inode->i_flock, new_fl); new_fl = NULL; @@ -948,8 +960,11 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request error = 0; if (!added) { - if (request->fl_type == F_UNLCK) + if (request->fl_type == F_UNLCK) { + if (request->fl_flags & FL_EXISTS) + error = -ENOENT; goto out; + } if (!new_fl) { error = -ENOLCK; @@ -996,6 +1011,10 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request * Add a POSIX style lock to a file. * We merge adjacent & overlapping locks whenever possible. * POSIX locks are sorted by owner task, then by starting address + * + * Note that if called with an FL_EXISTS argument, the caller may determine + * whether or not a lock was successfully freed by testing the return + * value for -ENOENT. */ int posix_lock_file(struct file *filp, struct file_lock *fl) { @@ -1402,8 +1421,9 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp) if (!leases_enable) goto out; - error = lease_alloc(filp, arg, &fl); - if (error) + error = -ENOMEM; + fl = locks_alloc_lock(); + if (fl == NULL) goto out; locks_copy_lock(fl, lease); @@ -1411,6 +1431,7 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp) locks_insert_lock(before, fl); *flp = fl; + error = 0; out: return error; } @@ -1493,7 +1514,7 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg) goto out_unlock; } - error = f_setown(filp, current->pid, 0); + error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); out_unlock: unlock_kernel(); return error;