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)
{
struct file_lock *fl;
struct file_lock *fl, *ret;
struct fasync_struct *new;
struct inode *inode = filp->f_path.dentry->d_inode;
int error;
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);
return -ENOMEM;
}
ret = fl;
lock_flocks();
error = __vfs_setlease(filp, arg, &fl);
error = __vfs_setlease(filp, arg, &ret);
if (error) {
unlock_flocks();
locks_free_lock(fl);
goto out_free_fasync;
}
if (ret != fl)
locks_free_lock(fl);
/*
* 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
* 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;
if (error < 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);
}
error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
unlock_flocks();
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);
}
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;
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)
{
struct nfsd4_conn *conn;
u32 flags = NFS4_CDFC4_FORE;
int ret;
if (ses->se_flags & SESSION4_BACK_CHAN)
flags |= NFS4_CDFC4_BACK;
@ -690,7 +691,10 @@ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses)
if (!conn)
return nfserr_jukebox;
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;
}
@ -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 nfsd4_conn *c;
int ret;
spin_lock(&clp->cl_lock);
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);
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;
}

View File

@ -82,13 +82,6 @@ struct svc_xprt {
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)
{
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);
}
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 *);
void svc_unreg_xprt_class(struct svc_xprt_class *);
void svc_xprt_init(struct svc_xprt_class *, struct svc_xprt *,