Commit 516e0cc5 authored by Al Viro's avatar Al Viro

[PATCH] f_count may wrap around

make it atomic_long_t; while we are at it, get rid of useless checks in affs,
hfs and hpfs - ->open() always has it equal to 1, ->release() - to 0.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 3c333937
...@@ -581,12 +581,12 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -581,12 +581,12 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (file == ppp->owner) if (file == ppp->owner)
ppp_shutdown_interface(ppp); ppp_shutdown_interface(ppp);
} }
if (atomic_read(&file->f_count) <= 2) { if (atomic_long_read(&file->f_count) <= 2) {
ppp_release(NULL, file); ppp_release(NULL, file);
err = 0; err = 0;
} else } else
printk(KERN_DEBUG "PPPIOCDETACH file->f_count=%d\n", printk(KERN_DEBUG "PPPIOCDETACH file->f_count=%ld\n",
atomic_read(&file->f_count)); atomic_long_read(&file->f_count));
unlock_kernel(); unlock_kernel();
return err; return err;
} }
......
...@@ -46,8 +46,6 @@ const struct inode_operations affs_file_inode_operations = { ...@@ -46,8 +46,6 @@ const struct inode_operations affs_file_inode_operations = {
static int static int
affs_file_open(struct inode *inode, struct file *filp) affs_file_open(struct inode *inode, struct file *filp)
{ {
if (atomic_read(&filp->f_count) != 1)
return 0;
pr_debug("AFFS: open(%lu,%d)\n", pr_debug("AFFS: open(%lu,%d)\n",
inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt)); inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
atomic_inc(&AFFS_I(inode)->i_opencnt); atomic_inc(&AFFS_I(inode)->i_opencnt);
...@@ -57,8 +55,6 @@ affs_file_open(struct inode *inode, struct file *filp) ...@@ -57,8 +55,6 @@ affs_file_open(struct inode *inode, struct file *filp)
static int static int
affs_file_release(struct inode *inode, struct file *filp) affs_file_release(struct inode *inode, struct file *filp)
{ {
if (atomic_read(&filp->f_count) != 0)
return 0;
pr_debug("AFFS: release(%lu, %d)\n", pr_debug("AFFS: release(%lu, %d)\n",
inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt)); inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
......
...@@ -512,8 +512,8 @@ static void aio_fput_routine(struct work_struct *data) ...@@ -512,8 +512,8 @@ static void aio_fput_routine(struct work_struct *data)
*/ */
static int __aio_put_req(struct kioctx *ctx, struct kiocb *req) static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
{ {
dprintk(KERN_DEBUG "aio_put(%p): f_count=%d\n", dprintk(KERN_DEBUG "aio_put(%p): f_count=%ld\n",
req, atomic_read(&req->ki_filp->f_count)); req, atomic_long_read(&req->ki_filp->f_count));
assert_spin_locked(&ctx->ctx_lock); assert_spin_locked(&ctx->ctx_lock);
...@@ -528,7 +528,7 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req) ...@@ -528,7 +528,7 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
/* Must be done under the lock to serialise against cancellation. /* Must be done under the lock to serialise against cancellation.
* Call this aio_fput as it duplicates fput via the fput_work. * Call this aio_fput as it duplicates fput via the fput_work.
*/ */
if (unlikely(atomic_dec_and_test(&req->ki_filp->f_count))) { if (unlikely(atomic_long_dec_and_test(&req->ki_filp->f_count))) {
get_ioctx(ctx); get_ioctx(ctx);
spin_lock(&fput_lock); spin_lock(&fput_lock);
list_add(&req->ki_list, &fput_head); list_add(&req->ki_list, &fput_head);
......
...@@ -120,7 +120,7 @@ struct file *get_empty_filp(void) ...@@ -120,7 +120,7 @@ struct file *get_empty_filp(void)
tsk = current; tsk = current;
INIT_LIST_HEAD(&f->f_u.fu_list); INIT_LIST_HEAD(&f->f_u.fu_list);
atomic_set(&f->f_count, 1); atomic_long_set(&f->f_count, 1);
rwlock_init(&f->f_owner.lock); rwlock_init(&f->f_owner.lock);
f->f_uid = tsk->fsuid; f->f_uid = tsk->fsuid;
f->f_gid = tsk->fsgid; f->f_gid = tsk->fsgid;
...@@ -219,7 +219,7 @@ EXPORT_SYMBOL(init_file); ...@@ -219,7 +219,7 @@ EXPORT_SYMBOL(init_file);
void fput(struct file *file) void fput(struct file *file)
{ {
if (atomic_dec_and_test(&file->f_count)) if (atomic_long_dec_and_test(&file->f_count))
__fput(file); __fput(file);
} }
...@@ -294,7 +294,7 @@ struct file *fget(unsigned int fd) ...@@ -294,7 +294,7 @@ struct file *fget(unsigned int fd)
rcu_read_lock(); rcu_read_lock();
file = fcheck_files(files, fd); file = fcheck_files(files, fd);
if (file) { if (file) {
if (!atomic_inc_not_zero(&file->f_count)) { if (!atomic_long_inc_not_zero(&file->f_count)) {
/* File object ref couldn't be taken */ /* File object ref couldn't be taken */
rcu_read_unlock(); rcu_read_unlock();
return NULL; return NULL;
...@@ -326,7 +326,7 @@ struct file *fget_light(unsigned int fd, int *fput_needed) ...@@ -326,7 +326,7 @@ struct file *fget_light(unsigned int fd, int *fput_needed)
rcu_read_lock(); rcu_read_lock();
file = fcheck_files(files, fd); file = fcheck_files(files, fd);
if (file) { if (file) {
if (atomic_inc_not_zero(&file->f_count)) if (atomic_long_inc_not_zero(&file->f_count))
*fput_needed = 1; *fput_needed = 1;
else else
/* Didn't get the reference, someone's freed */ /* Didn't get the reference, someone's freed */
...@@ -341,7 +341,7 @@ struct file *fget_light(unsigned int fd, int *fput_needed) ...@@ -341,7 +341,7 @@ struct file *fget_light(unsigned int fd, int *fput_needed)
void put_filp(struct file *file) void put_filp(struct file *file)
{ {
if (atomic_dec_and_test(&file->f_count)) { if (atomic_long_dec_and_test(&file->f_count)) {
security_file_free(file); security_file_free(file);
file_kill(file); file_kill(file);
file_free(file); file_free(file);
......
...@@ -522,8 +522,6 @@ static int hfs_file_open(struct inode *inode, struct file *file) ...@@ -522,8 +522,6 @@ static int hfs_file_open(struct inode *inode, struct file *file)
{ {
if (HFS_IS_RSRC(inode)) if (HFS_IS_RSRC(inode))
inode = HFS_I(inode)->rsrc_inode; inode = HFS_I(inode)->rsrc_inode;
if (atomic_read(&file->f_count) != 1)
return 0;
atomic_inc(&HFS_I(inode)->opencnt); atomic_inc(&HFS_I(inode)->opencnt);
return 0; return 0;
} }
...@@ -534,8 +532,6 @@ static int hfs_file_release(struct inode *inode, struct file *file) ...@@ -534,8 +532,6 @@ static int hfs_file_release(struct inode *inode, struct file *file)
if (HFS_IS_RSRC(inode)) if (HFS_IS_RSRC(inode))
inode = HFS_I(inode)->rsrc_inode; inode = HFS_I(inode)->rsrc_inode;
if (atomic_read(&file->f_count) != 0)
return 0;
if (atomic_dec_and_test(&HFS_I(inode)->opencnt)) { if (atomic_dec_and_test(&HFS_I(inode)->opencnt)) {
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
hfs_file_truncate(inode); hfs_file_truncate(inode);
......
...@@ -254,8 +254,6 @@ static int hfsplus_file_open(struct inode *inode, struct file *file) ...@@ -254,8 +254,6 @@ static int hfsplus_file_open(struct inode *inode, struct file *file)
{ {
if (HFSPLUS_IS_RSRC(inode)) if (HFSPLUS_IS_RSRC(inode))
inode = HFSPLUS_I(inode).rsrc_inode; inode = HFSPLUS_I(inode).rsrc_inode;
if (atomic_read(&file->f_count) != 1)
return 0;
atomic_inc(&HFSPLUS_I(inode).opencnt); atomic_inc(&HFSPLUS_I(inode).opencnt);
return 0; return 0;
} }
...@@ -266,8 +264,6 @@ static int hfsplus_file_release(struct inode *inode, struct file *file) ...@@ -266,8 +264,6 @@ static int hfsplus_file_release(struct inode *inode, struct file *file)
if (HFSPLUS_IS_RSRC(inode)) if (HFSPLUS_IS_RSRC(inode))
inode = HFSPLUS_I(inode).rsrc_inode; inode = HFSPLUS_I(inode).rsrc_inode;
if (atomic_read(&file->f_count) != 0)
return 0;
if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) { if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) {
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
hfsplus_file_truncate(inode); hfsplus_file_truncate(inode);
......
...@@ -795,7 +795,7 @@ struct file { ...@@ -795,7 +795,7 @@ struct file {
#define f_dentry f_path.dentry #define f_dentry f_path.dentry
#define f_vfsmnt f_path.mnt #define f_vfsmnt f_path.mnt
const struct file_operations *f_op; const struct file_operations *f_op;
atomic_t f_count; atomic_long_t f_count;
unsigned int f_flags; unsigned int f_flags;
mode_t f_mode; mode_t f_mode;
loff_t f_pos; loff_t f_pos;
...@@ -824,8 +824,8 @@ extern spinlock_t files_lock; ...@@ -824,8 +824,8 @@ extern spinlock_t files_lock;
#define file_list_lock() spin_lock(&files_lock); #define file_list_lock() spin_lock(&files_lock);
#define file_list_unlock() spin_unlock(&files_lock); #define file_list_unlock() spin_unlock(&files_lock);
#define get_file(x) atomic_inc(&(x)->f_count) #define get_file(x) atomic_long_inc(&(x)->f_count)
#define file_count(x) atomic_read(&(x)->f_count) #define file_count(x) atomic_long_read(&(x)->f_count)
#ifdef CONFIG_DEBUG_WRITECOUNT #ifdef CONFIG_DEBUG_WRITECOUNT
static inline void file_take_write(struct file *f) static inline void file_take_write(struct file *f)
......
...@@ -51,7 +51,7 @@ struct unix_sock { ...@@ -51,7 +51,7 @@ struct unix_sock {
struct sock *peer; struct sock *peer;
struct sock *other; struct sock *other;
struct list_head link; struct list_head link;
atomic_t inflight; atomic_long_t inflight;
spinlock_t lock; spinlock_t lock;
unsigned int gc_candidate : 1; unsigned int gc_candidate : 1;
wait_queue_head_t peer_wait; wait_queue_head_t peer_wait;
......
...@@ -162,7 +162,7 @@ static void atm_tc_put(struct Qdisc *sch, unsigned long cl) ...@@ -162,7 +162,7 @@ static void atm_tc_put(struct Qdisc *sch, unsigned long cl)
qdisc_destroy(flow->q); qdisc_destroy(flow->q);
tcf_destroy_chain(&flow->filter_list); tcf_destroy_chain(&flow->filter_list);
if (flow->sock) { if (flow->sock) {
pr_debug("atm_tc_put: f_count %d\n", pr_debug("atm_tc_put: f_count %ld\n",
file_count(flow->sock->file)); file_count(flow->sock->file));
flow->vcc->pop = flow->old_pop; flow->vcc->pop = flow->old_pop;
sockfd_put(flow->sock); sockfd_put(flow->sock);
...@@ -259,7 +259,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, ...@@ -259,7 +259,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
sock = sockfd_lookup(fd, &error); sock = sockfd_lookup(fd, &error);
if (!sock) if (!sock)
return error; /* f_count++ */ return error; /* f_count++ */
pr_debug("atm_tc_change: f_count %d\n", file_count(sock->file)); pr_debug("atm_tc_change: f_count %ld\n", file_count(sock->file));
if (sock->ops->family != PF_ATMSVC && sock->ops->family != PF_ATMPVC) { if (sock->ops->family != PF_ATMSVC && sock->ops->family != PF_ATMPVC) {
error = -EPROTOTYPE; error = -EPROTOTYPE;
goto err_out; goto err_out;
......
...@@ -603,7 +603,7 @@ static struct sock * unix_create1(struct net *net, struct socket *sock) ...@@ -603,7 +603,7 @@ static struct sock * unix_create1(struct net *net, struct socket *sock)
u->dentry = NULL; u->dentry = NULL;
u->mnt = NULL; u->mnt = NULL;
spin_lock_init(&u->lock); spin_lock_init(&u->lock);
atomic_set(&u->inflight, 0); atomic_long_set(&u->inflight, 0);
INIT_LIST_HEAD(&u->link); INIT_LIST_HEAD(&u->link);
mutex_init(&u->readlock); /* single task reading lock */ mutex_init(&u->readlock); /* single task reading lock */
init_waitqueue_head(&u->peer_wait); init_waitqueue_head(&u->peer_wait);
......
...@@ -127,7 +127,7 @@ void unix_inflight(struct file *fp) ...@@ -127,7 +127,7 @@ void unix_inflight(struct file *fp)
if(s) { if(s) {
struct unix_sock *u = unix_sk(s); struct unix_sock *u = unix_sk(s);
spin_lock(&unix_gc_lock); spin_lock(&unix_gc_lock);
if (atomic_inc_return(&u->inflight) == 1) { if (atomic_long_inc_return(&u->inflight) == 1) {
BUG_ON(!list_empty(&u->link)); BUG_ON(!list_empty(&u->link));
list_add_tail(&u->link, &gc_inflight_list); list_add_tail(&u->link, &gc_inflight_list);
} else { } else {
...@@ -145,7 +145,7 @@ void unix_notinflight(struct file *fp) ...@@ -145,7 +145,7 @@ void unix_notinflight(struct file *fp)
struct unix_sock *u = unix_sk(s); struct unix_sock *u = unix_sk(s);
spin_lock(&unix_gc_lock); spin_lock(&unix_gc_lock);
BUG_ON(list_empty(&u->link)); BUG_ON(list_empty(&u->link));
if (atomic_dec_and_test(&u->inflight)) if (atomic_long_dec_and_test(&u->inflight))
list_del_init(&u->link); list_del_init(&u->link);
unix_tot_inflight--; unix_tot_inflight--;
spin_unlock(&unix_gc_lock); spin_unlock(&unix_gc_lock);
...@@ -237,17 +237,17 @@ static void scan_children(struct sock *x, void (*func)(struct unix_sock *), ...@@ -237,17 +237,17 @@ static void scan_children(struct sock *x, void (*func)(struct unix_sock *),
static void dec_inflight(struct unix_sock *usk) static void dec_inflight(struct unix_sock *usk)
{ {
atomic_dec(&usk->inflight); atomic_long_dec(&usk->inflight);
} }
static void inc_inflight(struct unix_sock *usk) static void inc_inflight(struct unix_sock *usk)
{ {
atomic_inc(&usk->inflight); atomic_long_inc(&usk->inflight);
} }
static void inc_inflight_move_tail(struct unix_sock *u) static void inc_inflight_move_tail(struct unix_sock *u)
{ {
atomic_inc(&u->inflight); atomic_long_inc(&u->inflight);
/* /*
* If this is still a candidate, move it to the end of the * If this is still a candidate, move it to the end of the
* list, so that it's checked even if it was already passed * list, so that it's checked even if it was already passed
...@@ -288,11 +288,11 @@ void unix_gc(void) ...@@ -288,11 +288,11 @@ void unix_gc(void)
* before the detach without atomicity guarantees. * before the detach without atomicity guarantees.
*/ */
list_for_each_entry_safe(u, next, &gc_inflight_list, link) { list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
int total_refs; long total_refs;
int inflight_refs; long inflight_refs;
total_refs = file_count(u->sk.sk_socket->file); total_refs = file_count(u->sk.sk_socket->file);
inflight_refs = atomic_read(&u->inflight); inflight_refs = atomic_long_read(&u->inflight);
BUG_ON(inflight_refs < 1); BUG_ON(inflight_refs < 1);
BUG_ON(total_refs < inflight_refs); BUG_ON(total_refs < inflight_refs);
...@@ -324,7 +324,7 @@ void unix_gc(void) ...@@ -324,7 +324,7 @@ void unix_gc(void)
/* Move cursor to after the current position. */ /* Move cursor to after the current position. */
list_move(&cursor, &u->link); list_move(&cursor, &u->link);
if (atomic_read(&u->inflight) > 0) { if (atomic_long_read(&u->inflight) > 0) {
list_move_tail(&u->link, &gc_inflight_list); list_move_tail(&u->link, &gc_inflight_list);
u->gc_candidate = 0; u->gc_candidate = 0;
scan_children(&u->sk, inc_inflight_move_tail, NULL); scan_children(&u->sk, inc_inflight_move_tail, NULL);
......
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