Merge branch 'for-2.6.37' of git://linux-nfs.org/~bfields/linux

* 'for-2.6.37' of git://linux-nfs.org/~bfields/linux:
  locks: remove dead lease error-handling code
  locks: fix leak on merging leases
  nfsd4: fix 4.1 connection registration race
This commit is contained in:
Linus Torvalds 2010-11-12 07:59:41 -08:00
commit 0f90933c47
3 changed files with 36 additions and 23 deletions

View File

@ -1504,9 +1504,8 @@ static int do_fcntl_delete_lease(struct file *filp)
static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg)
{ {
struct file_lock *fl; struct file_lock *fl, *ret;
struct fasync_struct *new; struct fasync_struct *new;
struct inode *inode = filp->f_path.dentry->d_inode;
int error; int error;
fl = lease_alloc(filp, arg); fl = lease_alloc(filp, arg);
@ -1518,13 +1517,16 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg)
locks_free_lock(fl); locks_free_lock(fl);
return -ENOMEM; return -ENOMEM;
} }
ret = fl;
lock_flocks(); lock_flocks();
error = __vfs_setlease(filp, arg, &fl); error = __vfs_setlease(filp, arg, &ret);
if (error) { if (error) {
unlock_flocks(); unlock_flocks();
locks_free_lock(fl); locks_free_lock(fl);
goto out_free_fasync; goto out_free_fasync;
} }
if (ret != fl)
locks_free_lock(fl);
/* /*
* fasync_insert_entry() returns the old entry if any. * fasync_insert_entry() returns the old entry if any.
@ -1532,17 +1534,10 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg)
* inserted it into the fasync list. Clear new so that * inserted it into the fasync list. Clear new so that
* we don't release it here. * we don't release it here.
*/ */
if (!fasync_insert_entry(fd, filp, &fl->fl_fasync, new)) if (!fasync_insert_entry(fd, filp, &ret->fl_fasync, new))
new = NULL; new = NULL;
if (error < 0) { error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
/* remove lease just inserted by setlease */
fl->fl_type = F_UNLCK | F_INPROGRESS;
fl->fl_break_time = jiffies - 10;
time_out_leases(inode);
} else {
error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
}
unlock_flocks(); unlock_flocks();
out_free_fasync: out_free_fasync:

View File

@ -673,16 +673,17 @@ static void nfsd4_hash_conn(struct nfsd4_conn *conn, struct nfsd4_session *ses)
spin_unlock(&clp->cl_lock); spin_unlock(&clp->cl_lock);
} }
static void nfsd4_register_conn(struct nfsd4_conn *conn) static int nfsd4_register_conn(struct nfsd4_conn *conn)
{ {
conn->cn_xpt_user.callback = nfsd4_conn_lost; conn->cn_xpt_user.callback = nfsd4_conn_lost;
register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user);
} }
static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses) static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses)
{ {
struct nfsd4_conn *conn; struct nfsd4_conn *conn;
u32 flags = NFS4_CDFC4_FORE; u32 flags = NFS4_CDFC4_FORE;
int ret;
if (ses->se_flags & SESSION4_BACK_CHAN) if (ses->se_flags & SESSION4_BACK_CHAN)
flags |= NFS4_CDFC4_BACK; flags |= NFS4_CDFC4_BACK;
@ -690,7 +691,10 @@ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses)
if (!conn) if (!conn)
return nfserr_jukebox; return nfserr_jukebox;
nfsd4_hash_conn(conn, ses); nfsd4_hash_conn(conn, ses);
nfsd4_register_conn(conn); ret = nfsd4_register_conn(conn);
if (ret)
/* oops; xprt is already down: */
nfsd4_conn_lost(&conn->cn_xpt_user);
return nfs_ok; return nfs_ok;
} }
@ -1644,6 +1648,7 @@ static void nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_sessi
{ {
struct nfs4_client *clp = ses->se_client; struct nfs4_client *clp = ses->se_client;
struct nfsd4_conn *c; struct nfsd4_conn *c;
int ret;
spin_lock(&clp->cl_lock); spin_lock(&clp->cl_lock);
c = __nfsd4_find_conn(new->cn_xprt, ses); c = __nfsd4_find_conn(new->cn_xprt, ses);
@ -1654,7 +1659,10 @@ static void nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_sessi
} }
__nfsd4_hash_conn(new, ses); __nfsd4_hash_conn(new, ses);
spin_unlock(&clp->cl_lock); spin_unlock(&clp->cl_lock);
nfsd4_register_conn(new); ret = nfsd4_register_conn(new);
if (ret)
/* oops; xprt is already down: */
nfsd4_conn_lost(&new->cn_xpt_user);
return; return;
} }

View File

@ -82,13 +82,6 @@ struct svc_xprt {
struct net *xpt_net; struct net *xpt_net;
}; };
static inline void register_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
{
spin_lock(&xpt->xpt_lock);
list_add(&u->list, &xpt->xpt_users);
spin_unlock(&xpt->xpt_lock);
}
static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u) static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
{ {
spin_lock(&xpt->xpt_lock); spin_lock(&xpt->xpt_lock);
@ -96,6 +89,23 @@ static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user
spin_unlock(&xpt->xpt_lock); spin_unlock(&xpt->xpt_lock);
} }
static inline int register_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
{
spin_lock(&xpt->xpt_lock);
if (test_bit(XPT_CLOSE, &xpt->xpt_flags)) {
/*
* The connection is about to be deleted soon (or,
* worse, may already be deleted--in which case we've
* already notified the xpt_users).
*/
spin_unlock(&xpt->xpt_lock);
return -ENOTCONN;
}
list_add(&u->list, &xpt->xpt_users);
spin_unlock(&xpt->xpt_lock);
return 0;
}
int svc_reg_xprt_class(struct svc_xprt_class *); int svc_reg_xprt_class(struct svc_xprt_class *);
void svc_unreg_xprt_class(struct svc_xprt_class *); void svc_unreg_xprt_class(struct svc_xprt_class *);
void svc_xprt_init(struct svc_xprt_class *, struct svc_xprt *, void svc_xprt_init(struct svc_xprt_class *, struct svc_xprt *,