Commit 38d7463e authored by James Simmons's avatar James Simmons

Merge bk://linus.bkbits.net/linux-2.5

into maxwell.earthlink.net:/usr/src/linus-2.5
parents bca102e6 c39f7320
......@@ -56,11 +56,8 @@
#include <linux/blk.h>
#define DEBUG 0
#if DEBUG
# define dprintk(x...) printk(x)
#else
# define dprintk(x...) do { } while(0)
#endif
#define dprintk(x...) ((void)(DEBUG && printk(x)))
#ifndef MODULE
static void autostart_arrays (void);
......@@ -604,18 +601,6 @@ static void export_array(mddev_t *mddev)
mddev->raid_disks = 0;
}
static void free_mddev(mddev_t *mddev)
{
if (!mddev) {
MD_BUG();
return;
}
export_array(mddev);
md_size[mdidx(mddev)] = 0;
set_capacity(disks[mdidx(mddev)], 0);
}
#undef BAD_CSUM
#undef BAD_MAGIC
#undef OUT_OF_MEM
......@@ -1533,7 +1518,6 @@ static int do_md_stop(mddev_t * mddev, int ro)
{
int err = 0;
kdev_t dev = mddev_to_kdev(mddev);
struct gendisk *disk;
if (atomic_read(&mddev->active)>1) {
printk(STILL_IN_USE, mdidx(mddev));
......@@ -1582,6 +1566,16 @@ static int do_md_stop(mddev_t * mddev, int ro)
if (ro)
set_device_ro(dev, 1);
}
/*
* Free resources if final stop
*/
if (!ro) {
struct gendisk *disk;
printk(KERN_INFO "md: md%d stopped.\n", mdidx(mddev));
export_array(mddev);
md_size[mdidx(mddev)] = 0;
disk = disks[mdidx(mddev)];
disks[mdidx(mddev)] = NULL;
......@@ -1591,12 +1585,6 @@ static int do_md_stop(mddev_t * mddev, int ro)
kfree(disk);
}
/*
* Free resources if final stop
*/
if (!ro) {
printk(KERN_INFO "md: md%d stopped.\n", mdidx(mddev));
free_mddev(mddev);
} else
printk(KERN_INFO "md: md%d switched to read-only mode.\n", mdidx(mddev));
err = 0;
......@@ -2593,7 +2581,7 @@ static void md_recover_arrays(void)
void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
{
dprintk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",
MD_MAJOR,mdidx(mddev),MAJOR(bdev->bd_dev),MINOR(bdev->bd_dev),
MD_MAJOR,mdidx(mddev),MAJOR(rdev->bdev->bd_dev),MINOR(rdev->bdev->bd_dev),
__builtin_return_address(0),__builtin_return_address(1),
__builtin_return_address(2),__builtin_return_address(3));
......@@ -3149,11 +3137,11 @@ request_queue_t * md_queue_proc(kdev_t dev)
{
mddev_t *mddev = mddev_find(minor(dev));
request_queue_t *q = BLK_DEFAULT_QUEUE(MAJOR_NR);
if (!mddev || atomic_read(&mddev->active)<2)
BUG();
if (mddev) {
if (mddev->pers)
q = &mddev->queue;
mddev_put(mddev); /* the caller must hold a reference... */
mddev_put(mddev);
}
return q;
}
......
......@@ -37,20 +37,6 @@
#define NR_RESERVED_BUFS 32
/*
* The following can be used to debug the driver
*/
#define MULTIPATH_DEBUG 0
#if MULTIPATH_DEBUG
#define PRINTK(x...) printk(x)
#define inline
#define __inline__
#else
#define PRINTK(x...) do { } while (0)
#endif
static mdk_personality_t multipath_personality;
static spinlock_t retry_list_lock = SPIN_LOCK_UNLOCKED;
struct multipath_bh *multipath_retry_list = NULL, **multipath_retry_tail;
......
......@@ -49,12 +49,10 @@
# define CHECK_DEVLOCK()
#endif
#define PRINTK(x...) ((void)(RAID5_DEBUG && printk(x)))
#if RAID5_DEBUG
#define PRINTK(x...) printk(x)
#define inline
#define __inline__
#else
#define PRINTK(x...) do { } while (0)
#endif
static void print_raid5_conf (raid5_conf_t *conf);
......@@ -933,13 +931,16 @@ static void handle_stripe(struct stripe_head *sh)
test_bit(R5_UPTODATE, &dev->flags))
|| (failed == 1 && failed_num == sh->pd_idx))
) {
/* any written block on an uptodate or failed drive can be returned */
/* any written block on an uptodate or failed drive can be returned.
* Note that if we 'wrote' to a failed drive, it will be UPTODATE, but
* never LOCKED, so we don't need to test 'failed' directly.
*/
for (i=disks; i--; )
if (sh->dev[i].written) {
dev = &sh->dev[i];
if (!test_bit(R5_Insync, &sh->dev[sh->pd_idx].flags) &&
(!test_bit(R5_LOCKED, &dev->flags) && test_bit(R5_UPTODATE, &dev->flags)) ) {
/* maybe we can return some write requests */
if (!test_bit(R5_LOCKED, &dev->flags) &&
test_bit(R5_UPTODATE, &dev->flags) ) {
/* We can return any write requests */
struct bio *wbi, *wbi2;
PRINTK("Return write for disc %d\n", i);
wbi = dev->written;
......@@ -1164,7 +1165,7 @@ static void handle_stripe(struct stripe_head *sh)
md_sync_acct(rdev, STRIPE_SECTORS);
bi->bi_bdev = rdev->bdev;
PRINTK("for %ld schedule op %d on disc %d\n", sh->sector, bi->bi_rw, i);
PRINTK("for %ld schedule op %ld on disc %d\n", sh->sector, bi->bi_rw, i);
atomic_inc(&sh->count);
bi->bi_sector = sh->sector;
bi->bi_flags = 0;
......@@ -1175,7 +1176,7 @@ static void handle_stripe(struct stripe_head *sh)
bi->bi_next = NULL;
generic_make_request(bi);
} else {
PRINTK("skip op %d on disc %d for sector %ld\n", bi->bi_rw, i, sh->sector);
PRINTK("skip op %ld on disc %d for sector %ld\n", bi->bi_rw, i, sh->sector);
clear_bit(R5_LOCKED, &dev->flags);
set_bit(STRIPE_HANDLE, &sh->state);
}
......@@ -1242,8 +1243,8 @@ static int make_request (request_queue_t *q, struct bio * bi)
new_sector = raid5_compute_sector(logical_sector,
raid_disks, data_disks, &dd_idx, &pd_idx, conf);
PRINTK("raid5: make_request, sector %ul logical %ul\n",
new_sector, logical_sector);
PRINTK("raid5: make_request, sector %Lu logical %Lu\n",
(unsigned long long)new_sector, (unsigned long long)logical_sector);
sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK));
if (sh) {
......
......@@ -22,7 +22,6 @@
#define NLM_HOST_MAX 64
#define NLM_HOST_NRHASH 32
#define NLM_ADDRHASH(addr) (ntohl(addr) & (NLM_HOST_NRHASH-1))
#define NLM_PTRHASH(ptr) ((((u32)(unsigned long) ptr) / 32) & (NLM_HOST_NRHASH-1))
#define NLM_HOST_REBIND (60 * HZ)
#define NLM_HOST_EXPIRE ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ)
#define NLM_HOST_COLLECT ((nrhosts > NLM_HOST_MAX)? 120 * HZ : 60 * HZ)
......@@ -42,7 +41,7 @@ static void nlm_gc_hosts(void);
struct nlm_host *
nlmclnt_lookup_host(struct sockaddr_in *sin, int proto, int version)
{
return nlm_lookup_host(NULL, sin, proto, version);
return nlm_lookup_host(0, sin, proto, version);
}
/*
......@@ -51,44 +50,24 @@ nlmclnt_lookup_host(struct sockaddr_in *sin, int proto, int version)
struct nlm_host *
nlmsvc_lookup_host(struct svc_rqst *rqstp)
{
return nlm_lookup_host(rqstp->rq_client, &rqstp->rq_addr,
return nlm_lookup_host(1, &rqstp->rq_addr,
rqstp->rq_prot, rqstp->rq_vers);
}
/*
* Match the given host against client/address
*/
static inline int
nlm_match_host(struct nlm_host *host, struct svc_client *clnt,
struct sockaddr_in *sin)
{
if (clnt)
return host->h_exportent == clnt;
return nlm_cmp_addr(&host->h_addr, sin);
}
/*
* Common host lookup routine for server & client
*/
struct nlm_host *
nlm_lookup_host(struct svc_client *clnt, struct sockaddr_in *sin,
nlm_lookup_host(int server, struct sockaddr_in *sin,
int proto, int version)
{
struct nlm_host *host, **hp;
u32 addr;
int hash;
if (!clnt && !sin) {
printk(KERN_NOTICE "lockd: no clnt or addr in lookup_host!\n");
return NULL;
}
dprintk("lockd: nlm_lookup_host(%08x, p=%d, v=%d)\n",
(unsigned)(sin? ntohl(sin->sin_addr.s_addr) : 0), proto, version);
if (clnt)
hash = NLM_PTRHASH(clnt);
else
hash = NLM_ADDRHASH(sin->sin_addr.s_addr);
/* Lock hash table */
......@@ -98,12 +77,14 @@ nlm_lookup_host(struct svc_client *clnt, struct sockaddr_in *sin,
nlm_gc_hosts();
for (hp = &nlm_hosts[hash]; (host = *hp); hp = &host->h_next) {
if (proto && host->h_proto != proto)
if (host->h_proto != proto)
continue;
if (version && host->h_version != version)
if (host->h_version != version)
continue;
if (host->h_server != server)
continue;
if (nlm_match_host(host, clnt, sin)) {
if (nlm_cmp_addr(&host->h_addr, sin)) {
if (hp != nlm_hosts + hash) {
*hp = host->h_next;
host->h_next = nlm_hosts[hash];
......@@ -115,10 +96,6 @@ nlm_lookup_host(struct svc_client *clnt, struct sockaddr_in *sin,
}
}
/* special hack for nlmsvc_invalidate_client */
if (sin == NULL)
goto nohost;
/* Ooops, no host found, create it */
dprintk("lockd: creating host entry\n");
......@@ -146,8 +123,7 @@ nlm_lookup_host(struct svc_client *clnt, struct sockaddr_in *sin,
init_waitqueue_head(&host->h_gracewait);
host->h_state = 0; /* pseudo NSM state */
host->h_nsmstate = 0; /* real NSM state */
host->h_exportent = clnt;
host->h_server = server;
host->h_next = nlm_hosts[hash];
nlm_hosts[hash] = host;
......@@ -159,6 +135,30 @@ nlm_lookup_host(struct svc_client *clnt, struct sockaddr_in *sin,
return host;
}
struct nlm_host *
nlm_find_client(void)
{
/* find a nlm_host for a client for which h_killed == 0.
* and return it
*/
int hash;
down(&nlm_host_sema);
for (hash = 0 ; hash < NLM_HOST_NRHASH; hash++) {
struct nlm_host *host, **hp;
for (hp = &nlm_hosts[hash]; (host = *hp) ; hp = &host->h_next) {
if (host->h_server &&
host->h_killed == 0) {
nlm_get_host(host);
up(&nlm_host_sema);
return host;
}
}
}
up(&nlm_host_sema);
return NULL;
}
/*
* Create the NLM RPC client for an NLM peer
*/
......
......@@ -32,7 +32,6 @@ EXPORT_SYMBOL(lockd_down);
EXPORT_SYMBOL(nlmclnt_proc);
/* NFS server entry points/hooks */
EXPORT_SYMBOL(nlmsvc_invalidate_client);
EXPORT_SYMBOL(nlmsvc_ops);
#endif /* CONFIG_MODULES */
......@@ -42,6 +42,7 @@ nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res)
goto out;
args.addr = host->h_addr.sin_addr.s_addr;
args.proto= (host->h_proto<<1) | host->h_server;
args.prog = NLM_PROGRAM;
args.vers = host->h_version;
args.proc = NLMPROC_NSM_NOTIFY;
......@@ -167,8 +168,8 @@ xdr_encode_mon(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
/* This is the private part. Needed only for SM_MON call */
if (rqstp->rq_task->tk_msg.rpc_proc == SM_MON) {
*p++ = argp->addr;
*p++ = 0;
*p++ = 0;
*p++ = argp->vers;
*p++ = argp->proto;
*p++ = 0;
}
......@@ -206,61 +207,60 @@ xdr_decode_stat(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp)
static struct rpc_procinfo nsm_procedures[] = {
{
p_procname: "sm_null",
p_encode: (kxdrproc_t) xdr_error,
p_decode: (kxdrproc_t) xdr_error,
.p_procname = "sm_null",
.p_encode = (kxdrproc_t) xdr_error,
.p_decode = (kxdrproc_t) xdr_error,
},
{
p_procname: "sm_stat",
p_encode: (kxdrproc_t) xdr_error,
p_decode: (kxdrproc_t) xdr_error,
.p_procname = "sm_stat",
.p_encode = (kxdrproc_t) xdr_error,
.p_decode = (kxdrproc_t) xdr_error,
},
{
p_procname: "sm_mon",
p_encode: (kxdrproc_t) xdr_encode_mon,
p_decode: (kxdrproc_t) xdr_decode_stat_res,
p_bufsiz: MAX(SM_mon_sz, SM_monres_sz) << 2,
.p_procname = "sm_mon",
.p_encode = (kxdrproc_t) xdr_encode_mon,
.p_decode = (kxdrproc_t) xdr_decode_stat_res,
.p_bufsiz = MAX(SM_mon_sz, SM_monres_sz) << 2,
},
{
p_procname: "sm_unmon",
p_encode: (kxdrproc_t) xdr_encode_mon,
p_decode: (kxdrproc_t) xdr_decode_stat,
p_bufsiz: MAX(SM_mon_id_sz, SM_unmonres_sz) << 2,
.p_procname = "sm_unmon",
.p_encode = (kxdrproc_t) xdr_encode_mon,
.p_decode = (kxdrproc_t) xdr_decode_stat,
.p_bufsiz = MAX(SM_mon_id_sz, SM_unmonres_sz) << 2,
},
{
p_procname: "sm_unmon_all",
p_encode: (kxdrproc_t) xdr_error,
p_decode: (kxdrproc_t) xdr_error,
.p_procname = "sm_unmon_all",
.p_encode = (kxdrproc_t) xdr_error,
.p_decode = (kxdrproc_t) xdr_error,
},
{
p_procname: "sm_simu_crash",
p_encode: (kxdrproc_t) xdr_error,
p_decode: (kxdrproc_t) xdr_error, 0, 0
.p_procname = "sm_simu_crash",
.p_encode = (kxdrproc_t) xdr_error,
.p_decode = (kxdrproc_t) xdr_error,
},
{
p_procname: "sm_notify",
p_encode: (kxdrproc_t) xdr_error,
p_decode: (kxdrproc_t) xdr_error,
.p_procname = "sm_notify",
.p_encode = (kxdrproc_t) xdr_error,
.p_decode = (kxdrproc_t) xdr_error,
},
};
static struct rpc_version nsm_version1 = {
number: 1,
nrprocs: sizeof(nsm_procedures)/sizeof(nsm_procedures[0]),
procs: nsm_procedures
.number = 1,
.nrprocs = sizeof(nsm_procedures)/sizeof(nsm_procedures[0]),
.procs = nsm_procedures
};
static struct rpc_version * nsm_version[] = {
NULL,
&nsm_version1,
[1] = &nsm_version1,
};
static struct rpc_stat nsm_stats;
struct rpc_program nsm_program = {
name: "statd",
number: SM_PROGRAM,
nrvers: sizeof(nsm_version)/sizeof(nsm_version[0]),
version: nsm_version,
stats: &nsm_stats
.name = "statd",
.number = SM_PROGRAM,
.nrvers = sizeof(nsm_version)/sizeof(nsm_version[0]),
.version = nsm_version,
.stats = &nsm_stats
};
......@@ -130,7 +130,7 @@ lockd(struct svc_rqst *rqstp)
flush_signals(current);
spin_unlock_irq(&current->sigmask_lock);
if (nlmsvc_ops) {
nlmsvc_ops->detach();
nlmsvc_invalidate_all();
grace_period_expire = set_grace_period();
}
}
......@@ -163,22 +163,8 @@ lockd(struct svc_rqst *rqstp)
dprintk("lockd: request from %08x\n",
(unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr));
/*
* Look up the NFS client handle. The handle is needed for
* all but the GRANTED callback RPCs.
*/
rqstp->rq_client = NULL;
if (nlmsvc_ops) {
nlmsvc_ops->exp_readlock();
rqstp->rq_client =
nlmsvc_ops->exp_getclient(&rqstp->rq_addr);
}
svc_process(serv, rqstp);
/* Unlock export hash tables */
if (nlmsvc_ops)
nlmsvc_ops->exp_unlock();
}
/*
......@@ -187,7 +173,7 @@ lockd(struct svc_rqst *rqstp)
*/
if (!nlmsvc_pid || current->pid == nlmsvc_pid) {
if (nlmsvc_ops)
nlmsvc_ops->detach();
nlmsvc_invalidate_all();
nlm_shutdown_hosts();
nlmsvc_pid = 0;
} else
......@@ -369,29 +355,27 @@ __setup("lockd.tcpport=", tcpport_set);
* Define NLM program and procedures
*/
static struct svc_version nlmsvc_version1 = {
vs_vers: 1,
vs_nproc: 17,
vs_proc: nlmsvc_procedures,
.vs_vers = 1,
.vs_nproc = 17,
.vs_proc = nlmsvc_procedures,
};
static struct svc_version nlmsvc_version3 = {
vs_vers: 3,
vs_nproc: 24,
vs_proc: nlmsvc_procedures,
.vs_vers = 3,
.vs_nproc = 24,
.vs_proc = nlmsvc_procedures,
};
#ifdef CONFIG_LOCKD_V4
static struct svc_version nlmsvc_version4 = {
vs_vers: 4,
vs_nproc: 24,
vs_proc: nlmsvc_procedures4,
.vs_vers = 4,
.vs_nproc = 24,
.vs_proc = nlmsvc_procedures4,
};
#endif
static struct svc_version * nlmsvc_version[] = {
NULL,
&nlmsvc_version1,
NULL,
&nlmsvc_version3,
[1] = &nlmsvc_version1,
[3] = &nlmsvc_version3,
#ifdef CONFIG_LOCKD_V4
&nlmsvc_version4,
[4] = &nlmsvc_version4,
#endif
};
......@@ -399,11 +383,11 @@ static struct svc_stat nlmsvc_stats;
#define NLM_NRVERS (sizeof(nlmsvc_version)/sizeof(nlmsvc_version[0]))
struct svc_program nlmsvc_program = {
pg_prog: NLM_PROGRAM, /* program number */
pg_lovers: 1, // version
pg_hivers: NLM_NRVERS-1, // range
pg_nvers: NLM_NRVERS, /* number of entries in nlmsvc_version */
pg_vers: nlmsvc_version, /* version table */
pg_name: "lockd", /* service name */
pg_stats: &nlmsvc_stats, /* stats table */
.pg_prog = NLM_PROGRAM, /* program number */
.pg_lovers = 1, /* version */
.pg_hivers = NLM_NRVERS-1, /* range */
.pg_nvers = NLM_NRVERS, /* number of entries in nlmsvc_version */
.pg_vers = nlmsvc_version, /* version table */
.pg_name = "lockd", /* service name */
.pg_stats = &nlmsvc_stats, /* stats table */
};
......@@ -40,15 +40,6 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
if (!nlmsvc_ops)
return nlm_lck_denied_nolocks;
/* Obtain handle for client host */
if (rqstp->rq_client == NULL) {
printk(KERN_NOTICE
"lockd: unauthenticated request from (%08x:%d)\n",
ntohl(rqstp->rq_addr.sin_addr.s_addr),
ntohs(rqstp->rq_addr.sin_port));
return nlm_lck_denied_nolocks;
}
/* Obtain host handle */
if (!(host = nlmsvc_lookup_host(rqstp))
|| (argp->monitor && !host->h_monitored && nsm_monitor(host) < 0))
......@@ -420,8 +411,9 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
void *resp)
{
struct sockaddr_in saddr = rqstp->rq_addr;
int vers = rqstp->rq_vers;
int prot = rqstp->rq_prot;
int vers = argp->vers;
int prot = argp->proto >> 1;
struct nlm_host *host;
dprintk("lockd: SM_NOTIFY called\n");
......@@ -438,24 +430,20 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
* reclaim all locks we hold on this server.
*/
saddr.sin_addr.s_addr = argp->addr;
if ((argp->proto & 1)==0) {
if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) {
nlmclnt_recovery(host, argp->state);
nlm_release_host(host);
}
} else {
/* If we run on an NFS server, delete all locks held by the client */
if (nlmsvc_ops != NULL) {
struct svc_client *clnt;
saddr.sin_addr.s_addr = argp->addr;
nlmsvc_ops->exp_readlock();
if ((clnt = nlmsvc_ops->exp_getclient(&saddr)) != NULL
&& (host = nlm_lookup_host(clnt, &saddr, 0, 0)) != NULL) {
if ((host = nlm_lookup_host(1, &saddr, prot, vers)) != NULL) {
nlmsvc_free_host_resources(host);
}
nlm_release_host(host);
nlmsvc_ops->exp_unlock();
}
}
return rpc_success;
}
......@@ -527,15 +515,13 @@ nlm4svc_callback_exit(struct rpc_task *task)
struct nlm_void { int dummy; };
#define PROC(name, xargt, xrest, argt, rest, respsize) \
{ (svc_procfunc) nlm4svc_proc_##name, \
(kxdrproc_t) nlm4svc_decode_##xargt, \
(kxdrproc_t) nlm4svc_encode_##xrest, \
NULL, \
sizeof(struct nlm_##argt), \
sizeof(struct nlm_##rest), \
0, \
0, \
respsize, \
{ .pc_func = (svc_procfunc) nlm4svc_proc_##name, \
.pc_decode = (kxdrproc_t) nlm4svc_decode_##xargt, \
.pc_encode = (kxdrproc_t) nlm4svc_encode_##xrest, \
.pc_release = NULL, \
.pc_argsize = sizeof(struct nlm_##argt), \
.pc_ressize = sizeof(struct nlm_##rest), \
.pc_xdrressize = respsize, \
}
#define Ck (1+8) /* cookie */
#define No (1+1024/4) /* netobj */
......
......@@ -69,15 +69,6 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
if (!nlmsvc_ops)
return nlm_lck_denied_nolocks;
/* Obtain handle for client host */
if (rqstp->rq_client == NULL) {
printk(KERN_NOTICE
"lockd: unauthenticated request from (%08x:%d)\n",
ntohl(rqstp->rq_addr.sin_addr.s_addr),
ntohs(rqstp->rq_addr.sin_port));
return nlm_lck_denied_nolocks;
}
/* Obtain host handle */
if (!(host = nlmsvc_lookup_host(rqstp))
|| (argp->monitor && !host->h_monitored && nsm_monitor(host) < 0))
......@@ -448,8 +439,8 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
void *resp)
{
struct sockaddr_in saddr = rqstp->rq_addr;
int vers = rqstp->rq_vers;
int prot = rqstp->rq_prot;
int vers = argp->vers;
int prot = argp->proto >> 1;
struct nlm_host *host;
dprintk("lockd: SM_NOTIFY called\n");
......@@ -466,22 +457,17 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
* reclaim all locks we hold on this server.
*/
saddr.sin_addr.s_addr = argp->addr;
if ((argp->proto & 1)==0) {
if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) {
nlmclnt_recovery(host, argp->state);
nlm_release_host(host);
}
} else {
/* If we run on an NFS server, delete all locks held by the client */
if (nlmsvc_ops != NULL) {
struct svc_client *clnt;
saddr.sin_addr.s_addr = argp->addr;
nlmsvc_ops->exp_readlock();
if ((clnt = nlmsvc_ops->exp_getclient(&saddr)) != NULL
&& (host = nlm_lookup_host(clnt, &saddr, 0, 0)) != NULL) {
if ((host = nlm_lookup_host(1, &saddr, prot, vers)) != NULL) {
nlmsvc_free_host_resources(host);
}
nlm_release_host(host);
nlmsvc_ops->exp_unlock();
}
}
return rpc_success;
......@@ -555,15 +541,13 @@ nlmsvc_callback_exit(struct rpc_task *task)
struct nlm_void { int dummy; };
#define PROC(name, xargt, xrest, argt, rest, respsize) \
{ (svc_procfunc) nlmsvc_proc_##name, \
(kxdrproc_t) nlmsvc_decode_##xargt, \
(kxdrproc_t) nlmsvc_encode_##xrest, \
NULL, \
sizeof(struct nlm_##argt), \
sizeof(struct nlm_##rest), \
0, \
0, \
respsize, \
{ .pc_func = (svc_procfunc) nlmsvc_proc_##name, \
.pc_decode = (kxdrproc_t) nlmsvc_decode_##xargt, \
.pc_encode = (kxdrproc_t) nlmsvc_encode_##xrest, \
.pc_release = NULL, \
.pc_argsize = sizeof(struct nlm_##argt), \
.pc_ressize = sizeof(struct nlm_##rest), \
.pc_xdrressize = respsize, \
}
#define Ck (1+8) /* cookie */
......
......@@ -294,15 +294,13 @@ nlmsvc_free_host_resources(struct nlm_host *host)
}
/*
* Delete a client when the nfsd entry is removed.
* delete all hosts structs for clients
*/
void
nlmsvc_invalidate_client(struct svc_client *clnt)
nlmsvc_invalidate_all(void)
{
struct nlm_host *host;
if ((host = nlm_lookup_host(clnt, NULL, 0, 0)) != NULL) {
dprintk("lockd: invalidating client for %s\n", host->h_name);
while ((host = nlm_find_client()) != NULL) {
nlmsvc_free_host_resources(host);
host->h_expires = 0;
host->h_killed = 1;
......
......@@ -369,6 +369,8 @@ nlmsvc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp)
argp->state = ntohl(*p++);
/* Preserve the address in network byte order */
argp->addr = *p++;
argp->vers = *p++;
argp->proto = *p++;
return xdr_argsize_check(rqstp, p);
}
......@@ -602,15 +604,15 @@ static struct rpc_procinfo nlm_procedures[] = {
};
static struct rpc_version nlm_version1 = {
number: 1,
nrprocs: 16,
procs: nlm_procedures,
.number = 1,
.nrprocs = 16,
.procs = nlm_procedures,
};
static struct rpc_version nlm_version3 = {
number: 3,
nrprocs: 24,
procs: nlm_procedures,
.number = 3,
.nrprocs = 24,
.procs = nlm_procedures,
};
#ifdef CONFIG_LOCKD_V4
......@@ -618,23 +620,21 @@ extern struct rpc_version nlm_version4;
#endif
static struct rpc_version * nlm_versions[] = {
NULL,
&nlm_version1,
NULL,
&nlm_version3,
[1] = &nlm_version1,
[3] = &nlm_version3,
#ifdef CONFIG_LOCKD_V4
&nlm_version4,
[4] = &nlm_version4,
#endif
};
static struct rpc_stat nlm_stats;
struct rpc_program nlm_program = {
name: "lockd",
number: NLM_PROGRAM,
nrvers: sizeof(nlm_versions) / sizeof(nlm_versions[0]),
version: nlm_versions,
stats: &nlm_stats,
.name = "lockd",
.number = NLM_PROGRAM,
.nrvers = sizeof(nlm_versions) / sizeof(nlm_versions[0]),
.version = nlm_versions,
.stats = &nlm_stats,
};
#ifdef LOCKD_DEBUG
......
......@@ -608,7 +608,7 @@ static struct rpc_procinfo nlm4_procedures[] = {
};
struct rpc_version nlm_version4 = {
number: 4,
nrprocs: 24,
procs: nlm4_procedures,
.number = 4,
.nrprocs = 24,
.procs = nlm4_procedures,
};
This diff is collapsed.
......@@ -31,12 +31,19 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size);
fh.fh_export = NULL;
exp_readlock();
rqstp->rq_client = exp_getclient(&rqstp->rq_addr);
if (rqstp->rq_client == NULL)
nfserr = nfserr_stale;
else
nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
if (!nfserr) {
dget(filp->f_dentry);
mntget(filp->f_vfsmnt);
}
fh_put(&fh);
rqstp->rq_client = NULL;
exp_readunlock();
/* nlm and nfsd don't share error codes.
* we invent: 0 = no error
* 1 = stale file handle
......@@ -61,24 +68,10 @@ nlm_fclose(struct file *filp)
}
struct nlmsvc_binding nfsd_nlm_ops = {
.exp_readlock = exp_readlock, /* lock export table for reading */
.exp_unlock = exp_readunlock, /* unlock export table */
.exp_getclient = exp_getclient, /* look up NFS client */
.fopen = nlm_fopen, /* open file for locking */
.fclose = nlm_fclose, /* close file */
.detach = exp_nlmdetach, /* lockd shutdown notification */
};
/*
* When removing an NFS client entry, notify lockd that it is gone.
* FIXME: We should do the same when unexporting an NFS volume.
*/
void
nfsd_lockd_unexport(struct svc_client *clnt)
{
nlmsvc_invalidate_client(clnt);
}
void
nfsd_lockd_init(void)
{
......
......@@ -127,13 +127,30 @@ static struct file_operations reader_ops = {
extern struct seq_operations nfs_exports_op;
static int exports_open(struct inode *inode, struct file *file)
{
return seq_open(file, &nfs_exports_op);
int res;
res = seq_open(file, &nfs_exports_op);
if (!res) {
char *namebuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (namebuf == NULL)
res = -ENOMEM;
else
((struct seq_file *)file->private_data)->private = namebuf;
}
return res;
}
static int exports_release(struct inode *inode, struct file *file)
{
struct seq_file *m = (struct seq_file *)file->private_data;
kfree(m->private);
m->private = NULL;
return seq_release(inode, file);
}
static struct file_operations exports_operations = {
.open = exports_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
.release = exports_release,
};
/*
......
......@@ -97,14 +97,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
rqstp->rq_reffh = fh;
if (!fhp->fh_dentry) {
dev_t xdev = 0;
ino_t xino = 0;
__u32 *datap=NULL;
__u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */
int fileid_type;
int data_left = fh->fh_size/4;
int nfsdev;
int fsid = 0;
error = nfserr_stale;
if (rqstp->rq_vers > 2)
......@@ -113,6 +109,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
return nfserr_nofilehandle;
if (fh->fh_version == 1) {
int len;
datap = fh->fh_auth;
if (--data_left<0) goto out;
switch (fh->fh_auth_type) {
......@@ -122,39 +119,37 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
switch (fh->fh_fsid_type) {
case 0:
if ((data_left-=2)<0) goto out;
nfsdev = ntohl(*datap++);
xdev = MKDEV(nfsdev>>16, nfsdev&0xFFFF);
xino = *datap++;
len = 2;
break;
case 1:
if ((data_left-=1)<0) goto out;
fsid = *datap++;
len = 1;
break;
default:
goto out;
}
if ((data_left -= len)<0) goto out;
exp = exp_find(rqstp->rq_client, fh->fh_fsid_type, datap);
datap += len;
} else {
dev_t xdev;
ino_t xino;
if (fh->fh_size != NFS_FHSIZE)
goto out;
/* assume old filehandle format */
xdev = u32_to_dev_t(fh->ofh_xdev);
xino = u32_to_ino_t(fh->ofh_xino);
mk_fsid_v0(tfh, xdev, xino);
exp = exp_find(rqstp->rq_client, 0, tfh);
}
/*
* Look up the export entry.
*/
error = nfserr_stale;
if (fh->fh_version == 1 && fh->fh_fsid_type == 1)
exp = exp_get_fsid(rqstp->rq_client, fsid);
else
exp = exp_get(rqstp->rq_client, xdev, xino);
if (!exp) {
if (!exp)
/* export entry revoked */
goto out;
}
/* Check if the request originated from a secure port. */
error = nfserr_perm;
......@@ -322,9 +317,11 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
struct inode * inode = dentry->d_inode;
struct dentry *parent = dentry->d_parent;
__u32 *datap;
dev_t ex_dev = exp->ex_dentry->d_inode->i_sb->s_dev;
dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n",
MAJOR(exp->ex_dev), MINOR(exp->ex_dev), (long) exp->ex_ino,
MAJOR(ex_dev), MINOR(ex_dev),
(long) exp->ex_dentry->d_inode->i_ino,
parent->d_name.name, dentry->d_name.name,
(inode ? inode->i_ino : 0));
......@@ -351,9 +348,9 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE);
fhp->fh_handle.fh_size = NFS_FHSIZE;
fhp->fh_handle.ofh_dcookie = 0xfeebbaca;
fhp->fh_handle.ofh_dev = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
fhp->fh_handle.ofh_dev = htonl((MAJOR(ex_dev)<<16)| MINOR(ex_dev));
fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev;
fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_ino);
fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_dentry->d_inode->i_ino);
fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry));
if (inode)
_fh_update_old(dentry, exp, &fhp->fh_handle);
......@@ -365,13 +362,14 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
(ref_fh_fsid_type == 1)) {
fhp->fh_handle.fh_fsid_type = 1;
/* fsid_type 1 == 4 bytes filesystem id */
*datap++ = exp->ex_fsid;
mk_fsid_v1(datap, exp->ex_fsid);
datap += 1;
fhp->fh_handle.fh_size = 2*4;
} else {
fhp->fh_handle.fh_fsid_type = 0;
/* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */
*datap++ = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
*datap++ = ino_t_to_u32(exp->ex_ino);
mk_fsid_v0(datap, ex_dev, exp->ex_dentry->d_inode->i_ino);
datap += 2;
fhp->fh_handle.fh_size = 3*4;
}
if (inode) {
......
......@@ -119,24 +119,24 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
else {
/* checking mountpoint crossing is very different when stepping up */
struct svc_export *exp2 = NULL;
struct dentry *dp, *old;
struct dentry *dp;
struct vfsmount *mnt = mntget(exp->ex_mnt);
dentry = dget(dparent);
while(follow_up(&mnt, &dentry))
;
old = dentry;
read_lock(&dparent_lock);
dp = dentry->d_parent;
for ( ; !exp2 && dp->d_parent != dp; dp=dp->d_parent)
exp2 = exp_get_by_name(exp->ex_client, mnt, dp);
dp = dget(dentry->d_parent);
read_unlock(&dparent_lock);
dput(dentry);
dentry = dp;
exp2 = exp_parent(exp->ex_client, mnt, dentry);
if (!exp2) {
dput(dentry);
dentry = dget(dparent);
} else {
dget(dentry->d_parent);
exp = exp2;
}
read_unlock(&dparent_lock);
dput(old);
mntput(mnt);
}
} else {
......
......@@ -19,14 +19,10 @@ struct svc_client; /* opaque type */
* This is the set of functions for lockd->nfsd communication
*/
struct nlmsvc_binding {
void (*exp_readlock)(void);
void (*exp_unlock)(void);
struct svc_client * (*exp_getclient)(struct sockaddr_in *);
u32 (*fopen)(struct svc_rqst *,
struct nfs_fh *,
struct file *);
void (*fclose)(struct file *);
void (*detach)(void);
};
extern struct nlmsvc_binding * nlmsvc_ops;
......@@ -34,7 +30,6 @@ extern struct nlmsvc_binding * nlmsvc_ops;
/*
* Functions exported by the lockd module
*/
extern void nlmsvc_invalidate_client(struct svc_client *clnt);
extern int nlmclnt_proc(struct inode *, int, struct file_lock *);
extern int lockd_up(void);
extern void lockd_down(void);
......
......@@ -39,13 +39,13 @@
struct nlm_host {
struct nlm_host * h_next; /* linked list (hash table) */
struct sockaddr_in h_addr; /* peer address */
struct svc_client * h_exportent; /* NFS client */
struct rpc_clnt * h_rpcclnt; /* RPC client to talk to peer */
char h_name[20]; /* remote hostname */
u32 h_version; /* interface version */
unsigned short h_proto; /* transport proto */
unsigned short h_authflavor; /* RPC authentication type */
unsigned short h_reclaiming : 1,
h_server : 1, /* server side, not client side */
h_inuse : 1,
h_killed : 1,
h_monitored : 1;
......@@ -143,13 +143,14 @@ void nlmclnt_freegrantargs(struct nlm_rqst *);
*/
struct nlm_host * nlmclnt_lookup_host(struct sockaddr_in *, int, int);
struct nlm_host * nlmsvc_lookup_host(struct svc_rqst *);
struct nlm_host * nlm_lookup_host(struct svc_client *,
struct sockaddr_in *, int, int);
struct nlm_host * nlm_lookup_host(int server, struct sockaddr_in *, int, int);
struct rpc_clnt * nlm_bind_host(struct nlm_host *);
void nlm_rebind_host(struct nlm_host *);
struct nlm_host * nlm_get_host(struct nlm_host *);
void nlm_release_host(struct nlm_host *);
void nlm_shutdown_hosts(void);
extern struct nlm_host *nlm_find_client(void);
/*
* Server-side lock handling
......@@ -173,6 +174,7 @@ u32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
void nlm_release_file(struct nlm_file *);
void nlmsvc_mark_resources(void);
void nlmsvc_free_host_resources(struct nlm_host *);
void nlmsvc_invalidate_all(void);
static __inline__ struct inode *
nlmsvc_file_inode(struct nlm_file *file)
......
......@@ -28,6 +28,7 @@ struct nsm_args {
u32 prog; /* RPC callback info */
u32 vers;
u32 proc;
u32 proto; /* protocol (udp/tcp) plus server/client flag */
};
/*
......
......@@ -76,6 +76,8 @@ struct nlm_reboot {
int len;
u32 state;
u32 addr;
u32 vers;
u32 proto;
};
/*
......
......@@ -23,23 +23,5 @@
*/
void nfsd_setuser(struct svc_rqst *, struct svc_export *);
#if 0
/*
* These must match the actual size of uid_t and gid_t
*/
#define UGID_BITS (8 * sizeof(uid_t))
#define UGID_SHIFT 8
#define UGID_MASK ((1 << UGID_SHIFT) - 1)
#define UGID_NRENTRIES ((1 << (UGID_BITS - UGID_SHIFT)) + 1)
#define UGID_NONE ((unsigned short)-1)
typedef struct svc_uidmap {
uid_t * um_ruid[UGID_NRENTRIES];
uid_t * um_luid[UGID_NRENTRIES];
gid_t * um_rgid[UGID_NRENTRIES];
gid_t * um_lgid[UGID_NRENTRIES];
} svc_uidmap;
#endif
#endif /* __KERNEL__ */
#endif /* LINUX_NFSD_AUTH_H */
......@@ -45,38 +45,36 @@
#ifdef __KERNEL__
/* The following are hashtable sizes and must be powers of 2 */
#define NFSCLNT_EXPMAX 16
struct svc_client {
struct svc_client * cl_next;
char cl_ident[NFSCLNT_IDMAX];
int cl_idlen;
int cl_naddr;
struct in_addr cl_addr[NFSCLNT_ADDRMAX];
struct svc_uidmap * cl_umap;
struct list_head cl_export[NFSCLNT_EXPMAX];
struct list_head cl_expfsid[NFSCLNT_EXPMAX];
struct list_head cl_list;
};
struct svc_export {
struct list_head ex_hash;
struct list_head ex_fsid_hash;
struct list_head ex_list;
char ex_path[NFS_MAXPATHLEN+1];
struct svc_export * ex_parent;
struct svc_client * ex_client;
int ex_flags;
struct vfsmount * ex_mnt;
struct dentry * ex_dentry;
dev_t ex_dev;
ino_t ex_ino;
uid_t ex_anon_uid;
gid_t ex_anon_gid;
int ex_fsid;
};
/* an "export key" (expkey) maps a filehandlefragement to an
* svc_export for a given client. There can be two per export, one
* for type 0 (dev/ino), one for type 1 (fsid)
*/
struct svc_expkey {
struct list_head ek_hash;
struct svc_client *ek_client;
int ek_fsidtype;
u32 ek_fsid[2];
struct svc_export *ek_export;
};
#define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC))
#define EX_RDONLY(exp) ((exp)->ex_flags & NFSEXP_READONLY)
......@@ -94,16 +92,25 @@ void exp_readlock(void);
void exp_readunlock(void);
struct svc_client * exp_getclient(struct sockaddr_in *sin);
void exp_putclient(struct svc_client *clp);
struct svc_export * exp_get(struct svc_client *clp, dev_t dev, ino_t ino);
struct svc_export * exp_get_fsid(struct svc_client *clp, int fsid);
struct svc_expkey * exp_find_key(struct svc_client *clp, int fsid_type, u32 *fsidv);
struct svc_export * exp_get_by_name(struct svc_client *clp,
struct vfsmount *mnt,
struct dentry *dentry);
struct svc_export * exp_parent(struct svc_client *clp, struct vfsmount *mnt,
struct dentry *dentry);
int exp_rootfh(struct svc_client *,
char *path, struct knfsd_fh *, int maxsize);
int nfserrno(int errno);
void exp_nlmdetach(void);
static inline struct svc_export *
exp_find(struct svc_client *clp, int fsid_type, u32 *fsidv)
{
struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv);
if (ek)
return ek->ek_export;
else
return NULL;
}
#endif /* __KERNEL__ */
......
......@@ -199,6 +199,19 @@ typedef struct svc_fh {
} svc_fh;
static inline void mk_fsid_v0(u32 *fsidv, dev_t dev, ino_t ino)
{
fsidv[0] = htonl((MAJOR(dev)<<16) |
MINOR(dev));
fsidv[1] = ino_t_to_u32(ino);
}
static inline void mk_fsid_v1(u32 *fsidv, u32 fsid)
{
fsidv[0] = fsid;
}
/*
* Shorthand for dprintk()'s
*/
......
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