Skip to content

Commit

Permalink
Merge branch 'for-2.6.37' of git://linux-nfs.org/~bfields/linux
Browse files Browse the repository at this point in the history
* '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
  • Loading branch information
torvalds committed Nov 12, 2010
2 parents e2b3483 + 8896b93 commit 0f90933
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 20 deletions.
19 changes: 7 additions & 12 deletions fs/locks.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -1518,31 +1517,27 @@ 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.
* If there was no old entry, then it used 'new' and
* 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:
Expand Down
16 changes: 12 additions & 4 deletions fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -673,24 +673,28 @@ 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;
conn = alloc_conn(rqstp, flags);
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;
}

Expand Down Expand Up @@ -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);
Expand All @@ -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;
}

Expand Down
18 changes: 14 additions & 4 deletions include/linux/sunrpc/svc_xprt.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,28 @@ struct svc_xprt {
struct net *xpt_net;
};

static inline void register_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);
list_add(&u->list, &xpt->xpt_users);
list_del_init(&u->list);
spin_unlock(&xpt->xpt_lock);
}

static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
static inline int register_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
{
spin_lock(&xpt->xpt_lock);
list_del_init(&u->list);
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 *);
Expand Down

0 comments on commit 0f90933

Please sign in to comment.