Commit df38421d authored by Kai Germaschewski's avatar Kai Germaschewski

Hand merged.

parents be5178be 44a706d5
......@@ -69,7 +69,9 @@ void generic_set_mtrr(unsigned int reg, unsigned long base,
{
u32 cr0, cr4 = 0;
u32 deftype_lo, deftype_hi;
static spinlock_t set_atomicity_lock = SPIN_LOCK_UNLOCKED;
spin_lock(&set_atomicity_lock);
/* Save value of CR4 and clear Page Global Enable (bit 7) */
if ( cpu_has_pge ) {
cr4 = read_cr4();
......@@ -112,6 +114,7 @@ void generic_set_mtrr(unsigned int reg, unsigned long base,
/* Restore value of CR4 */
if ( cpu_has_pge )
write_cr4(cr4);
spin_unlock(&set_atomicity_lock);
}
int generic_validate_add_page(unsigned long base, unsigned long size, unsigned int type)
......
......@@ -184,7 +184,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
* If we're in an interrupt, have no user context or are running in an
* atomic region then we must not take the fault..
*/
if (preempt_count() || !mm)
if (in_atomic() || !mm)
goto no_context;
down_read(&mm->mmap_sem);
......
......@@ -55,12 +55,12 @@ static int linear_run (mddev_t *mddev)
int j = rdev->raid_disk;
dev_info_t *disk = conf->disks + j;
if (j < 0 || j > mddev->raid_disks || disk->bdev) {
if (j < 0 || j > mddev->raid_disks || disk->rdev) {
printk("linear: disk numbering problem. Aborting!\n");
goto out;
}
disk->bdev = rdev->bdev;
disk->rdev = rdev;
disk->size = rdev->size;
if (!conf->smallest || (disk->size < conf->smallest->size))
......@@ -153,11 +153,11 @@ static int linear_make_request (request_queue_t *q, struct bio *bio)
if (block >= (tmp_dev->size + tmp_dev->offset)
|| block < tmp_dev->offset) {
printk ("linear_make_request: Block %ld out of bounds on dev %s size %ld offset %ld\n", block, bdevname(tmp_dev->bdev), tmp_dev->size, tmp_dev->offset);
printk ("linear_make_request: Block %ld out of bounds on dev %s size %ld offset %ld\n", block, bdevname(tmp_dev->rdev->bdev), tmp_dev->size, tmp_dev->offset);
bio_io_error(bio);
return 0;
}
bio->bi_bdev = tmp_dev->bdev;
bio->bi_bdev = tmp_dev->rdev->bdev;
bio->bi_sector = bio->bi_sector - (tmp_dev->offset << 1);
return 1;
......@@ -176,11 +176,11 @@ static int linear_status (char *page, mddev_t *mddev)
for (j = 0; j < conf->nr_zones; j++)
{
sz += sprintf(page+sz, "[%s",
bdev_partition_name(conf->hash_table[j].dev0->bdev));
bdev_partition_name(conf->hash_table[j].dev0->rdev->bdev));
if (conf->hash_table[j].dev1)
sz += sprintf(page+sz, "/%s] ",
bdev_partition_name(conf->hash_table[j].dev1->bdev));
bdev_partition_name(conf->hash_table[j].dev1->rdev->bdev));
else
sz += sprintf(page+sz, "] ");
}
......
This diff is collapsed.
......@@ -70,7 +70,7 @@ static void mp_pool_free(void *mpb, void *data)
kfree(mpb);
}
static int multipath_map (mddev_t *mddev, struct block_device **bdev)
static int multipath_map (mddev_t *mddev, mdk_rdev_t **rdevp)
{
multipath_conf_t *conf = mddev_to_conf(mddev);
int i, disks = MD_SB_DISKS;
......@@ -80,12 +80,17 @@ static int multipath_map (mddev_t *mddev, struct block_device **bdev)
* now we use the first available disk.
*/
spin_lock_irq(&conf->device_lock);
for (i = 0; i < disks; i++) {
if (conf->multipaths[i].operational) {
*bdev = conf->multipaths[i].bdev;
return (0);
mdk_rdev_t *rdev = conf->multipaths[i].rdev;
if (rdev && rdev->in_sync) {
*rdevp = rdev;
atomic_inc(&rdev->nr_pending);
spin_unlock_irq(&conf->device_lock);
return 0;
}
}
spin_unlock_irq(&conf->device_lock);
printk (KERN_ERR "multipath_map(): no more operational IO paths?\n");
return (-1);
......@@ -126,21 +131,21 @@ void multipath_end_request(struct bio *bio)
{
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
struct multipath_bh * mp_bh = (struct multipath_bh *)(bio->bi_private);
multipath_conf_t *conf;
struct block_device *bdev;
if (uptodate) {
multipath_conf_t *conf = mddev_to_conf(mp_bh->mddev);
mdk_rdev_t *rdev = conf->multipaths[mp_bh->path].rdev;
if (uptodate)
multipath_end_bh_io(mp_bh, uptodate);
return;
}
else {
/*
* oops, IO error:
*/
conf = mddev_to_conf(mp_bh->mddev);
bdev = conf->multipaths[mp_bh->path].bdev;
md_error (mp_bh->mddev, bdev);
md_error (mp_bh->mddev, rdev);
printk(KERN_ERR "multipath: %s: rescheduling sector %lu\n",
bdev_partition_name(bdev), bio->bi_sector);
bdev_partition_name(rdev->bdev), bio->bi_sector);
multipath_reschedule_retry(mp_bh);
}
atomic_dec(&rdev->nr_pending);
return;
}
......@@ -153,9 +158,11 @@ static int multipath_read_balance (multipath_conf_t *conf)
{
int disk;
for (disk = 0; disk < MD_SB_DISKS; disk++)
if (conf->multipaths[disk].operational)
for (disk = 0; disk < MD_SB_DISKS; disk++) {
mdk_rdev_t *rdev = conf->multipaths[disk].rdev;
if (rdev && rdev->in_sync)
return disk;
}
BUG();
return 0;
}
......@@ -175,11 +182,14 @@ static int multipath_make_request (request_queue_t *q, struct bio * bio)
/*
* read balancing logic:
*/
spin_lock_irq(&conf->device_lock);
mp_bh->path = multipath_read_balance(conf);
multipath = conf->multipaths + mp_bh->path;
atomic_inc(&multipath->rdev->nr_pending);
spin_unlock_irq(&conf->device_lock);
mp_bh->bio = *bio;
mp_bh->bio.bi_bdev = multipath->bdev;
mp_bh->bio.bi_bdev = multipath->rdev->bdev;
mp_bh->bio.bi_end_io = multipath_end_request;
mp_bh->bio.bi_private = mp_bh;
generic_make_request(&mp_bh->bio);
......@@ -195,7 +205,8 @@ static int multipath_status (char *page, mddev_t *mddev)
conf->working_disks);
for (i = 0; i < conf->raid_disks; i++)
sz += sprintf (page+sz, "%s",
conf->multipaths[i].operational ? "U" : "_");
conf->multipaths[i].rdev &&
conf->multipaths[i].rdev->in_sync ? "U" : "_");
sz += sprintf (page+sz, "]");
return sz;
}
......@@ -210,28 +221,13 @@ static int multipath_status (char *page, mddev_t *mddev)
"multipath: IO failure on %s, disabling IO path. \n" \
" Operation continuing on %d IO paths.\n"
static void mark_disk_bad (mddev_t *mddev, int failed)
{
multipath_conf_t *conf = mddev_to_conf(mddev);
struct multipath_info *multipath = conf->multipaths+failed;
multipath->operational = 0;
mddev->sb_dirty = 1;
conf->working_disks--;
printk (DISK_FAILED, bdev_partition_name (multipath->bdev),
conf->working_disks);
}
/*
* Careful, this can execute in IRQ contexts as well!
*/
static int multipath_error (mddev_t *mddev, struct block_device *bdev)
static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev)
{
multipath_conf_t *conf = mddev_to_conf(mddev);
struct multipath_info * multipaths = conf->multipaths;
int disks = MD_SB_DISKS;
int i;
if (conf->working_disks <= 1) {
/*
......@@ -239,24 +235,21 @@ static int multipath_error (mddev_t *mddev, struct block_device *bdev)
* first check if this is a queued request for a device
* which has just failed.
*/
for (i = 0; i < disks; i++) {
if (multipaths[i].bdev == bdev && !multipaths[i].operational)
return 0;
}
printk (LAST_DISK);
return 1; /* leave it active... it's all we have */
/* leave it active... it's all we have */
} else {
/*
* Mark disk as unusable
*/
for (i = 0; i < disks; i++) {
if (multipaths[i].bdev == bdev && multipaths[i].operational) {
mark_disk_bad(mddev, i);
break;
}
if (!rdev->faulty) {
rdev->in_sync = 0;
rdev->faulty = 1;
mddev->sb_dirty = 1;
conf->working_disks--;
printk (DISK_FAILED, bdev_partition_name (rdev->bdev),
conf->working_disks);
}
}
return 0;
}
#undef LAST_DISK
......@@ -279,11 +272,10 @@ static void print_multipath_conf (multipath_conf_t *conf)
for (i = 0; i < MD_SB_DISKS; i++) {
tmp = conf->multipaths + i;
if (tmp->operational || tmp->used_slot)
printk(" disk%d, o:%d, us:%d dev:%s\n",
i,tmp->operational,
tmp->used_slot,
bdev_partition_name(tmp->bdev));
if (tmp->rdev)
printk(" disk%d, o:%d, dev:%s\n",
i,!tmp->rdev->faulty,
bdev_partition_name(tmp->rdev->bdev));
}
}
......@@ -291,24 +283,23 @@ static void print_multipath_conf (multipath_conf_t *conf)
static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
{
multipath_conf_t *conf = mddev->private;
int err = 1;
struct multipath_info *p = conf->multipaths + rdev->raid_disk;
int found = 0;
int path;
struct multipath_info *p;
print_multipath_conf(conf);
spin_lock_irq(&conf->device_lock);
if (!p->used_slot) {
p->bdev = rdev->bdev;
p->operational = 1;
p->used_slot = 1;
for (path=0; path<mddev->raid_disks; path++)
if ((p=conf->multipaths+path)->rdev == NULL) {
p->rdev = rdev;
conf->working_disks++;
err = 0;
rdev->raid_disk = path;
found = 1;
}
if (err)
MD_BUG();
spin_unlock_irq(&conf->device_lock);
print_multipath_conf(conf);
return err;
return found;
}
static int multipath_remove_disk(mddev_t *mddev, int number)
......@@ -320,14 +311,14 @@ static int multipath_remove_disk(mddev_t *mddev, int number)
print_multipath_conf(conf);
spin_lock_irq(&conf->device_lock);
if (p->used_slot) {
if (p->operational) {
if (p->rdev) {
if (p->rdev->in_sync ||
atomic_read(&p->rdev->nr_pending)) {
printk(KERN_ERR "hot-remove-disk, slot %d is identified but is still operational!\n", number);
err = -EBUSY;
goto abort;
}
p->bdev = NULL;
p->used_slot = 0;
p->rdev = NULL;
err = 0;
}
if (err)
......@@ -359,7 +350,7 @@ static void multipathd (void *data)
struct bio *bio;
unsigned long flags;
mddev_t *mddev;
struct block_device *bdev;
mdk_rdev_t *rdev;
for (;;) {
spin_lock_irqsave(&retry_list_lock, flags);
......@@ -372,16 +363,16 @@ static void multipathd (void *data)
mddev = mp_bh->mddev;
bio = &mp_bh->bio;
bio->bi_sector = mp_bh->master_bio->bi_sector;
bdev = bio->bi_bdev;
multipath_map (mddev, &bio->bi_bdev);
if (bio->bi_bdev == bdev) {
rdev = NULL;
if (multipath_map (mddev, &rdev)<0) {
printk(IO_ERROR,
bdev_partition_name(bio->bi_bdev), bio->bi_sector);
multipath_end_bh_io(mp_bh, 0);
} else {
printk(REDIRECT_SECTOR,
bdev_partition_name(bio->bi_bdev), bio->bi_sector);
bio->bi_bdev = rdev->bdev;
generic_make_request(bio);
}
}
......@@ -436,7 +427,6 @@ static int multipath_run (mddev_t *mddev)
struct multipath_info *disk;
mdk_rdev_t *rdev;
struct list_head *tmp;
int num_rdevs = 0;
MOD_INC_USE_COUNT;
......@@ -458,40 +448,20 @@ static int multipath_run (mddev_t *mddev)
}
memset(conf, 0, sizeof(*conf));
conf->working_disks = 0;
ITERATE_RDEV(mddev,rdev,tmp) {
if (rdev->faulty) {
/* this is a "should never happen" case and if it */
/* ever does happen, a continue; won't help */
printk(ERRORS, bdev_partition_name(rdev->bdev));
continue;
} else {
/* this is a "should never happen" case and if it */
/* ever does happen, a continue; won't help */
if (!rdev->sb) {
MD_BUG();
continue;
}
}
if (rdev->desc_nr == -1) {
MD_BUG();
disk_idx = rdev->raid_disk;
if (disk_idx < 0 ||
disk_idx >= mddev->raid_disks)
continue;
}
disk_idx = rdev->raid_disk;
disk = conf->multipaths + disk_idx;
/*
* Mark all disks as active to start with, there are no
* spares. multipath_read_balance deals with choose
* the "best" operational device.
*/
disk->bdev = rdev->bdev;
disk->operational = 1;
disk->used_slot = 1;
num_rdevs++;
disk->rdev = rdev;
if (!rdev->faulty)
conf->working_disks++;
}
conf->raid_disks = mddev->raid_disks = num_rdevs;
conf->raid_disks = mddev->raid_disks;
mddev->sb_dirty = 1;
conf->mddev = mddev;
conf->device_lock = SPIN_LOCK_UNLOCKED;
......@@ -500,6 +470,7 @@ static int multipath_run (mddev_t *mddev)
printk(NONE_OPERATIONAL, mdidx(mddev));
goto out_free_conf;
}
mddev->degraded = conf->raid_disks = conf->working_disks;
conf->pool = mempool_create(NR_RESERVED_BUFS,
mp_pool_alloc, mp_pool_free,
......
......@@ -87,7 +87,7 @@ static int create_strip_zones (mddev_t *mddev)
cnt = 0;
smallest = NULL;
ITERATE_RDEV(mddev, rdev1, tmp1) {
int j = rdev1->sb->this_disk.raid_disk;
int j = rdev1->raid_disk;
if (j < 0 || j >= mddev->raid_disks) {
printk("raid0: bad disk number %d - aborting!\n", j);
......
This diff is collapsed.
This diff is collapsed.
......@@ -16,3 +16,4 @@ if [ "$CONFIG_DEV_APPLETALK" = "y" ]; then
bool ' Appletalk-IP to IP Decapsulation support' CONFIG_IPDDP_DECAP
fi
fi
......@@ -134,7 +134,7 @@ nfsd3_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp,
fh_copy(&resp->fh, &argp->fh);
resp->access = argp->access;
nfserr = nfsd_access(rqstp, &resp->fh, &resp->access);
nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
RETURN_STATUS(nfserr);
}
......@@ -267,7 +267,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
/* Now create the file and set attributes */
nfserr = nfsd_create_v3(rqstp, dirfhp, argp->name, argp->len,
attr, newfhp,
argp->createmode, argp->verf);
argp->createmode, argp->verf, NULL);
RETURN_STATUS(nfserr);
}
......@@ -460,7 +460,7 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t) argp->cookie,
nfs3svc_encode_entry,
buffer, &count, argp->verf);
buffer, &count, argp->verf, NULL);
memcpy(resp->verf, argp->verf, 8);
resp->count = count;
......@@ -495,7 +495,7 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t) argp->cookie,
nfs3svc_encode_entry_plus,
buffer, &count, argp->verf);
buffer, &count, argp->verf, NULL);
memcpy(resp->verf, argp->verf, 8);
resp->count = count;
......
......@@ -107,8 +107,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
int fsid = 0;
error = nfserr_stale;
if (rqstp->rq_vers == 3)
if (rqstp->rq_vers > 2)
error = nfserr_badhandle;
if (rqstp->rq_vers == 4 && fh->fh_size == 0)
return nfserr_nofilehandle;
if (fh->fh_version == 1) {
datap = fh->fh_auth;
......@@ -171,7 +173,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
* Look up the dentry using the NFS file handle.
*/
error = nfserr_stale;
if (rqstp->rq_vers == 3)
if (rqstp->rq_vers > 2)
error = nfserr_badhandle;
if (fh->fh_version != 1) {
......@@ -234,11 +236,23 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
/* Type can be negative when creating hardlinks - not to a dir */
if (type > 0 && (inode->i_mode & S_IFMT) != type) {
error = (type == S_IFDIR)? nfserr_notdir : nfserr_isdir;
if (rqstp->rq_vers == 4 && (inode->i_mode & S_IFMT) == S_IFLNK)
error = nfserr_symlink;
else if (type == S_IFDIR)
error = nfserr_notdir;
else if ((inode->i_mode & S_IFMT) == S_IFDIR)
error = nfserr_isdir;
else
error = nfserr_inval;
goto out;
}
if (type < 0 && (inode->i_mode & S_IFMT) == -type) {
error = (type == -S_IFDIR)? nfserr_notdir : nfserr_isdir;
if (rqstp->rq_vers == 4 && (inode->i_mode & S_IFMT) == S_IFLNK)
error = nfserr_symlink;
else if (type == -S_IFDIR)
error = nfserr_isdir;
else
error = nfserr_notdir;
goto out;
}
......@@ -303,6 +317,8 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
*
*/
u8 ref_fh_version = 0;
u8 ref_fh_fsid_type = 0;
struct inode * inode = dentry->d_inode;
struct dentry *parent = dentry->d_parent;
__u32 *datap;
......@@ -312,6 +328,13 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
parent->d_name.name, dentry->d_name.name,
(inode ? inode->i_ino : 0));
if (ref_fh) {
ref_fh_version = ref_fh->fh_handle.fh_version;
ref_fh_fsid_type = ref_fh->fh_handle.fh_fsid_type;
if (ref_fh == fhp)
fh_put(ref_fh);
}
if (fhp->fh_locked || fhp->fh_dentry) {
printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n",
parent->d_name.name, dentry->d_name.name);
......@@ -323,8 +346,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
fhp->fh_dentry = dentry; /* our internal copy */
fhp->fh_export = exp;
if (ref_fh &&
ref_fh->fh_handle.fh_version == 0xca) {
if (ref_fh_version == 0xca) {
/* old style filehandle please */
memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE);
fhp->fh_handle.fh_size = NFS_FHSIZE;
......@@ -340,7 +362,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
fhp->fh_handle.fh_auth_type = 0;
datap = fhp->fh_handle.fh_auth+0;
if ((exp->ex_flags & NFSEXP_FSID) &&
(!ref_fh || ref_fh->fh_handle.fh_fsid_type == 1)) {
(ref_fh_fsid_type == 1)) {
fhp->fh_handle.fh_fsid_type = 1;
/* fsid_type 1 == 4 bytes filesystem id */
*datap++ = exp->ex_fsid;
......@@ -424,6 +446,10 @@ fh_put(struct svc_fh *fhp)
fh_unlock(fhp);
fhp->fh_dentry = NULL;
dput(dentry);
#ifdef CONFIG_NFSD_V3
fhp->fh_pre_saved = 0;
fhp->fh_post_saved = 0;
#endif
nfsd_nr_put++;
}
return;
......
......@@ -492,7 +492,7 @@ nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp,
/* Read directory and encode entries on the fly */
nfserr = nfsd_readdir(rqstp, &argp->fh, (loff_t) argp->cookie,
nfssvc_encode_entry,
buffer, &count, NULL);
buffer, &count, NULL, NULL);
resp->count = count;
fh_put(&argp->fh);
......
......@@ -348,12 +348,12 @@ static struct accessmap nfs3_anyaccess[] = {
};
int
nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access)
nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *supported)
{
struct accessmap *map;
struct svc_export *export;
struct dentry *dentry;
u32 query, result = 0;
u32 query, result = 0, sresult = 0;
unsigned int error;
error = fh_verify(rqstp, fhp, 0, MAY_NOP);
......@@ -375,6 +375,9 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access)
for (; map->access; map++) {
if (map->access & query) {
unsigned int err2;
sresult |= map->access;
err2 = nfsd_permission(export, dentry, map->how);
switch (err2) {
case nfs_ok:
......@@ -395,6 +398,8 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access)
}
}
*access = result;
if (supported)
*supported = sresult;
out:
return error;
......@@ -756,6 +761,9 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
struct file file;
int err;
if ((u64)count > ~(u64)offset)
return nfserr_inval;
if ((err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file)) != 0)
return err;
if (EX_ISSYNC(fhp->fh_export)) {
......@@ -904,7 +912,8 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
int
nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
char *fname, int flen, struct iattr *iap,
struct svc_fh *resfhp, int createmode, u32 *verifier)
struct svc_fh *resfhp, int createmode, u32 *verifier,
int *truncp)
{
struct dentry *dentry, *dchild;
struct inode *dirp;
......@@ -966,6 +975,16 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
case NFS3_CREATE_UNCHECKED:
if (! S_ISREG(dchild->d_inode->i_mode))
err = nfserr_exist;
else if (truncp) {
/* in nfsv4, we need to treat this case a little
* differently. we don't want to truncate the
* file now; this would be wrong if the OPEN
* fails for some other reason. furthermore,
* if the size is nonzero, we should ignore it
* according to spec!
*/
*truncp = (iap->ia_valid & ATTR_SIZE) && !iap->ia_size;
}
else {
iap->ia_valid &= ATTR_SIZE;
goto set_attr;
......@@ -1326,6 +1345,9 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
goto out;
}
if (!type)
type = rdentry->d_inode->i_mode & S_IFMT;
if (type != S_IFDIR) { /* It's UNLINK */
#ifdef MSNFS
if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
......@@ -1359,7 +1381,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
*/
int
nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
encode_dent_fn func, u32 *buffer, int *countp, u32 *verf)
encode_dent_fn func, u32 *buffer, int *countp, u32 *verf, u32 *bmval)
{
u32 *p;
int oldlen, eof, err;
......@@ -1380,6 +1402,10 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
cd.buffer = buffer;
cd.buflen = *countp; /* count of words */
cd.dirfh = fhp;
if (bmval) {
cd.bmval[0] = bmval[0];
cd.bmval[1] = bmval[1];
}
/*
* Read the directory entries. This silly loop is necessary because
......@@ -1395,13 +1421,20 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
if (err < 0)
goto out_nfserr;
err = cd.nfserr;
if (err)
goto out_close;
} while (oldlen != cd.buflen && !cd.eob);
err = nfserr_readdir_nospc;
if (rqstp->rq_vers == 4 && cd.eob && cd.buffer == buffer)
goto out_close;
/* If we didn't fill the buffer completely, we're at EOF */
eof = !cd.eob;
if (cd.offset) {
if (rqstp->rq_vers == 3)
if (rqstp->rq_vers > 2)
(void)xdr_encode_hyper(cd.offset, file.f_pos);
else
*cd.offset = htonl(file.f_pos);
......
......@@ -77,8 +77,10 @@ typedef struct {
#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
#if CONFIG_PREEMPT
# define in_atomic() (preempt_count() != kernel_locked())
# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
#else
# define in_atomic() (preempt_count() != 0)
# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
#endif
#define irq_exit() \
......
......@@ -39,39 +39,68 @@
* standard, but seem to be widely used nevertheless.
*/
enum nfs_stat {
NFS_OK = 0, /* v2 v3 */
NFSERR_PERM = 1, /* v2 v3 */
NFSERR_NOENT = 2, /* v2 v3 */
NFSERR_IO = 5, /* v2 v3 */
NFSERR_NXIO = 6, /* v2 v3 */
NFS_OK = 0, /* v2 v3 v4 */
NFSERR_PERM = 1, /* v2 v3 v4 */
NFSERR_NOENT = 2, /* v2 v3 v4 */
NFSERR_IO = 5, /* v2 v3 v4 */
NFSERR_NXIO = 6, /* v2 v3 v4 */
NFSERR_EAGAIN = 11, /* v2 v3 */
NFSERR_ACCES = 13, /* v2 v3 */
NFSERR_EXIST = 17, /* v2 v3 */
NFSERR_XDEV = 18, /* v3 */
NFSERR_NODEV = 19, /* v2 v3 */
NFSERR_NOTDIR = 20, /* v2 v3 */
NFSERR_ISDIR = 21, /* v2 v3 */
NFSERR_INVAL = 22, /* v2 v3 that Sun forgot */
NFSERR_FBIG = 27, /* v2 v3 */
NFSERR_NOSPC = 28, /* v2 v3 */
NFSERR_ROFS = 30, /* v2 v3 */
NFSERR_MLINK = 31, /* v3 */
NFSERR_ACCES = 13, /* v2 v3 v4 */
NFSERR_EXIST = 17, /* v2 v3 v4 */
NFSERR_XDEV = 18, /* v3 v4 */
NFSERR_NODEV = 19, /* v2 v3 v4 */
NFSERR_NOTDIR = 20, /* v2 v3 v4 */
NFSERR_ISDIR = 21, /* v2 v3 v4 */
NFSERR_INVAL = 22, /* v2 v3 v4 */
NFSERR_FBIG = 27, /* v2 v3 v4 */
NFSERR_NOSPC = 28, /* v2 v3 v4 */
NFSERR_ROFS = 30, /* v2 v3 v4 */
NFSERR_MLINK = 31, /* v3 v4 */
NFSERR_OPNOTSUPP = 45, /* v2 v3 */
NFSERR_NAMETOOLONG = 63, /* v2 v3 */
NFSERR_NOTEMPTY = 66, /* v2 v3 */
NFSERR_DQUOT = 69, /* v2 v3 */
NFSERR_STALE = 70, /* v2 v3 */
NFSERR_NAMETOOLONG = 63, /* v2 v3 v4 */
NFSERR_NOTEMPTY = 66, /* v2 v3 v4 */
NFSERR_DQUOT = 69, /* v2 v3 v4 */
NFSERR_STALE = 70, /* v2 v3 v4 */
NFSERR_REMOTE = 71, /* v2 v3 */
NFSERR_WFLUSH = 99, /* v2 */
NFSERR_BADHANDLE = 10001, /* v3 */
NFSERR_BADHANDLE = 10001, /* v3 v4 */
NFSERR_NOT_SYNC = 10002, /* v3 */
NFSERR_BAD_COOKIE = 10003, /* v3 */
NFSERR_NOTSUPP = 10004, /* v3 */
NFSERR_TOOSMALL = 10005, /* v3 */
NFSERR_SERVERFAULT = 10006, /* v3 */
NFSERR_BADTYPE = 10007, /* v3 */
NFSERR_JUKEBOX = 10008 /* v3 */
};
NFSERR_BAD_COOKIE = 10003, /* v3 v4 */
NFSERR_NOTSUPP = 10004, /* v3 v4 */
NFSERR_TOOSMALL = 10005, /* v3 v4 */
NFSERR_SERVERFAULT = 10006, /* v3 v4 */
NFSERR_BADTYPE = 10007, /* v3 v4 */
NFSERR_JUKEBOX = 10008, /* v3 v4 */
NFSERR_SAME = 10009, /* v4 */
NFSERR_DENIED = 10010, /* v4 */
NFSERR_EXPIRED = 10011, /* v4 */
NFSERR_LOCKED = 10012, /* v4 */
NFSERR_GRACE = 10013, /* v4 */
NFSERR_FHEXPIRED = 10014, /* v4 */
NFSERR_SHARE_DENIED = 10015, /* v4 */
NFSERR_WRONGSEC = 10016, /* v4 */
NFSERR_CLID_INUSE = 10017, /* v4 */
NFSERR_RESOURCE = 10018, /* v4 */
NFSERR_MOVED = 10019, /* v4 */
NFSERR_NOFILEHANDLE = 10020, /* v4 */
NFSERR_MINOR_VERS_MISMATCH = 10021, /* v4 */
NFSERR_STALE_CLIENTID = 10022, /* v4 */
NFSERR_STALE_STATEID = 10023, /* v4 */
NFSERR_OLD_STATEID = 10024, /* v4 */
NFSERR_BAD_STATEID = 10025, /* v4 */
NFSERR_BAD_SEQID = 10026, /* v4 */
NFSERR_NOT_SAME = 10027, /* v4 */
NFSERR_LOCK_RANGE = 10028, /* v4 */
NFSERR_SYMLINK = 10029, /* v4 */
NFSERR_READDIR_NOSPC = 10030, /* v4 */
NFSERR_LEASE_MOVED = 10031, /* v4 */
NFSERR_ATTRNOTSUPP = 10032, /* v4 */
NFSERR_NO_GRACE = 10033, /* v4 */
NFSERR_RECLAIM_BAD = 10034, /* v4 */
NFSERR_RECLAIM_CONFLICT = 10035,/* v4 */
NFSERR_BAD_XDR = 10036, /* v4 */
NFSERR_LOCKS_HELD = 10037 /* v4 */
};
/* NFSv2 file types - beware, these are not the same in NFSv3 */
......
......@@ -55,6 +55,8 @@ struct readdir_cd {
char plus; /* readdirplus */
char eob; /* end of buffer */
char dotonly;
int nfserr; /* v4 only */
u32 bmval[2]; /* v4 only */
};
typedef int (*encode_dent_fn)(struct readdir_cd *, const char *,
int, loff_t, ino_t, unsigned int);
......@@ -86,11 +88,11 @@ int nfsd_create(struct svc_rqst *, struct svc_fh *,
char *name, int len, struct iattr *attrs,
int type, dev_t rdev, struct svc_fh *res);
#ifdef CONFIG_NFSD_V3
int nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *);
int nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *);
int nfsd_create_v3(struct svc_rqst *, struct svc_fh *,
char *name, int len, struct iattr *attrs,
struct svc_fh *res, int createmode,
u32 *verifier);
u32 *verifier, int *truncp);
int nfsd_commit(struct svc_rqst *, struct svc_fh *,
off_t, unsigned long);
#endif /* CONFIG_NFSD_V3 */
......@@ -119,7 +121,8 @@ int nfsd_truncate(struct svc_rqst *, struct svc_fh *,
unsigned long size);
int nfsd_readdir(struct svc_rqst *, struct svc_fh *,
loff_t, encode_dent_fn,
u32 *buffer, int *countp, u32 *verf);
u32 *buffer, int *countp, u32 *verf,
u32 *bmval);
int nfsd_statfs(struct svc_rqst *, struct svc_fh *,
struct statfs *);
......@@ -170,6 +173,16 @@ void nfsd_lockd_unexport(struct svc_client *);
#define nfserr_serverfault __constant_htonl(NFSERR_SERVERFAULT)
#define nfserr_badtype __constant_htonl(NFSERR_BADTYPE)
#define nfserr_jukebox __constant_htonl(NFSERR_JUKEBOX)
#define nfserr_bad_cookie __constant_htonl(NFSERR_BAD_COOKIE)
#define nfserr_same __constant_htonl(NFSERR_SAME)
#define nfserr_clid_inuse __constant_htonl(NFSERR_CLID_INUSE)
#define nfserr_resource __constant_htonl(NFSERR_RESOURCE)
#define nfserr_nofilehandle __constant_htonl(NFSERR_NOFILEHANDLE)
#define nfserr_minor_vers_mismatch __constant_htonl(NFSERR_MINOR_VERS_MISMATCH)
#define nfserr_symlink __constant_htonl(NFSERR_SYMLINK)
#define nfserr_not_same __constant_htonl(NFSERR_NOT_SAME)
#define nfserr_readdir_nospc __constant_htonl(NFSERR_READDIR_NOSPC)
#define nfserr_bad_xdr __constant_htonl(NFSERR_BAD_XDR)
/* error code for internal use - if a request fails due to
* kmalloc failure, it gets dropped. Client should resend eventually
......
......@@ -4,7 +4,7 @@
#include <linux/raid/md.h>
struct dev_info {
struct block_device *bdev;
mdk_rdev_t *rdev;
unsigned long size;
unsigned long offset;
};
......
......@@ -76,9 +76,8 @@ extern void md_unregister_thread (mdk_thread_t *thread);
extern void md_wakeup_thread(mdk_thread_t *thread);
extern void md_interrupt_thread (mdk_thread_t *thread);
extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
extern void md_sync_acct(struct block_device *bdev, unsigned long nr_sectors);
extern int md_error (mddev_t *mddev, struct block_device *bdev);
extern int md_run_setup(void);
extern void md_sync_acct(mdk_rdev_t *rdev, unsigned long nr_sectors);
extern void md_error (mddev_t *mddev, mdk_rdev_t *rdev);
extern void md_print_devices (void);
......
......@@ -154,12 +154,26 @@ struct mdk_rdev_s
mdp_super_t *sb;
unsigned long sb_offset;
int alias_device; /* device alias to the same disk */
/* A device can be in one of three states based on two flags:
* Not working: faulty==1 in_sync==0
* Fully working: faulty==0 in_sync==1
* Working, but not
* in sync with array
* faulty==0 in_sync==0
*
* It can never have faulty==1, in_sync==1
* This reduces the burden of testing multiple flags in many cases
*/
int faulty; /* if faulty do not issue IO requests */
int in_sync; /* device is a full member of the array */
int desc_nr; /* descriptor index in the superblock */
int raid_disk; /* role of device in array */
atomic_t nr_pending; /* number of pending requests.
* only maintained for arrays that
* support hot removal
*/
};
typedef struct mdk_personality_s mdk_personality_t;
......@@ -202,7 +216,7 @@ struct mddev_s
int in_sync; /* know to not need resync */
struct semaphore reconfig_sem;
atomic_t active;
mdk_rdev_t *spare;
int spares;
int degraded; /* whether md should consider
* adding a spare
......@@ -223,11 +237,12 @@ struct mdk_personality_s
int (*run)(mddev_t *mddev);
int (*stop)(mddev_t *mddev);
int (*status)(char *page, mddev_t *mddev);
int (*error_handler)(mddev_t *mddev, struct block_device *bdev);
/* error_handler must set ->faulty and clear ->in_sync
* if appropriate, and should abort recovery if needed
*/
void (*error_handler)(mddev_t *mddev, mdk_rdev_t *rdev);
int (*hot_add_disk) (mddev_t *mddev, mdk_rdev_t *rdev);
int (*hot_remove_disk) (mddev_t *mddev, int number);
int (*spare_write) (mddev_t *mddev);
int (*spare_inactive) (mddev_t *mddev);
int (*spare_active) (mddev_t *mddev);
int (*sync_request)(mddev_t *mddev, sector_t sector_nr, int go_faster);
};
......@@ -272,9 +287,6 @@ extern mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr);
#define ITERATE_RDEV_PENDING(rdev,tmp) \
ITERATE_RDEV_GENERIC(pending_raid_disks,rdev,tmp)
#define xchg_values(x,y) do { __typeof__(x) __tmp = x; \
x = y; y = __tmp; } while (0)
typedef struct mdk_thread_s {
void (*run) (void *data);
void *data;
......
......@@ -5,14 +5,7 @@
#include <linux/bio.h>
struct multipath_info {
struct block_device *bdev;
/*
* State bits:
*/
int operational;
int used_slot;
mdk_rdev_t *rdev;
};
struct multipath_private_data {
......
......@@ -6,18 +6,8 @@
typedef struct mirror_info mirror_info_t;
struct mirror_info {
struct block_device *bdev;
mdk_rdev_t *rdev;
sector_t head_position;
atomic_t nr_pending;
/*
* State bits:
*/
int operational;
int write_only;
int spare;
int used_slot;
};
typedef struct r1bio_s r1bio_t;
......@@ -30,7 +20,6 @@ struct r1_private_data_s {
int last_used;
sector_t next_seq_sect;
mdk_thread_t *thread;
mirror_info_t *spare;
spinlock_t device_lock;
/* for use when syncing mirrors: */
......
......@@ -148,6 +148,11 @@ struct stripe_head {
#define R5_UPTODATE 0 /* page contains current data */
#define R5_LOCKED 1 /* IO has been submitted on "req" */
#define R5_OVERWRITE 2 /* towrite covers whole page */
/* and some that are internal to handle_stripe */
#define R5_Insync 3 /* rdev && rdev->in_sync at start */
#define R5_Wantread 4 /* want to schedule a read */
#define R5_Wantwrite 5
#define R5_Syncio 6 /* this io need to be accounted as resync io */
/*
* Write method
......@@ -192,11 +197,7 @@ struct stripe_head {
struct disk_info {
struct block_device *bdev;
int operational;
int write_only;
int spare;
int used_slot;
mdk_rdev_t *rdev;
};
struct raid5_private_data {
......
......@@ -76,9 +76,8 @@ void lru_add_drain(void)
*/
void __page_cache_release(struct page *page)
{
BUG_ON(page_count(page) != 0);
if (PageLRU(page)) {
unsigned long flags;
BUG_ON(page_count(page) != 0);
spin_lock_irqsave(&_pagemap_lru_lock, flags);
if (TestClearPageLRU(page)) {
......@@ -90,7 +89,6 @@ void __page_cache_release(struct page *page)
if (page_count(page) != 0)
page = NULL;
spin_unlock_irqrestore(&_pagemap_lru_lock, flags);
}
if (page)
__free_pages_ok(page, 0);
}
......
......@@ -153,15 +153,20 @@ int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
unsigned long address = VMALLOC_VMADDR(area->addr);
unsigned long end = address + (area->size-PAGE_SIZE);
pgd_t *dir;
int err = 0;
dir = pgd_offset_k(address);
spin_lock(&init_mm.page_table_lock);
do {
pmd_t *pmd = pmd_alloc(&init_mm, dir, address);
if (!pmd)
return -ENOMEM;
if (map_area_pmd(pmd, address, end - address, prot, pages))
return -ENOMEM;
if (!pmd) {
err = -ENOMEM;
break;
}
if (map_area_pmd(pmd, address, end - address, prot, pages)) {
err = -ENOMEM;
break;
}
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
......@@ -169,7 +174,7 @@ int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
spin_unlock(&init_mm.page_table_lock);
flush_cache_all();
return 0;
return err;
}
......@@ -379,15 +384,21 @@ void *__vmalloc(unsigned long size, int gfp_mask, pgprot_t prot)
area->nr_pages = nr_pages;
area->pages = pages = kmalloc(array_size, (gfp_mask & ~__GFP_HIGHMEM));
if (!area->pages)
if (!area->pages) {
remove_vm_area(area->addr);
kfree(area);
return NULL;
}
memset(area->pages, 0, array_size);
for (i = 0; i < area->nr_pages; i++) {
area->pages[i] = alloc_page(gfp_mask);
if (unlikely(!area->pages[i]))
if (unlikely(!area->pages[i])) {
/* Successfully allocated i pages, free them in __vunmap() */
area->nr_pages = i;
goto fail;
}
}
if (map_vm_area(area, prot, &pages))
goto fail;
......
......@@ -140,7 +140,7 @@ svc_sock_enqueue(struct svc_sock *svsk)
&& !test_bit(SK_CLOSE, &svsk->sk_flags)
&& !test_bit(SK_CONN, &svsk->sk_flags)) {
/* Don't enqueue while not enough space for reply */
dprintk("svc: socket %p no space, %d > %ld, not enqueued\n",
dprintk("svc: socket %p no space, %d*2 > %ld, not enqueued\n",
svsk->sk_sk, svsk->sk_reserved+serv->sv_bufsz,
sock_wspace(svsk->sk_sk));
goto out_unlock;
......@@ -574,6 +574,14 @@ svc_udp_init(struct svc_sock *svsk)
svsk->sk_recvfrom = svc_udp_recvfrom;
svsk->sk_sendto = svc_udp_sendto;
/* initialise setting must have enough space to
* receive and respond to one request.
* svc_udp_recvfrom will re-adjust if necessary
*/
svc_sock_setbufsize(svsk->sk_sock,
3 * svsk->sk_server->sv_bufsz,
3 * svsk->sk_server->sv_bufsz);
set_bit(SK_CHNGBUF, &svsk->sk_flags);
return 0;
......@@ -679,6 +687,8 @@ svc_tcp_accept(struct svc_sock *svsk)
goto failed; /* aborted connection or whatever */
}
set_bit(SK_CONN, &svsk->sk_flags);
svc_sock_enqueue(svsk);
slen = sizeof(sin);
err = ops->getname(newsock, (struct sockaddr *) &sin, &slen, 1);
if (err < 0) {
......@@ -944,6 +954,14 @@ svc_tcp_init(struct svc_sock *svsk)
svsk->sk_reclen = 0;
svsk->sk_tcplen = 0;
/* initialise setting must have enough space to
* receive and respond to one request.
* svc_tcp_recvfrom will re-adjust if necessary
*/
svc_sock_setbufsize(svsk->sk_sock,
3 * svsk->sk_server->sv_bufsz,
3 * svsk->sk_server->sv_bufsz);
set_bit(SK_CHNGBUF, &svsk->sk_flags);
}
......@@ -1220,7 +1238,7 @@ svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin)
}
if (protocol == IPPROTO_TCP) {
if ((error = sock->ops->listen(sock, 5)) < 0)
if ((error = sock->ops->listen(sock, 64)) < 0)
goto bummer;
}
......
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