Skip to content
Snippets Groups Projects
Commit 6faeeda6 authored by Yang Sheng's avatar Yang Sheng
Browse files

Branch HEAD

b=13397
i=adilger
i=shadow

Add kernel patches for vanilla-2.6.22.14.
parent 12349e8b
No related branches found
No related tags found
No related merge requests found
diff -urp linux-2.6.18.1.orig/block/ll_rw_blk.c linux-2.6.18.1/block/ll_rw_blk.c
--- linux-2.6.18.1.orig/block/ll_rw_blk.c 2006-10-14 06:34:03.000000000 +0300
+++ linux-2.6.18.1/block/ll_rw_blk.c 2007-05-29 14:50:46.000000000 +0300
@@ -2993,6 +2993,8 @@ static void handle_bad_sector(struct bio
set_bit(BIO_EOF, &bio->bi_flags);
}
+int dev_check_rdonly(struct block_device *bdev);
+
/**
* generic_make_request: hand a buffer to its device driver for I/O
* @bio: The bio describing the location in memory and on the device.
@@ -3076,6 +3078,12 @@ end_io:
if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
goto end_io;
+ /* this is cfs's dev_rdonly check */
+ if (bio->bi_rw == WRITE &&
+ dev_check_rdonly(bio->bi_bdev)) {
+ bio_endio(bio, bio->bi_size, 0);
+ break;
+ }
/*
* If this device has partitions, remap block n
@@ -3675,6 +3683,91 @@ void swap_io_context(struct io_context *
*ioc2 = temp;
}
EXPORT_SYMBOL(swap_io_context);
+ /*
+ * Debug code for turning block devices "read-only" (will discard writes
+ * silently). This is for filesystem crash/recovery testing.
+ */
+struct deventry {
+ dev_t dev;
+ struct deventry *next;
+};
+
+static struct deventry *devlist = NULL;
+static spinlock_t devlock = SPIN_LOCK_UNLOCKED;
+
+int dev_check_rdonly(struct block_device *bdev)
+{
+ struct deventry *cur;
+ if (!bdev) return 0;
+ spin_lock(&devlock);
+ cur = devlist;
+ while(cur) {
+ if (bdev->bd_dev == cur->dev) {
+ spin_unlock(&devlock);
+ return 1;
+ }
+ cur = cur->next;
+ }
+ spin_unlock(&devlock);
+ return 0;
+}
+
+void dev_set_rdonly(struct block_device *bdev)
+{
+ struct deventry *newdev, *cur;
+
+ if (!bdev)
+ return;
+ newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
+ if (!newdev)
+ return;
+
+ spin_lock(&devlock);
+ cur = devlist;
+ while(cur) {
+ if (bdev->bd_dev == cur->dev) {
+ spin_unlock(&devlock);
+ kfree(newdev);
+ return;
+ }
+ cur = cur->next;
+ }
+ newdev->dev = bdev->bd_dev;
+ newdev->next = devlist;
+ devlist = newdev;
+ spin_unlock(&devlock);
+ printk(KERN_WARNING "Turning device %s (%#x) read-only\n",
+ bdev->bd_disk ? bdev->bd_disk->disk_name : "", bdev->bd_dev);
+}
+
+void dev_clear_rdonly(struct block_device *bdev)
+{
+ struct deventry *cur, *last = NULL;
+ if (!bdev) return;
+ spin_lock(&devlock);
+ cur = devlist;
+ while(cur) {
+ if (bdev->bd_dev == cur->dev) {
+ if (last)
+ last->next = cur->next;
+ else
+ devlist = cur->next;
+ spin_unlock(&devlock);
+ kfree(cur);
+ printk(KERN_WARNING "Removing read-only on %s (%#x)\n",
+ bdev->bd_disk ? bdev->bd_disk->disk_name :
+ "unknown block", bdev->bd_dev);
+ return;
+ }
+ last = cur;
+ cur = cur->next;
+ }
+ spin_unlock(&devlock);
+}
+
+EXPORT_SYMBOL(dev_set_rdonly);
+EXPORT_SYMBOL(dev_clear_rdonly);
+EXPORT_SYMBOL(dev_check_rdonly);
/*
* sysfs parts below
diff -urp linux-2.6.18.1.orig/fs/block_dev.c linux-2.6.18.1/fs/block_dev.c
--- linux-2.6.18.1.orig/fs/block_dev.c 2006-10-14 06:34:03.000000000 +0300
+++ linux-2.6.18.1/fs/block_dev.c 2007-05-29 14:53:38.000000000 +0300
@@ -58,6 +58,7 @@ static void kill_bdev(struct block_devic
{
invalidate_bdev(bdev, 1);
truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
+ dev_clear_rdonly(bdev);
}
int set_blocksize(struct block_device *bdev, int size)
diff -urp linux-2.6.18.1.orig/include/linux/fs.h linux-2.6.18.1/include/linux/fs.h
--- linux-2.6.18.1.orig/include/linux/fs.h 2006-10-14 06:34:03.000000000 +0300
+++ linux-2.6.18.1/include/linux/fs.h 2007-05-29 14:50:46.000000000 +0300
@@ -1632,6 +1632,10 @@ extern void file_kill(struct file *f);
extern void submit_bio(int, struct bio *);
extern int bdev_read_only(struct block_device *);
#endif
+#define HAVE_CLEAR_RDONLY_ON_PUT
+extern void dev_set_rdonly(struct block_device *bdev);
+extern int dev_check_rdonly(struct block_device *bdev);
+extern void dev_clear_rdonly(struct block_device *bdev);
extern int set_blocksize(struct block_device *, int);
extern int sb_set_blocksize(struct super_block *, int);
extern int sb_min_blocksize(struct super_block *, int);
Index: linux-2.6/fs/filesystems.c
===================================================================
--- linux-2.6.orig/fs/filesystems.c 2006-07-15 16:08:35.000000000 +0800
+++ linux-2.6/fs/filesystems.c 2006-07-15 16:14:19.000000000 +0800
@@ -29,7 +29,9 @@
*/
static struct file_system_type *file_systems;
-static DEFINE_RWLOCK(file_systems_lock);
+DEFINE_RWLOCK(file_systems_lock);
+
+EXPORT_SYMBOL(file_systems_lock);
/* WARNING: This can be used only if we _already_ own a reference */
void get_filesystem(struct file_system_type *fs)
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h 2006-07-15 16:10:37.000000000 +0800
+++ linux-2.6/include/linux/fs.h 2006-07-15 16:14:19.000000000 +0800
@@ -1768,6 +1768,7 @@ static inline ssize_t blockdev_direct_IO
extern const struct file_operations generic_ro_fops;
+extern rwlock_t file_systems_lock;
#define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
extern int vfs_readlink(struct dentry *, char __user *, int, const char *);
Index: linux-2.6/fs/namespace.c
===================================================================
--- linux-2.6.orig/fs/namespace.c 2006-07-15 16:10:33.000000000 +0800
+++ linux-2.6/fs/namespace.c 2006-07-15 16:14:19.000000000 +0800
@@ -1641,6 +1641,7 @@ void set_fs_pwd(struct fs_struct *fs, st
mntput(old_pwdmnt);
}
}
+EXPORT_SYMBOL(set_fs_pwd);
static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd)
{
Index: linux-2.6/fs/dcache.c
===================================================================
--- linux-2.6.orig/fs/dcache.c 2006-07-15 16:14:00.000000000 +0800
+++ linux-2.6/fs/dcache.c 2006-07-15 16:14:19.000000000 +0800
@@ -1628,6 +1628,7 @@ int is_subdir(struct dentry * new_dentry
return result;
}
+EXPORT_SYMBOL(is_subdir);
void d_genocide(struct dentry *root)
{
Index: linux-2.6/Documentation/filesystems/ext2.txt
===================================================================
--- linux-2.6.orig/Documentation/filesystems/ext2.txt 2006-04-03 22:46:38.000000000 +0800
+++ linux-2.6/Documentation/filesystems/ext2.txt 2006-07-15 12:54:06.000000000 +0800
@@ -58,6 +58,22 @@ nobh Do not attach buffer_heads to fi
xip Use execute in place (no caching) if possible
+iopen Makes an invisible pseudo-directory called
+ __iopen__ available in the root directory
+ of the filesystem. Allows open-by-inode-
+ number. i.e., inode 3145 can be accessed
+ via /mntpt/__iopen__/3145
+
+iopen_nopriv This option makes the iopen directory be
+ world-readable. This may be safer since it
+ allows daemons to run as an unprivileged user,
+ however it significantly changes the security
+ model of a Unix filesystem, since previously
+ all files under a mode 700 directory were not
+ generally avilable even if the
+ permissions on the file itself is
+ world-readable.
+
grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2.
Index: linux-2.6/fs/dcache.c
===================================================================
--- linux-2.6.orig/fs/dcache.c 2006-07-15 12:48:18.000000000 +0800
+++ linux-2.6/fs/dcache.c 2006-07-15 12:54:06.000000000 +0800
@@ -1608,6 +1608,12 @@
spin_unlock(&dcache_lock);
}
+void __d_move(struct dentry * dentry, struct dentry * target)
+{
+ d_move_locked(dentry, target);
+}
+EXPORT_SYMBOL(__d_move);
+
/*
* Helper that returns 1 if p1 is a parent of p2, else 0
*/
Index: linux-2.6/include/linux/dcache.h
===================================================================
--- linux-2.6.orig/include/linux/dcache.h 2006-07-15 12:48:41.000000000 +0800
+++ linux-2.6/include/linux/dcache.h 2006-07-15 12:54:06.000000000 +0800
@@ -257,6 +257,7 @@ extern int have_submounts(struct dentry
* This adds the entry to the hash queues.
*/
extern void d_rehash(struct dentry *);
+extern void d_rehash_cond(struct dentry *, int lock);
/**
* d_add - add dentry to hash queues
@@ -292,6 +293,7 @@ static inline struct dentry *d_add_uniqu
/* used for rename() and baskets */
extern void d_move(struct dentry *, struct dentry *);
+extern void __d_move(struct dentry *, struct dentry *);
/* appendix may either be NULL or be used for transname suffixes */
extern struct dentry * d_lookup(struct dentry *, struct qstr *);
Index: linux-2.6.22.5/drivers/scsi/Kconfig
===================================================================
--- linux-2.6.22.5.orig/drivers/scsi/Kconfig
+++ linux-2.6.22.5/drivers/scsi/Kconfig
@@ -76,6 +76,14 @@ config BLK_DEV_SD
In this case, do not compile the driver for your SCSI host adapter
(below) as a module either.
+config SD_IOSTATS
+ bool "Enable SCSI disk I/O stats"
+ depends on BLK_DEV_SD
+ default y
+ ---help---
+ This enables SCSI disk I/O stats collection. You must also enable
+ /proc file system support if you want this feature.
+
config CHR_DEV_ST
tristate "SCSI tape support"
depends on SCSI
Index: linux+rhel4+chaos/drivers/scsi/sd.c
===================================================================
--- linux+rhel4+chaos.orig/drivers/scsi/sd.c
+++ linux+rhel4+chaos/drivers/scsi/sd.c
@@ -63,6 +63,38 @@
#include "scsi_logging.h"
+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
+# include <linux/proc_fs.h>
+# include <linux/seq_file.h>
+
+typedef struct {
+ unsigned long long iostat_size;
+ unsigned long long iostat_count;
+} iostat_counter_t;
+
+#define IOSTAT_NCOUNTERS 16
+typedef struct {
+ iostat_counter_t iostat_read_histogram[IOSTAT_NCOUNTERS];
+ iostat_counter_t iostat_write_histogram[IOSTAT_NCOUNTERS];
+ struct timeval iostat_timeval;
+} iostat_stats_t;
+
+iostat_stats_t **sd_iostats;
+spinlock_t sd_iostats_lock;
+struct proc_dir_entry *sd_iostats_procdir;
+char sd_iostats_procdir_name[] = "sd_iostats";
+
+extern void sd_iostats_init(void);
+extern void sd_iostats_init_disk(struct gendisk *);
+extern void sd_iostats_fini(void);
+extern void sd_iostats_bump(int disk, unsigned int nsect, int iswrite);
+#else
+static inline void sd_iostats_init(void) {}
+static inline void sd_iostats_init_disk(struct gendisk *disk) {}
+static inline void sd_iostats_fini(void) {}
+static inline void sd_iostats_bump(int disk, unsigned int nsect, int iswrite) {}
+#endif
+
MODULE_AUTHOR("Eric Youngdale");
MODULE_DESCRIPTION("SCSI disk (sd) driver");
MODULE_LICENSE("GPL");
@@ -89,6 +121,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
static DEFINE_IDR(sd_index_idr);
static DEFINE_SPINLOCK(sd_index_lock);
+#define SD_STATS 256
/* This semaphore is used to mediate the 0->1 reference get in the
* face of object destruction (i.e. we can't allow a get on an
* object after last put) */
@@ -368,6 +401,9 @@ static int sd_init_command(struct scsi_c
SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n",
(unsigned long long)block));
+ sd_iostats_bump(scsi_disk(disk)->index, this_count,
+ rq_data_dir(SCpnt->request) == WRITE);
+
/*
* If we have a 1K hardware sectorsize, prevent access to single
* 512 byte sectors. In theory we could handle this - in fact
@@ -575,6 +611,7 @@ static int sd_open(struct inode *inode,
scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT);
}
+ sd_iostats_init_disk(disk);
return 0;
error_out:
@@ -601,8 +638,20 @@ static int sd_release(struct inode *inod
SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n"));
- if (!--sdkp->openers && sdev->removable) {
- if (scsi_block_when_processing_errors(sdev))
+ if (!--sdkp->openers) {
+ /*
+ * Remove sd_iostats information about this disk
+ */
+ if (sd_iostats_procdir != NULL) {
+ remove_proc_entry(disk->disk_name, sd_iostats_procdir);
+ }
+ if (sd_iostats != NULL) {
+ if (sd_iostats[sdkp->index] != NULL) {
+ kfree (sd_iostats[sdkp->index]);
+ sd_iostats[sdkp->index] = NULL;
+ }
+ }
+ if (sdev->removable && scsi_block_when_processing_errors(sdev))
scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW);
}
@@ -1563,6 +1612,342 @@ static int sd_revalidate_disk(struct gen
return 0;
}
+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
+static int
+sd_iostats_seq_show(struct seq_file *seq, void *v)
+{
+ struct timeval now;
+ struct gendisk *disk;
+ iostat_stats_t *stats;
+ unsigned long long read_len;
+ unsigned long long read_len_tot;
+ unsigned long read_num;
+ unsigned long read_num_tot;
+ unsigned long long write_len;
+ unsigned long long write_len_tot;
+ unsigned long write_num;
+ unsigned long write_num_tot;
+ int i;
+ int maxi;
+
+ if (seq == NULL || seq->private == NULL) {
+ printk(KERN_ERR "sd_iostats_seq_show: NULL disk\n");
+ BUG();
+ }
+
+ disk = seq->private;
+
+ if (scsi_disk(disk) == NULL || (disk->flags & GENHD_FL_UP) == 0) {
+ seq_printf(seq, "sd_iostats_seq_show: Device %s "
+ "does not exist\n", disk->disk_name);
+ return 0;
+ }
+
+ if (sd_iostats == NULL) {
+ printk(KERN_ERR "sd_iostats_seq_show: NULL stats array\n");
+ BUG();
+ }
+
+ stats = sd_iostats[scsi_disk(disk)->index];
+ if (stats == NULL) {
+ seq_printf(seq, "sd_iostats_seq_show: sd_iostats "
+ "entry %d does not exist\n",
+ scsi_disk(disk)->index);
+ return 0;
+ }
+
+ do_gettimeofday(&now);
+ now.tv_sec -= stats->iostat_timeval.tv_sec;
+ now.tv_usec -= stats->iostat_timeval.tv_usec;
+ if (now.tv_usec < 0) {
+ now.tv_usec += 1000000;
+ now.tv_sec--;
+ }
+
+ /* this sampling races with updates */
+ seq_printf(seq, "index: %lu snapshot_time: %lu.%06lu\n",
+ scsi_disk(disk)->index, now.tv_sec, now.tv_usec);
+
+ for (i = IOSTAT_NCOUNTERS - 1; i > 0; i--)
+ if (stats->iostat_read_histogram[i].iostat_count != 0 ||
+ stats->iostat_write_histogram[i].iostat_count != 0)
+ break;
+ maxi = i;
+
+ seq_printf(seq, "%8s %8s %12s %8s %12s\n", "size",
+ "reads", "total", "writes", "total");
+
+ read_len_tot = write_len_tot = 0;
+ read_num_tot = write_num_tot = 0;
+ for (i = 0; i <= maxi; i++) {
+ read_len = stats->iostat_read_histogram[i].iostat_size;
+ read_len_tot += read_len;
+ read_num = stats->iostat_read_histogram[i].iostat_count;
+ read_num_tot += read_num;
+
+ write_len = stats->iostat_write_histogram[i].iostat_size;
+ write_len_tot += write_len;
+ write_num = stats->iostat_write_histogram[i].iostat_count;
+ write_num_tot += write_num;
+
+ seq_printf (seq, "%8d %8lu %12llu %8lu %12llu\n",
+ 512<<i, read_num, read_len, write_num, write_len);
+ }
+
+ seq_printf(seq, "%8s %8lu %12llu %8lu %12llu\n", "total",
+ read_num_tot, read_len_tot,
+ write_num_tot, write_len_tot);
+ return 0;
+}
+
+static void *
+sd_iostats_seq_start(struct seq_file *p, loff_t *pos)
+{
+ return (*pos == 0) ? (void *)1 : NULL;
+}
+
+static void *
+sd_iostats_seq_next(struct seq_file *p, void *v, loff_t *pos)
+{
+ ++*pos;
+ return NULL;
+}
+
+static void
+sd_iostats_seq_stop(struct seq_file *p, void *v)
+{
+}
+
+static struct seq_operations sd_iostats_seqops = {
+ .start = sd_iostats_seq_start,
+ .stop = sd_iostats_seq_stop,
+ .next = sd_iostats_seq_next,
+ .show = sd_iostats_seq_show,
+};
+
+static int
+sd_iostats_seq_open (struct inode *inode, struct file *file)
+{
+ int rc;
+
+ rc = seq_open(file, &sd_iostats_seqops);
+ if (rc != 0)
+ return rc;
+
+ ((struct seq_file *)file->private_data)->private = PDE(inode)->data;
+ return 0;
+}
+
+static ssize_t
+sd_iostats_seq_write(struct file *file, const char *buffer,
+ size_t len, loff_t *off)
+{
+ struct seq_file *seq = file->private_data;
+ struct gendisk *disk = seq->private;
+ iostat_stats_t *stats = sd_iostats[scsi_disk(disk)->index];
+ unsigned long flags;
+
+
+ spin_lock_irqsave (&sd_iostats_lock, flags);
+ memset (stats, 0, sizeof(*stats));
+ do_gettimeofday(&stats->iostat_timeval);
+ spin_unlock_irqrestore (&sd_iostats_lock, flags);
+
+ return len;
+}
+
+static struct file_operations sd_iostats_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = sd_iostats_seq_open,
+ .read = seq_read,
+ .write = sd_iostats_seq_write,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+extern struct proc_dir_entry *proc_scsi;
+
+void
+sd_iostats_init(void)
+{
+ int i;
+
+ spin_lock_init(&sd_iostats_lock);
+
+ sd_iostats = kmalloc(SD_STATS * sizeof(iostat_stats_t *), GFP_KERNEL);
+ if (sd_iostats == NULL) {
+ printk(KERN_WARNING "Can't keep sd iostats: "
+ "ENOMEM allocating stats array size %ld\n",
+ SD_STATS * sizeof(iostat_stats_t *));
+ return;
+ }
+
+ for (i = 0; i < SD_STATS; i++)
+ sd_iostats[i] = NULL;
+
+ if (proc_scsi == NULL) {
+ printk(KERN_WARNING "No access to sd iostats: "
+ "proc_scsi is NULL\n");
+ return;
+ }
+
+ sd_iostats_procdir = create_proc_entry(sd_iostats_procdir_name,
+ S_IFDIR | S_IRUGO | S_IXUGO,
+ proc_scsi);
+ if (sd_iostats_procdir == NULL) {
+ printk(KERN_WARNING "No access to sd iostats: "
+ "can't create /proc/scsi/%s\n", sd_iostats_procdir_name);
+ return;
+ }
+}
+
+void
+sd_iostats_init_disk(struct gendisk *disk)
+{
+ struct proc_dir_entry *pde;
+ unsigned long flags;
+ iostat_stats_t *stats;
+
+ if (sd_iostats == NULL ||
+ sd_iostats_procdir == NULL)
+ return;
+
+ if (scsi_disk(disk)->index > SD_STATS) {
+ printk(KERN_ERR "sd_iostats_init_disk: "
+ "unexpected disk index %d(%d)\n",
+ scsi_disk(disk)->index, SD_STATS);
+ return;
+ }
+
+ if (sd_iostats[scsi_disk(disk)->index] != NULL)
+ return;
+
+ stats = kmalloc(sizeof(*stats), GFP_KERNEL);
+ if (stats == NULL) {
+ printk(KERN_WARNING "Can't keep %s iostats: "
+ "ENOMEM allocating stats size %ld\n",
+ disk->disk_name, sizeof(*stats));
+ return;
+ }
+
+ memset (stats, 0, sizeof(*stats));
+ do_gettimeofday(&stats->iostat_timeval);
+
+ spin_lock_irqsave(&sd_iostats_lock, flags);
+
+ if (sd_iostats[scsi_disk(disk)->index] != NULL) {
+ spin_unlock_irqrestore(&sd_iostats_lock, flags);
+ kfree (stats);
+ return;
+ }
+
+ sd_iostats[scsi_disk(disk)->index] = stats;
+
+ spin_unlock_irqrestore(&sd_iostats_lock, flags);
+
+ pde = create_proc_entry(disk->disk_name, S_IRUGO | S_IWUSR,
+ sd_iostats_procdir);
+ if (pde == NULL) {
+ printk(KERN_WARNING "Can't create /proc/scsi/%s/%s\n",
+ sd_iostats_procdir_name, disk->disk_name);
+ } else {
+ pde->proc_fops = &sd_iostats_proc_fops;
+ pde->data = disk;
+ }
+}
+
+static void sd_devname(unsigned int disknum, char *buffer)
+{
+ if (disknum < 26)
+ sprintf(buffer, "sd%c", 'a' + disknum);
+ else {
+ unsigned int min1;
+ unsigned int min2;
+ /*
+ * For larger numbers of disks, we need to go to a new
+ * naming scheme.
+ */
+ min1 = disknum / 26;
+ min2 = disknum % 26;
+ sprintf(buffer, "sd%c%c", 'a' + min1 - 1, 'a' + min2);
+ }
+}
+
+void
+sd_iostats_fini(void)
+{
+ char name[6];
+ int i;
+
+ if (sd_iostats_procdir != NULL) {
+ for (i = 0; i < SD_STATS; i++) {
+ sd_devname(i, name);
+ remove_proc_entry(name, sd_iostats_procdir);
+ }
+
+ if (proc_scsi == NULL) {
+ printk(KERN_ERR "sd_iostats_fini: proc_scsi NULL\n");
+ BUG();
+ }
+ remove_proc_entry(sd_iostats_procdir_name,
+ proc_scsi);
+
+ sd_iostats_procdir = NULL;
+ }
+
+ if (sd_iostats != NULL) {
+ for (i = 0; i < SD_STATS; i++) {
+ if (sd_iostats[i] != NULL)
+ kfree (sd_iostats[i]);
+ }
+
+ kfree(sd_iostats);
+ sd_iostats = NULL;
+ }
+}
+
+void
+sd_iostats_bump(int disk, unsigned int nsect, int iswrite)
+{
+ iostat_stats_t *stats;
+ iostat_counter_t *counter;
+ int bucket;
+ int tmp;
+ unsigned long irqflags;
+
+ if (sd_iostats == NULL)
+ return;
+
+ if (disk < 0 || disk >= SD_STATS) {
+ printk(KERN_ERR "sd_iostats_bump: unexpected disk index %d([0-%d])\n",
+ disk, SD_STATS);
+ BUG();
+ }
+
+ for (bucket = 0, tmp = nsect; tmp > 1; bucket++)
+ tmp /= 2;
+
+ if (bucket >= IOSTAT_NCOUNTERS) {
+ printk (KERN_ERR "sd_iostats_bump: nsect %d too big\n", nsect);
+ BUG();
+ }
+
+ spin_lock_irqsave(&sd_iostats_lock, irqflags);
+
+ stats = sd_iostats[disk];
+ if (stats != NULL) {
+ counter = iswrite ?
+ &stats->iostat_write_histogram[bucket] :
+ &stats->iostat_read_histogram[bucket];
+
+ counter->iostat_size += nsect;
+ counter->iostat_count++;
+ }
+
+ spin_unlock_irqrestore(&sd_iostats_lock, irqflags);
+}
+#endif
+
/**
* sd_probe - called during driver initialization and whenever a
* new scsi device is attached to the system. It is called once
@@ -1854,6 +2239,7 @@ static int __init init_sd(void)
err = scsi_register_driver(&sd_template.gendrv);
if (err)
goto err_out_class;
+ sd_iostats_init();
return 0;
@@ -1876,6 +2262,7 @@ static void __exit exit_sd(void)
SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));
+ sd_iostats_fini();
scsi_unregister_driver(&sd_template.gendrv);
class_unregister(&sd_disk_class);
Index: linux-2.6.22.5/drivers/scsi/scsi_proc.c
===================================================================
--- linux-2.6.22.5.orig/drivers/scsi/scsi_proc.c
+++ linux-2.6.22.5/drivers/scsi/scsi_proc.c
@@ -40,7 +40,8 @@
/* 4K page size, but our output routines, use some slack for overruns */
#define PROC_BLOCK_SIZE (3*1024)
-static struct proc_dir_entry *proc_scsi;
+struct proc_dir_entry *proc_scsi;
+EXPORT_SYMBOL(proc_scsi);
/* Protect sht->present and sht->proc_dir */
static DEFINE_MUTEX(global_host_template_mutex);
Index: linux-2.6/fs/dcache.c
===================================================================
--- linux-2.6.orig/fs/dcache.c 2006-08-31 11:59:09.000000000 +0800
+++ linux-2.6/fs/dcache.c 2006-09-06 14:01:37.000000000 +0800
@@ -226,6 +226,13 @@ int d_invalidate(struct dentry * dentry)
spin_unlock(&dcache_lock);
return 0;
}
+
+ /* network invalidation by Lustre */
+ if (dentry->d_flags & DCACHE_LUSTRE_INVALID) {
+ spin_unlock(&dcache_lock);
+ return 0;
+ }
+
/*
* Check whether to do a partial shrink_dcache
* to get rid of unused child entries.
@@ -1242,15 +1249,24 @@ static void __d_rehash(struct dentry * e
* Adds a dentry to the hash according to its name.
*/
-void d_rehash(struct dentry * entry)
+void d_rehash_cond(struct dentry * entry, int lock)
{
- spin_lock(&dcache_lock);
+ if (lock)
+ spin_lock(&dcache_lock);
spin_lock(&entry->d_lock);
_d_rehash(entry);
spin_unlock(&entry->d_lock);
- spin_unlock(&dcache_lock);
+ if (lock)
+ spin_unlock(&dcache_lock);
}
+EXPORT_SYMBOL(d_rehash_cond);
+
+void d_rehash(struct dentry * entry)
+{
+ d_rehash_cond(entry, 1);
+}
+
#define do_switch(x,y) do { \
__typeof__ (x) __tmp = x; \
x = y; y = __tmp; } while (0)
Index: linux-2.6/include/linux/dcache.h
===================================================================
--- linux-2.6.orig/include/linux/dcache.h 2006-08-31 12:00:23.000000000 +0800
+++ linux-2.6/include/linux/dcache.h 2006-09-06 14:02:36.000000000 +0800
@@ -176,6 +176,7 @@ d_iput: no no no yes
#define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */
#define DCACHE_UNHASHED 0x0010
+#define DCACHE_LUSTRE_INVALID 0x0040 /* Lustre invalidated */
#define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched */
lustre_version.patch
vfs_races-2.6.22-vanilla.patch
i_filter_data.patch
jbd-jcberr-2.6.18-vanilla.patch
iopen-misc-2.6.22-vanilla.patch
export-truncate-2.6.18-vanilla.patch
export_symbols-2.6.22-vanilla.patch
export-nr_free_buffer_pages.patch
dev_read_only-2.6.22-vanilla.patch
export-2.6.18-vanilla.patch
8kstack-2.6.12.patch
export-show_task-2.6.18-vanilla.patch
sd_iostats-2.6.22-vanilla.patch
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment