From a888a27ac14736d3df8e730a3909d026d6f40f49 Mon Sep 17 00:00:00 2001 From: adilger Date: Thu, 18 Mar 2004 07:19:06 +0000 Subject: [PATCH] Land b1_2 onto HEAD (20040317_2319) b=2939, b=2325, b=2059 (partial), b=2925, b=2399, b=2517 --- lustre/ChangeLog | 9 +- lustre/include/linux/lustre_fsfilt.h | 73 +- lustre/include/linux/obd.h | 2 +- .../patches/dcache_refcount_debug.patch | 24 + .../patches/ext3-pdirops-2.4.20-chaos.patch | 1248 ++++++++++++++++++++ .../patches/inode-max-readahead-2.4.24.patch | 22 + lustre/kernel_patches/patches/iopen-2.4.20.patch | 175 ++- .../patches/iopen-2.4.21-chaos.patch | 196 +-- .../kernel_patches/patches/iopen-2.6.3-mm4.patch | 125 +- .../patches/linux-2.6.3-CITI_NFS4_ALL.patch | 2 +- lustre/kernel_patches/patches/lustre_version.patch | 2 +- .../patches/vfs_intent-2.4.18-18-chaos65.patch | 2 +- .../patches/vfs_intent-2.4.19-pre1.patch | 2 +- .../patches/vfs_intent-2.4.19-suse.patch | 2 +- .../patches/vfs_intent-2.4.20-hp.patch | 348 +++--- .../patches/vfs_intent-2.4.20-rh.patch | 334 +++--- .../patches/vfs_intent-2.4.20-vanilla.patch | 298 +++-- .../patches/vfs_intent-2.4.21-chaos.patch | 332 +++--- .../patches/vfs_intent-2.4.21-suse2.patch | 2 +- .../patches/vfs_intent-2.4.22-rh.patch | 2 +- lustre/kernel_patches/series/chaos-2.4.21 | 1 + lustre/kernel_patches/series/hp-pnnl-2.4.20 | 4 +- lustre/kernel_patches/series/rh-2.4.20 | 5 +- lustre/kernel_patches/series/vanilla-2.4.24 | 3 +- lustre/liblustre/namei.c | 4 +- lustre/llite/Makefile.am | 2 +- lustre/llite/Makefile.mk | 2 +- lustre/llite/file.c | 46 +- lustre/llite/sysctl.c | 70 -- lustre/lvfs/.cvsignore | 1 + lustre/lvfs/Makefile.am | 3 + lustre/lvfs/fsfilt_ext3.c | 78 +- lustre/lvfs/fsfilt_extN.c | 865 -------------- lustre/lvfs/fsfilt_reiserfs.c | 42 +- lustre/mds/mds_fs.c | 22 +- lustre/mds/mds_open.c | 21 +- lustre/mds/mds_reint.c | 7 +- lustre/mds/mds_unlink_open.c | 3 +- lustre/obdclass/class_obd.c | 2 +- lustre/obdclass/llog_lvfs.c | 37 +- lustre/obdfilter/filter.c | 8 +- lustre/obdfilter/filter_io.c | 15 +- lustre/obdfilter/filter_lvb.c | 6 +- lustre/ptlrpc/llog_server.c | 4 +- lustre/ptlrpc/recover.c | 10 +- lustre/tests/replay-ost-single.sh | 10 +- lustre/tests/sanity.sh | 42 +- 47 files changed, 2629 insertions(+), 1884 deletions(-) create mode 100644 lustre/kernel_patches/patches/dcache_refcount_debug.patch create mode 100644 lustre/kernel_patches/patches/ext3-pdirops-2.4.20-chaos.patch create mode 100644 lustre/kernel_patches/patches/inode-max-readahead-2.4.24.patch delete mode 100644 lustre/llite/sysctl.c delete mode 100644 lustre/lvfs/fsfilt_extN.c diff --git a/lustre/ChangeLog b/lustre/ChangeLog index c80989f..0eb3b7f 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -19,8 +19,13 @@ tbd Cluster File Systems, Inc. - mds_reint_create() should take same inode create lock (2926) - correct journal credits calculated for CANCEL_UNLINK_LOG (2931) - don't close files for self_export to avoid uninitialized obd (2936) - - let lustre could be mounted with the same name for node and mds (2939) - + - allow MDS with the same name as client node (2939) + - hold dentry reference for closed log files for unlink (2325) + - reserve space for all logs during transactions (2059) + - don't evict page beyond end of stripe extent (2925) + - don't oops on a deleted current working directory (2399) + - handle hard links to targets without a parent properly (2517) + 2004-03-04 Cluster File Systems, Inc. * version 1.2.0 * bug fixes diff --git a/lustre/include/linux/lustre_fsfilt.h b/lustre/include/linux/lustre_fsfilt.h index 3f3421a..40e9914 100644 --- a/lustre/include/linux/lustre_fsfilt.h +++ b/lustre/include/linux/lustre_fsfilt.h @@ -28,6 +28,7 @@ #ifdef __KERNEL__ #include +#include typedef void (*fsfilt_cb_t)(struct obd_device *obd, __u64 last_rcvd, void *data, int error); @@ -41,10 +42,11 @@ struct fsfilt_operations { struct list_head fs_list; struct module *fs_owner; char *fs_type; - void *(* fs_start)(struct inode *inode, int op, void *desc_private); + void *(* fs_start)(struct inode *inode, int op, void *desc_private, + int logs); void *(* fs_brw_start)(int objcount, struct fsfilt_objinfo *fso, int niocount, struct niobuf_local *nb, - void *desc_private); + void *desc_private, int logs); int (* fs_commit)(struct inode *inode, void *handle,int force_sync); int (* fs_commit_async)(struct inode *inode, void *handle, void **wait_handle); @@ -72,6 +74,7 @@ struct fsfilt_operations { int force_sync); int (* fs_read_record)(struct file *, void *, int size, loff_t *); int (* fs_setup)(struct super_block *sb); + int (* fs_get_op_len)(int, struct fsfilt_objinfo *, int); }; extern int fsfilt_register_ops(struct fsfilt_operations *fs_ops); @@ -88,24 +91,23 @@ extern void fsfilt_put_ops(struct fsfilt_operations *fs_ops); #define FSFILT_OP_MKNOD 7 #define FSFILT_OP_SETATTR 8 #define FSFILT_OP_LINK 9 -#define FSFILT_OP_CREATE_LOG 10 -#define FSFILT_OP_UNLINK_LOG 11 -#define FSFILT_OP_CANCEL_UNLINK_LOG 12 +#define FSFILT_OP_CANCEL_UNLINK 10 -static inline void *fsfilt_start(struct obd_device *obd, struct inode *inode, - int op, struct obd_trans_info *oti) +static inline void *fsfilt_start_log(struct obd_device *obd, + struct inode *inode, int op, + struct obd_trans_info *oti, int logs) { unsigned long now = jiffies; void *parent_handle = oti ? oti->oti_handle : NULL; - void *handle = obd->obd_fsops->fs_start(inode, op, parent_handle); - CDEBUG(D_INFO, "started handle %p (%p)\n", handle, parent_handle); + void *handle = obd->obd_fsops->fs_start(inode, op, parent_handle, logs); + CDEBUG(D_HA, "started handle %p (%p)\n", handle, parent_handle); if (oti != NULL) { if (parent_handle == NULL) { oti->oti_handle = handle; } else if (handle != parent_handle) { CERROR("mismatch: parent %p, handle %p, oti %p\n", - parent_handle, handle, oti->oti_handle); + parent_handle, handle, oti); LBUG(); } } @@ -114,17 +116,22 @@ static inline void *fsfilt_start(struct obd_device *obd, struct inode *inode, return handle; } -static inline void *fsfilt_brw_start(struct obd_device *obd, int objcount, - struct fsfilt_objinfo *fso, int niocount, - struct niobuf_local *nb, - struct obd_trans_info *oti) +static inline void *fsfilt_start(struct obd_device *obd, struct inode *inode, + int op, struct obd_trans_info *oti) +{ + return fsfilt_start_log(obd, inode, op, oti, 0); +} + +static inline void *fsfilt_brw_start_log(struct obd_device *obd, + int objcount, + struct fsfilt_objinfo *fso, + int niocount, struct niobuf_local *nb, + struct obd_trans_info *oti, int logs) { unsigned long now = jiffies; void *parent_handle = oti ? oti->oti_handle : NULL; - void *handle; - - handle = obd->obd_fsops->fs_brw_start(objcount, fso, niocount, nb, - parent_handle); + void *handle = obd->obd_fsops->fs_brw_start(objcount, fso, niocount, nb, + parent_handle, logs); CDEBUG(D_HA, "started handle %p (%p)\n", handle, parent_handle); if (oti != NULL) { @@ -132,41 +139,53 @@ static inline void *fsfilt_brw_start(struct obd_device *obd, int objcount, oti->oti_handle = handle; } else if (handle != parent_handle) { CERROR("mismatch: parent %p, handle %p, oti %p\n", - parent_handle, handle, oti->oti_handle); + parent_handle, handle, oti); LBUG(); } } if (time_after(jiffies, now + 15 * HZ)) CERROR("long journal start time %lus\n", (jiffies - now) / HZ); + return handle; } +static inline void *fsfilt_brw_start(struct obd_device *obd, int objcount, + struct fsfilt_objinfo *fso, int niocount, + struct niobuf_local *nb, + struct obd_trans_info *oti) +{ + return fsfilt_brw_start_log(obd, objcount, fso, niocount, nb, oti, 0); +} + static inline int fsfilt_commit(struct obd_device *obd, struct inode *inode, void *handle, int force_sync) { unsigned long now = jiffies; int rc = obd->obd_fsops->fs_commit(inode, handle, force_sync); - CDEBUG(D_INFO, "committing handle %p\n", handle); + CDEBUG(D_HA, "committing handle %p\n", handle); + if (time_after(jiffies, now + 15 * HZ)) CERROR("long journal start time %lus\n", (jiffies - now) / HZ); + return rc; } static inline int fsfilt_commit_async(struct obd_device *obd, - struct inode *inode, - void *handle, - void **wait_handle) + struct inode *inode, void *handle, + void **wait_handle) { unsigned long now = jiffies; int rc = obd->obd_fsops->fs_commit_async(inode, handle, wait_handle); + CDEBUG(D_HA, "committing handle %p (async)\n", *wait_handle); if (time_after(jiffies, now + 15 * HZ)) CERROR("long journal start time %lus\n", (jiffies - now) / HZ); + return rc; } -static inline int fsfilt_commit_wait(struct obd_device *obd, struct inode *inode, - void *handle) +static inline int fsfilt_commit_wait(struct obd_device *obd, + struct inode *inode, void *handle) { unsigned long now = jiffies; int rc = obd->obd_fsops->fs_commit_wait(inode, handle); @@ -217,8 +236,8 @@ static inline int fsfilt_add_journal_cb(struct obd_device *obd, __u64 last_rcvd, void *handle, fsfilt_cb_t cb_func, void *cb_data) { - return obd->obd_fsops->fs_add_journal_cb(obd, last_rcvd, handle, - cb_func, cb_data); + return obd->obd_fsops->fs_add_journal_cb(obd, last_rcvd, + handle, cb_func, cb_data); } /* very similar to obd_statfs(), but caller already holds obd_osfs_lock */ diff --git a/lustre/include/linux/obd.h b/lustre/include/linux/obd.h index 9da934f..fb2da73 100644 --- a/lustre/include/linux/obd.h +++ b/lustre/include/linux/obd.h @@ -479,10 +479,10 @@ struct obd_device { __u64 obd_last_committed; struct fsfilt_operations *obd_fsops; spinlock_t obd_osfs_lock; - struct llog_ctxt *obd_llog_ctxt[LLOG_MAX_CTXTS]; struct obd_statfs obd_osfs; unsigned long obd_osfs_age; struct obd_run_ctxt obd_ctxt; + struct llog_ctxt *obd_llog_ctxt[LLOG_MAX_CTXTS]; struct obd_device *obd_observer; struct obd_export *obd_self_export; diff --git a/lustre/kernel_patches/patches/dcache_refcount_debug.patch b/lustre/kernel_patches/patches/dcache_refcount_debug.patch new file mode 100644 index 0000000..0eddc23 --- /dev/null +++ b/lustre/kernel_patches/patches/dcache_refcount_debug.patch @@ -0,0 +1,24 @@ +--- ./fs/dcache.c.orig 2004-01-30 14:54:45.000000000 -0700 ++++ ./fs/dcache.c 2004-02-20 14:49:18.000000000 -0700 +@@ -348,8 +348,20 @@ + dentry_stat.nr_unused--; + + /* Unused dentry with a count? */ +- if (atomic_read(&dentry->d_count)) ++ if (atomic_read(&dentry->d_count)) { ++ struct inode *inode = dentry->d_inode; ++ printk(KERN_CRIT "dentry %*s %p->%lu/%u(%p/%s) ct %d\n", ++ dentry->d_name.len, dentry->d_name.name, dentry, ++ inode ? inode->i_ino : 0, ++ inode ? inode->i_generation : 0, inode, ++ inode ? inode->i_sb ? ++ inode->i_sb->s_type->name : "" : "", ++ atomic_read(&dentry->d_count)); ++ spin_unlock(&dcache_lock); ++ set_task_state(current, TASK_UNINTERRUPTIBLE); ++ schedule(); + BUG(); ++ } + + prune_one_dentry(dentry); + if (!--count) diff --git a/lustre/kernel_patches/patches/ext3-pdirops-2.4.20-chaos.patch b/lustre/kernel_patches/patches/ext3-pdirops-2.4.20-chaos.patch new file mode 100644 index 0000000..28badd6 --- /dev/null +++ b/lustre/kernel_patches/patches/ext3-pdirops-2.4.20-chaos.patch @@ -0,0 +1,1248 @@ + fs/ext3/ialloc.c | 3 + fs/ext3/inode.c | 3 + fs/ext3/namei.c | 582 +++++++++++++++++++++++++++++++++++++--------- + fs/ext3/super.c | 14 + + include/linux/ext3_fs.h | 1 + include/linux/ext3_fs_i.h | 6 + 6 files changed, 500 insertions(+), 109 deletions(-) + +Index: linux-2.4.20/fs/ext3/namei.c +=================================================================== +--- linux-2.4.20.orig/fs/ext3/namei.c Wed Mar 17 15:37:09 2004 ++++ linux-2.4.20/fs/ext3/namei.c Wed Mar 17 15:37:56 2004 +@@ -51,6 +51,9 @@ + { + struct buffer_head *bh; + ++ /* with parallel dir operations all appends ++ * have to be serialized -bzzz */ ++ down(&EXT3_I(inode)->i_append_sem); + *block = inode->i_size >> inode->i_sb->s_blocksize_bits; + + if ((bh = ext3_bread(handle, inode, *block, 1, err))) { +@@ -58,6 +61,8 @@ + EXT3_I(inode)->i_disksize = inode->i_size; + ext3_journal_get_write_access(handle,bh); + } ++ up(&EXT3_I(inode)->i_append_sem); ++ + return bh; + } + +@@ -134,6 +139,8 @@ + struct buffer_head *bh; + struct dx_entry *entries; + struct dx_entry *at; ++ unsigned long leaf; ++ unsigned int curidx; + }; + + struct dx_map_entry +@@ -142,6 +149,30 @@ + u32 offs; + }; + ++/* FIXME: this should be reworked using bb_spin_lock ++ * introduced in -mm tree ++ */ ++#define BH_DXLock 25 ++ ++static inline void dx_lock_bh(struct buffer_head volatile *bh) ++{ ++#ifdef CONFIG_SMP ++ while (test_and_set_bit(BH_DXLock, &bh->b_state)) { ++ while (test_bit(BH_DXLock, &bh->b_state)) ++ cpu_relax(); ++ } ++#endif ++} ++ ++static inline void dx_unlock_bh(struct buffer_head *bh) ++{ ++#ifdef CONFIG_SMP ++ smp_mb__before_clear_bit(); ++ clear_bit(BH_DXLock, &bh->b_state); ++#endif ++} ++ ++ + #ifdef CONFIG_EXT3_INDEX + static inline unsigned dx_get_block (struct dx_entry *entry); + static void dx_set_block (struct dx_entry *entry, unsigned value); +@@ -153,7 +184,7 @@ + static void dx_set_limit (struct dx_entry *entries, unsigned value); + static unsigned dx_root_limit (struct inode *dir, unsigned infosize); + static unsigned dx_node_limit (struct inode *dir); +-static struct dx_frame *dx_probe(struct dentry *dentry, ++static struct dx_frame *dx_probe(struct qstr *name, + struct inode *dir, + struct dx_hash_info *hinfo, + struct dx_frame *frame, +@@ -165,15 +196,18 @@ + static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to, + struct dx_map_entry *offsets, int count); + static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size); +-static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block); ++static void dx_insert_block (struct inode *, struct dx_frame *, u32, u32, u32); + static int ext3_htree_next_block(struct inode *dir, __u32 hash, + struct dx_frame *frame, + struct dx_frame *frames, int *err, + __u32 *start_hash); + static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, +- struct ext3_dir_entry_2 **res_dir, int *err); ++ struct ext3_dir_entry_2 **res_dir, int *err, ++ int rwlock, void **lock); + static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, + struct inode *inode); ++static inline void *ext3_lock_htree(struct inode *, unsigned long, int); ++static inline void ext3_unlock_htree(struct inode *, void *); + + /* + * Future: use high four bits of block for coalesce-on-delete flags +@@ -306,6 +340,94 @@ + #endif /* DX_DEBUG */ + + /* ++ * dx_find_position ++ * ++ * search position of specified hash in index ++ * ++ */ ++ ++struct dx_entry * dx_find_position(struct dx_entry * entries, u32 hash) ++{ ++ struct dx_entry *p, *q, *m; ++ int count; ++ ++ count = dx_get_count(entries); ++ p = entries + 1; ++ q = entries + count - 1; ++ while (p <= q) ++ { ++ m = p + (q - p)/2; ++ if (dx_get_hash(m) > hash) ++ q = m - 1; ++ else ++ p = m + 1; ++ } ++ return p - 1; ++} ++ ++/* ++ * returns 1 if path is unchanged ++ */ ++int dx_check_path(struct dx_frame *frame, u32 hash) ++{ ++ struct dx_entry *p; ++ int ret = 1; ++ ++ dx_lock_bh(frame->bh); ++ p = dx_find_position(frame->entries, hash); ++ if (frame->leaf != dx_get_block(p)) ++ ret = 0; ++ dx_unlock_bh(frame->bh); ++ ++ return ret; ++} ++ ++/* ++ * 0 - changed ++ * 1 - hasn't changed ++ */ ++static int ++dx_check_full_path(struct dx_frame *frames, struct dx_hash_info *hinfo) ++{ ++ struct dx_entry *p; ++ struct dx_frame *frame = frames; ++ u32 leaf; ++ ++ /* check first level */ ++ dx_lock_bh(frame->bh); ++ p = dx_find_position(frame->entries, hinfo->hash); ++ leaf = dx_get_block(p); ++ dx_unlock_bh(frame->bh); ++ ++ if (leaf != frame->leaf) ++ return 0; ++ ++ /* is there 2nd level? */ ++ frame++; ++ if (frame->bh == NULL) ++ return 1; ++ ++ /* check second level */ ++ dx_lock_bh(frame->bh); ++ ++ /* probably 1st level got changed, check it */ ++ if (!dx_check_path(frames, hinfo->hash)) { ++ /* path changed */ ++ dx_unlock_bh(frame->bh); ++ return 0; ++ } ++ ++ p = dx_find_position(frame->entries, hinfo->hash); ++ leaf = dx_get_block(p); ++ dx_unlock_bh(frame->bh); ++ ++ if (leaf != frame->leaf) ++ return 0; ++ ++ return 1; ++} ++ ++/* + * Probe for a directory leaf block to search. + * + * dx_probe can return ERR_BAD_DX_DIR, which means there was a format +@@ -315,19 +437,20 @@ + * back to userspace. + */ + static struct dx_frame * +-dx_probe(struct dentry *dentry, struct inode *dir, ++dx_probe(struct qstr *name, struct inode *dir, + struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err) + { +- unsigned count, indirect; +- struct dx_entry *at, *entries, *p, *q, *m; ++ unsigned indirect; ++ struct dx_entry *at, *entries; + struct dx_root *root; + struct buffer_head *bh; + struct dx_frame *frame = frame_in; + u32 hash; ++ unsigned int curidx; + + frame->bh = NULL; +- if (dentry) +- dir = dentry->d_parent->d_inode; ++ frame[1].bh = NULL; ++ + if (!(bh = ext3_bread (NULL,dir, 0, 0, err))) + goto fail; + root = (struct dx_root *) bh->b_data; +@@ -343,8 +466,8 @@ + } + hinfo->hash_version = root->info.hash_version; + hinfo->seed = dir->i_sb->u.ext3_sb.s_hash_seed; +- if (dentry) +- ext3fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo); ++ if (name) ++ ext3fs_dirhash(name->name, name->len, hinfo); + hash = hinfo->hash; + + if (root->info.unused_flags & 1) { +@@ -356,7 +479,19 @@ + goto fail; + } + ++repeat: ++ curidx = 0; ++ entries = (struct dx_entry *) (((char *)&root->info) + ++ root->info.info_length); ++ assert(dx_get_limit(entries) == dx_root_limit(dir, ++ root->info.info_length)); ++ dxtrace (printk("Look up %x", hash)); ++ dx_lock_bh(bh); ++ /* indirect must be initialized under bh lock because ++ * 2nd level creation procedure may change it and dx_probe() ++ * will suggest htree is still single-level -bzzz */ + if ((indirect = root->info.indirect_levels) > 1) { ++ dx_unlock_bh(bh); + ext3_warning(dir->i_sb, __FUNCTION__, + "Unimplemented inode hash depth: %#06x", + root->info.indirect_levels); +@@ -364,56 +499,46 @@ + *err = ERR_BAD_DX_DIR; + goto fail; + } +- +- entries = (struct dx_entry *) (((char *)&root->info) + +- root->info.info_length); +- assert(dx_get_limit(entries) == dx_root_limit(dir, +- root->info.info_length)); +- dxtrace (printk("Look up %x", hash)); ++ + while (1) + { +- count = dx_get_count(entries); +- assert (count && count <= dx_get_limit(entries)); +- p = entries + 1; +- q = entries + count - 1; +- while (p <= q) +- { +- m = p + (q - p)/2; +- dxtrace(printk(".")); +- if (dx_get_hash(m) > hash) +- q = m - 1; +- else +- p = m + 1; +- } +- +- if (0) // linear search cross check +- { +- unsigned n = count - 1; +- at = entries; +- while (n--) +- { +- dxtrace(printk(",")); +- if (dx_get_hash(++at) > hash) +- { +- at--; +- break; +- } +- } +- assert (at == p - 1); +- } +- +- at = p - 1; +- dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at))); ++ at = dx_find_position(entries, hinfo->hash); ++ dxtrace(printk(" %x->%u\n", ++ at == entries? 0: dx_get_hash(at), ++ dx_get_block(at))); + frame->bh = bh; + frame->entries = entries; + frame->at = at; +- if (!indirect--) return frame; +- if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err))) ++ frame->curidx = curidx; ++ frame->leaf = dx_get_block(at); ++ if (!indirect--) { ++ dx_unlock_bh(bh); ++ return frame; ++ } ++ ++ /* step into next htree level */ ++ curidx = dx_get_block(at); ++ dx_unlock_bh(bh); ++ if (!(bh = ext3_bread (NULL,dir, frame->leaf, 0, err))) + goto fail2; ++ ++ dx_lock_bh(bh); ++ /* splitting may change root index block and move ++ * hash we're looking for into another index block ++ * so, we have to check this situation and repeat ++ * from begining if path got changed -bzzz */ ++ if (!dx_check_path(frame, hash)) { ++ dx_unlock_bh(bh); ++ bh = frame->bh; ++ indirect++; ++ goto repeat; ++ } ++ + at = entries = ((struct dx_node *) bh->b_data)->entries; + assert (dx_get_limit(entries) == dx_node_limit (dir)); + frame++; + } ++ dx_unlock_bh(bh); + fail2: + while (frame >= frame_in) { + brelse(frame->bh); +@@ -427,8 +552,7 @@ + { + if (frames[0].bh == NULL) + return; +- +- if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels) ++ if (frames[1].bh != NULL) + brelse(frames[1].bh); + brelse(frames[0].bh); + } +@@ -470,8 +594,10 @@ + * nodes need to be read. + */ + while (1) { +- if (++(p->at) < p->entries + dx_get_count(p->entries)) ++ if (++(p->at) < p->entries + dx_get_count(p->entries)) { ++ p->leaf = dx_get_block(p->at); + break; ++ } + if (p == frames) + return 0; + num_frames++; +@@ -497,13 +623,17 @@ + * block so no check is necessary + */ + while (num_frames--) { +- if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at), +- 0, err))) ++ u32 idx; ++ ++ idx = p->leaf = dx_get_block(p->at); ++ if (!(bh = ext3_bread(NULL, dir, idx, 0, err))) + return -1; /* Failure */ + p++; + brelse (p->bh); + p->bh = bh; + p->at = p->entries = ((struct dx_node *) bh->b_data)->entries; ++ p->curidx = idx; ++ p->leaf = dx_get_block(p->at); + } + return 1; + } +@@ -543,7 +673,7 @@ + dir = dir_file->f_dentry->d_inode; + hinfo.hash = start_hash; + hinfo.minor_hash = 0; +- frame = dx_probe(0, dir_file->f_dentry->d_inode, &hinfo, frames, &err); ++ frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err); + if (!frame) + return err; + +@@ -625,7 +755,8 @@ + count++; + } + /* XXX: do we need to check rec_len == 0 case? -Chris */ +- de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); ++ de = (struct ext3_dir_entry_2 *)((char*)de + ++ le16_to_cpu(de->rec_len)); + } + return count; + } +@@ -658,7 +789,8 @@ + } while(more); + } + +-static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block) ++static void dx_insert_block(struct inode *dir, struct dx_frame *frame, ++ u32 hash, u32 block, u32 idx) + { + struct dx_entry *entries = frame->entries; + struct dx_entry *old = frame->at, *new = old + 1; +@@ -670,6 +802,7 @@ + dx_set_hash(new, hash); + dx_set_block(new, block); + dx_set_count(entries, count + 1); ++ + } + #endif + +@@ -752,7 +885,8 @@ + + + static struct buffer_head * ext3_find_entry (struct dentry *dentry, +- struct ext3_dir_entry_2 ** res_dir) ++ struct ext3_dir_entry_2 ** res_dir, ++ int rwlock, void **lock) + { + struct super_block * sb; + struct buffer_head * bh_use[NAMEI_RA_SIZE]; +@@ -768,6 +902,7 @@ + int namelen; + const u8 *name; + unsigned blocksize; ++ int do_not_use_dx = 0; + + *res_dir = NULL; + sb = dir->i_sb; +@@ -776,9 +911,10 @@ + name = dentry->d_name.name; + if (namelen > EXT3_NAME_LEN) + return NULL; ++repeat: + #ifdef CONFIG_EXT3_INDEX + if (is_dx(dir)) { +- bh = ext3_dx_find_entry(dentry, res_dir, &err); ++ bh = ext3_dx_find_entry(dentry, res_dir, &err, rwlock, lock); + /* + * On success, or if the error was file not found, + * return. Otherwise, fall back to doing a search the +@@ -787,8 +923,14 @@ + if (bh || (err != ERR_BAD_DX_DIR)) + return bh; + dxtrace(printk("ext3_find_entry: dx failed, falling back\n")); ++ do_not_use_dx = 1; + } + #endif ++ *lock = ext3_lock_htree(dir, 0, rwlock); ++ if (is_dx(dir) && !do_not_use_dx) { ++ ext3_unlock_htree(dir, *lock); ++ goto repeat; ++ } + nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb); + start = EXT3_I(dir)->i_dir_start_lookup; + if (start >= nblocks) +@@ -860,12 +1002,17 @@ + /* Clean up the read-ahead blocks */ + for (; ra_ptr < ra_max; ra_ptr++) + brelse (bh_use[ra_ptr]); ++ if (!ret) { ++ ext3_unlock_htree(dir, *lock); ++ *lock = NULL; ++ } + return ret; + } + + #ifdef CONFIG_EXT3_INDEX + static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, +- struct ext3_dir_entry_2 **res_dir, int *err) ++ struct ext3_dir_entry_2 **res_dir, int *err, ++ int rwlock, void **lock) + { + struct super_block * sb; + struct dx_hash_info hinfo; +@@ -880,11 +1027,22 @@ + struct inode *dir = dentry->d_parent->d_inode; + + sb = dir->i_sb; +- if (!(frame = dx_probe (dentry, 0, &hinfo, frames, err))) ++repeat: ++ if (!(frame = dx_probe (&dentry->d_name, dir, &hinfo, frames, err))) + return NULL; ++ ++ *lock = ext3_lock_htree(dir, frame->leaf, rwlock); ++ /* while locking leaf we just found may get splitted ++ * so, we need another leaf. check this */ ++ if (!dx_check_full_path(frames, &hinfo)) { ++ ext3_unlock_htree(dir, *lock); ++ dx_release(frames); ++ goto repeat; ++ } ++ + hash = hinfo.hash; + do { +- block = dx_get_block(frame->at); ++ block = frame->leaf; + if (!(bh = ext3_bread (NULL,dir, block, 0, err))) + goto errout; + de = (struct ext3_dir_entry_2 *) bh->b_data; +@@ -918,6 +1076,8 @@ + *err = -ENOENT; + errout: + dxtrace(printk("%s not found\n", name)); ++ ext3_unlock_htree(dir, *lock); ++ *lock = NULL; + dx_release (frames); + return NULL; + } +@@ -928,6 +1088,7 @@ + struct inode * inode; + struct ext3_dir_entry_2 * de; + struct buffer_head * bh; ++ void *lock = NULL; + + if (dentry->d_name.len > EXT3_NAME_LEN) + return ERR_PTR(-ENAMETOOLONG); +@@ -935,10 +1096,11 @@ + if (ext3_check_for_iopen(dir, dentry)) + return NULL; + +- bh = ext3_find_entry(dentry, &de); ++ bh = ext3_find_entry(dentry, &de, 0, &lock); + inode = NULL; + if (bh) { + unsigned long ino = le32_to_cpu(de->inode); ++ ext3_unlock_htree(dir, lock); + brelse (bh); + inode = iget(dir->i_sb, ino); + +@@ -975,7 +1137,8 @@ + unsigned rec_len = 0; + + while (count--) { +- struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) (from + map->offs); ++ struct ext3_dir_entry_2 *de = ++ (struct ext3_dir_entry_2 *) (from + map->offs); + rec_len = EXT3_DIR_REC_LEN(de->name_len); + memcpy (to, de, rec_len); + ((struct ext3_dir_entry_2 *) to)->rec_len = rec_len; +@@ -988,7 +1151,8 @@ + + static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size) + { +- struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base; ++ struct ext3_dir_entry_2 *next, *to, *prev; ++ struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) base; + unsigned rec_len = 0; + + prev = to = de; +@@ -1010,7 +1174,8 @@ + + static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, + struct buffer_head **bh,struct dx_frame *frame, +- struct dx_hash_info *hinfo, int *error) ++ struct dx_hash_info *hinfo, void **target, ++ int *error) + { + unsigned blocksize = dir->i_sb->s_blocksize; + unsigned count, continued; +@@ -1057,23 +1222,30 @@ + hash2 = map[split].hash; + continued = hash2 == map[split - 1].hash; + dxtrace(printk("Split block %i at %x, %i/%i\n", +- dx_get_block(frame->at), hash2, split, count-split)); +- ++ frame->leaf, hash2, split, count-split)); ++ + /* Fancy dance to stay within two buffers */ + de2 = dx_move_dirents(data1, data2, map + split, count - split); + de = dx_pack_dirents(data1,blocksize); + de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); + de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2); +- dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1)); +- dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1)); ++ dxtrace(dx_show_leaf(hinfo,(struct ext3_dir_entry_2*) data1, blocksize, 1)); ++ dxtrace(dx_show_leaf(hinfo,(struct ext3_dir_entry_2*) data2, blocksize, 1)); + + /* Which block gets the new entry? */ ++ *target = NULL; + if (hinfo->hash >= hash2) + { + swap(*bh, bh2); + de = de2; +- } +- dx_insert_block (frame, hash2 + continued, newblock); ++ ++ /* entry will be stored into new block ++ * we have to lock it before add_dirent_to_buf */ ++ *target = ext3_lock_htree(dir, newblock, 1); ++ } ++ dx_lock_bh(frame->bh); ++ dx_insert_block (dir, frame, hash2 + continued, newblock, frame->curidx); ++ dx_unlock_bh(frame->bh); + err = ext3_journal_dirty_metadata (handle, bh2); + if (err) + goto journal_error; +@@ -1147,7 +1319,8 @@ + nlen = EXT3_DIR_REC_LEN(de->name_len); + rlen = le16_to_cpu(de->rec_len); + if (de->inode) { +- struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen); ++ struct ext3_dir_entry_2 *de1 = ++ (struct ext3_dir_entry_2 *)((char *)de + nlen); + de1->rec_len = cpu_to_le16(rlen - nlen); + de->rec_len = cpu_to_le16(nlen); + de = de1; +@@ -1205,7 +1378,8 @@ + unsigned blocksize; + struct dx_hash_info hinfo; + u32 block; +- ++ void *lock, *new_lock; ++ + blocksize = dir->i_sb->s_blocksize; + dxtrace(printk("Creating index\n")); + retval = ext3_journal_get_write_access(handle, bh); +@@ -1216,7 +1390,6 @@ + } + root = (struct dx_root *) bh->b_data; + +- EXT3_I(dir)->i_flags |= EXT3_INDEX_FL; + bh2 = ext3_append (handle, dir, &block, &retval); + if (!(bh2)) { + brelse(bh); +@@ -1224,6 +1397,8 @@ + } + data1 = bh2->b_data; + ++ lock = ext3_lock_htree(dir, block, 1); ++ + /* The 0th block becomes the root, move the dirents out */ + de = (struct ext3_dir_entry_2 *) &root->dotdot; + de = (struct ext3_dir_entry_2 *) ((char *)de + de->rec_len); +@@ -1253,13 +1428,25 @@ + frame->entries = entries; + frame->at = entries; + frame->bh = bh; ++ frame->curidx = 0; ++ frame->leaf = 0; ++ frame[1].bh = NULL; + bh = bh2; +- de = do_split(handle,dir, &bh, frame, &hinfo, &retval); ++ de = do_split(handle,dir, &bh, frame, &hinfo, &new_lock, &retval); + dx_release (frames); + if (!(de)) +- return retval; ++ goto cleanup; ++ ++ retval = add_dirent_to_buf(handle, dentry, inode, de, bh); ++cleanup: ++ if (new_lock) ++ ext3_unlock_htree(dir, new_lock); ++ /* we mark directory indexed in order to ++ * avoid races while htree being created -bzzz */ ++ EXT3_I(dir)->i_flags |= EXT3_INDEX_FL; ++ ext3_unlock_htree(dir, lock); + +- return add_dirent_to_buf(handle, dentry, inode, de, bh); ++ return retval; + } + #endif + +@@ -1288,11 +1475,13 @@ + unsigned blocksize; + unsigned nlen, rlen; + u32 block, blocks; ++ void *lock; + + sb = dir->i_sb; + blocksize = sb->s_blocksize; + if (!dentry->d_name.len) + return -EINVAL; ++repeat: + #ifdef CONFIG_EXT3_INDEX + if (is_dx(dir)) { + retval = ext3_dx_add_entry(handle, dentry, inode); +@@ -1303,36 +1492,53 @@ + ext3_mark_inode_dirty(handle, dir); + } + #endif ++ lock = ext3_lock_htree(dir, 0, 1); ++ if (is_dx(dir)) { ++ /* we got lock for block 0 ++ * probably previous holder of the lock ++ * created htree -bzzz */ ++ ext3_unlock_htree(dir, lock); ++ goto repeat; ++ } ++ + blocks = dir->i_size >> sb->s_blocksize_bits; + for (block = 0, offset = 0; block < blocks; block++) { + bh = ext3_bread(handle, dir, block, 0, &retval); +- if(!bh) ++ if(!bh) { ++ ext3_unlock_htree(dir, lock); + return retval; ++ } + retval = add_dirent_to_buf(handle, dentry, inode, 0, bh); +- if (retval != -ENOSPC) ++ if (retval != -ENOSPC) { ++ ext3_unlock_htree(dir, lock); + return retval; ++ } + + #ifdef CONFIG_EXT3_INDEX + if (blocks == 1 && !dx_fallback && +- EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX)) +- return make_indexed_dir(handle, dentry, inode, bh); ++ EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX)) { ++ retval = make_indexed_dir(handle, dentry, inode, bh); ++ ext3_unlock_htree(dir, lock); ++ return retval; ++ } + #endif + brelse(bh); + } + bh = ext3_append(handle, dir, &block, &retval); +- if (!bh) ++ if (!bh) { ++ ext3_unlock_htree(dir, lock); + return retval; ++ } + de = (struct ext3_dir_entry_2 *) bh->b_data; + de->inode = 0; + de->rec_len = cpu_to_le16(rlen = blocksize); + nlen = 0; +- return add_dirent_to_buf(handle, dentry, inode, de, bh); ++ retval = add_dirent_to_buf(handle, dentry, inode, de, bh); ++ ext3_unlock_htree(dir, lock); ++ return retval; + } + + #ifdef CONFIG_EXT3_INDEX +-/* +- * Returns 0 for success, or a negative error value +- */ + static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, + struct inode *inode) + { +@@ -1344,15 +1550,28 @@ + struct super_block * sb = dir->i_sb; + struct ext3_dir_entry_2 *de; + int err; +- +- frame = dx_probe(dentry, 0, &hinfo, frames, &err); ++ int curidx; ++ void *idx_lock, *leaf_lock, *newleaf_lock; ++ ++repeat: ++ frame = dx_probe(&dentry->d_name, dir, &hinfo, frames, &err); + if (!frame) + return err; +- entries = frame->entries; +- at = frame->at; + +- if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err))) ++ /* we're going to chage leaf, so lock it first */ ++ leaf_lock = ext3_lock_htree(dir, frame->leaf, 1); ++ ++ /* while locking leaf we just found may get splitted ++ * so we need to check this */ ++ if (!dx_check_full_path(frames, &hinfo)) { ++ ext3_unlock_htree(dir, leaf_lock); ++ dx_release(frames); ++ goto repeat; ++ } ++ if (!(bh = ext3_bread(handle,dir, frame->leaf, 0, &err))) { ++ printk("can't ext3_bread(%d) = %d\n", (int) frame->leaf, err); + goto cleanup; ++ } + + BUFFER_TRACE(bh, "get_write_access"); + err = ext3_journal_get_write_access(handle, bh); +@@ -1365,6 +1584,35 @@ + goto cleanup; + } + ++ /* our leaf has no enough space. hence, we have to ++ * split it. so lock index for this leaf first */ ++ curidx = frame->curidx; ++ idx_lock = ext3_lock_htree(dir, curidx, 1); ++ ++ /* now check did path get changed? */ ++ dx_release(frames); ++ ++ frame = dx_probe(&dentry->d_name, dentry->d_parent->d_inode, ++ &hinfo, frames, &err); ++ if (!frame) { ++ /* FIXME: error handling here */ ++ brelse(bh); ++ ext3_unlock_htree(dir, idx_lock); ++ return err; ++ } ++ ++ if (frame->curidx != curidx) { ++ /* path has been changed. we have to drop old lock ++ * and repeat */ ++ brelse(bh); ++ ext3_unlock_htree(dir, idx_lock); ++ ext3_unlock_htree(dir, leaf_lock); ++ dx_release(frames); ++ goto repeat; ++ } ++ entries = frame->entries; ++ at = frame->at; ++ + /* Block full, should compress but for now just split */ + dxtrace(printk("using %u of %u node entries\n", + dx_get_count(entries), dx_get_limit(entries))); +@@ -1376,7 +1624,8 @@ + struct dx_entry *entries2; + struct dx_node *node2; + struct buffer_head *bh2; +- ++ void *nb_lock; ++ + if (levels && (dx_get_count(frames->entries) == + dx_get_limit(frames->entries))) { + ext3_warning(sb, __FUNCTION__, +@@ -1387,6 +1636,7 @@ + bh2 = ext3_append (handle, dir, &newblock, &err); + if (!(bh2)) + goto cleanup; ++ nb_lock = ext3_lock_htree(dir, newblock, 1); + node2 = (struct dx_node *)(bh2->b_data); + entries2 = node2->entries; + node2->fake.rec_len = cpu_to_le16(sb->s_blocksize); +@@ -1398,27 +1648,73 @@ + if (levels) { + unsigned icount1 = icount/2, icount2 = icount - icount1; + unsigned hash2 = dx_get_hash(entries + icount1); ++ void *ri_lock; ++ ++ /* we have to protect root htree index against ++ * another dx_add_entry() which would want to ++ * split it too -bzzz */ ++ ri_lock = ext3_lock_htree(dir, 0, 1); ++ ++ /* as root index block blocked we must repeat ++ * searching for current position of our 2nd index -bzzz */ ++ dx_lock_bh(frame->bh); ++ frames->at = dx_find_position(frames->entries, hinfo.hash); ++ dx_unlock_bh(frame->bh); ++ + dxtrace(printk("Split index %i/%i\n", icount1, icount2)); +- +- BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */ ++ ++ BUFFER_TRACE(frame->bh, "get_write_access"); + err = ext3_journal_get_write_access(handle, + frames[0].bh); + if (err) + goto journal_error; +- ++ ++ /* copy index into new one */ + memcpy ((char *) entries2, (char *) (entries + icount1), + icount2 * sizeof(struct dx_entry)); +- dx_set_count (entries, icount1); + dx_set_count (entries2, icount2); + dx_set_limit (entries2, dx_node_limit(dir)); + + /* Which index block gets the new entry? */ + if (at - entries >= icount1) { ++ /* unlock index we won't use */ ++ ext3_unlock_htree(dir, idx_lock); ++ idx_lock = nb_lock; + frame->at = at = at - entries - icount1 + entries2; +- frame->entries = entries = entries2; ++ frame->entries = entries2; ++ frame->curidx = curidx = newblock; + swap(frame->bh, bh2); ++ } else { ++ /* we'll use old index,so new one may be freed */ ++ ext3_unlock_htree(dir, nb_lock); + } +- dx_insert_block (frames + 0, hash2, newblock); ++ ++ /* NOTE: very subtle piece of code ++ * competing dx_probe() may find 2nd level index in root ++ * index, then we insert new index here and set new count ++ * in that 2nd level index. so, dx_probe() may see 2nd ++ * level index w/o hash it looks for. the solution is ++ * to check root index after we locked just founded 2nd ++ * level index -bzzz */ ++ dx_lock_bh(frames[0].bh); ++ dx_insert_block (dir, frames + 0, hash2, newblock, 0); ++ dx_unlock_bh(frames[0].bh); ++ ++ /* now old and new 2nd level index blocks contain ++ * all pointers, so dx_probe() may find it in the both. ++ * it's OK -bzzz */ ++ ++ dx_lock_bh(frame->bh); ++ dx_set_count(entries, icount1); ++ dx_unlock_bh(frame->bh); ++ ++ /* now old 2nd level index block points to first half ++ * of leafs. it's importand that dx_probe() must ++ * check root index block for changes under ++ * dx_lock_bh(frame->bh) -bzzz */ ++ ++ ext3_unlock_htree(dir, ri_lock); ++ + dxtrace(dx_show_index ("node", frames[1].entries)); + dxtrace(dx_show_index ("node", + ((struct dx_node *) bh2->b_data)->entries)); +@@ -1427,38 +1723,61 @@ + goto journal_error; + brelse (bh2); + } else { ++ unsigned long leaf = frame->leaf; ++ + dxtrace(printk("Creating second level index...\n")); + memcpy((char *) entries2, (char *) entries, + icount * sizeof(struct dx_entry)); + dx_set_limit(entries2, dx_node_limit(dir)); + + /* Set up root */ ++ dx_lock_bh(frames[0].bh); + dx_set_count(entries, 1); + dx_set_block(entries + 0, newblock); + ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1; ++ dx_unlock_bh(frames[0].bh); + + /* Add new access path frame */ + frame = frames + 1; + frame->at = at = at - entries + entries2; + frame->entries = entries = entries2; + frame->bh = bh2; ++ frame->curidx = newblock; ++ frame->leaf = leaf; + err = ext3_journal_get_write_access(handle, + frame->bh); + if (err) + goto journal_error; ++ ++ /* first level index was root. it's already initialized */ ++ /* we my unlock it now */ ++ ext3_unlock_htree(dir, idx_lock); ++ ++ /* current index is just created 2nd level index */ ++ curidx = newblock; ++ idx_lock = nb_lock; + } + ext3_journal_dirty_metadata(handle, frames[0].bh); + } +- de = do_split(handle, dir, &bh, frame, &hinfo, &err); ++ de = do_split(handle, dir, &bh, frame, &hinfo, &newleaf_lock, &err); + if (!de) + goto cleanup; ++ ++ /* index splitted */ ++ ext3_unlock_htree(dir, idx_lock); ++ + err = add_dirent_to_buf(handle, dentry, inode, de, bh); ++ ++ if (newleaf_lock) ++ ext3_unlock_htree(dir, newleaf_lock); ++ + bh = 0; + goto cleanup; + + journal_error: + ext3_std_error(dir->i_sb, err); + cleanup: ++ ext3_unlock_htree(dir, leaf_lock); + if (bh) + brelse(bh); + dx_release(frames); +@@ -1902,6 +2221,7 @@ + struct buffer_head * bh; + struct ext3_dir_entry_2 * de; + handle_t *handle; ++ void *lock; + + handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); + if (IS_ERR(handle)) { +@@ -1909,7 +2229,7 @@ + } + + retval = -ENOENT; +- bh = ext3_find_entry (dentry, &de); ++ bh = ext3_find_entry (dentry, &de, 1, &lock); + if (!bh) + goto end_rmdir; + +@@ -1920,14 +2240,19 @@ + DQUOT_INIT(inode); + + retval = -EIO; +- if (le32_to_cpu(de->inode) != inode->i_ino) ++ if (le32_to_cpu(de->inode) != inode->i_ino) { ++ ext3_unlock_htree(dir, lock); + goto end_rmdir; ++ } + + retval = -ENOTEMPTY; +- if (!empty_dir (inode)) ++ if (!empty_dir (inode)) { ++ ext3_unlock_htree(dir, lock); + goto end_rmdir; ++ } + + retval = ext3_delete_entry(handle, dir, de, bh); ++ ext3_unlock_htree(dir, lock); + if (retval) + goto end_rmdir; + if (inode->i_nlink != 2) +@@ -1956,6 +2281,7 @@ + struct buffer_head * bh; + struct ext3_dir_entry_2 * de; + handle_t *handle; ++ void *lock; + + handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); + if (IS_ERR(handle)) { +@@ -1966,7 +2292,7 @@ + handle->h_sync = 1; + + retval = -ENOENT; +- bh = ext3_find_entry (dentry, &de); ++ bh = ext3_find_entry (dentry, &de, 1, &lock); + if (!bh) + goto end_unlink; + +@@ -1974,8 +2300,10 @@ + DQUOT_INIT(inode); + + retval = -EIO; +- if (le32_to_cpu(de->inode) != inode->i_ino) ++ if (le32_to_cpu(de->inode) != inode->i_ino) { ++ ext3_unlock_htree(dir, lock); + goto end_unlink; ++ } + + if (!inode->i_nlink) { + ext3_warning (inode->i_sb, "ext3_unlink", +@@ -1984,6 +2312,7 @@ + inode->i_nlink = 1; + } + retval = ext3_delete_entry(handle, dir, de, bh); ++ ext3_unlock_htree(dir, lock); + if (retval) + goto end_unlink; + dir->i_ctime = dir->i_mtime = CURRENT_TIME; +@@ -2121,6 +2450,7 @@ + struct buffer_head * old_bh, * new_bh, * dir_bh; + struct ext3_dir_entry_2 * old_de, * new_de; + int retval; ++ void *lock1 = NULL, *lock2 = NULL, *lock3 = NULL; + + old_bh = new_bh = dir_bh = NULL; + +@@ -2133,7 +2463,10 @@ + if (IS_SYNC(old_dir) || IS_SYNC(new_dir)) + handle->h_sync = 1; + +- old_bh = ext3_find_entry (old_dentry, &old_de); ++ if (old_dentry->d_parent == new_dentry->d_parent) ++ down(&EXT3_I(old_dentry->d_parent->d_inode)->i_rename_sem); ++ ++ old_bh = ext3_find_entry (old_dentry, &old_de, 1, &lock1 /* FIXME */); + /* + * Check for inode number is _not_ due to possible IO errors. + * We might rmdir the source, keep it as pwd of some process +@@ -2146,7 +2479,7 @@ + goto end_rename; + + new_inode = new_dentry->d_inode; +- new_bh = ext3_find_entry (new_dentry, &new_de); ++ new_bh = ext3_find_entry (new_dentry, &new_de, 1, &lock2 /* FIXME */); + if (new_bh) { + if (!new_inode) { + brelse (new_bh); +@@ -2209,7 +2542,7 @@ + struct buffer_head *old_bh2; + struct ext3_dir_entry_2 *old_de2; + +- old_bh2 = ext3_find_entry(old_dentry, &old_de2); ++ old_bh2 = ext3_find_entry(old_dentry, &old_de2, 1, &lock3 /* FIXME */); + if (old_bh2) { + retval = ext3_delete_entry(handle, old_dir, + old_de2, old_bh2); +@@ -2252,6 +2585,14 @@ + retval = 0; + + end_rename: ++ if (lock1) ++ ext3_unlock_htree(old_dentry->d_parent->d_inode, lock1); ++ if (lock2) ++ ext3_unlock_htree(new_dentry->d_parent->d_inode, lock2); ++ if (lock3) ++ ext3_unlock_htree(old_dentry->d_parent->d_inode, lock3); ++ if (old_dentry->d_parent == new_dentry->d_parent) ++ up(&EXT3_I(old_dentry->d_parent->d_inode)->i_rename_sem); + brelse (dir_bh); + brelse (old_bh); + brelse (new_bh); +@@ -2260,6 +2601,29 @@ + } + + /* ++ * this locking primitives are used to protect parts ++ * of dir's htree. protection unit is block: leaf or index ++ */ ++static inline void *ext3_lock_htree(struct inode *dir, ++ unsigned long value, int rwlock) ++{ ++ void *lock; ++ ++ if (!test_opt(dir->i_sb, PDIROPS)) ++ return NULL; ++ lock = dynlock_lock(&EXT3_I(dir)->i_htree_lock, value, 1, GFP_KERNEL); ++ return lock; ++} ++ ++static inline void ext3_unlock_htree(struct inode *dir, ++ void *lock) ++{ ++ if (!test_opt(dir->i_sb, PDIROPS) || !lock) ++ return; ++ dynlock_unlock(&EXT3_I(dir)->i_htree_lock, lock); ++} ++ ++/* + * directories can handle most operations... + */ + struct inode_operations ext3_dir_inode_operations = { +Index: linux-2.4.20/fs/ext3/super.c +=================================================================== +--- linux-2.4.20.orig/fs/ext3/super.c Wed Mar 17 15:37:09 2004 ++++ linux-2.4.20/fs/ext3/super.c Wed Mar 17 15:37:10 2004 +@@ -796,6 +796,8 @@ + return 0; + } + } ++ else if (!strcmp (this_char, "pdirops")) ++ set_opt (sbi->s_mount_opt, PDIROPS); + else if (!strcmp (this_char, "grpid") || + !strcmp (this_char, "bsdgroups")) + set_opt (*mount_options, GRPID); +@@ -822,6 +824,9 @@ + if (want_numeric(value, "sb", sb_block)) + return 0; + } ++ else if (!strcmp (this_char, "pdirops")) { ++ set_opt (sbi->s_mount_opt, PDIROPS); ++ } + #ifdef CONFIG_JBD_DEBUG + else if (!strcmp (this_char, "ro-after")) { + unsigned long v; +@@ -985,6 +990,10 @@ + ext3_check_inodes_bitmap (sb); + } + #endif ++#ifdef S_PDIROPS ++ if (test_opt (sb, PDIROPS)) ++ sb->s_flags |= S_PDIROPS; ++#endif + setup_ro_after(sb); + return res; + } +@@ -1484,6 +1493,11 @@ + test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered": + "writeback"); + ++ if (test_opt(sb, PDIROPS)) { ++ printk (KERN_INFO "EXT3-fs: mounted filesystem with parallel dirops\n"); ++ sb->s_flags |= S_PDIROPS; ++ } ++ + return sb; + + failed_mount3: +Index: linux-2.4.20/fs/ext3/inode.c +=================================================================== +--- linux-2.4.20.orig/fs/ext3/inode.c Wed Mar 17 15:37:09 2004 ++++ linux-2.4.20/fs/ext3/inode.c Wed Mar 17 15:37:10 2004 +@@ -2435,6 +2435,9 @@ + } else if (S_ISDIR(inode->i_mode)) { + inode->i_op = &ext3_dir_inode_operations; + inode->i_fop = &ext3_dir_operations; ++ dynlock_init(&EXT3_I(inode)->i_htree_lock); ++ sema_init(&EXT3_I(inode)->i_rename_sem, 1); ++ sema_init(&EXT3_I(inode)->i_append_sem, 1); + } else if (S_ISLNK(inode->i_mode)) { + if (ext3_inode_is_fast_symlink(inode)) + inode->i_op = &ext3_fast_symlink_inode_operations; +Index: linux-2.4.20/fs/ext3/ialloc.c +=================================================================== +--- linux-2.4.20.orig/fs/ext3/ialloc.c Wed Mar 17 15:37:09 2004 ++++ linux-2.4.20/fs/ext3/ialloc.c Wed Mar 17 15:37:10 2004 +@@ -601,6 +601,9 @@ + return ERR_PTR(-EDQUOT); + } + ext3_debug ("allocating inode %lu\n", inode->i_ino); ++ dynlock_init(&EXT3_I(inode)->i_htree_lock); ++ sema_init(&EXT3_I(inode)->i_rename_sem, 1); ++ sema_init(&EXT3_I(inode)->i_append_sem, 1); + return inode; + + fail: +Index: linux-2.4.20/include/linux/ext3_fs.h +=================================================================== +--- linux-2.4.20.orig/include/linux/ext3_fs.h Wed Mar 17 15:37:09 2004 ++++ linux-2.4.20/include/linux/ext3_fs.h Wed Mar 17 15:37:10 2004 +@@ -306,6 +306,7 @@ + /* + * Mount flags + */ ++#define EXT3_MOUNT_PDIROPS 0x800000/* Parallel dir operations */ + #define EXT3_MOUNT_CHECK 0x0001 /* Do mount-time checks */ + #define EXT3_MOUNT_GRPID 0x0004 /* Create files with directory's group */ + #define EXT3_MOUNT_DEBUG 0x0008 /* Some debugging messages */ +Index: linux-2.4.20/include/linux/ext3_fs_i.h +=================================================================== +--- linux-2.4.20.orig/include/linux/ext3_fs_i.h Thu Nov 22 11:46:19 2001 ++++ linux-2.4.20/include/linux/ext3_fs_i.h Wed Mar 17 15:37:10 2004 +@@ -17,6 +17,7 @@ + #define _LINUX_EXT3_FS_I + + #include ++#include + + /* + * second extended file system inode data in memory +@@ -73,6 +74,11 @@ + * by other means, so we have truncate_sem. + */ + struct rw_semaphore truncate_sem; ++ ++ /* following fields for parallel directory operations -bzzz */ ++ struct dynlock i_htree_lock; ++ struct semaphore i_append_sem; ++ struct semaphore i_rename_sem; + }; + + #endif /* _LINUX_EXT3_FS_I */ diff --git a/lustre/kernel_patches/patches/inode-max-readahead-2.4.24.patch b/lustre/kernel_patches/patches/inode-max-readahead-2.4.24.patch new file mode 100644 index 0000000..9203859 --- /dev/null +++ b/lustre/kernel_patches/patches/inode-max-readahead-2.4.24.patch @@ -0,0 +1,22 @@ +--- linux-2.4.24-l32/mm/filemap.c.inode_ramax 2004-03-14 13:16:21.000000000 -0800 ++++ linux-2.4.24-l32/mm/filemap.c 2004-03-16 10:57:14.000000000 -0800 +@@ -1226,6 +1226,8 @@ + + static inline int get_max_readahead(struct inode * inode) + { ++ if (inode->i_mapping->a_ops->max_readahead) ++ return inode->i_mapping->a_ops->max_readahead(inode); + if (!inode->i_dev || !max_readahead[MAJOR(inode->i_dev)]) + return vm_max_readahead; + return max_readahead[MAJOR(inode->i_dev)][MINOR(inode->i_dev)]; +--- linux-2.4.24-l32/include/linux/fs.h.inode_ramax 2004-03-14 13:15:49.000000000 -0800 ++++ linux-2.4.24-l32/include/linux/fs.h 2004-03-15 11:56:56.000000000 -0800 +@@ -410,6 +410,8 @@ + #define KERNEL_HAS_DIRECT_FILEIO /* Unfortunate kludge due to lack of foresight */ + int (*direct_fileIO)(int, struct file *, struct kiobuf *, unsigned long, int); + void (*removepage)(struct page *); /* called when page gets removed from the inode */ ++#define KERNEL_HAS_AS_MAX_READAHEAD ++ int (*max_readahead)(struct inode *); + }; + + struct address_space { diff --git a/lustre/kernel_patches/patches/iopen-2.4.20.patch b/lustre/kernel_patches/patches/iopen-2.4.20.patch index 8800e1f..f409533 100644 --- a/lustre/kernel_patches/patches/iopen-2.4.20.patch +++ b/lustre/kernel_patches/patches/iopen-2.4.20.patch @@ -8,10 +8,10 @@ include/linux/ext3_fs.h | 2 8 files changed, 318 insertions(+), 2 deletions(-) -Index: linux-2.4.22-uml/Documentation/filesystems/ext2.txt +Index: lum/Documentation/filesystems/ext2.txt =================================================================== ---- linux-2.4.22-uml.orig/Documentation/filesystems/ext2.txt 2001-07-11 16:44:45.000000000 -0600 -+++ linux-2.4.22-uml/Documentation/filesystems/ext2.txt 2004-01-30 14:18:10.000000000 -0700 +--- lum.orig/Documentation/filesystems/ext2.txt 2001-07-11 16:44:45.000000000 -0600 ++++ lum/Documentation/filesystems/ext2.txt 2004-03-09 16:46:38.000000000 -0700 @@ -35,6 +35,22 @@ sb=n Use alternate superblock at this location. @@ -35,10 +35,10 @@ Index: linux-2.4.22-uml/Documentation/filesystems/ext2.txt grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2. -Index: linux-2.4.22-uml/fs/ext3/Makefile +Index: lum/fs/ext3/Makefile =================================================================== ---- linux-2.4.22-uml.orig/fs/ext3/Makefile 2004-01-30 14:17:58.000000000 -0700 -+++ linux-2.4.22-uml/fs/ext3/Makefile 2004-01-30 14:18:10.000000000 -0700 +--- lum.orig/fs/ext3/Makefile 2004-01-30 14:54:50.000000000 -0700 ++++ lum/fs/ext3/Makefile 2004-03-09 16:46:39.000000000 -0700 @@ -11,7 +11,7 @@ export-objs := ext3-exports.o @@ -48,10 +48,10 @@ Index: linux-2.4.22-uml/fs/ext3/Makefile ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o obj-m := $(O_TARGET) -Index: linux-2.4.22-uml/fs/ext3/inode.c +Index: lum/fs/ext3/inode.c =================================================================== ---- linux-2.4.22-uml.orig/fs/ext3/inode.c 2004-01-30 14:17:59.000000000 -0700 -+++ linux-2.4.22-uml/fs/ext3/inode.c 2004-01-30 14:18:10.000000000 -0700 +--- lum.orig/fs/ext3/inode.c 2004-01-30 14:54:55.000000000 -0700 ++++ lum/fs/ext3/inode.c 2004-03-09 16:46:41.000000000 -0700 @@ -31,6 +31,7 @@ #include #include @@ -70,11 +70,11 @@ Index: linux-2.4.22-uml/fs/ext3/inode.c if(ext3_get_inode_loc(inode, &iloc)) goto bad_inode; bh = iloc.bh; -Index: linux-2.4.22-uml/fs/ext3/iopen.c +Index: lum/fs/ext3/iopen.c =================================================================== ---- linux-2.4.22-uml.orig/fs/ext3/iopen.c 2004-01-30 14:18:10.000000000 -0700 -+++ linux-2.4.22-uml/fs/ext3/iopen.c 2004-01-30 14:18:10.000000000 -0700 -@@ -0,0 +1,258 @@ +--- lum.orig/fs/ext3/iopen.c 2004-03-09 16:46:37.000000000 -0700 ++++ lum/fs/ext3/iopen.c 2004-03-09 16:48:03.000000000 -0700 +@@ -0,0 +1,282 @@ +/* + * linux/fs/ext3/iopen.c + * @@ -211,13 +211,24 @@ Index: linux-2.4.22-uml/fs/ext3/iopen.c + +/* This function is spliced into ext3_lookup and does the move of a + * disconnected dentry (if it exists) to a connected dentry. -+ * Caller must hold dcache_lock. + */ -+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode) ++struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode, ++ int rehash) +{ + struct dentry *tmp, *goal = NULL; + struct list_head *lp; + ++ /* verify this dentry is really new */ ++ assert(dentry->d_inode == NULL); ++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */ ++ if (rehash) ++ assert(list_empty(&dentry->d_hash)); /* d_rehash */ ++ assert(list_empty(&dentry->d_subdirs)); ++ ++ spin_lock(&dcache_lock); ++ if (!inode) ++ goto do_rehash; ++ + /* preferrably return a connected dentry */ + list_for_each(lp, &inode->i_dentry) { + tmp = list_entry(lp, struct dentry, d_alias); @@ -231,27 +242,40 @@ Index: linux-2.4.22-uml/fs/ext3/iopen.c + } + + if (!goal) -+ return NULL; ++ goto do_instantiate; + + /* Move the goal to the de hash queue - like d_move() */ + goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED; + list_del_init(&goal->d_hash); + + list_del(&goal->d_child); -+ list_del(&de->d_child); ++ list_del(&dentry->d_child); + + /* Switch the parents and the names.. */ -+ switch_names(goal, de); -+ do_switch(goal->d_parent, de->d_parent); -+ do_switch(goal->d_name.len, de->d_name.len); -+ do_switch(goal->d_name.hash, de->d_name.hash); ++ switch_names(goal, dentry); ++ do_switch(goal->d_parent, dentry->d_parent); ++ do_switch(goal->d_name.len, dentry->d_name.len); ++ do_switch(goal->d_name.hash, dentry->d_name.hash); + + /* And add them back to the (new) parent lists */ + list_add(&goal->d_child, &goal->d_parent->d_subdirs); -+ list_add(&de->d_child, &de->d_parent->d_subdirs); ++ list_add(&dentry->d_child, &dentry->d_parent->d_subdirs); + __d_rehash(goal, 0); ++ spin_unlock(&dcache_lock); ++ iput(inode); + + return goal; ++ ++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */ ++do_instantiate: ++ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */ ++ dentry->d_inode = inode; ++do_rehash: ++ if (rehash) ++ __d_rehash(dentry, 0); /* d_rehash */ ++ spin_unlock(&dcache_lock); ++ ++ return NULL; +} + +/* @@ -333,10 +357,10 @@ Index: linux-2.4.22-uml/fs/ext3/iopen.c + + return 1; +} -Index: linux-2.4.22-uml/fs/ext3/iopen.h +Index: lum/fs/ext3/iopen.h =================================================================== ---- linux-2.4.22-uml.orig/fs/ext3/iopen.h 2004-01-30 14:18:10.000000000 -0700 -+++ linux-2.4.22-uml/fs/ext3/iopen.h 2004-01-30 14:18:10.000000000 -0700 +--- lum.orig/fs/ext3/iopen.h 2004-03-09 16:46:37.000000000 -0700 ++++ lum/fs/ext3/iopen.h 2004-03-09 16:48:03.000000000 -0700 @@ -0,0 +1,15 @@ +/* + * iopen.h @@ -351,12 +375,12 @@ Index: linux-2.4.22-uml/fs/ext3/iopen.h + +extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry); +extern int ext3_iopen_get_inode(struct inode *inode); -+extern struct dentry *iopen_connect_dentry(struct dentry *de, -+ struct inode *inode); -Index: linux-2.4.22-uml/fs/ext3/namei.c ++extern struct dentry *iopen_connect_dentry(struct dentry *dentry, ++ struct inode *inode, int rehash); +Index: lum/fs/ext3/namei.c =================================================================== ---- linux-2.4.22-uml.orig/fs/ext3/namei.c 2004-01-30 14:17:59.000000000 -0700 -+++ linux-2.4.22-uml/fs/ext3/namei.c 2004-01-30 14:19:44.000000000 -0700 +--- lum.orig/fs/ext3/namei.c 2004-01-30 14:54:53.000000000 -0700 ++++ lum/fs/ext3/namei.c 2004-03-09 16:49:25.000000000 -0700 @@ -35,7 +35,7 @@ #include #include @@ -366,12 +390,7 @@ Index: linux-2.4.22-uml/fs/ext3/namei.c /* * define how far ahead to read directories while searching them. -@@ -927,10 +927,14 @@ - struct inode * inode; - struct ext3_dir_entry_2 * de; - struct buffer_head * bh; -+ struct dentry *alternate = NULL; - +@@ -931,6 +931,9 @@ if (dentry->d_name.len > EXT3_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); @@ -381,41 +400,67 @@ Index: linux-2.4.22-uml/fs/ext3/namei.c bh = ext3_find_entry(dentry, &de); inode = NULL; if (bh) { -@@ -942,7 +946,28 @@ +@@ -942,8 +945,8 @@ return ERR_PTR(-EACCES); } } - d_add(dentry, inode); +- return NULL; + -+ /* verify this dentry is really new */ -+ assert(!dentry->d_inode); -+ assert(list_empty(&dentry->d_alias)); /* d_instantiate */ -+ assert(list_empty(&dentry->d_hash)); /* d_rehash */ -+ assert(list_empty(&dentry->d_subdirs)); -+ -+ spin_lock(&dcache_lock); -+ if (inode && (alternate = iopen_connect_dentry(dentry, inode))) { -+ spin_unlock(&dcache_lock); -+ iput(inode); -+ return alternate; ++ return iopen_connect_dentry(dentry, inode, 1); + } + + #define S_SHIFT 12 +@@ -1932,10 +1935,6 @@ + inode->i_nlink); + inode->i_version = ++event; + inode->i_nlink = 0; +- /* There's no need to set i_disksize: the fact that i_nlink is +- * zero will ensure that the right thing happens during any +- * recovery. */ +- inode->i_size = 0; + ext3_orphan_add(handle, inode); + dir->i_nlink--; + inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; +@@ -2086,6 +2085,23 @@ + return err; + } + ++/* Like ext3_add_nondir() except for call to iopen_connect_dentry */ ++static int ext3_add_link(handle_t *handle, struct dentry *dentry, ++ struct inode *inode) ++{ ++ int err = ext3_add_entry(handle, dentry, inode); ++ if (!err) { ++ err = ext3_mark_inode_dirty(handle, inode); ++ if (err == 0) { ++ (void)iopen_connect_dentry(dentry, inode, 0); ++ return 0; ++ } + } ++ ext3_dec_count(handle, inode); ++ iput(inode); ++ return err; ++} + -+ /* d_add(), but don't drop dcache_lock before adding dentry to inode */ -+ if (inode) /* d_instantiate */ -+ list_add(&dentry->d_alias, &inode->i_dentry); -+ dentry->d_inode = inode; -+ -+ __d_rehash(dentry, 0); /* d_rehash */ -+ spin_unlock(&dcache_lock); -+ - return NULL; - } + static int ext3_link (struct dentry * old_dentry, + struct inode * dir, struct dentry *dentry) + { +@@ -2113,7 +2129,8 @@ + ext3_inc_count(handle, inode); + atomic_inc(&inode->i_count); -Index: linux-2.4.22-uml/fs/ext3/super.c +- err = ext3_add_nondir(handle, dentry, inode); ++ err = ext3_add_link(handle, dentry, inode); ++ ext3_orphan_del(handle, inode); + ext3_journal_stop(handle, dir); + return err; + } +Index: lum/fs/ext3/super.c =================================================================== ---- linux-2.4.22-uml.orig/fs/ext3/super.c Sun Nov 16 01:19:22 2003 -+++ linux-2.4.22-uml/fs/ext3/super.c Sun Nov 16 01:27:31 2003 -@@ -839,6 +839,18 @@ +--- lum.orig/fs/ext3/super.c 2004-01-30 14:54:53.000000000 -0700 ++++ lum/fs/ext3/super.c 2004-03-09 16:46:45.000000000 -0700 +@@ -742,6 +742,18 @@ || !strcmp (this_char, "quota") || !strcmp (this_char, "usrquota")) /* Don't do anything ;-) */ ; @@ -434,10 +479,10 @@ Index: linux-2.4.22-uml/fs/ext3/super.c else if (!strcmp (this_char, "journal")) { /* @@@ FIXME */ /* Eventually we will want to be able to create -Index: linux-2.4.22-uml/include/linux/ext3_fs.h +Index: lum/include/linux/ext3_fs.h =================================================================== ---- linux-2.4.22-uml.orig/include/linux/ext3_fs.h 2004-01-30 14:17:59.000000000 -0700 -+++ linux-2.4.22-uml/include/linux/ext3_fs.h 2004-01-30 14:18:10.000000000 -0700 +--- lum.orig/include/linux/ext3_fs.h 2004-01-30 14:54:53.000000000 -0700 ++++ lum/include/linux/ext3_fs.h 2004-03-09 16:46:46.000000000 -0700 @@ -322,6 +322,8 @@ #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */ #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */ diff --git a/lustre/kernel_patches/patches/iopen-2.4.21-chaos.patch b/lustre/kernel_patches/patches/iopen-2.4.21-chaos.patch index 16bde95..62bd8e1 100644 --- a/lustre/kernel_patches/patches/iopen-2.4.21-chaos.patch +++ b/lustre/kernel_patches/patches/iopen-2.4.21-chaos.patch @@ -8,11 +8,11 @@ include/linux/ext3_fs.h | 2 8 files changed, 318 insertions(+), 2 deletions(-) -Index: linux-2.4.21-chaos/Documentation/filesystems/ext2.txt +Index: linux-ia64/Documentation/filesystems/ext2.txt =================================================================== ---- linux-2.4.21-chaos.orig/Documentation/filesystems/ext2.txt 2002-05-08 01:53:59.000000000 +0400 -+++ linux-2.4.21-chaos/Documentation/filesystems/ext2.txt 2003-12-12 16:19:04.000000000 +0300 -@@ -35,6 +35,22 @@ +--- linux-ia64.orig/Documentation/filesystems/ext2.txt 2004-03-17 15:47:15.000000000 -0800 ++++ linux-ia64/Documentation/filesystems/ext2.txt 2004-03-17 18:03:15.000000000 -0800 +@@ -35,6 +35,22 @@ resgid=n The group ID which may use th sb=n Use alternate superblock at this location. @@ -35,11 +35,11 @@ Index: linux-2.4.21-chaos/Documentation/filesystems/ext2.txt grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2. -Index: linux-2.4.21-chaos/fs/ext3/Makefile +Index: linux-ia64/fs/ext3/Makefile =================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/Makefile 2003-12-12 16:18:36.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/Makefile 2003-12-12 16:19:04.000000000 +0300 -@@ -11,7 +11,7 @@ +--- linux-ia64.orig/fs/ext3/Makefile 2004-03-17 18:03:14.000000000 -0800 ++++ linux-ia64/fs/ext3/Makefile 2004-03-17 18:03:15.000000000 -0800 +@@ -11,7 +11,7 @@ O_TARGET := ext3.o export-objs := ext3-exports.o @@ -48,10 +48,10 @@ Index: linux-2.4.21-chaos/fs/ext3/Makefile ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o obj-m := $(O_TARGET) -Index: linux-2.4.21-chaos/fs/ext3/inode.c +Index: linux-ia64/fs/ext3/inode.c =================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/inode.c 2003-12-12 16:19:02.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/inode.c 2003-12-12 16:19:05.000000000 +0300 +--- linux-ia64.orig/fs/ext3/inode.c 2004-03-17 18:03:15.000000000 -0800 ++++ linux-ia64/fs/ext3/inode.c 2004-03-17 18:10:36.000000000 -0800 @@ -34,6 +34,7 @@ #include #include @@ -60,7 +60,7 @@ Index: linux-2.4.21-chaos/fs/ext3/inode.c /* * SEARCH_FROM_ZERO forces each block allocation to search from the start -@@ -2430,6 +2431,9 @@ +@@ -2430,6 +2431,9 @@ void ext3_read_inode(struct inode * inod struct buffer_head *bh; int block; @@ -70,21 +70,14 @@ Index: linux-2.4.21-chaos/fs/ext3/inode.c if(ext3_get_inode_loc(inode, &iloc)) goto bad_inode; bh = iloc.bh; -Index: linux-2.4.21-chaos/fs/ext3/iopen.c +Index: linux-ia64/fs/ext3/iopen.c =================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/iopen.c 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/iopen.c 2003-12-12 16:19:05.000000000 +0300 -@@ -0,0 +1,258 @@ -+/* -+ * linux/fs/ext3/iopen.c -+ * -+ * Special support for open by inode number -+ * -+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu). -+ * -+ * This file may be redistributed under the terms of the GNU General -+ * Public License. -+ * +--- linux-ia64.orig/fs/ext3/iopen.c 2004-03-17 18:02:08.000000000 -0800 ++++ linux-ia64/fs/ext3/iopen.c 2004-03-17 18:10:58.000000000 -0800 +@@ -8,3 +8,275 @@ + * This file may be redistributed under the terms of the GNU General + * Public License. + * + * + * Invariants: + * - there is only ever a single DCACHE_NFSD_DISCONNECTED dentry alias @@ -211,13 +204,24 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c + +/* This function is spliced into ext3_lookup and does the move of a + * disconnected dentry (if it exists) to a connected dentry. -+ * Caller must hold dcache_lock. + */ -+struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode) ++struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode, ++ int rehash) +{ + struct dentry *tmp, *goal = NULL; + struct list_head *lp; + ++ /* verify this dentry is really new */ ++ assert(dentry->d_inode == NULL); ++ assert(list_empty(&dentry->d_alias)); /* d_instantiate */ ++ if (rehash) ++ assert(list_empty(&dentry->d_hash)); /* d_rehash */ ++ assert(list_empty(&dentry->d_subdirs)); ++ ++ spin_lock(&dcache_lock); ++ if (!inode) ++ goto do_rehash; ++ + /* preferrably return a connected dentry */ + list_for_each(lp, &inode->i_dentry) { + tmp = list_entry(lp, struct dentry, d_alias); @@ -231,27 +235,40 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c + } + + if (!goal) -+ return NULL; ++ goto do_instantiate; + + /* Move the goal to the de hash queue - like d_move() */ + goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED; + list_del_init(&goal->d_hash); + + list_del(&goal->d_child); -+ list_del(&de->d_child); ++ list_del(&dentry->d_child); + + /* Switch the parents and the names.. */ -+ switch_names(goal, de); -+ do_switch(goal->d_parent, de->d_parent); -+ do_switch(goal->d_name.len, de->d_name.len); -+ do_switch(goal->d_name.hash, de->d_name.hash); ++ switch_names(goal, dentry); ++ do_switch(goal->d_parent, dentry->d_parent); ++ do_switch(goal->d_name.len, dentry->d_name.len); ++ do_switch(goal->d_name.hash, dentry->d_name.hash); + + /* And add them back to the (new) parent lists */ + list_add(&goal->d_child, &goal->d_parent->d_subdirs); -+ list_add(&de->d_child, &de->d_parent->d_subdirs); ++ list_add(&dentry->d_child, &dentry->d_parent->d_subdirs); + __d_rehash(goal, 0); ++ spin_unlock(&dcache_lock); ++ iput(inode); + + return goal; ++ ++ /* d_add(), but don't drop dcache_lock before adding dentry to inode */ ++do_instantiate: ++ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */ ++ dentry->d_inode = inode; ++do_rehash: ++ if (rehash) ++ __d_rehash(dentry, 0); /* d_rehash */ ++ spin_unlock(&dcache_lock); ++ ++ return NULL; +} + +/* @@ -333,10 +350,10 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.c + + return 1; +} -Index: linux-2.4.21-chaos/fs/ext3/iopen.h +Index: linux-ia64/fs/ext3/iopen.h =================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/iopen.h 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/iopen.h 2003-12-12 16:19:05.000000000 +0300 +--- linux-ia64.orig/fs/ext3/iopen.h 2004-03-17 15:47:15.000000000 -0800 ++++ linux-ia64/fs/ext3/iopen.h 2004-03-17 18:03:15.000000000 -0800 @@ -0,0 +1,15 @@ +/* + * iopen.h @@ -351,12 +368,12 @@ Index: linux-2.4.21-chaos/fs/ext3/iopen.h + +extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry); +extern int ext3_iopen_get_inode(struct inode *inode); -+extern struct dentry *iopen_connect_dentry(struct dentry *de, -+ struct inode *inode); -Index: linux-2.4.21-chaos/fs/ext3/namei.c ++extern struct dentry *iopen_connect_dentry(struct dentry *dentry, ++ struct inode *inode, int rehash); +Index: linux-ia64/fs/ext3/namei.c =================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/namei.c 2003-12-12 16:18:59.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/namei.c 2003-12-12 16:19:05.000000000 +0300 +--- linux-ia64.orig/fs/ext3/namei.c 2004-03-17 18:03:15.000000000 -0800 ++++ linux-ia64/fs/ext3/namei.c 2004-03-17 18:10:35.000000000 -0800 @@ -36,7 +36,7 @@ #include #include @@ -366,12 +383,7 @@ Index: linux-2.4.21-chaos/fs/ext3/namei.c /* * define how far ahead to read directories while searching them. -@@ -922,10 +922,14 @@ - struct inode * inode; - struct ext3_dir_entry_2 * de; - struct buffer_head * bh; -+ struct dentry *alternate = NULL; - +@@ -932,6 +932,9 @@ static struct dentry *ext3_lookup(struct if (dentry->d_name.len > EXT3_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); @@ -381,41 +393,67 @@ Index: linux-2.4.21-chaos/fs/ext3/namei.c bh = ext3_find_entry(dentry, &de); inode = NULL; if (bh) { -@@ -943,7 +948,28 @@ +@@ -943,8 +946,8 @@ static struct dentry *ext3_lookup(struct return ERR_PTR(-EACCES); } } - d_add(dentry, inode); +- return NULL; + -+ /* verify this dentry is really new */ -+ assert(!dentry->d_inode); -+ assert(list_empty(&dentry->d_alias)); /* d_instantiate */ -+ assert(list_empty(&dentry->d_hash)); /* d_rehash */ -+ assert(list_empty(&dentry->d_subdirs)); -+ -+ spin_lock(&dcache_lock); -+ if (inode && (alternate = iopen_connect_dentry(dentry, inode))) { -+ spin_unlock(&dcache_lock); -+ iput(inode); -+ return alternate; ++ return iopen_connect_dentry(dentry, inode, 1); + } + + #define S_SHIFT 12 +@@ -1935,10 +1938,6 @@ static int ext3_rmdir (struct inode * di + inode->i_nlink); + inode->i_version = ++event; + inode->i_nlink = 0; +- /* There's no need to set i_disksize: the fact that i_nlink is +- * zero will ensure that the right thing happens during any +- * recovery. */ +- inode->i_size = 0; + ext3_orphan_add(handle, inode); + dir->i_nlink--; + inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; +@@ -2057,6 +2056,23 @@ out_stop: + return err; + } + ++/* Like ext3_add_nondir() except for call to iopen_connect_dentry */ ++static int ext3_add_link(handle_t *handle, struct dentry *dentry, ++ struct inode *inode) ++{ ++ int err = ext3_add_entry(handle, dentry, inode); ++ if (!err) { ++ err = ext3_mark_inode_dirty(handle, inode); ++ if (err == 0) { ++ (void)iopen_connect_dentry(dentry, inode, 0); ++ return 0; ++ } + } ++ ext3_dec_count(handle, inode); ++ iput(inode); ++ return err; ++} + -+ /* d_add(), but don't drop dcache_lock before adding dentry to inode */ -+ if (inode) /* d_instantiate */ -+ list_add(&dentry->d_alias, &inode->i_dentry); -+ dentry->d_inode = inode; -+ -+ __d_rehash(dentry, 0); /* d_rehash */ -+ spin_unlock(&dcache_lock); -+ - return NULL; - } + static int ext3_link (struct dentry * old_dentry, + struct inode * dir, struct dentry *dentry) + { +@@ -2084,7 +2100,8 @@ static int ext3_link (struct dentry * ol + ext3_inc_count(handle, inode); + atomic_inc(&inode->i_count); -Index: linux-2.4.21-chaos/fs/ext3/super.c +- err = ext3_add_nondir(handle, dentry, inode); ++ err = ext3_add_link(handle, dentry, inode); ++ ext3_orphan_del(handle, inode); + ext3_journal_stop(handle, dir); + return err; + } +Index: linux-ia64/fs/ext3/super.c =================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/super.c 2003-12-12 16:18:51.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/super.c 2003-12-12 16:19:05.000000000 +0300 -@@ -890,6 +890,18 @@ +--- linux-ia64.orig/fs/ext3/super.c 2004-03-17 18:03:14.000000000 -0800 ++++ linux-ia64/fs/ext3/super.c 2004-03-17 18:10:35.000000000 -0800 +@@ -891,6 +891,18 @@ static int parse_options (char * options || !strcmp (this_char, "quota") || !strcmp (this_char, "usrquota")) /* Don't do anything ;-) */ ; @@ -434,11 +472,11 @@ Index: linux-2.4.21-chaos/fs/ext3/super.c else if (!strcmp (this_char, "journal")) { /* @@@ FIXME */ /* Eventually we will want to be able to create -Index: linux-2.4.21-chaos/include/linux/ext3_fs.h +Index: linux-ia64/include/linux/ext3_fs.h =================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_fs.h 2003-12-12 16:19:01.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_fs.h 2003-12-12 16:19:05.000000000 +0300 -@@ -328,6 +328,8 @@ +--- linux-ia64.orig/include/linux/ext3_fs.h 2004-03-17 18:03:15.000000000 -0800 ++++ linux-ia64/include/linux/ext3_fs.h 2004-03-17 18:03:15.000000000 -0800 +@@ -328,6 +328,8 @@ struct ext3_inode { #define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ #define EXT3_MOUNT_POSIX_ACL 0x8000 /* POSIX Access Control Lists */ #define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */ diff --git a/lustre/kernel_patches/patches/iopen-2.6.3-mm4.patch b/lustre/kernel_patches/patches/iopen-2.6.3-mm4.patch index 79b1f17..5500320 100644 --- a/lustre/kernel_patches/patches/iopen-2.6.3-mm4.patch +++ b/lustre/kernel_patches/patches/iopen-2.6.3-mm4.patch @@ -15,7 +15,7 @@ Index: linux-2.6.3-mm4/Documentation/filesystems/ext2.txt sb=n Use alternate superblock at this location. -+iopen Makes an invisible pseudo-directory called ++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 @@ -59,16 +59,14 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c =================================================================== --- linux-2.6.3-mm4.orig/fs/ext3/iopen.c 2004-03-08 14:58:44.413198848 +0800 +++ linux-2.6.3-mm4/fs/ext3/iopen.c 2004-03-08 14:58:44.576174072 +0800 -@@ -0,0 +1,223 @@ -+ -+ +@@ -0,0 +1,218 @@ +/* + * linux/fs/ext3/iopen.c + * + * Special support for open by inode number + * + * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu). -+ * ++ * + * This file may be redistributed under the terms of the GNU General + * Public License. + */ @@ -90,12 +88,13 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c +/* + * This implements looking up an inode by number. + */ -+static struct dentry *iopen_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) ++static struct dentry *iopen_lookup(struct inode *dir, struct dentry *dentry, ++ struct nameidata *nd) +{ + struct inode * inode; + unsigned long ino; -+ struct list_head *lp; -+ struct dentry *alternate; ++ struct list_head *lp; ++ struct dentry *alternate; + char buf[IOPEN_NAME_LEN]; + + if (dentry->d_name.len >= IOPEN_NAME_LEN) @@ -111,10 +110,7 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c + else + ino = simple_strtoul(buf, 0, 0); + -+ if ((ino != EXT3_ROOT_INO && -+ //ino != EXT3_ACL_IDX_INO && -+ //ino != EXT3_ACL_DATA_INO && -+ ino < EXT3_FIRST_INO(dir->i_sb)) || ++ if ((ino != EXT3_ROOT_INO && ino < EXT3_FIRST_INO(dir->i_sb)) || + ino > le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count)) + return ERR_PTR(-ENOENT); + @@ -126,24 +122,24 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c + return ERR_PTR(-ENOENT); + } + -+ /* preferrably return a connected dentry */ -+ spin_lock(&dcache_lock); -+ list_for_each(lp, &inode->i_dentry) { -+ alternate = list_entry(lp, struct dentry, d_alias); -+ assert(!(alternate->d_flags & DCACHE_DISCONNECTED)); -+ } -+ -+ if (!list_empty(&inode->i_dentry)) { -+ alternate = list_entry(inode->i_dentry.next, -+ struct dentry, d_alias); -+ dget_locked(alternate); -+ alternate->d_vfs_flags |= DCACHE_REFERENCED; -+ iput(inode); -+ spin_unlock(&dcache_lock); -+ return alternate; -+ } -+ dentry->d_flags |= DCACHE_DISCONNECTED; -+ spin_unlock(&dcache_lock); ++ /* preferrably return a connected dentry */ ++ spin_lock(&dcache_lock); ++ list_for_each(lp, &inode->i_dentry) { ++ alternate = list_entry(lp, struct dentry, d_alias); ++ assert(!(alternate->d_flags & DCACHE_DISCONNECTED)); ++ } ++ ++ if (!list_empty(&inode->i_dentry)) { ++ alternate = list_entry(inode->i_dentry.next, ++ struct dentry, d_alias); ++ dget_locked(alternate); ++ alternate->d_vfs_flags |= DCACHE_REFERENCED; ++ iput(inode); ++ spin_unlock(&dcache_lock); ++ return alternate; ++ } ++ dentry->d_flags |= DCACHE_DISCONNECTED; ++ spin_unlock(&dcache_lock); + + d_add(dentry, inode); + return NULL; @@ -157,7 +153,7 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c +{ + const unsigned char *old_name, *new_name; + -+ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN); ++ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN); + old_name = target->d_name.name; + new_name = dentry->d_name.name; + if (old_name == target->d_iname) @@ -171,37 +167,36 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c + +struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode) +{ -+ struct dentry *tmp, *goal = NULL; -+ struct list_head *lp; -+ -+ /* preferrably return a connected dentry */ -+ spin_lock(&dcache_lock); -+ /* verify this dentry is really new */ -+ assert(!de->d_inode); -+ assert(list_empty(&de->d_subdirs)); -+ assert(list_empty(&de->d_alias)); -+ -+ -+ list_for_each(lp, &inode->i_dentry) { -+ tmp = list_entry(lp, struct dentry, d_alias); -+ if (tmp->d_flags & DCACHE_DISCONNECTED) { -+ assert(tmp->d_alias.next == &inode->i_dentry); -+ assert(tmp->d_alias.prev == &inode->i_dentry); -+ goal = tmp; -+ dget_locked(goal); -+ break; -+ } -+ } -+ spin_unlock(&dcache_lock); -+ -+ if (!goal) -+ return NULL; -+ -+ goal->d_flags &= ~DCACHE_DISCONNECTED; ++ struct dentry *tmp, *goal = NULL; ++ struct list_head *lp; ++ ++ /* preferrably return a connected dentry */ ++ spin_lock(&dcache_lock); ++ /* verify this dentry is really new */ ++ assert(!de->d_inode); ++ assert(list_empty(&de->d_subdirs)); ++ assert(list_empty(&de->d_alias)); ++ ++ list_for_each(lp, &inode->i_dentry) { ++ tmp = list_entry(lp, struct dentry, d_alias); ++ if (tmp->d_flags & DCACHE_DISCONNECTED) { ++ assert(tmp->d_alias.next == &inode->i_dentry); ++ assert(tmp->d_alias.prev == &inode->i_dentry); ++ goal = tmp; ++ dget_locked(goal); ++ break; ++ } ++ } ++ spin_unlock(&dcache_lock); ++ ++ if (!goal) ++ return NULL; ++ ++ goal->d_flags &= ~DCACHE_DISCONNECTED; + d_rehash(de); + d_move(goal, de); + -+ return goal; ++ return goal; +} + +/* @@ -243,7 +238,7 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c + + inode = iget(dir->i_sb, EXT3_BAD_INO); + -+ if (!inode) ++ if (!inode) + return 0; + d_add(dentry, inode); + return 1; @@ -272,7 +267,7 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.c + EXT3_I(inode)->i_dtime = 0; + inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size + * (for stat), not the fs block -+ * size */ ++ * size */ + inode->i_blocks = 0; + inode->i_version = 1; + inode->i_generation = 0; @@ -292,9 +287,9 @@ Index: linux-2.6.3-mm4/fs/ext3/iopen.h + * iopen.h + * + * Special support for opening files by inode number. -+ * ++ * + * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu). -+ * ++ * + * This file may be redistributed under the terms of the GNU General + * Public License. + */ @@ -320,13 +315,13 @@ Index: linux-2.6.3-mm4/fs/ext3/namei.c #endif +struct dentry *iopen_connect_dentry(struct dentry *de, struct inode *inode); -+ ++ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) { struct inode * inode; struct ext3_dir_entry_2 * de; struct buffer_head * bh; -+ struct dentry *alternate = NULL; ++ struct dentry *alternate = NULL; if (dentry->d_name.len > EXT3_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); diff --git a/lustre/kernel_patches/patches/linux-2.6.3-CITI_NFS4_ALL.patch b/lustre/kernel_patches/patches/linux-2.6.3-CITI_NFS4_ALL.patch index 16e191b..726957c 100644 --- a/lustre/kernel_patches/patches/linux-2.6.3-CITI_NFS4_ALL.patch +++ b/lustre/kernel_patches/patches/linux-2.6.3-CITI_NFS4_ALL.patch @@ -5336,7 +5336,7 @@ diff -puN /dev/null include/linux/sunrpc/svcauth_gss.h + * Bruce Fields + * Copyright (c) 2002 The Regents of the Unviersity of Michigan + * -+ * $Id: linux-2.6.3-CITI_NFS4_ALL.patch,v 1.2 2004/03/17 01:04:13 nic Exp $ ++ * Id: linux-2.6.3-CITI_NFS4_ALL.patch,v 1.2.4.1 2004/03/17 23:55:23 adilger Exp $ + * + */ + diff --git a/lustre/kernel_patches/patches/lustre_version.patch b/lustre/kernel_patches/patches/lustre_version.patch index 86f514b..7ebb838 100644 --- a/lustre/kernel_patches/patches/lustre_version.patch +++ b/lustre/kernel_patches/patches/lustre_version.patch @@ -7,6 +7,6 @@ --- /dev/null Fri Aug 30 17:31:37 2002 +++ linux-2.4.18-18.8.0-l12-braam/include/linux/lustre_version.h Thu Feb 13 07:58:33 2003 @@ -0,0 +1 @@ -+#define LUSTRE_KERNEL_VERSION 32 ++#define LUSTRE_KERNEL_VERSION 34 _ diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.18-18-chaos65.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.18-18-chaos65.patch index e29ae29..41c2772 100644 --- a/lustre/kernel_patches/patches/vfs_intent-2.4.18-18-chaos65.patch +++ b/lustre/kernel_patches/patches/vfs_intent-2.4.18-18-chaos65.patch @@ -467,7 +467,7 @@ + &dentry->d_name, 0, NULL); + d_invalidate(dentry); + dput(dentry); -+ if (IS_ERR(new)) { ++ if (IS_ERR(new)) { + err = PTR_ERR(new); + break; + } diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.19-pre1.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.19-pre1.patch index 5fbd0fc..7c4ea56 100644 --- a/lustre/kernel_patches/patches/vfs_intent-2.4.19-pre1.patch +++ b/lustre/kernel_patches/patches/vfs_intent-2.4.19-pre1.patch @@ -453,7 +453,7 @@ Index: linux-2.4.19-pre1/fs/namei.c + &dentry->d_name, 0, NULL); + d_invalidate(dentry); + dput(dentry); -+ if (IS_ERR(new)) { ++ if (IS_ERR(new)) { + err = PTR_ERR(new); + break; + } diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.19-suse.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.19-suse.patch index 6b6027a..7741be4 100644 --- a/lustre/kernel_patches/patches/vfs_intent-2.4.19-suse.patch +++ b/lustre/kernel_patches/patches/vfs_intent-2.4.19-suse.patch @@ -436,7 +436,7 @@ Index: linux-2.4.19.SuSE/fs/namei.c + &dentry->d_name, 0, NULL); + d_invalidate(dentry); + dput(dentry); -+ if (IS_ERR(new)) { ++ if (IS_ERR(new)) { + err = PTR_ERR(new); + break; + } diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch index 082b8b7..8585701 100644 --- a/lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch +++ b/lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch @@ -13,9 +13,11 @@ kernel/ksyms.c | 1 13 files changed, 591 insertions(+), 133 deletions(-) ---- linux-2.4.20-hp4-pnnl13/fs/exec.c~vfs_intent-2.4.20-hp 2003-09-13 15:19:27.000000000 +0400 -+++ linux-2.4.20-hp4-pnnl13-alexey/fs/exec.c 2003-09-14 17:33:51.000000000 +0400 -@@ -116,8 +116,10 @@ asmlinkage long sys_uselib(const char * +Index: linux/fs/exec.c +=================================================================== +--- linux.orig/fs/exec.c Wed Mar 17 13:00:38 2004 ++++ linux/fs/exec.c Wed Mar 17 13:11:25 2004 +@@ -115,8 +115,10 @@ struct file * file; struct nameidata nd; int error; @@ -27,7 +29,7 @@ if (error) goto out; -@@ -129,7 +131,8 @@ asmlinkage long sys_uselib(const char * +@@ -128,7 +130,8 @@ if (error) goto exit; @@ -37,7 +39,7 @@ error = PTR_ERR(file); if (IS_ERR(file)) goto out; -@@ -372,8 +375,10 @@ struct file *open_exec(const char *name) +@@ -371,8 +374,10 @@ struct inode *inode; struct file *file; int err = 0; @@ -49,7 +51,7 @@ file = ERR_PTR(err); if (!err) { inode = nd.dentry->d_inode; -@@ -385,7 +390,8 @@ struct file *open_exec(const char *name) +@@ -384,7 +389,8 @@ err = -EACCES; file = ERR_PTR(err); if (!err) { @@ -59,7 +61,7 @@ if (!IS_ERR(file)) { err = deny_write_access(file); if (err) { -@@ -397,6 +403,7 @@ out: +@@ -396,6 +402,7 @@ return file; } } @@ -67,7 +69,7 @@ path_release(&nd); } goto out; -@@ -1128,7 +1135,7 @@ int do_coredump(long signr, struct pt_re +@@ -1120,7 +1127,7 @@ goto close_fail; if (!file->f_op->write) goto close_fail; @@ -76,9 +78,11 @@ goto close_fail; retval = binfmt->core_dump(signr, regs, file); ---- linux-2.4.20-hp4-pnnl13/fs/dcache.c~vfs_intent-2.4.20-hp 2002-11-29 02:53:15.000000000 +0300 -+++ linux-2.4.20-hp4-pnnl13-alexey/fs/dcache.c 2003-09-14 17:33:51.000000000 +0400 -@@ -181,6 +181,13 @@ int d_invalidate(struct dentry * dentry) +Index: linux/fs/dcache.c +=================================================================== +--- linux.orig/fs/dcache.c Thu Nov 28 18:53:15 2002 ++++ linux/fs/dcache.c Wed Mar 17 13:11:25 2004 +@@ -181,6 +181,13 @@ spin_unlock(&dcache_lock); return 0; } @@ -92,7 +96,7 @@ /* * Check whether to do a partial shrink_dcache * to get rid of unused child entries. -@@ -830,13 +837,19 @@ void d_delete(struct dentry * dentry) +@@ -830,13 +837,19 @@ * Adds a dentry to the hash according to its name. */ @@ -115,9 +119,11 @@ } #define do_switch(x,y) do { \ ---- linux-2.4.20-hp4-pnnl13/fs/namespace.c~vfs_intent-2.4.20-hp 2002-11-29 02:53:15.000000000 +0300 -+++ linux-2.4.20-hp4-pnnl13-alexey/fs/namespace.c 2003-09-14 17:33:51.000000000 +0400 -@@ -99,6 +99,7 @@ static void detach_mnt(struct vfsmount * +Index: linux/fs/namespace.c +=================================================================== +--- linux.orig/fs/namespace.c Thu Nov 28 18:53:15 2002 ++++ linux/fs/namespace.c Wed Mar 17 13:11:25 2004 +@@ -99,6 +99,7 @@ { old_nd->dentry = mnt->mnt_mountpoint; old_nd->mnt = mnt->mnt_parent; @@ -125,7 +131,7 @@ mnt->mnt_parent = mnt; mnt->mnt_mountpoint = mnt->mnt_root; list_del_init(&mnt->mnt_child); -@@ -110,6 +111,7 @@ static void attach_mnt(struct vfsmount * +@@ -110,6 +111,7 @@ { mnt->mnt_parent = mntget(nd->mnt); mnt->mnt_mountpoint = dget(nd->dentry); @@ -133,7 +139,7 @@ list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry)); list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts); nd->dentry->d_mounted++; -@@ -485,14 +487,17 @@ static int do_loopback(struct nameidata +@@ -485,14 +487,17 @@ { struct nameidata old_nd; struct vfsmount *mnt = NULL; @@ -153,7 +159,7 @@ down_write(¤t->namespace->sem); err = -EINVAL; -@@ -515,6 +520,7 @@ static int do_loopback(struct nameidata +@@ -515,6 +520,7 @@ } up_write(¤t->namespace->sem); @@ -161,7 +167,7 @@ path_release(&old_nd); return err; } -@@ -698,6 +704,7 @@ long do_mount(char * dev_name, char * di +@@ -698,6 +704,7 @@ unsigned long flags, void *data_page) { struct nameidata nd; @@ -169,7 +175,7 @@ int retval = 0; int mnt_flags = 0; -@@ -722,10 +729,11 @@ long do_mount(char * dev_name, char * di +@@ -722,10 +729,11 @@ flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV); /* ... and get the mountpoint */ @@ -184,7 +190,7 @@ if (flags & MS_REMOUNT) retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, data_page); -@@ -736,6 +744,8 @@ long do_mount(char * dev_name, char * di +@@ -736,6 +744,8 @@ else retval = do_add_mount(&nd, type_page, flags, mnt_flags, dev_name, data_page); @@ -193,7 +199,7 @@ path_release(&nd); return retval; } -@@ -901,6 +911,8 @@ asmlinkage long sys_pivot_root(const cha +@@ -901,6 +911,8 @@ { struct vfsmount *tmp; struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd; @@ -202,7 +208,7 @@ int error; if (!capable(CAP_SYS_ADMIN)) -@@ -908,14 +920,14 @@ asmlinkage long sys_pivot_root(const cha +@@ -908,14 +920,14 @@ lock_kernel(); @@ -219,7 +225,7 @@ if (error) goto out1; -@@ -970,8 +982,10 @@ out2: +@@ -970,8 +982,10 @@ up(&old_nd.dentry->d_inode->i_zombie); up_write(¤t->namespace->sem); path_release(&user_nd); @@ -230,8 +236,10 @@ path_release(&new_nd); out0: unlock_kernel(); ---- linux-2.4.20-hp4-pnnl13/fs/namei.c~vfs_intent-2.4.20-hp 2003-09-13 15:19:23.000000000 +0400 -+++ linux-2.4.20-hp4-pnnl13-alexey/fs/namei.c 2003-09-14 17:33:51.000000000 +0400 +Index: linux/fs/namei.c +=================================================================== +--- linux.orig/fs/namei.c Wed Mar 17 13:00:37 2004 ++++ linux/fs/namei.c Wed Mar 17 13:12:31 2004 @@ -94,6 +94,13 @@ * XEmacs seems to be relying on it... */ @@ -246,7 +254,7 @@ /* In order to reduce some races, while at the same time doing additional * checking and hopefully speeding things up, we copy filenames to the * kernel data space before using them.. -@@ -260,10 +267,19 @@ void path_release(struct nameidata *nd) +@@ -260,10 +267,19 @@ * Internal lookup() using the new generic dcache. * SMP-safe */ @@ -267,7 +275,7 @@ if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) { dput(dentry); -@@ -281,11 +297,15 @@ static struct dentry * cached_lookup(str +@@ -281,11 +297,15 @@ * make sure that nobody added the entry to the dcache in the meantime.. * SMP-safe */ @@ -284,7 +292,7 @@ down(&dir->i_sem); /* * First re-do the cached lookup just in case it was created -@@ -300,6 +320,9 @@ static struct dentry * real_lookup(struc +@@ -300,6 +320,9 @@ result = ERR_PTR(-ENOMEM); if (dentry) { lock_kernel(); @@ -294,7 +302,7 @@ result = dir->i_op->lookup(dir, dentry); unlock_kernel(); if (result) -@@ -321,6 +344,15 @@ static struct dentry * real_lookup(struc +@@ -321,6 +344,15 @@ dput(result); result = ERR_PTR(-ENOENT); } @@ -310,7 +318,7 @@ } return result; } -@@ -332,7 +364,8 @@ static struct dentry * real_lookup(struc +@@ -332,7 +364,8 @@ * Without that kind of total limit, nasty chains of consecutive * symlinks can cause almost arbitrarily long lookups. */ @@ -320,7 +328,7 @@ { int err; if (current->link_count >= 5) -@@ -346,10 +379,18 @@ static inline int do_follow_link(struct +@@ -346,10 +379,18 @@ current->link_count++; current->total_link_count++; UPDATE_ATIME(dentry->d_inode); @@ -339,7 +347,7 @@ path_release(nd); return -ELOOP; } -@@ -379,15 +420,26 @@ int follow_up(struct vfsmount **mnt, str +@@ -379,15 +420,26 @@ return __follow_up(mnt, dentry); } @@ -367,7 +375,7 @@ dput(*dentry); mntput(mounted->mnt_parent); *dentry = dget(mounted->mnt_root); -@@ -399,7 +451,7 @@ static inline int __follow_down(struct v +@@ -399,7 +451,7 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry) { @@ -376,7 +384,7 @@ } static inline void follow_dotdot(struct nameidata *nd) -@@ -435,7 +487,7 @@ static inline void follow_dotdot(struct +@@ -435,7 +487,7 @@ mntput(nd->mnt); nd->mnt = parent; } @@ -385,7 +393,7 @@ ; } -@@ -447,7 +499,8 @@ static inline void follow_dotdot(struct +@@ -447,7 +499,8 @@ * * We expect 'base' to be positive and a directory. */ @@ -395,7 +403,7 @@ { struct dentry *dentry; struct inode *inode; -@@ -520,15 +573,15 @@ int link_path_walk(const char * name, st +@@ -520,15 +573,15 @@ break; } /* This does the actual lookups.. */ @@ -414,7 +422,7 @@ ; err = -ENOENT; -@@ -540,7 +593,7 @@ int link_path_walk(const char * name, st +@@ -540,7 +593,7 @@ goto out_dput; if (inode->i_op->follow_link) { @@ -423,7 +431,7 @@ dput(dentry); if (err) goto return_err; -@@ -556,7 +609,7 @@ int link_path_walk(const char * name, st +@@ -556,7 +609,7 @@ nd->dentry = dentry; } err = -ENOTDIR; @@ -432,7 +440,7 @@ break; continue; /* here ends the main loop */ -@@ -583,19 +636,19 @@ last_component: +@@ -583,19 +636,19 @@ if (err < 0) break; } @@ -456,7 +464,7 @@ dput(dentry); if (err) goto return_err; -@@ -609,7 +662,8 @@ last_component: +@@ -609,7 +662,8 @@ goto no_inode; if (lookup_flags & LOOKUP_DIRECTORY) { err = -ENOTDIR; @@ -466,7 +474,7 @@ break; } goto return_base; -@@ -633,6 +687,25 @@ return_reval: +@@ -633,6 +687,27 @@ * Check the cached dentry for staleness. */ dentry = nd->dentry; @@ -482,17 +490,19 @@ + &dentry->d_name, 0, NULL); + d_invalidate(dentry); + dput(dentry); -+ if (IS_ERR(new)) { ++ if (IS_ERR(new)) { + err = PTR_ERR(new); + break; + } + nd->dentry = new; + } ++ if (!nd->dentry->d_inode) ++ goto no_inode; + } else if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { err = -ESTALE; if (!dentry->d_op->d_revalidate(dentry, 0)) { -@@ -646,15 +719,28 @@ out_dput: +@@ -646,15 +721,28 @@ dput(dentry); break; } @@ -522,7 +532,7 @@ } /* SMP-safe */ -@@ -739,6 +825,17 @@ walk_init_root(const char *name, struct +@@ -739,6 +827,17 @@ } /* SMP-safe */ @@ -540,7 +550,7 @@ int path_lookup(const char *path, unsigned flags, struct nameidata *nd) { int error = 0; -@@ -753,6 +850,7 @@ int path_init(const char *name, unsigned +@@ -753,6 +852,7 @@ { nd->last_type = LAST_ROOT; /* if there are only slashes... */ nd->flags = flags; @@ -548,7 +558,7 @@ if (*name=='/') return walk_init_root(name,nd); read_lock(¤t->fs->lock); -@@ -767,7 +865,8 @@ int path_init(const char *name, unsigned +@@ -767,7 +867,8 @@ * needs parent already locked. Doesn't follow mounts. * SMP-safe. */ @@ -558,7 +568,7 @@ { struct dentry * dentry; struct inode *inode; -@@ -790,13 +889,16 @@ struct dentry * lookup_hash(struct qstr +@@ -790,13 +891,16 @@ goto out; } @@ -576,7 +586,7 @@ dentry = inode->i_op->lookup(inode, new); unlock_kernel(); if (!dentry) -@@ -808,6 +910,12 @@ out: +@@ -808,6 +912,12 @@ return dentry; } @@ -589,7 +599,7 @@ /* SMP-safe */ struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) { -@@ -829,7 +937,7 @@ struct dentry * lookup_one_len(const cha +@@ -829,7 +939,7 @@ } this.hash = end_name_hash(hash); @@ -598,7 +608,7 @@ access: return ERR_PTR(-EACCES); } -@@ -860,6 +968,23 @@ int __user_walk(const char *name, unsign +@@ -860,6 +970,23 @@ return err; } @@ -622,7 +632,7 @@ /* * It's inline, so penalty for filesystems that don't use sticky bit is * minimal. -@@ -955,7 +1080,8 @@ static inline int lookup_flags(unsigned +@@ -955,7 +1082,8 @@ return retval; } @@ -632,7 +642,7 @@ { int error; -@@ -968,12 +1094,15 @@ int vfs_create(struct inode *dir, struct +@@ -968,12 +1096,15 @@ goto exit_lock; error = -EACCES; /* shouldn't it be ENOSYS? */ @@ -650,7 +660,7 @@ unlock_kernel(); exit_lock: up(&dir->i_zombie); -@@ -982,6 +1111,11 @@ exit_lock: +@@ -982,6 +1113,11 @@ return error; } @@ -662,7 +672,7 @@ /* * open_namei() * -@@ -996,7 +1130,8 @@ exit_lock: +@@ -996,7 +1132,8 @@ * for symlinks (where the permissions are checked later). * SMP-safe */ @@ -672,7 +682,7 @@ { int acc_mode, error = 0; struct inode *inode; -@@ -1006,11 +1141,14 @@ int open_namei(const char * pathname, in +@@ -1006,11 +1143,14 @@ acc_mode = ACC_MODE(flag); @@ -688,7 +698,7 @@ if (error) return error; dentry = nd->dentry; -@@ -1020,6 +1158,10 @@ int open_namei(const char * pathname, in +@@ -1020,6 +1160,10 @@ /* * Create - we need to know the parent. */ @@ -699,7 +709,7 @@ error = path_lookup(pathname, LOOKUP_PARENT, nd); if (error) return error; -@@ -1035,7 +1177,7 @@ int open_namei(const char * pathname, in +@@ -1035,7 +1179,7 @@ dir = nd->dentry; down(&dir->d_inode->i_sem); @@ -708,7 +718,7 @@ do_last: error = PTR_ERR(dentry); -@@ -1044,11 +1186,12 @@ do_last: +@@ -1044,11 +1188,12 @@ goto exit; } @@ -722,7 +732,7 @@ up(&dir->d_inode->i_sem); dput(nd->dentry); nd->dentry = dentry; -@@ -1073,7 +1216,7 @@ do_last: +@@ -1073,7 +1218,7 @@ error = -ELOOP; if (flag & O_NOFOLLOW) goto exit_dput; @@ -731,7 +741,7 @@ } error = -ENOENT; if (!dentry->d_inode) -@@ -1152,7 +1295,7 @@ ok: +@@ -1152,7 +1297,7 @@ if (!error) { DQUOT_INIT(inode); @@ -740,7 +750,7 @@ } put_write_access(inode); if (error) -@@ -1164,8 +1307,10 @@ ok: +@@ -1164,8 +1309,10 @@ return 0; exit_dput: @@ -751,7 +761,7 @@ path_release(nd); return error; -@@ -1184,7 +1329,16 @@ do_link: +@@ -1184,7 +1331,16 @@ * are done. Procfs-like symlinks just set LAST_BIND. */ UPDATE_ATIME(dentry->d_inode); @@ -768,7 +778,7 @@ dput(dentry); if (error) return error; -@@ -1206,13 +1360,20 @@ do_link: +@@ -1206,13 +1362,20 @@ } dir = nd->dentry; down(&dir->d_inode->i_sem); @@ -791,7 +801,7 @@ { struct dentry *dentry; -@@ -1220,7 +1381,7 @@ static struct dentry *lookup_create(stru +@@ -1220,7 +1383,7 @@ dentry = ERR_PTR(-EEXIST); if (nd->last_type != LAST_NORM) goto fail; @@ -800,12 +810,16 @@ if (IS_ERR(dentry)) goto fail; if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) -@@ -1276,7 +1437,16 @@ asmlinkage long sys_mknod(const char * f +@@ -1276,7 +1439,20 @@ error = path_lookup(tmp, LOOKUP_PARENT, &nd); if (error) goto out; - dentry = lookup_create(&nd, 0); + ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out2; ++ } + if (nd.dentry->d_inode->i_op->mknod_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->mknod_raw(&nd, mode, dev); @@ -818,7 +832,7 @@ error = PTR_ERR(dentry); if (!IS_POSIXACL(nd.dentry->d_inode)) -@@ -1298,6 +1468,7 @@ asmlinkage long sys_mknod(const char * f +@@ -1298,6 +1474,7 @@ dput(dentry); } up(&nd.dentry->d_inode->i_sem); @@ -826,11 +840,15 @@ path_release(&nd); out: putname(tmp); -@@ -1345,7 +1516,14 @@ asmlinkage long sys_mkdir(const char * p +@@ -1345,7 +1522,18 @@ error = path_lookup(tmp, LOOKUP_PARENT, &nd); if (error) goto out; - dentry = lookup_create(&nd, 1); ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out2; ++ } + if (nd.dentry->d_inode->i_op->mkdir_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->mkdir_raw(&nd, mode); @@ -842,7 +860,7 @@ error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { if (!IS_POSIXACL(nd.dentry->d_inode)) -@@ -1354,6 +1532,7 @@ asmlinkage long sys_mkdir(const char * p +@@ -1354,6 +1542,7 @@ dput(dentry); } up(&nd.dentry->d_inode->i_sem); @@ -850,7 +868,7 @@ path_release(&nd); out: putname(tmp); -@@ -1454,8 +1633,16 @@ asmlinkage long sys_rmdir(const char * p +@@ -1454,8 +1643,16 @@ error = -EBUSY; goto exit1; } @@ -868,7 +886,7 @@ error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { error = vfs_rmdir(nd.dentry->d_inode, dentry); -@@ -1513,8 +1700,15 @@ asmlinkage long sys_unlink(const char * +@@ -1513,8 +1710,15 @@ error = -EISDIR; if (nd.last_type != LAST_NORM) goto exit1; @@ -885,11 +903,15 @@ error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { /* Why not before? Because we want correct error value */ -@@ -1581,15 +1775,23 @@ asmlinkage long sys_symlink(const char * +@@ -1581,15 +1785,27 @@ error = path_lookup(to, LOOKUP_PARENT, &nd); if (error) goto out; - dentry = lookup_create(&nd, 0); ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out2; ++ } + if (nd.dentry->d_inode->i_op->symlink_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->symlink_raw(&nd, from); @@ -911,11 +933,15 @@ putname(to); } putname(from); -@@ -1665,7 +1867,14 @@ asmlinkage long sys_link(const char * ol +@@ -1665,7 +1881,18 @@ error = -EXDEV; if (old_nd.mnt != nd.mnt) goto out_release; - new_dentry = lookup_create(&nd, 0); ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out_release; ++ } + if (nd.dentry->d_inode->i_op->link_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->link_raw(&old_nd, &nd); @@ -927,7 +953,7 @@ error = PTR_ERR(new_dentry); if (!IS_ERR(new_dentry)) { error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); -@@ -1709,7 +1918,7 @@ exit: +@@ -1709,7 +1936,7 @@ * locking]. */ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, @@ -936,7 +962,7 @@ { int error; struct inode *target; -@@ -1788,7 +1997,7 @@ out_unlock: +@@ -1788,7 +2015,7 @@ } int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, @@ -945,7 +971,7 @@ { int error; -@@ -1876,9 +2085,18 @@ static inline int do_rename(const char * +@@ -1876,9 +2103,18 @@ if (newnd.last_type != LAST_NORM) goto exit2; @@ -965,7 +991,7 @@ error = PTR_ERR(old_dentry); if (IS_ERR(old_dentry)) goto exit3; -@@ -1894,16 +2112,16 @@ static inline int do_rename(const char * +@@ -1894,16 +2130,16 @@ if (newnd.last.name[newnd.last.len]) goto exit4; } @@ -984,7 +1010,7 @@ dput(new_dentry); exit4: dput(old_dentry); -@@ -1954,20 +2172,28 @@ out: +@@ -1954,20 +2190,28 @@ } static inline int @@ -1015,7 +1041,7 @@ out: if (current->link_count || res || nd->last_type!=LAST_NORM) return res; -@@ -1989,7 +2215,13 @@ fail: +@@ -1989,7 +2233,13 @@ int vfs_follow_link(struct nameidata *nd, const char *link) { @@ -1030,7 +1056,7 @@ } /* get the link contents into pagecache */ -@@ -2031,7 +2263,7 @@ int page_follow_link(struct dentry *dent +@@ -2031,7 +2281,7 @@ { struct page *page = NULL; char *s = page_getlink(dentry, &page); @@ -1039,8 +1065,10 @@ if (page) { kunmap(page); page_cache_release(page); ---- linux-2.4.20-hp4-pnnl13/fs/open.c~vfs_intent-2.4.20-hp 2002-11-29 02:53:15.000000000 +0300 -+++ linux-2.4.20-hp4-pnnl13-alexey/fs/open.c 2003-09-14 17:33:51.000000000 +0400 +Index: linux/fs/open.c +=================================================================== +--- linux.orig/fs/open.c Thu Nov 28 18:53:15 2002 ++++ linux/fs/open.c Wed Mar 17 13:11:25 2004 @@ -19,6 +19,8 @@ #include @@ -1050,7 +1078,7 @@ int vfs_statfs(struct super_block *sb, struct statfs *buf) { -@@ -95,9 +97,10 @@ void fd_install(unsigned int fd, struct +@@ -95,9 +97,10 @@ write_unlock(&files->file_lock); } @@ -1062,7 +1090,7 @@ int error; struct iattr newattrs; -@@ -108,7 +111,13 @@ int do_truncate(struct dentry *dentry, l +@@ -108,7 +111,13 @@ down(&inode->i_sem); newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; @@ -1077,7 +1105,7 @@ up(&inode->i_sem); return error; } -@@ -118,12 +127,13 @@ static inline long do_sys_truncate(const +@@ -118,12 +127,13 @@ struct nameidata nd; struct inode * inode; int error; @@ -1092,7 +1120,7 @@ if (error) goto out; inode = nd.dentry->d_inode; -@@ -163,11 +173,13 @@ static inline long do_sys_truncate(const +@@ -163,11 +173,13 @@ error = locks_verify_truncate(inode, NULL, length); if (!error) { DQUOT_INIT(inode); @@ -1107,7 +1135,7 @@ path_release(&nd); out: return error; -@@ -215,7 +227,7 @@ static inline long do_sys_ftruncate(unsi +@@ -215,7 +227,7 @@ error = locks_verify_truncate(inode, file, length); if (!error) @@ -1116,7 +1144,7 @@ out_putf: fput(file); out: -@@ -260,11 +272,13 @@ asmlinkage long sys_utime(char * filenam +@@ -260,11 +272,13 @@ struct inode * inode; struct iattr newattrs; @@ -1131,7 +1159,7 @@ error = -EROFS; if (IS_RDONLY(inode)) goto dput_and_out; -@@ -279,11 +293,25 @@ asmlinkage long sys_utime(char * filenam +@@ -279,11 +293,25 @@ goto dput_and_out; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; @@ -1158,7 +1186,7 @@ error = notify_change(nd.dentry, &newattrs); dput_and_out: path_release(&nd); -@@ -304,12 +332,14 @@ asmlinkage long sys_utimes(char * filena +@@ -304,12 +332,14 @@ struct inode * inode; struct iattr newattrs; @@ -1174,7 +1202,7 @@ error = -EROFS; if (IS_RDONLY(inode)) goto dput_and_out; -@@ -324,7 +354,20 @@ asmlinkage long sys_utimes(char * filena +@@ -324,7 +354,20 @@ newattrs.ia_atime = times[0].tv_sec; newattrs.ia_mtime = times[1].tv_sec; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; @@ -1196,7 +1224,7 @@ if (current->fsuid != inode->i_uid && (error = permission(inode,MAY_WRITE)) != 0) goto dput_and_out; -@@ -347,6 +390,7 @@ asmlinkage long sys_access(const char * +@@ -347,6 +390,7 @@ int old_fsuid, old_fsgid; kernel_cap_t old_cap; int res; @@ -1204,7 +1232,7 @@ if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ return -EINVAL; -@@ -364,13 +408,14 @@ asmlinkage long sys_access(const char * +@@ -364,13 +408,14 @@ else current->cap_effective = current->cap_permitted; @@ -1220,7 +1248,7 @@ path_release(&nd); } -@@ -385,8 +430,9 @@ asmlinkage long sys_chdir(const char * f +@@ -385,8 +430,9 @@ { int error; struct nameidata nd; @@ -1231,7 +1259,7 @@ if (error) goto out; -@@ -397,6 +443,7 @@ asmlinkage long sys_chdir(const char * f +@@ -397,6 +443,7 @@ set_fs_pwd(current->fs, nd.mnt, nd.dentry); dput_and_out: @@ -1239,7 +1267,7 @@ path_release(&nd); out: return error; -@@ -436,9 +483,10 @@ asmlinkage long sys_chroot(const char * +@@ -436,9 +483,10 @@ { int error; struct nameidata nd; @@ -1252,7 +1280,7 @@ if (error) goto out; -@@ -454,39 +502,56 @@ asmlinkage long sys_chroot(const char * +@@ -454,39 +502,56 @@ set_fs_altroot(); error = 0; dput_and_out: @@ -1323,7 +1351,7 @@ fput(file); out: return err; -@@ -495,30 +560,14 @@ out: +@@ -495,30 +560,14 @@ asmlinkage long sys_chmod(const char * filename, mode_t mode) { struct nameidata nd; @@ -1355,7 +1383,7 @@ path_release(&nd); out: return error; -@@ -538,6 +587,20 @@ static int chown_common(struct dentry * +@@ -538,6 +587,20 @@ error = -EROFS; if (IS_RDONLY(inode)) goto out; @@ -1376,7 +1404,7 @@ error = -EPERM; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out; -@@ -642,6 +705,7 @@ struct file *filp_open(const char * file +@@ -642,6 +705,7 @@ { int namei_flags, error; struct nameidata nd; @@ -1384,7 +1412,7 @@ namei_flags = flags; if ((namei_flags+1) & O_ACCMODE) -@@ -649,14 +713,15 @@ struct file *filp_open(const char * file +@@ -649,14 +713,15 @@ if (namei_flags & O_TRUNC) namei_flags |= 2; @@ -1405,7 +1433,7 @@ { struct file * f; struct inode *inode; -@@ -693,12 +758,15 @@ struct file *dentry_open(struct dentry * +@@ -693,12 +758,15 @@ } if (f->f_op && f->f_op->open) { @@ -1421,7 +1449,7 @@ return f; cleanup_all: -@@ -713,11 +781,17 @@ cleanup_all: +@@ -713,11 +781,17 @@ cleanup_file: put_filp(f); cleanup_dentry: @@ -1439,9 +1467,11 @@ /* * Find an empty file descriptor entry, and mark it busy. */ ---- linux-2.4.20-hp4-pnnl13/fs/stat.c~vfs_intent-2.4.20-hp 2001-09-14 03:04:43.000000000 +0400 -+++ linux-2.4.20-hp4-pnnl13-alexey/fs/stat.c 2003-09-14 17:34:07.000000000 +0400 -@@ -17,10 +17,14 @@ +Index: linux/fs/stat.c +=================================================================== +--- linux.orig/fs/stat.c Thu Sep 13 19:04:43 2001 ++++ linux/fs/stat.c Wed Mar 17 13:12:31 2004 +@@ -17,10 +17,12 @@ * Revalidate the inode. This is required for proper NFS attribute caching. */ static __inline__ int @@ -1450,15 +1480,13 @@ { struct inode * inode = dentry->d_inode; - if (inode->i_op && inode->i_op->revalidate) -+ if (!inode) -+ return -ENOENT; + if (inode->i_op && inode->i_op->revalidate_it) + return inode->i_op->revalidate_it(dentry, it); + else if (inode->i_op && inode->i_op->revalidate) return inode->i_op->revalidate(dentry); return 0; } -@@ -135,13 +139,15 @@ static int cp_new_stat(struct inode * in +@@ -135,13 +137,15 @@ asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf) { struct nameidata nd; @@ -1476,7 +1504,7 @@ path_release(&nd); } return error; -@@ -151,13 +157,15 @@ asmlinkage long sys_stat(char * filename +@@ -151,13 +155,15 @@ asmlinkage long sys_newstat(char * filename, struct stat * statbuf) { struct nameidata nd; @@ -1494,7 +1522,7 @@ path_release(&nd); } return error; -@@ -172,13 +180,15 @@ asmlinkage long sys_newstat(char * filen +@@ -172,13 +178,15 @@ asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf) { struct nameidata nd; @@ -1512,7 +1540,7 @@ path_release(&nd); } return error; -@@ -189,13 +199,15 @@ asmlinkage long sys_lstat(char * filenam +@@ -189,13 +197,15 @@ asmlinkage long sys_newlstat(char * filename, struct stat * statbuf) { struct nameidata nd; @@ -1530,7 +1558,7 @@ path_release(&nd); } return error; -@@ -216,7 +228,7 @@ asmlinkage long sys_fstat(unsigned int f +@@ -216,7 +226,7 @@ if (f) { struct dentry * dentry = f->f_dentry; @@ -1539,7 +1567,7 @@ if (!err) err = cp_old_stat(dentry->d_inode, statbuf); fput(f); -@@ -235,7 +247,7 @@ asmlinkage long sys_newfstat(unsigned in +@@ -235,7 +245,7 @@ if (f) { struct dentry * dentry = f->f_dentry; @@ -1548,7 +1576,7 @@ if (!err) err = cp_new_stat(dentry->d_inode, statbuf); fput(f); -@@ -257,7 +269,7 @@ asmlinkage long sys_readlink(const char +@@ -257,7 +267,7 @@ error = -EINVAL; if (inode->i_op && inode->i_op->readlink && @@ -1557,7 +1585,7 @@ UPDATE_ATIME(inode); error = inode->i_op->readlink(nd.dentry, buf, bufsiz); } -@@ -333,12 +345,14 @@ asmlinkage long sys_stat64(char * filena +@@ -333,12 +343,14 @@ { struct nameidata nd; int error; @@ -1574,7 +1602,7 @@ path_release(&nd); } return error; -@@ -348,12 +362,14 @@ asmlinkage long sys_lstat64(char * filen +@@ -348,12 +360,14 @@ { struct nameidata nd; int error; @@ -1591,7 +1619,7 @@ path_release(&nd); } return error; -@@ -368,7 +384,7 @@ asmlinkage long sys_fstat64(unsigned lon +@@ -368,7 +382,7 @@ if (f) { struct dentry * dentry = f->f_dentry; @@ -1600,9 +1628,11 @@ if (!err) err = cp_new_stat64(dentry->d_inode, statbuf); fput(f); ---- linux-2.4.20-hp4-pnnl13/fs/proc/base.c~vfs_intent-2.4.20-hp 2003-09-13 15:19:19.000000000 +0400 -+++ linux-2.4.20-hp4-pnnl13-alexey/fs/proc/base.c 2003-09-14 17:33:51.000000000 +0400 -@@ -481,6 +481,9 @@ static int proc_pid_follow_link(struct d +Index: linux/fs/proc/base.c +=================================================================== +--- linux.orig/fs/proc/base.c Wed Mar 17 13:00:35 2004 ++++ linux/fs/proc/base.c Wed Mar 17 13:11:25 2004 +@@ -481,6 +481,9 @@ error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt); nd->last_type = LAST_BIND; @@ -1612,8 +1642,10 @@ out: return error; } ---- linux-2.4.20-hp4-pnnl13/include/linux/dcache.h~vfs_intent-2.4.20-hp 2002-11-29 02:53:15.000000000 +0300 -+++ linux-2.4.20-hp4-pnnl13-alexey/include/linux/dcache.h 2003-09-14 17:33:51.000000000 +0400 +Index: linux/include/linux/dcache.h +=================================================================== +--- linux.orig/include/linux/dcache.h Thu Nov 28 18:53:15 2002 ++++ linux/include/linux/dcache.h Wed Mar 17 13:11:25 2004 @@ -6,6 +6,51 @@ #include #include @@ -1666,7 +1698,7 @@ /* * linux/include/linux/dcache.h -@@ -91,8 +136,22 @@ struct dentry_operations { +@@ -91,8 +136,22 @@ int (*d_delete)(struct dentry *); void (*d_release)(struct dentry *); void (*d_iput)(struct dentry *, struct inode *); @@ -1689,7 +1721,7 @@ /* the dentry parameter passed to d_hash and d_compare is the parent * directory of the entries to be compared. It is used in case these * functions need any directory specific information for determining -@@ -124,6 +183,7 @@ d_iput: no no yes +@@ -124,6 +183,7 @@ * s_nfsd_free_path semaphore will be down */ #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ @@ -1697,9 +1729,11 @@ extern spinlock_t dcache_lock; ---- linux-2.4.20-hp4-pnnl13/include/linux/fs.h~vfs_intent-2.4.20-hp 2003-09-14 17:33:50.000000000 +0400 -+++ linux-2.4.20-hp4-pnnl13-alexey/include/linux/fs.h 2003-09-14 17:33:51.000000000 +0400 -@@ -73,6 +73,7 @@ extern int leases_enable, dir_notify_ena +Index: linux/include/linux/fs.h +=================================================================== +--- linux.orig/include/linux/fs.h Wed Mar 17 13:11:23 2004 ++++ linux/include/linux/fs.h Wed Mar 17 13:11:31 2004 +@@ -73,6 +73,7 @@ #define FMODE_READ 1 #define FMODE_WRITE 2 @@ -1707,7 +1741,7 @@ #define READ 0 #define WRITE 1 -@@ -340,6 +341,9 @@ extern void set_bh_page(struct buffer_he +@@ -340,6 +341,9 @@ #define ATTR_MTIME_SET 256 #define ATTR_FORCE 512 /* Not a change, but a change it */ #define ATTR_ATTR_FLAG 1024 @@ -1717,7 +1751,7 @@ /* * This is the Inode Attributes structure, used for notify_change(). It -@@ -474,6 +478,7 @@ struct inode { +@@ -474,6 +478,7 @@ struct pipe_inode_info *i_pipe; struct block_device *i_bdev; struct char_device *i_cdev; @@ -1725,7 +1759,7 @@ unsigned long i_dnotify_mask; /* Directory notify events */ struct dnotify_struct *i_dnotify; /* for directory notifications */ -@@ -576,6 +581,7 @@ struct file { +@@ -576,6 +581,7 @@ /* needed for tty driver, and maybe others */ void *private_data; @@ -1733,7 +1767,7 @@ /* preallocated helper kiobuf to speedup O_DIRECT */ struct kiobuf *f_iobuf; -@@ -697,6 +703,7 @@ struct nameidata { +@@ -697,6 +703,7 @@ struct qstr last; unsigned int flags; int last_type; @@ -1741,7 +1775,7 @@ }; /* -@@ -817,7 +824,8 @@ extern int vfs_symlink(struct inode *, s +@@ -817,7 +824,8 @@ extern int vfs_link(struct dentry *, struct inode *, struct dentry *); extern int vfs_rmdir(struct inode *, struct dentry *); extern int vfs_unlink(struct inode *, struct dentry *); @@ -1751,7 +1785,7 @@ /* * File types -@@ -877,21 +885,32 @@ struct file_operations { +@@ -877,21 +885,32 @@ struct inode_operations { int (*create) (struct inode *,struct dentry *,int); @@ -1784,7 +1818,7 @@ int (*getattr) (struct dentry *, struct iattr *); int (*setxattr) (struct dentry *, const char *, void *, size_t, int); ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); -@@ -1088,10 +1107,14 @@ static inline int get_lease(struct inode +@@ -1088,10 +1107,14 @@ asmlinkage long sys_open(const char *, int, int); asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */ @@ -1800,7 +1834,7 @@ extern int filp_close(struct file *, fl_owner_t id); extern char * getname(const char *); -@@ -1353,6 +1376,7 @@ typedef int (*read_actor_t)(read_descrip +@@ -1354,6 +1377,7 @@ extern loff_t default_llseek(struct file *file, loff_t offset, int origin); extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *)); @@ -1808,7 +1842,7 @@ extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *)); extern int FASTCALL(path_walk(const char *, struct nameidata *)); extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); -@@ -1364,6 +1388,8 @@ extern struct dentry * lookup_one_len(co +@@ -1365,6 +1389,8 @@ extern struct dentry * lookup_hash(struct qstr *, struct dentry *); #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) @@ -1816,8 +1850,8 @@ +#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it) extern void inode_init_once(struct inode *); - extern void iput(struct inode *); -@@ -1499,6 +1525,8 @@ extern struct file_operations generic_ro + extern void _inode_init_once(struct inode *); +@@ -1503,6 +1529,8 @@ extern int vfs_readlink(struct dentry *, char *, int, const char *); extern int vfs_follow_link(struct nameidata *, const char *); @@ -1826,9 +1860,11 @@ extern int page_readlink(struct dentry *, char *, int); extern int page_follow_link(struct dentry *, struct nameidata *); extern struct inode_operations page_symlink_inode_operations; ---- linux-2.4.20-hp4-pnnl13/include/linux/fs_struct.h~vfs_intent-2.4.20-hp 2001-07-14 02:10:44.000000000 +0400 -+++ linux-2.4.20-hp4-pnnl13-alexey/include/linux/fs_struct.h 2003-09-14 17:33:51.000000000 +0400 -@@ -34,10 +34,12 @@ static inline void set_fs_root(struct fs +Index: linux/include/linux/fs_struct.h +=================================================================== +--- linux.orig/include/linux/fs_struct.h Fri Jul 13 18:10:44 2001 ++++ linux/include/linux/fs_struct.h Wed Mar 17 13:11:25 2004 +@@ -34,10 +34,12 @@ write_lock(&fs->lock); old_root = fs->root; old_rootmnt = fs->rootmnt; @@ -1841,7 +1877,7 @@ dput(old_root); mntput(old_rootmnt); } -@@ -57,10 +59,12 @@ static inline void set_fs_pwd(struct fs_ +@@ -57,10 +59,12 @@ write_lock(&fs->lock); old_pwd = fs->pwd; old_pwdmnt = fs->pwdmnt; @@ -1854,9 +1890,11 @@ dput(old_pwd); mntput(old_pwdmnt); } ---- linux-2.4.20-hp4-pnnl13/kernel/ksyms.c~vfs_intent-2.4.20-hp 2003-09-14 17:33:50.000000000 +0400 -+++ linux-2.4.20-hp4-pnnl13-alexey/kernel/ksyms.c 2003-09-14 17:33:51.000000000 +0400 -@@ -296,6 +296,7 @@ EXPORT_SYMBOL(read_cache_page); +Index: linux/kernel/ksyms.c +=================================================================== +--- linux.orig/kernel/ksyms.c Wed Mar 17 13:11:23 2004 ++++ linux/kernel/ksyms.c Wed Mar 17 13:11:25 2004 +@@ -315,6 +315,7 @@ EXPORT_SYMBOL(set_page_dirty); EXPORT_SYMBOL(vfs_readlink); EXPORT_SYMBOL(vfs_follow_link); @@ -1864,9 +1902,11 @@ EXPORT_SYMBOL(page_readlink); EXPORT_SYMBOL(page_follow_link); EXPORT_SYMBOL(page_symlink_inode_operations); ---- linux-2.4.20-hp4-pnnl13/kernel/fork.c~vfs_intent-2.4.20-hp 2003-09-13 15:19:27.000000000 +0400 -+++ linux-2.4.20-hp4-pnnl13-alexey/kernel/fork.c 2003-09-14 17:33:51.000000000 +0400 -@@ -388,10 +388,13 @@ static inline struct fs_struct *__copy_f +Index: linux/kernel/fork.c +=================================================================== +--- linux.orig/kernel/fork.c Wed Mar 17 13:00:38 2004 ++++ linux/kernel/fork.c Wed Mar 17 13:11:25 2004 +@@ -387,10 +387,13 @@ fs->umask = old->umask; read_lock(&old->lock); fs->rootmnt = mntget(old->rootmnt); @@ -1880,9 +1920,11 @@ fs->altrootmnt = mntget(old->altrootmnt); fs->altroot = dget(old->altroot); } else { ---- linux-2.4.20-hp4-pnnl13/kernel/exit.c~vfs_intent-2.4.20-hp 2003-09-13 15:19:27.000000000 +0400 -+++ linux-2.4.20-hp4-pnnl13-alexey/kernel/exit.c 2003-09-14 17:33:51.000000000 +0400 -@@ -239,11 +239,14 @@ static inline void __put_fs_struct(struc +Index: linux/kernel/exit.c +=================================================================== +--- linux.orig/kernel/exit.c Wed Mar 17 13:00:38 2004 ++++ linux/kernel/exit.c Wed Mar 17 13:11:25 2004 +@@ -239,11 +239,14 @@ { /* No need to hold fs->lock if we are killing it */ if (atomic_dec_and_test(&fs->count)) { @@ -1897,5 +1939,3 @@ dput(fs->altroot); mntput(fs->altrootmnt); } - -_ diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.20-rh.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.20-rh.patch index f9096db..409c8f0 100644 --- a/lustre/kernel_patches/patches/vfs_intent-2.4.20-rh.patch +++ b/lustre/kernel_patches/patches/vfs_intent-2.4.20-rh.patch @@ -13,9 +13,11 @@ kernel/ksyms.c | 1 13 files changed, 578 insertions(+), 129 deletions(-) ---- linux-2.4.20-rh-20.9/fs/dcache.c~vfs_intent-2.4.20-rh 2003-09-13 19:34:35.000000000 +0400 -+++ linux-2.4.20-rh-20.9-alexey/fs/dcache.c 2003-09-14 17:34:53.000000000 +0400 -@@ -186,6 +186,13 @@ int d_invalidate(struct dentry * dentry) +Index: linux-2.4.20/fs/dcache.c +=================================================================== +--- linux-2.4.20.orig/fs/dcache.c Wed Mar 17 13:57:05 2004 ++++ linux-2.4.20/fs/dcache.c Wed Mar 17 13:57:11 2004 +@@ -186,6 +186,13 @@ spin_unlock(&dcache_lock); return 0; } @@ -29,7 +31,7 @@ /* * Check whether to do a partial shrink_dcache * to get rid of unused child entries. -@@ -841,13 +848,19 @@ void d_delete(struct dentry * dentry) +@@ -841,13 +848,19 @@ * Adds a dentry to the hash according to its name. */ @@ -52,9 +54,11 @@ } #define do_switch(x,y) do { \ ---- linux-2.4.20-rh-20.9/fs/exec.c~vfs_intent-2.4.20-rh 2003-09-13 19:34:35.000000000 +0400 -+++ linux-2.4.20-rh-20.9-alexey/fs/exec.c 2003-09-14 17:34:53.000000000 +0400 -@@ -114,8 +114,10 @@ asmlinkage long sys_uselib(const char * +Index: linux-2.4.20/fs/exec.c +=================================================================== +--- linux-2.4.20.orig/fs/exec.c Wed Mar 17 13:57:05 2004 ++++ linux-2.4.20/fs/exec.c Wed Mar 17 13:57:11 2004 +@@ -114,8 +114,10 @@ struct file * file; struct nameidata nd; int error; @@ -66,7 +70,7 @@ if (error) goto out; -@@ -127,7 +129,8 @@ asmlinkage long sys_uselib(const char * +@@ -127,7 +129,8 @@ if (error) goto exit; @@ -76,7 +80,7 @@ error = PTR_ERR(file); if (IS_ERR(file)) goto out; -@@ -382,8 +385,10 @@ struct file *open_exec(const char *name) +@@ -382,8 +385,10 @@ struct inode *inode; struct file *file; int err = 0; @@ -88,7 +92,7 @@ file = ERR_PTR(err); if (!err) { inode = nd.dentry->d_inode; -@@ -395,7 +400,8 @@ struct file *open_exec(const char *name) +@@ -395,7 +400,8 @@ err = -EACCES; file = ERR_PTR(err); if (!err) { @@ -98,7 +102,7 @@ if (!IS_ERR(file)) { err = deny_write_access(file); if (err) { -@@ -407,6 +413,7 @@ out: +@@ -407,6 +413,7 @@ return file; } } @@ -106,7 +110,7 @@ path_release(&nd); } goto out; -@@ -1296,7 +1303,7 @@ int do_coredump(long signr, int exit_cod +@@ -1296,7 +1303,7 @@ goto close_fail; if (!file->f_op->write) goto close_fail; @@ -115,8 +119,10 @@ goto close_fail; retval = binfmt->core_dump(signr, regs, file); ---- linux-2.4.20-rh-20.9/fs/namei.c~vfs_intent-2.4.20-rh 2003-09-13 19:34:25.000000000 +0400 -+++ linux-2.4.20-rh-20.9-alexey/fs/namei.c 2003-09-14 17:34:53.000000000 +0400 +Index: linux-2.4.20/fs/namei.c +=================================================================== +--- linux-2.4.20.orig/fs/namei.c Wed Mar 17 13:57:03 2004 ++++ linux-2.4.20/fs/namei.c Wed Mar 17 13:58:01 2004 @@ -94,6 +94,13 @@ * XEmacs seems to be relying on it... */ @@ -131,7 +137,7 @@ /* In order to reduce some races, while at the same time doing additional * checking and hopefully speeding things up, we copy filenames to the * kernel data space before using them.. -@@ -260,10 +267,19 @@ void path_release(struct nameidata *nd) +@@ -260,10 +267,19 @@ * Internal lookup() using the new generic dcache. * SMP-safe */ @@ -152,7 +158,7 @@ if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) { dput(dentry); -@@ -281,11 +297,15 @@ static struct dentry * cached_lookup(str +@@ -281,11 +297,15 @@ * make sure that nobody added the entry to the dcache in the meantime.. * SMP-safe */ @@ -169,7 +175,7 @@ down(&dir->i_sem); /* * First re-do the cached lookup just in case it was created -@@ -300,6 +320,9 @@ static struct dentry * real_lookup(struc +@@ -300,6 +320,9 @@ result = ERR_PTR(-ENOMEM); if (dentry) { lock_kernel(); @@ -179,7 +185,7 @@ result = dir->i_op->lookup(dir, dentry); unlock_kernel(); if (result) -@@ -321,6 +344,15 @@ static struct dentry * real_lookup(struc +@@ -321,6 +344,15 @@ dput(result); result = ERR_PTR(-ENOENT); } @@ -195,7 +201,7 @@ } return result; } -@@ -334,7 +366,8 @@ int max_recursive_link = 5; +@@ -334,7 +366,8 @@ * Without that kind of total limit, nasty chains of consecutive * symlinks can cause almost arbitrarily long lookups. */ @@ -205,7 +211,7 @@ { int err; if (current->link_count >= max_recursive_link) -@@ -348,10 +381,18 @@ static inline int do_follow_link(struct +@@ -348,10 +381,18 @@ current->link_count++; current->total_link_count++; UPDATE_ATIME(dentry->d_inode); @@ -224,7 +230,7 @@ path_release(nd); return -ELOOP; } -@@ -381,15 +422,26 @@ int follow_up(struct vfsmount **mnt, str +@@ -381,15 +422,26 @@ return __follow_up(mnt, dentry); } @@ -252,7 +258,7 @@ dput(*dentry); mntput(mounted->mnt_parent); *dentry = dget(mounted->mnt_root); -@@ -401,7 +453,7 @@ static inline int __follow_down(struct v +@@ -401,7 +453,7 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry) { @@ -261,7 +267,7 @@ } static inline void follow_dotdot(struct nameidata *nd) -@@ -437,7 +489,7 @@ static inline void follow_dotdot(struct +@@ -437,7 +489,7 @@ mntput(nd->mnt); nd->mnt = parent; } @@ -270,7 +276,7 @@ ; } -@@ -449,7 +501,8 @@ static inline void follow_dotdot(struct +@@ -449,7 +501,8 @@ * * We expect 'base' to be positive and a directory. */ @@ -280,7 +286,7 @@ { struct dentry *dentry; struct inode *inode; -@@ -526,19 +579,18 @@ int link_path_walk(const char * name, st +@@ -526,19 +579,18 @@ break; } /* This does the actual lookups.. */ @@ -303,7 +309,7 @@ err = -ENOENT; inode = dentry->d_inode; -@@ -549,7 +601,7 @@ int link_path_walk(const char * name, st +@@ -549,7 +601,7 @@ goto out_dput; if (inode->i_op->follow_link) { @@ -312,7 +318,7 @@ dput(dentry); if (err) goto return_err; -@@ -565,7 +617,7 @@ int link_path_walk(const char * name, st +@@ -565,7 +617,7 @@ nd->dentry = dentry; } err = -ENOTDIR; @@ -321,7 +327,7 @@ break; continue; /* here ends the main loop */ -@@ -592,22 +644,22 @@ last_component: +@@ -592,22 +644,22 @@ if (err < 0) break; } @@ -348,7 +354,7 @@ dput(dentry); if (err) goto return_err; -@@ -621,7 +673,8 @@ last_component: +@@ -621,7 +673,8 @@ goto no_inode; if (lookup_flags & LOOKUP_DIRECTORY) { err = -ENOTDIR; @@ -358,7 +364,7 @@ break; } goto return_base; -@@ -645,6 +698,25 @@ return_reval: +@@ -645,6 +698,27 @@ * Check the cached dentry for staleness. */ dentry = nd->dentry; @@ -380,11 +386,13 @@ + } + nd->dentry = new; + } ++ if (!nd->dentry->d_inode) ++ goto no_inode; + } else if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { err = -ESTALE; if (!dentry->d_op->d_revalidate(dentry, 0)) { -@@ -658,15 +730,28 @@ out_dput: +@@ -658,15 +732,28 @@ dput(dentry); break; } @@ -414,7 +422,7 @@ } /* SMP-safe */ -@@ -751,6 +836,17 @@ walk_init_root(const char *name, struct +@@ -751,6 +838,17 @@ } /* SMP-safe */ @@ -432,7 +440,7 @@ int path_lookup(const char *path, unsigned flags, struct nameidata *nd) { int error = 0; -@@ -765,6 +861,7 @@ int path_init(const char *name, unsigned +@@ -765,6 +863,7 @@ { nd->last_type = LAST_ROOT; /* if there are only slashes... */ nd->flags = flags; @@ -440,7 +448,7 @@ if (*name=='/') return walk_init_root(name,nd); read_lock(¤t->fs->lock); -@@ -779,7 +876,8 @@ int path_init(const char *name, unsigned +@@ -779,7 +878,8 @@ * needs parent already locked. Doesn't follow mounts. * SMP-safe. */ @@ -450,7 +458,7 @@ { struct dentry * dentry; struct inode *inode; -@@ -802,13 +900,16 @@ struct dentry * lookup_hash(struct qstr +@@ -802,13 +902,16 @@ goto out; } @@ -468,7 +476,7 @@ dentry = inode->i_op->lookup(inode, new); unlock_kernel(); if (!dentry) -@@ -820,6 +921,12 @@ out: +@@ -820,6 +923,12 @@ return dentry; } @@ -481,7 +489,7 @@ /* SMP-safe */ struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) { -@@ -841,7 +948,7 @@ struct dentry * lookup_one_len(const cha +@@ -841,7 +950,7 @@ } this.hash = end_name_hash(hash); @@ -490,7 +498,7 @@ access: return ERR_PTR(-EACCES); } -@@ -872,6 +979,23 @@ int __user_walk(const char *name, unsign +@@ -872,6 +981,23 @@ return err; } @@ -514,7 +522,7 @@ /* * It's inline, so penalty for filesystems that don't use sticky bit is * minimal. -@@ -969,7 +1093,8 @@ static inline int lookup_flags(unsigned +@@ -969,7 +1095,8 @@ return retval; } @@ -524,7 +532,7 @@ { int error; -@@ -982,12 +1107,15 @@ int vfs_create(struct inode *dir, struct +@@ -982,12 +1109,15 @@ goto exit_lock; error = -EACCES; /* shouldn't it be ENOSYS? */ @@ -542,7 +550,7 @@ unlock_kernel(); exit_lock: up(&dir->i_zombie); -@@ -996,6 +1124,11 @@ exit_lock: +@@ -996,6 +1126,11 @@ return error; } @@ -554,7 +562,7 @@ /* * open_namei() * -@@ -1010,7 +1143,8 @@ exit_lock: +@@ -1010,7 +1145,8 @@ * for symlinks (where the permissions are checked later). * SMP-safe */ @@ -564,7 +572,7 @@ { int acc_mode, error = 0; struct inode *inode; -@@ -1020,11 +1154,14 @@ int open_namei(const char * pathname, in +@@ -1020,11 +1156,14 @@ acc_mode = ACC_MODE(flag); @@ -580,7 +588,7 @@ if (error) return error; dentry = nd->dentry; -@@ -1034,6 +1171,10 @@ int open_namei(const char * pathname, in +@@ -1034,6 +1173,10 @@ /* * Create - we need to know the parent. */ @@ -591,7 +599,7 @@ error = path_lookup(pathname, LOOKUP_PARENT, nd); if (error) return error; -@@ -1049,7 +1190,7 @@ int open_namei(const char * pathname, in +@@ -1049,7 +1192,7 @@ dir = nd->dentry; down(&dir->d_inode->i_sem); @@ -600,7 +608,7 @@ do_last: error = PTR_ERR(dentry); -@@ -1058,10 +1199,11 @@ do_last: +@@ -1058,10 +1201,11 @@ goto exit; } @@ -614,7 +622,7 @@ up(&dir->d_inode->i_sem); dput(nd->dentry); nd->dentry = dentry; -@@ -1086,7 +1228,7 @@ do_last: +@@ -1086,7 +1230,7 @@ error = -ELOOP; if (flag & O_NOFOLLOW) goto exit_dput; @@ -623,7 +631,7 @@ } error = -ENOENT; if (!dentry->d_inode) -@@ -1165,7 +1307,7 @@ ok: +@@ -1165,7 +1309,7 @@ if (!error) { DQUOT_INIT(inode); @@ -632,7 +640,7 @@ } put_write_access(inode); if (error) -@@ -1177,8 +1319,10 @@ ok: +@@ -1177,8 +1321,10 @@ return 0; exit_dput: @@ -643,7 +651,7 @@ path_release(nd); return error; -@@ -1197,7 +1341,16 @@ do_link: +@@ -1197,7 +1343,16 @@ * are done. Procfs-like symlinks just set LAST_BIND. */ UPDATE_ATIME(dentry->d_inode); @@ -660,7 +668,7 @@ dput(dentry); if (error) return error; -@@ -1219,13 +1372,20 @@ do_link: +@@ -1219,13 +1374,20 @@ } dir = nd->dentry; down(&dir->d_inode->i_sem); @@ -683,7 +691,7 @@ { struct dentry *dentry; -@@ -1233,7 +1393,7 @@ static struct dentry *lookup_create(stru +@@ -1233,7 +1395,7 @@ dentry = ERR_PTR(-EEXIST); if (nd->last_type != LAST_NORM) goto fail; @@ -692,12 +700,16 @@ if (IS_ERR(dentry)) goto fail; if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) -@@ -1289,7 +1449,16 @@ asmlinkage long sys_mknod(const char * f +@@ -1289,7 +1451,20 @@ error = path_lookup(tmp, LOOKUP_PARENT, &nd); if (error) goto out; - dentry = lookup_create(&nd, 0); + ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out2; ++ } + if (nd.dentry->d_inode->i_op->mknod_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->mknod_raw(&nd, mode, dev); @@ -710,7 +722,7 @@ error = PTR_ERR(dentry); mode &= ~current->fs->umask; -@@ -1310,6 +1479,7 @@ asmlinkage long sys_mknod(const char * f +@@ -1310,6 +1485,7 @@ dput(dentry); } up(&nd.dentry->d_inode->i_sem); @@ -718,11 +730,15 @@ path_release(&nd); out: putname(tmp); -@@ -1357,7 +1527,14 @@ asmlinkage long sys_mkdir(const char * p +@@ -1357,7 +1533,18 @@ error = path_lookup(tmp, LOOKUP_PARENT, &nd); if (error) goto out; - dentry = lookup_create(&nd, 1); ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out2; ++ } + if (nd.dentry->d_inode->i_op->mkdir_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->mkdir_raw(&nd, mode); @@ -734,7 +750,7 @@ error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { error = vfs_mkdir(nd.dentry->d_inode, dentry, -@@ -1365,6 +1542,7 @@ asmlinkage long sys_mkdir(const char * p +@@ -1365,6 +1552,7 @@ dput(dentry); } up(&nd.dentry->d_inode->i_sem); @@ -742,7 +758,7 @@ path_release(&nd); out: putname(tmp); -@@ -1465,8 +1643,16 @@ asmlinkage long sys_rmdir(const char * p +@@ -1465,8 +1653,16 @@ error = -EBUSY; goto exit1; } @@ -760,7 +776,7 @@ error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { error = vfs_rmdir(nd.dentry->d_inode, dentry); -@@ -1524,8 +1710,15 @@ asmlinkage long sys_unlink(const char * +@@ -1524,8 +1720,15 @@ error = -EISDIR; if (nd.last_type != LAST_NORM) goto exit1; @@ -777,11 +793,15 @@ error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { /* Why not before? Because we want correct error value */ -@@ -1592,15 +1785,23 @@ asmlinkage long sys_symlink(const char * +@@ -1592,15 +1795,27 @@ error = path_lookup(to, LOOKUP_PARENT, &nd); if (error) goto out; - dentry = lookup_create(&nd, 0); ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out2; ++ } + if (nd.dentry->d_inode->i_op->symlink_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->symlink_raw(&nd, from); @@ -803,11 +823,15 @@ putname(to); } putname(from); -@@ -1676,7 +1877,14 @@ asmlinkage long sys_link(const char * ol +@@ -1676,7 +1891,18 @@ error = -EXDEV; if (old_nd.mnt != nd.mnt) goto out_release; - new_dentry = lookup_create(&nd, 0); ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out_release; ++ } + if (nd.dentry->d_inode->i_op->link_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->link_raw(&old_nd, &nd); @@ -819,7 +843,7 @@ error = PTR_ERR(new_dentry); if (!IS_ERR(new_dentry)) { error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); -@@ -1720,7 +1928,7 @@ exit: +@@ -1720,7 +1946,7 @@ * locking]. */ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, @@ -828,7 +852,7 @@ { int error; struct inode *target; -@@ -1799,7 +2007,7 @@ out_unlock: +@@ -1799,7 +2025,7 @@ } int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, @@ -837,7 +861,7 @@ { int error; -@@ -1887,9 +2095,18 @@ static inline int do_rename(const char * +@@ -1887,9 +2113,18 @@ if (newnd.last_type != LAST_NORM) goto exit2; @@ -857,7 +881,7 @@ error = PTR_ERR(old_dentry); if (IS_ERR(old_dentry)) goto exit3; -@@ -1905,16 +2122,16 @@ static inline int do_rename(const char * +@@ -1905,16 +2140,16 @@ if (newnd.last.name[newnd.last.len]) goto exit4; } @@ -876,7 +900,7 @@ dput(new_dentry); exit4: dput(old_dentry); -@@ -1965,20 +2182,28 @@ out: +@@ -1965,20 +2200,28 @@ } static inline int @@ -907,7 +931,7 @@ out: if (current->link_count || res || nd->last_type!=LAST_NORM) return res; -@@ -2002,7 +2227,13 @@ fail: +@@ -2002,7 +2245,13 @@ int vfs_follow_link(struct nameidata *nd, const char *link) { @@ -922,7 +946,7 @@ } /* get the link contents into pagecache */ -@@ -2044,7 +2275,7 @@ int page_follow_link(struct dentry *dent +@@ -2044,7 +2293,7 @@ { struct page *page = NULL; char *s = page_getlink(dentry, &page); @@ -931,9 +955,11 @@ if (page) { kunmap(page); page_cache_release(page); ---- linux-2.4.20-rh-20.9/fs/namespace.c~vfs_intent-2.4.20-rh 2003-09-13 19:34:35.000000000 +0400 -+++ linux-2.4.20-rh-20.9-alexey/fs/namespace.c 2003-09-14 17:34:53.000000000 +0400 -@@ -99,6 +99,7 @@ static void detach_mnt(struct vfsmount * +Index: linux-2.4.20/fs/namespace.c +=================================================================== +--- linux-2.4.20.orig/fs/namespace.c Wed Mar 17 13:57:05 2004 ++++ linux-2.4.20/fs/namespace.c Wed Mar 17 13:57:11 2004 +@@ -99,6 +99,7 @@ { old_nd->dentry = mnt->mnt_mountpoint; old_nd->mnt = mnt->mnt_parent; @@ -941,7 +967,7 @@ mnt->mnt_parent = mnt; mnt->mnt_mountpoint = mnt->mnt_root; list_del_init(&mnt->mnt_child); -@@ -110,6 +111,7 @@ static void attach_mnt(struct vfsmount * +@@ -110,6 +111,7 @@ { mnt->mnt_parent = mntget(nd->mnt); mnt->mnt_mountpoint = dget(nd->dentry); @@ -949,7 +975,7 @@ list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry)); list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts); nd->dentry->d_mounted++; -@@ -485,14 +487,17 @@ static int do_loopback(struct nameidata +@@ -485,14 +487,17 @@ { struct nameidata old_nd; struct vfsmount *mnt = NULL; @@ -969,7 +995,7 @@ down_write(¤t->namespace->sem); err = -EINVAL; -@@ -515,6 +520,7 @@ static int do_loopback(struct nameidata +@@ -515,6 +520,7 @@ } up_write(¤t->namespace->sem); @@ -977,7 +1003,7 @@ path_release(&old_nd); return err; } -@@ -698,6 +704,7 @@ long do_mount(char * dev_name, char * di +@@ -698,6 +704,7 @@ unsigned long flags, void *data_page) { struct nameidata nd; @@ -985,7 +1011,7 @@ int retval = 0; int mnt_flags = 0; -@@ -722,10 +729,11 @@ long do_mount(char * dev_name, char * di +@@ -722,10 +729,11 @@ flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV); /* ... and get the mountpoint */ @@ -1000,7 +1026,7 @@ if (flags & MS_REMOUNT) retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, data_page); -@@ -736,6 +744,8 @@ long do_mount(char * dev_name, char * di +@@ -736,6 +744,8 @@ else retval = do_add_mount(&nd, type_page, flags, mnt_flags, dev_name, data_page); @@ -1009,7 +1035,7 @@ path_release(&nd); return retval; } -@@ -901,6 +911,8 @@ asmlinkage long sys_pivot_root(const cha +@@ -901,6 +911,8 @@ { struct vfsmount *tmp; struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd; @@ -1018,7 +1044,7 @@ int error; if (!capable(CAP_SYS_ADMIN)) -@@ -908,14 +920,14 @@ asmlinkage long sys_pivot_root(const cha +@@ -908,14 +920,14 @@ lock_kernel(); @@ -1035,7 +1061,7 @@ if (error) goto out1; -@@ -970,8 +982,10 @@ out2: +@@ -970,8 +982,10 @@ up(&old_nd.dentry->d_inode->i_zombie); up_write(¤t->namespace->sem); path_release(&user_nd); @@ -1046,8 +1072,10 @@ path_release(&new_nd); out0: unlock_kernel(); ---- linux-2.4.20-rh-20.9/fs/open.c~vfs_intent-2.4.20-rh 2003-09-13 19:34:25.000000000 +0400 -+++ linux-2.4.20-rh-20.9-alexey/fs/open.c 2003-09-14 17:34:53.000000000 +0400 +Index: linux-2.4.20/fs/open.c +=================================================================== +--- linux-2.4.20.orig/fs/open.c Wed Mar 17 13:57:03 2004 ++++ linux-2.4.20/fs/open.c Wed Mar 17 13:57:11 2004 @@ -19,6 +19,8 @@ #include @@ -1057,7 +1085,7 @@ int vfs_statfs(struct super_block *sb, struct statfs *buf) { -@@ -95,9 +97,10 @@ void fd_install(unsigned int fd, struct +@@ -95,9 +97,10 @@ write_unlock(&files->file_lock); } @@ -1069,7 +1097,7 @@ int error; struct iattr newattrs; -@@ -108,7 +111,13 @@ int do_truncate(struct dentry *dentry, l +@@ -108,7 +111,13 @@ down(&inode->i_sem); newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; @@ -1084,7 +1112,7 @@ up(&inode->i_sem); return error; } -@@ -118,12 +127,13 @@ static inline long do_sys_truncate(const +@@ -118,12 +127,13 @@ struct nameidata nd; struct inode * inode; int error; @@ -1099,7 +1127,7 @@ if (error) goto out; inode = nd.dentry->d_inode; -@@ -163,11 +173,13 @@ static inline long do_sys_truncate(const +@@ -163,11 +173,13 @@ error = locks_verify_truncate(inode, NULL, length); if (!error) { DQUOT_INIT(inode); @@ -1114,7 +1142,7 @@ path_release(&nd); out: return error; -@@ -215,7 +227,7 @@ static inline long do_sys_ftruncate(unsi +@@ -215,7 +227,7 @@ error = locks_verify_truncate(inode, file, length); if (!error) @@ -1123,7 +1151,7 @@ out_putf: fput(file); out: -@@ -260,11 +272,13 @@ asmlinkage long sys_utime(char * filenam +@@ -260,11 +272,13 @@ struct inode * inode; struct iattr newattrs; @@ -1138,7 +1166,7 @@ error = -EROFS; if (IS_RDONLY(inode)) goto dput_and_out; -@@ -279,11 +293,25 @@ asmlinkage long sys_utime(char * filenam +@@ -279,11 +293,25 @@ goto dput_and_out; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; @@ -1165,7 +1193,7 @@ error = notify_change(nd.dentry, &newattrs); dput_and_out: path_release(&nd); -@@ -304,12 +332,14 @@ asmlinkage long sys_utimes(char * filena +@@ -304,12 +332,14 @@ struct inode * inode; struct iattr newattrs; @@ -1181,7 +1209,7 @@ error = -EROFS; if (IS_RDONLY(inode)) goto dput_and_out; -@@ -324,7 +354,20 @@ asmlinkage long sys_utimes(char * filena +@@ -324,7 +354,20 @@ newattrs.ia_atime = times[0].tv_sec; newattrs.ia_mtime = times[1].tv_sec; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; @@ -1203,7 +1231,7 @@ if (current->fsuid != inode->i_uid && (error = permission(inode,MAY_WRITE)) != 0) goto dput_and_out; -@@ -347,6 +390,7 @@ asmlinkage long sys_access(const char * +@@ -347,6 +390,7 @@ int old_fsuid, old_fsgid; kernel_cap_t old_cap; int res; @@ -1211,7 +1239,7 @@ if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ return -EINVAL; -@@ -364,13 +408,14 @@ asmlinkage long sys_access(const char * +@@ -364,13 +408,14 @@ else current->cap_effective = current->cap_permitted; @@ -1227,7 +1255,7 @@ path_release(&nd); } -@@ -385,8 +430,9 @@ asmlinkage long sys_chdir(const char * f +@@ -385,8 +430,9 @@ { int error; struct nameidata nd; @@ -1238,7 +1266,7 @@ if (error) goto out; -@@ -397,6 +443,7 @@ asmlinkage long sys_chdir(const char * f +@@ -397,6 +443,7 @@ set_fs_pwd(current->fs, nd.mnt, nd.dentry); dput_and_out: @@ -1246,7 +1274,7 @@ path_release(&nd); out: return error; -@@ -436,9 +483,10 @@ asmlinkage long sys_chroot(const char * +@@ -436,9 +483,10 @@ { int error; struct nameidata nd; @@ -1259,7 +1287,7 @@ if (error) goto out; -@@ -454,39 +502,56 @@ asmlinkage long sys_chroot(const char * +@@ -454,39 +502,56 @@ set_fs_altroot(); error = 0; dput_and_out: @@ -1330,7 +1358,7 @@ fput(file); out: return err; -@@ -495,30 +560,14 @@ out: +@@ -495,30 +560,14 @@ asmlinkage long sys_chmod(const char * filename, mode_t mode) { struct nameidata nd; @@ -1362,7 +1390,7 @@ path_release(&nd); out: return error; -@@ -538,6 +587,20 @@ static int chown_common(struct dentry * +@@ -538,6 +587,20 @@ error = -EROFS; if (IS_RDONLY(inode)) goto out; @@ -1383,7 +1411,7 @@ error = -EPERM; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out; -@@ -642,8 +705,9 @@ struct file *filp_open(const char * file +@@ -642,8 +705,9 @@ { int namei_flags, error; struct nameidata nd; @@ -1395,7 +1423,7 @@ namei_flags = flags; if ((namei_flags+1) & O_ACCMODE) -@@ -651,14 +715,15 @@ struct file *filp_open(const char * file +@@ -651,14 +715,15 @@ if (namei_flags & O_TRUNC) namei_flags |= 2; @@ -1416,7 +1444,7 @@ { struct file * f; struct inode *inode; -@@ -695,12 +760,15 @@ struct file *dentry_open(struct dentry * +@@ -695,12 +760,15 @@ } if (f->f_op && f->f_op->open) { @@ -1432,7 +1460,7 @@ return f; cleanup_all: -@@ -715,11 +783,17 @@ cleanup_all: +@@ -715,11 +783,17 @@ cleanup_file: put_filp(f); cleanup_dentry: @@ -1450,9 +1478,11 @@ /* * Find an empty file descriptor entry, and mark it busy. */ ---- linux-2.4.20-rh-20.9/fs/proc/base.c~vfs_intent-2.4.20-rh 2003-09-13 19:34:35.000000000 +0400 -+++ linux-2.4.20-rh-20.9-alexey/fs/proc/base.c 2003-09-14 17:34:53.000000000 +0400 -@@ -494,6 +494,9 @@ static int proc_pid_follow_link(struct d +Index: linux-2.4.20/fs/proc/base.c +=================================================================== +--- linux-2.4.20.orig/fs/proc/base.c Wed Mar 17 13:57:05 2004 ++++ linux-2.4.20/fs/proc/base.c Wed Mar 17 13:57:11 2004 +@@ -494,6 +494,9 @@ error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt); nd->last_type = LAST_BIND; @@ -1462,9 +1492,11 @@ out: return error; } ---- linux-2.4.20-rh-20.9/fs/stat.c~vfs_intent-2.4.20-rh 2003-09-13 19:34:35.000000000 +0400 -+++ linux-2.4.20-rh-20.9-alexey/fs/stat.c 2003-09-14 17:35:10.000000000 +0400 -@@ -17,10 +17,14 @@ +Index: linux-2.4.20/fs/stat.c +=================================================================== +--- linux-2.4.20.orig/fs/stat.c Wed Mar 17 13:57:05 2004 ++++ linux-2.4.20/fs/stat.c Wed Mar 17 13:58:01 2004 +@@ -17,10 +17,12 @@ * Revalidate the inode. This is required for proper NFS attribute caching. */ static __inline__ int @@ -1473,15 +1505,13 @@ { struct inode * inode = dentry->d_inode; - if (inode->i_op && inode->i_op->revalidate) -+ if (!inode) -+ return -ENOENT; + if (inode->i_op && inode->i_op->revalidate_it) + return inode->i_op->revalidate_it(dentry, it); + else if (inode->i_op && inode->i_op->revalidate) return inode->i_op->revalidate(dentry); return 0; } -@@ -32,13 +36,13 @@ static inline nlink_t user_nlink(struct +@@ -32,13 +34,13 @@ return inode->i_nlink; } @@ -1497,7 +1527,7 @@ if (res) return res; -@@ -111,10 +115,12 @@ int vfs_stat(char *name, struct kstat *s +@@ -111,10 +113,12 @@ { struct nameidata nd; int error; @@ -1512,7 +1542,7 @@ path_release(&nd); } return error; -@@ -124,10 +130,12 @@ int vfs_lstat(char *name, struct kstat * +@@ -124,10 +128,12 @@ { struct nameidata nd; int error; @@ -1527,7 +1557,7 @@ path_release(&nd); } return error; -@@ -139,7 +147,7 @@ int vfs_fstat(unsigned int fd, struct ks +@@ -139,7 +145,7 @@ int error = -EBADF; if (f) { @@ -1536,7 +1566,7 @@ fput(f); } return error; -@@ -286,7 +294,7 @@ asmlinkage long sys_readlink(const char +@@ -286,7 +292,7 @@ error = -EINVAL; if (inode->i_op && inode->i_op->readlink && @@ -1545,8 +1575,10 @@ UPDATE_ATIME(inode); error = inode->i_op->readlink(nd.dentry, buf, bufsiz); } ---- linux-2.4.20-rh-20.9/include/linux/dcache.h~vfs_intent-2.4.20-rh 2003-09-13 19:34:28.000000000 +0400 -+++ linux-2.4.20-rh-20.9-alexey/include/linux/dcache.h 2003-09-14 17:34:53.000000000 +0400 +Index: linux-2.4.20/include/linux/dcache.h +=================================================================== +--- linux-2.4.20.orig/include/linux/dcache.h Wed Mar 17 13:57:04 2004 ++++ linux-2.4.20/include/linux/dcache.h Wed Mar 17 13:57:11 2004 @@ -6,6 +6,51 @@ #include #include @@ -1599,7 +1631,7 @@ /* * linux/include/linux/dcache.h -@@ -96,8 +141,22 @@ struct dentry_operations { +@@ -96,8 +141,22 @@ int (*d_delete)(struct dentry *); void (*d_release)(struct dentry *); void (*d_iput)(struct dentry *, struct inode *); @@ -1622,7 +1654,7 @@ /* the dentry parameter passed to d_hash and d_compare is the parent * directory of the entries to be compared. It is used in case these * functions need any directory specific information for determining -@@ -129,6 +188,7 @@ d_iput: no no yes +@@ -129,6 +188,7 @@ * s_nfsd_free_path semaphore will be down */ #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ @@ -1630,9 +1662,11 @@ extern spinlock_t dcache_lock; ---- linux-2.4.20-rh-20.9/include/linux/fs.h~vfs_intent-2.4.20-rh 2003-09-14 17:34:50.000000000 +0400 -+++ linux-2.4.20-rh-20.9-alexey/include/linux/fs.h 2003-09-14 17:34:53.000000000 +0400 -@@ -73,6 +73,7 @@ extern int leases_enable, dir_notify_ena +Index: linux-2.4.20/include/linux/fs.h +=================================================================== +--- linux-2.4.20.orig/include/linux/fs.h Wed Mar 17 13:57:11 2004 ++++ linux-2.4.20/include/linux/fs.h Wed Mar 17 13:57:11 2004 +@@ -73,6 +73,7 @@ #define FMODE_READ 1 #define FMODE_WRITE 2 @@ -1640,7 +1674,7 @@ #define READ 0 #define WRITE 1 -@@ -338,6 +339,9 @@ extern void set_bh_page(struct buffer_he +@@ -338,6 +339,9 @@ #define ATTR_MTIME_SET 256 #define ATTR_FORCE 512 /* Not a change, but a change it */ #define ATTR_ATTR_FLAG 1024 @@ -1650,7 +1684,7 @@ /* * This is the Inode Attributes structure, used for notify_change(). It -@@ -473,6 +477,7 @@ struct inode { +@@ -473,6 +477,7 @@ struct pipe_inode_info *i_pipe; struct block_device *i_bdev; struct char_device *i_cdev; @@ -1658,7 +1692,7 @@ unsigned long i_dnotify_mask; /* Directory notify events */ struct dnotify_struct *i_dnotify; /* for directory notifications */ -@@ -575,6 +580,7 @@ struct file { +@@ -575,6 +580,7 @@ /* needed for tty driver, and maybe others */ void *private_data; @@ -1666,7 +1700,7 @@ /* preallocated helper kiobuf to speedup O_DIRECT */ struct kiobuf *f_iobuf; -@@ -702,6 +708,7 @@ struct nameidata { +@@ -702,6 +708,7 @@ struct qstr last; unsigned int flags; int last_type; @@ -1674,7 +1708,7 @@ }; /* -@@ -822,7 +829,8 @@ extern int vfs_symlink(struct inode *, s +@@ -822,7 +829,8 @@ extern int vfs_link(struct dentry *, struct inode *, struct dentry *); extern int vfs_rmdir(struct inode *, struct dentry *); extern int vfs_unlink(struct inode *, struct dentry *); @@ -1684,7 +1718,7 @@ /* * File types -@@ -882,21 +890,32 @@ struct file_operations { +@@ -882,21 +890,32 @@ struct inode_operations { int (*create) (struct inode *,struct dentry *,int); @@ -1717,7 +1751,7 @@ int (*getattr) (struct dentry *, struct iattr *); int (*setxattr) (struct dentry *, const char *, void *, size_t, int); ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); -@@ -1092,10 +1111,14 @@ static inline int get_lease(struct inode +@@ -1092,10 +1111,14 @@ asmlinkage long sys_open(const char *, int, int); asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */ @@ -1733,7 +1767,7 @@ extern int filp_close(struct file *, fl_owner_t id); extern char * getname(const char *); -@@ -1386,6 +1409,7 @@ typedef int (*read_actor_t)(read_descrip +@@ -1386,6 +1409,7 @@ extern loff_t default_llseek(struct file *file, loff_t offset, int origin); extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *)); @@ -1741,7 +1775,7 @@ extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *)); extern int FASTCALL(path_walk(const char *, struct nameidata *)); extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); -@@ -1397,6 +1421,8 @@ extern struct dentry * lookup_one_len(co +@@ -1397,6 +1421,8 @@ extern struct dentry * lookup_hash(struct qstr *, struct dentry *); #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) @@ -1750,7 +1784,7 @@ extern void inode_init_once(struct inode *); extern void iput(struct inode *); -@@ -1504,6 +1530,8 @@ extern struct file_operations generic_ro +@@ -1504,6 +1530,8 @@ extern int vfs_readlink(struct dentry *, char *, int, const char *); extern int vfs_follow_link(struct nameidata *, const char *); @@ -1759,9 +1793,11 @@ extern int page_readlink(struct dentry *, char *, int); extern int page_follow_link(struct dentry *, struct nameidata *); extern struct inode_operations page_symlink_inode_operations; ---- linux-2.4.20-rh-20.9/include/linux/fs_struct.h~vfs_intent-2.4.20-rh 2003-09-13 19:34:19.000000000 +0400 -+++ linux-2.4.20-rh-20.9-alexey/include/linux/fs_struct.h 2003-09-14 17:34:53.000000000 +0400 -@@ -37,10 +37,12 @@ static inline void set_fs_root(struct fs +Index: linux-2.4.20/include/linux/fs_struct.h +=================================================================== +--- linux-2.4.20.orig/include/linux/fs_struct.h Wed Mar 17 13:57:02 2004 ++++ linux-2.4.20/include/linux/fs_struct.h Wed Mar 17 13:57:11 2004 +@@ -37,10 +37,12 @@ write_lock(&fs->lock); old_root = fs->root; old_rootmnt = fs->rootmnt; @@ -1774,7 +1810,7 @@ dput(old_root); mntput(old_rootmnt); } -@@ -60,10 +62,12 @@ static inline void set_fs_pwd(struct fs_ +@@ -60,10 +62,12 @@ write_lock(&fs->lock); old_pwd = fs->pwd; old_pwdmnt = fs->pwdmnt; @@ -1787,9 +1823,11 @@ dput(old_pwd); mntput(old_pwdmnt); } ---- linux-2.4.20-rh-20.9/kernel/ksyms.c~vfs_intent-2.4.20-rh 2003-09-14 17:34:51.000000000 +0400 -+++ linux-2.4.20-rh-20.9-alexey/kernel/ksyms.c 2003-09-14 17:34:53.000000000 +0400 -@@ -298,6 +298,7 @@ EXPORT_SYMBOL(read_cache_page); +Index: linux-2.4.20/kernel/ksyms.c +=================================================================== +--- linux-2.4.20.orig/kernel/ksyms.c Wed Mar 17 13:57:11 2004 ++++ linux-2.4.20/kernel/ksyms.c Wed Mar 17 13:57:11 2004 +@@ -297,6 +297,7 @@ EXPORT_SYMBOL(set_page_dirty); EXPORT_SYMBOL(vfs_readlink); EXPORT_SYMBOL(vfs_follow_link); @@ -1797,9 +1835,11 @@ EXPORT_SYMBOL(page_readlink); EXPORT_SYMBOL(page_follow_link); EXPORT_SYMBOL(page_symlink_inode_operations); ---- linux-2.4.20-rh-20.9/kernel/fork.c~vfs_intent-2.4.20-rh 2003-09-13 19:34:35.000000000 +0400 -+++ linux-2.4.20-rh-20.9-alexey/kernel/fork.c 2003-09-14 17:34:53.000000000 +0400 -@@ -440,10 +440,13 @@ static inline struct fs_struct *__copy_f +Index: linux-2.4.20/kernel/fork.c +=================================================================== +--- linux-2.4.20.orig/kernel/fork.c Wed Mar 17 13:57:05 2004 ++++ linux-2.4.20/kernel/fork.c Wed Mar 17 13:57:11 2004 +@@ -440,10 +440,13 @@ fs->umask = old->umask; read_lock(&old->lock); fs->rootmnt = mntget(old->rootmnt); @@ -1813,9 +1853,11 @@ fs->altrootmnt = mntget(old->altrootmnt); fs->altroot = dget(old->altroot); } else { ---- linux-2.4.20-rh-20.9/kernel/exit.c~vfs_intent-2.4.20-rh 2003-09-13 19:34:35.000000000 +0400 -+++ linux-2.4.20-rh-20.9-alexey/kernel/exit.c 2003-09-14 17:34:53.000000000 +0400 -@@ -345,11 +345,14 @@ static inline void __put_fs_struct(struc +Index: linux-2.4.20/kernel/exit.c +=================================================================== +--- linux-2.4.20.orig/kernel/exit.c Wed Mar 17 13:57:05 2004 ++++ linux-2.4.20/kernel/exit.c Wed Mar 17 13:57:11 2004 +@@ -345,11 +345,14 @@ { /* No need to hold fs->lock if we are killing it */ if (atomic_dec_and_test(&fs->count)) { @@ -1830,5 +1872,3 @@ dput(fs->altroot); mntput(fs->altrootmnt); } - -_ diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.20-vanilla.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.20-vanilla.patch index 7d83b5e..1ef0b01 100644 --- a/lustre/kernel_patches/patches/vfs_intent-2.4.20-vanilla.patch +++ b/lustre/kernel_patches/patches/vfs_intent-2.4.20-vanilla.patch @@ -12,9 +12,11 @@ kernel/ksyms.c | 1 12 files changed, 558 insertions(+), 128 deletions(-) ---- linux-2.4.20-vanilla/fs/exec.c~vfs_intent-2.4.20-vanilla 2003-05-16 05:29:12.000000000 +0400 -+++ linux-2.4.20-vanilla-alexey/fs/exec.c 2003-09-17 21:05:04.000000000 +0400 -@@ -107,8 +107,10 @@ asmlinkage long sys_uselib(const char * +Index: linux-2.4.24/fs/exec.c +=================================================================== +--- linux-2.4.24.orig/fs/exec.c Fri Nov 28 10:26:21 2003 ++++ linux-2.4.24/fs/exec.c Wed Mar 17 17:36:14 2004 +@@ -112,8 +112,10 @@ asmlinkage long sys_uselib(const char * struct file * file; struct nameidata nd; int error; @@ -26,7 +28,7 @@ if (error) goto out; -@@ -120,7 +122,8 @@ asmlinkage long sys_uselib(const char * +@@ -125,7 +127,8 @@ asmlinkage long sys_uselib(const char * if (error) goto exit; @@ -36,7 +38,7 @@ error = PTR_ERR(file); if (IS_ERR(file)) goto out; -@@ -363,8 +366,10 @@ struct file *open_exec(const char *name) +@@ -374,8 +377,10 @@ struct file *open_exec(const char *name) struct inode *inode; struct file *file; int err = 0; @@ -48,7 +50,7 @@ file = ERR_PTR(err); if (!err) { inode = nd.dentry->d_inode; -@@ -376,7 +381,8 @@ struct file *open_exec(const char *name) +@@ -387,7 +392,8 @@ struct file *open_exec(const char *name) err = -EACCES; file = ERR_PTR(err); if (!err) { @@ -58,7 +60,7 @@ if (!IS_ERR(file)) { err = deny_write_access(file); if (err) { -@@ -388,6 +394,7 @@ out: +@@ -399,6 +405,7 @@ out: return file; } } @@ -66,7 +68,7 @@ path_release(&nd); } goto out; -@@ -989,7 +996,7 @@ int do_coredump(long signr, struct pt_re +@@ -1132,7 +1139,7 @@ int do_coredump(long signr, struct pt_re goto close_fail; if (!file->f_op->write) goto close_fail; @@ -75,8 +77,10 @@ goto close_fail; retval = binfmt->core_dump(signr, regs, file); ---- linux-2.4.20-vanilla/fs/dcache.c~vfs_intent-2.4.20-vanilla 2003-05-16 05:29:12.000000000 +0400 -+++ linux-2.4.20-vanilla-alexey/fs/dcache.c 2003-09-17 21:05:04.000000000 +0400 +Index: linux-2.4.24/fs/dcache.c +=================================================================== +--- linux-2.4.24.orig/fs/dcache.c Fri Jun 13 07:51:37 2003 ++++ linux-2.4.24/fs/dcache.c Wed Mar 17 17:36:14 2004 @@ -181,6 +181,13 @@ int d_invalidate(struct dentry * dentry) spin_unlock(&dcache_lock); return 0; @@ -114,9 +118,11 @@ } #define do_switch(x,y) do { \ ---- linux-2.4.20-vanilla/fs/namespace.c~vfs_intent-2.4.20-vanilla 2003-05-16 05:29:12.000000000 +0400 -+++ linux-2.4.20-vanilla-alexey/fs/namespace.c 2003-09-17 21:05:04.000000000 +0400 -@@ -99,6 +99,7 @@ static void detach_mnt(struct vfsmount * +Index: linux-2.4.24/fs/namespace.c +=================================================================== +--- linux-2.4.24.orig/fs/namespace.c Fri Nov 28 10:26:21 2003 ++++ linux-2.4.24/fs/namespace.c Wed Mar 17 17:36:14 2004 +@@ -98,6 +98,7 @@ static void detach_mnt(struct vfsmount * { old_nd->dentry = mnt->mnt_mountpoint; old_nd->mnt = mnt->mnt_parent; @@ -124,15 +130,15 @@ mnt->mnt_parent = mnt; mnt->mnt_mountpoint = mnt->mnt_root; list_del_init(&mnt->mnt_child); -@@ -110,6 +111,7 @@ static void attach_mnt(struct vfsmount * +@@ -109,6 +110,7 @@ static void attach_mnt(struct vfsmount * { mnt->mnt_parent = mntget(nd->mnt); mnt->mnt_mountpoint = dget(nd->dentry); + PIN(nd->dentry, nd->mnt, 1); list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry)); - list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts); + list_add_tail(&mnt->mnt_child, &nd->mnt->mnt_mounts); nd->dentry->d_mounted++; -@@ -485,14 +487,17 @@ static int do_loopback(struct nameidata +@@ -488,14 +490,17 @@ static int do_loopback(struct nameidata { struct nameidata old_nd; struct vfsmount *mnt = NULL; @@ -152,7 +158,7 @@ down_write(¤t->namespace->sem); err = -EINVAL; -@@ -515,6 +520,7 @@ static int do_loopback(struct nameidata +@@ -518,6 +523,7 @@ static int do_loopback(struct nameidata } up_write(¤t->namespace->sem); @@ -160,7 +166,7 @@ path_release(&old_nd); return err; } -@@ -698,6 +704,7 @@ long do_mount(char * dev_name, char * di +@@ -701,6 +707,7 @@ long do_mount(char * dev_name, char * di unsigned long flags, void *data_page) { struct nameidata nd; @@ -168,7 +174,7 @@ int retval = 0; int mnt_flags = 0; -@@ -722,10 +729,11 @@ long do_mount(char * dev_name, char * di +@@ -725,10 +732,11 @@ long do_mount(char * dev_name, char * di flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV); /* ... and get the mountpoint */ @@ -183,7 +189,7 @@ if (flags & MS_REMOUNT) retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, data_page); -@@ -736,6 +744,8 @@ long do_mount(char * dev_name, char * di +@@ -739,6 +747,8 @@ long do_mount(char * dev_name, char * di else retval = do_add_mount(&nd, type_page, flags, mnt_flags, dev_name, data_page); @@ -192,7 +198,7 @@ path_release(&nd); return retval; } -@@ -901,6 +911,8 @@ asmlinkage long sys_pivot_root(const cha +@@ -904,6 +914,8 @@ asmlinkage long sys_pivot_root(const cha { struct vfsmount *tmp; struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd; @@ -201,7 +207,7 @@ int error; if (!capable(CAP_SYS_ADMIN)) -@@ -908,14 +920,14 @@ asmlinkage long sys_pivot_root(const cha +@@ -911,14 +923,14 @@ asmlinkage long sys_pivot_root(const cha lock_kernel(); @@ -218,7 +224,7 @@ if (error) goto out1; -@@ -970,8 +982,10 @@ out2: +@@ -973,8 +985,10 @@ out2: up(&old_nd.dentry->d_inode->i_zombie); up_write(¤t->namespace->sem); path_release(&user_nd); @@ -229,8 +235,10 @@ path_release(&new_nd); out0: unlock_kernel(); ---- linux-2.4.20-vanilla/fs/namei.c~vfs_intent-2.4.20-vanilla 2003-05-16 05:29:12.000000000 +0400 -+++ linux-2.4.20-vanilla-alexey/fs/namei.c 2003-09-17 21:05:04.000000000 +0400 +Index: linux-2.4.24/fs/namei.c +=================================================================== +--- linux-2.4.24.orig/fs/namei.c Mon Aug 25 04:44:43 2003 ++++ linux-2.4.24/fs/namei.c Wed Mar 17 17:36:52 2004 @@ -94,6 +94,13 @@ * XEmacs seems to be relying on it... */ @@ -403,7 +411,7 @@ break; } goto return_base; -@@ -633,6 +670,25 @@ return_reval: +@@ -635,6 +672,27 @@ return_reval: * Check the cached dentry for staleness. */ dentry = nd->dentry; @@ -419,17 +427,19 @@ + &dentry->d_name, 0, NULL); + d_invalidate(dentry); + dput(dentry); -+ if (IS_ERR(new)) { ++ if (IS_ERR(new)) { + err = PTR_ERR(new); + break; + } + nd->dentry = new; + } ++ if (!nd->dentry->d_inode) ++ goto no_inode; + } else if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { err = -ESTALE; if (!dentry->d_op->d_revalidate(dentry, 0)) { -@@ -646,15 +702,28 @@ out_dput: +@@ -648,15 +706,28 @@ out_dput: dput(dentry); break; } @@ -459,7 +469,7 @@ } /* SMP-safe */ -@@ -739,6 +808,17 @@ walk_init_root(const char *name, struct +@@ -741,6 +812,17 @@ walk_init_root(const char *name, struct } /* SMP-safe */ @@ -477,7 +487,7 @@ int path_lookup(const char *path, unsigned flags, struct nameidata *nd) { int error = 0; -@@ -753,6 +833,7 @@ int path_init(const char *name, unsigned +@@ -755,6 +837,7 @@ int path_init(const char *name, unsigned { nd->last_type = LAST_ROOT; /* if there are only slashes... */ nd->flags = flags; @@ -485,7 +495,7 @@ if (*name=='/') return walk_init_root(name,nd); read_lock(¤t->fs->lock); -@@ -767,7 +848,8 @@ int path_init(const char *name, unsigned +@@ -769,7 +852,8 @@ int path_init(const char *name, unsigned * needs parent already locked. Doesn't follow mounts. * SMP-safe. */ @@ -495,7 +505,7 @@ { struct dentry * dentry; struct inode *inode; -@@ -790,13 +872,16 @@ struct dentry * lookup_hash(struct qstr +@@ -792,13 +876,16 @@ struct dentry * lookup_hash(struct qstr goto out; } @@ -513,7 +523,7 @@ dentry = inode->i_op->lookup(inode, new); unlock_kernel(); if (!dentry) -@@ -808,6 +893,12 @@ out: +@@ -810,6 +897,12 @@ out: return dentry; } @@ -526,7 +536,7 @@ /* SMP-safe */ struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) { -@@ -829,7 +920,7 @@ struct dentry * lookup_one_len(const cha +@@ -831,7 +924,7 @@ struct dentry * lookup_one_len(const cha } this.hash = end_name_hash(hash); @@ -535,7 +545,7 @@ access: return ERR_PTR(-EACCES); } -@@ -860,6 +951,23 @@ int __user_walk(const char *name, unsign +@@ -862,6 +955,23 @@ int __user_walk(const char *name, unsign return err; } @@ -559,7 +569,7 @@ /* * It's inline, so penalty for filesystems that don't use sticky bit is * minimal. -@@ -955,7 +1063,8 @@ static inline int lookup_flags(unsigned +@@ -957,7 +1067,8 @@ static inline int lookup_flags(unsigned return retval; } @@ -569,7 +579,7 @@ { int error; -@@ -968,12 +1077,15 @@ int vfs_create(struct inode *dir, struct +@@ -970,12 +1081,15 @@ int vfs_create(struct inode *dir, struct goto exit_lock; error = -EACCES; /* shouldn't it be ENOSYS? */ @@ -587,7 +597,7 @@ unlock_kernel(); exit_lock: up(&dir->i_zombie); -@@ -982,6 +1094,11 @@ exit_lock: +@@ -984,6 +1098,11 @@ exit_lock: return error; } @@ -599,7 +609,7 @@ /* * open_namei() * -@@ -996,7 +1113,8 @@ exit_lock: +@@ -998,7 +1117,8 @@ exit_lock: * for symlinks (where the permissions are checked later). * SMP-safe */ @@ -609,7 +619,7 @@ { int acc_mode, error = 0; struct inode *inode; -@@ -1006,11 +1124,14 @@ int open_namei(const char * pathname, in +@@ -1008,11 +1128,14 @@ int open_namei(const char * pathname, in acc_mode = ACC_MODE(flag); @@ -625,7 +635,7 @@ if (error) return error; dentry = nd->dentry; -@@ -1020,6 +1141,10 @@ int open_namei(const char * pathname, in +@@ -1022,6 +1145,10 @@ int open_namei(const char * pathname, in /* * Create - we need to know the parent. */ @@ -636,7 +646,7 @@ error = path_lookup(pathname, LOOKUP_PARENT, nd); if (error) return error; -@@ -1035,7 +1160,7 @@ int open_namei(const char * pathname, in +@@ -1037,7 +1164,7 @@ int open_namei(const char * pathname, in dir = nd->dentry; down(&dir->d_inode->i_sem); @@ -645,7 +655,7 @@ do_last: error = PTR_ERR(dentry); -@@ -1044,10 +1169,11 @@ do_last: +@@ -1046,10 +1173,11 @@ do_last: goto exit; } @@ -659,7 +669,7 @@ up(&dir->d_inode->i_sem); dput(nd->dentry); nd->dentry = dentry; -@@ -1151,7 +1277,7 @@ ok: +@@ -1153,7 +1281,7 @@ ok: if (!error) { DQUOT_INIT(inode); @@ -668,7 +678,7 @@ } put_write_access(inode); if (error) -@@ -1163,8 +1289,10 @@ ok: +@@ -1165,8 +1293,10 @@ ok: return 0; exit_dput: @@ -679,7 +689,7 @@ path_release(nd); return error; -@@ -1183,7 +1311,10 @@ do_link: +@@ -1185,7 +1315,10 @@ do_link: * are done. Procfs-like symlinks just set LAST_BIND. */ UPDATE_ATIME(dentry->d_inode); @@ -690,7 +700,7 @@ dput(dentry); if (error) return error; -@@ -1205,13 +1336,20 @@ do_link: +@@ -1207,13 +1340,20 @@ do_link: } dir = nd->dentry; down(&dir->d_inode->i_sem); @@ -713,7 +723,7 @@ { struct dentry *dentry; -@@ -1219,7 +1357,7 @@ static struct dentry *lookup_create(stru +@@ -1221,7 +1361,7 @@ static struct dentry *lookup_create(stru dentry = ERR_PTR(-EEXIST); if (nd->last_type != LAST_NORM) goto fail; @@ -722,12 +732,16 @@ if (IS_ERR(dentry)) goto fail; if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) -@@ -1275,7 +1413,16 @@ asmlinkage long sys_mknod(const char * f +@@ -1277,7 +1417,20 @@ asmlinkage long sys_mknod(const char * f error = path_lookup(tmp, LOOKUP_PARENT, &nd); if (error) goto out; - dentry = lookup_create(&nd, 0); + ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out2; ++ } + if (nd.dentry->d_inode->i_op->mknod_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->mknod_raw(&nd, mode, dev); @@ -740,7 +754,7 @@ error = PTR_ERR(dentry); mode &= ~current->fs->umask; -@@ -1296,6 +1443,7 @@ asmlinkage long sys_mknod(const char * f +@@ -1298,6 +1451,7 @@ asmlinkage long sys_mknod(const char * f dput(dentry); } up(&nd.dentry->d_inode->i_sem); @@ -748,11 +762,15 @@ path_release(&nd); out: putname(tmp); -@@ -1343,7 +1491,14 @@ asmlinkage long sys_mkdir(const char * p +@@ -1345,7 +1499,18 @@ asmlinkage long sys_mkdir(const char * p error = path_lookup(tmp, LOOKUP_PARENT, &nd); if (error) goto out; - dentry = lookup_create(&nd, 1); ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out2; ++ } + if (nd.dentry->d_inode->i_op->mkdir_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->mkdir_raw(&nd, mode); @@ -764,7 +782,7 @@ error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { error = vfs_mkdir(nd.dentry->d_inode, dentry, -@@ -1351,6 +1506,7 @@ asmlinkage long sys_mkdir(const char * p +@@ -1353,6 +1518,7 @@ asmlinkage long sys_mkdir(const char * p dput(dentry); } up(&nd.dentry->d_inode->i_sem); @@ -772,7 +790,7 @@ path_release(&nd); out: putname(tmp); -@@ -1451,8 +1607,16 @@ asmlinkage long sys_rmdir(const char * p +@@ -1453,8 +1619,16 @@ asmlinkage long sys_rmdir(const char * p error = -EBUSY; goto exit1; } @@ -790,7 +808,7 @@ error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { error = vfs_rmdir(nd.dentry->d_inode, dentry); -@@ -1510,8 +1674,15 @@ asmlinkage long sys_unlink(const char * +@@ -1512,8 +1686,15 @@ asmlinkage long sys_unlink(const char * error = -EISDIR; if (nd.last_type != LAST_NORM) goto exit1; @@ -807,11 +825,15 @@ error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { /* Why not before? Because we want correct error value */ -@@ -1578,15 +1749,23 @@ asmlinkage long sys_symlink(const char * +@@ -1580,15 +1761,27 @@ asmlinkage long sys_symlink(const char * error = path_lookup(to, LOOKUP_PARENT, &nd); if (error) goto out; - dentry = lookup_create(&nd, 0); ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out2; ++ } + if (nd.dentry->d_inode->i_op->symlink_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->symlink_raw(&nd, from); @@ -833,11 +855,15 @@ putname(to); } putname(from); -@@ -1662,7 +1841,14 @@ asmlinkage long sys_link(const char * ol +@@ -1664,7 +1857,18 @@ asmlinkage long sys_link(const char * ol error = -EXDEV; if (old_nd.mnt != nd.mnt) goto out_release; - new_dentry = lookup_create(&nd, 0); ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out_release; ++ } + if (nd.dentry->d_inode->i_op->link_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->link_raw(&old_nd, &nd); @@ -849,7 +875,7 @@ error = PTR_ERR(new_dentry); if (!IS_ERR(new_dentry)) { error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); -@@ -1706,7 +1892,7 @@ exit: +@@ -1708,7 +1912,7 @@ exit: * locking]. */ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, @@ -858,7 +884,7 @@ { int error; struct inode *target; -@@ -1785,7 +1971,7 @@ out_unlock: +@@ -1787,7 +1991,7 @@ out_unlock: } int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, @@ -867,7 +893,7 @@ { int error; -@@ -1873,9 +2059,18 @@ static inline int do_rename(const char * +@@ -1875,9 +2079,18 @@ static inline int do_rename(const char * if (newnd.last_type != LAST_NORM) goto exit2; @@ -887,7 +913,7 @@ error = PTR_ERR(old_dentry); if (IS_ERR(old_dentry)) goto exit3; -@@ -1891,16 +2086,16 @@ static inline int do_rename(const char * +@@ -1893,16 +2106,16 @@ static inline int do_rename(const char * if (newnd.last.name[newnd.last.len]) goto exit4; } @@ -906,7 +932,7 @@ dput(new_dentry); exit4: dput(old_dentry); -@@ -1951,20 +2146,26 @@ out: +@@ -1953,20 +2166,26 @@ out: } static inline int @@ -935,7 +961,7 @@ out: if (current->link_count || res || nd->last_type!=LAST_NORM) return res; -@@ -1986,7 +2187,13 @@ fail: +@@ -1990,7 +2209,13 @@ fail: int vfs_follow_link(struct nameidata *nd, const char *link) { @@ -950,7 +976,7 @@ } /* get the link contents into pagecache */ -@@ -2028,7 +2235,7 @@ int page_follow_link(struct dentry *dent +@@ -2032,7 +2257,7 @@ int page_follow_link(struct dentry *dent { struct page *page = NULL; char *s = page_getlink(dentry, &page); @@ -959,8 +985,10 @@ if (page) { kunmap(page); page_cache_release(page); ---- linux-2.4.20-vanilla/fs/open.c~vfs_intent-2.4.20-vanilla 2003-05-16 05:29:13.000000000 +0400 -+++ linux-2.4.20-vanilla-alexey/fs/open.c 2003-09-17 21:05:04.000000000 +0400 +Index: linux-2.4.24/fs/open.c +=================================================================== +--- linux-2.4.24.orig/fs/open.c Mon Aug 25 04:44:43 2003 ++++ linux-2.4.24/fs/open.c Wed Mar 17 17:36:14 2004 @@ -19,6 +19,8 @@ #include @@ -982,7 +1010,7 @@ int error; struct iattr newattrs; -@@ -108,7 +111,13 @@ int do_truncate(struct dentry *dentry, l +@@ -109,7 +112,13 @@ int do_truncate(struct dentry *dentry, l down(&inode->i_sem); newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; @@ -995,9 +1023,9 @@ + } else + error = notify_change(dentry, &newattrs); up(&inode->i_sem); + up_write(&inode->i_alloc_sem); return error; - } -@@ -118,12 +127,13 @@ static inline long do_sys_truncate(const +@@ -120,12 +129,13 @@ static inline long do_sys_truncate(const struct nameidata nd; struct inode * inode; int error; @@ -1012,7 +1040,7 @@ if (error) goto out; inode = nd.dentry->d_inode; -@@ -163,11 +173,13 @@ static inline long do_sys_truncate(const +@@ -165,11 +175,13 @@ static inline long do_sys_truncate(const error = locks_verify_truncate(inode, NULL, length); if (!error) { DQUOT_INIT(inode); @@ -1027,7 +1055,7 @@ path_release(&nd); out: return error; -@@ -215,7 +227,7 @@ static inline long do_sys_ftruncate(unsi +@@ -217,7 +229,7 @@ static inline long do_sys_ftruncate(unsi error = locks_verify_truncate(inode, file, length); if (!error) @@ -1036,7 +1064,7 @@ out_putf: fput(file); out: -@@ -260,11 +272,13 @@ asmlinkage long sys_utime(char * filenam +@@ -262,11 +274,13 @@ asmlinkage long sys_utime(char * filenam struct inode * inode; struct iattr newattrs; @@ -1051,7 +1079,7 @@ error = -EROFS; if (IS_RDONLY(inode)) goto dput_and_out; -@@ -279,11 +293,25 @@ asmlinkage long sys_utime(char * filenam +@@ -281,11 +295,25 @@ asmlinkage long sys_utime(char * filenam goto dput_and_out; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; @@ -1078,7 +1106,7 @@ error = notify_change(nd.dentry, &newattrs); dput_and_out: path_release(&nd); -@@ -304,12 +332,14 @@ asmlinkage long sys_utimes(char * filena +@@ -306,12 +334,14 @@ asmlinkage long sys_utimes(char * filena struct inode * inode; struct iattr newattrs; @@ -1094,7 +1122,7 @@ error = -EROFS; if (IS_RDONLY(inode)) goto dput_and_out; -@@ -324,7 +354,20 @@ asmlinkage long sys_utimes(char * filena +@@ -326,7 +356,20 @@ asmlinkage long sys_utimes(char * filena newattrs.ia_atime = times[0].tv_sec; newattrs.ia_mtime = times[1].tv_sec; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; @@ -1116,7 +1144,7 @@ if (current->fsuid != inode->i_uid && (error = permission(inode,MAY_WRITE)) != 0) goto dput_and_out; -@@ -347,6 +390,7 @@ asmlinkage long sys_access(const char * +@@ -349,6 +392,7 @@ asmlinkage long sys_access(const char * int old_fsuid, old_fsgid; kernel_cap_t old_cap; int res; @@ -1124,7 +1152,7 @@ if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ return -EINVAL; -@@ -364,13 +408,14 @@ asmlinkage long sys_access(const char * +@@ -366,13 +410,14 @@ asmlinkage long sys_access(const char * else current->cap_effective = current->cap_permitted; @@ -1140,7 +1168,7 @@ path_release(&nd); } -@@ -385,8 +430,9 @@ asmlinkage long sys_chdir(const char * f +@@ -387,8 +432,9 @@ asmlinkage long sys_chdir(const char * f { int error; struct nameidata nd; @@ -1151,7 +1179,7 @@ if (error) goto out; -@@ -397,6 +443,7 @@ asmlinkage long sys_chdir(const char * f +@@ -399,6 +445,7 @@ asmlinkage long sys_chdir(const char * f set_fs_pwd(current->fs, nd.mnt, nd.dentry); dput_and_out: @@ -1159,7 +1187,7 @@ path_release(&nd); out: return error; -@@ -436,9 +483,10 @@ asmlinkage long sys_chroot(const char * +@@ -438,9 +485,10 @@ asmlinkage long sys_chroot(const char * { int error; struct nameidata nd; @@ -1172,7 +1200,7 @@ if (error) goto out; -@@ -454,39 +502,56 @@ asmlinkage long sys_chroot(const char * +@@ -456,39 +504,56 @@ asmlinkage long sys_chroot(const char * set_fs_altroot(); error = 0; dput_and_out: @@ -1243,7 +1271,7 @@ fput(file); out: return err; -@@ -495,30 +560,14 @@ out: +@@ -497,30 +562,14 @@ out: asmlinkage long sys_chmod(const char * filename, mode_t mode) { struct nameidata nd; @@ -1275,7 +1303,7 @@ path_release(&nd); out: return error; -@@ -538,6 +587,20 @@ static int chown_common(struct dentry * +@@ -540,6 +589,20 @@ static int chown_common(struct dentry * error = -EROFS; if (IS_RDONLY(inode)) goto out; @@ -1296,7 +1324,7 @@ error = -EPERM; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out; -@@ -642,6 +705,7 @@ struct file *filp_open(const char * file +@@ -644,6 +707,7 @@ struct file *filp_open(const char * file { int namei_flags, error; struct nameidata nd; @@ -1304,7 +1332,7 @@ namei_flags = flags; if ((namei_flags+1) & O_ACCMODE) -@@ -649,14 +713,15 @@ struct file *filp_open(const char * file +@@ -651,14 +715,15 @@ struct file *filp_open(const char * file if (namei_flags & O_TRUNC) namei_flags |= 2; @@ -1325,7 +1353,7 @@ { struct file * f; struct inode *inode; -@@ -693,12 +758,15 @@ struct file *dentry_open(struct dentry * +@@ -695,12 +760,15 @@ struct file *dentry_open(struct dentry * } if (f->f_op && f->f_op->open) { @@ -1341,7 +1369,7 @@ return f; cleanup_all: -@@ -713,11 +781,17 @@ cleanup_all: +@@ -715,11 +783,17 @@ cleanup_all: cleanup_file: put_filp(f); cleanup_dentry: @@ -1359,9 +1387,11 @@ /* * Find an empty file descriptor entry, and mark it busy. */ ---- linux-2.4.20-vanilla/fs/stat.c~vfs_intent-2.4.20-vanilla 2001-09-14 03:04:43.000000000 +0400 -+++ linux-2.4.20-vanilla-alexey/fs/stat.c 2003-09-17 21:05:04.000000000 +0400 -@@ -17,10 +17,14 @@ +Index: linux-2.4.24/fs/stat.c +=================================================================== +--- linux-2.4.24.orig/fs/stat.c Mon Aug 25 04:44:43 2003 ++++ linux-2.4.24/fs/stat.c Wed Mar 17 17:36:52 2004 +@@ -17,10 +17,12 @@ * Revalidate the inode. This is required for proper NFS attribute caching. */ static __inline__ int @@ -1370,15 +1400,13 @@ { struct inode * inode = dentry->d_inode; - if (inode->i_op && inode->i_op->revalidate) -+ if (!inode) -+ return -ENOENT; + if (inode->i_op && inode->i_op->revalidate_it) + return inode->i_op->revalidate_it(dentry, it); + else if (inode->i_op && inode->i_op->revalidate) return inode->i_op->revalidate(dentry); return 0; } -@@ -135,13 +139,15 @@ static int cp_new_stat(struct inode * in +@@ -137,13 +139,15 @@ static int cp_new_stat(struct inode * in asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf) { struct nameidata nd; @@ -1396,7 +1424,7 @@ path_release(&nd); } return error; -@@ -151,13 +157,15 @@ asmlinkage long sys_stat(char * filename +@@ -153,13 +157,15 @@ asmlinkage long sys_stat(char * filename asmlinkage long sys_newstat(char * filename, struct stat * statbuf) { struct nameidata nd; @@ -1414,7 +1442,7 @@ path_release(&nd); } return error; -@@ -172,13 +180,15 @@ asmlinkage long sys_newstat(char * filen +@@ -174,13 +180,15 @@ asmlinkage long sys_newstat(char * filen asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf) { struct nameidata nd; @@ -1432,7 +1460,7 @@ path_release(&nd); } return error; -@@ -189,13 +199,15 @@ asmlinkage long sys_lstat(char * filenam +@@ -191,13 +199,15 @@ asmlinkage long sys_lstat(char * filenam asmlinkage long sys_newlstat(char * filename, struct stat * statbuf) { struct nameidata nd; @@ -1450,7 +1478,7 @@ path_release(&nd); } return error; -@@ -216,7 +228,7 @@ asmlinkage long sys_fstat(unsigned int f +@@ -218,7 +228,7 @@ asmlinkage long sys_fstat(unsigned int f if (f) { struct dentry * dentry = f->f_dentry; @@ -1459,7 +1487,7 @@ if (!err) err = cp_old_stat(dentry->d_inode, statbuf); fput(f); -@@ -235,7 +247,7 @@ asmlinkage long sys_newfstat(unsigned in +@@ -237,7 +247,7 @@ asmlinkage long sys_newfstat(unsigned in if (f) { struct dentry * dentry = f->f_dentry; @@ -1468,7 +1496,7 @@ if (!err) err = cp_new_stat(dentry->d_inode, statbuf); fput(f); -@@ -257,7 +269,7 @@ asmlinkage long sys_readlink(const char +@@ -259,7 +269,7 @@ asmlinkage long sys_readlink(const char error = -EINVAL; if (inode->i_op && inode->i_op->readlink && @@ -1477,7 +1505,7 @@ UPDATE_ATIME(inode); error = inode->i_op->readlink(nd.dentry, buf, bufsiz); } -@@ -333,12 +345,14 @@ asmlinkage long sys_stat64(char * filena +@@ -335,12 +345,14 @@ asmlinkage long sys_stat64(char * filena { struct nameidata nd; int error; @@ -1494,7 +1522,7 @@ path_release(&nd); } return error; -@@ -348,12 +362,14 @@ asmlinkage long sys_lstat64(char * filen +@@ -350,12 +362,14 @@ asmlinkage long sys_lstat64(char * filen { struct nameidata nd; int error; @@ -1511,7 +1539,7 @@ path_release(&nd); } return error; -@@ -368,7 +384,7 @@ asmlinkage long sys_fstat64(unsigned lon +@@ -370,7 +384,7 @@ asmlinkage long sys_fstat64(unsigned lon if (f) { struct dentry * dentry = f->f_dentry; @@ -1520,8 +1548,10 @@ if (!err) err = cp_new_stat64(dentry->d_inode, statbuf); fput(f); ---- linux-2.4.20-vanilla/include/linux/dcache.h~vfs_intent-2.4.20-vanilla 2003-05-16 05:29:15.000000000 +0400 -+++ linux-2.4.20-vanilla-alexey/include/linux/dcache.h 2003-09-17 21:05:42.000000000 +0400 +Index: linux-2.4.24/include/linux/dcache.h +=================================================================== +--- linux-2.4.24.orig/include/linux/dcache.h Thu Nov 28 15:53:15 2002 ++++ linux-2.4.24/include/linux/dcache.h Wed Mar 17 17:36:14 2004 @@ -6,6 +6,51 @@ #include #include @@ -1605,8 +1635,10 @@ extern spinlock_t dcache_lock; ---- linux-2.4.20-vanilla/include/linux/fs.h~vfs_intent-2.4.20-vanilla 2003-09-17 21:05:03.000000000 +0400 -+++ linux-2.4.20-vanilla-alexey/include/linux/fs.h 2003-09-17 21:05:04.000000000 +0400 +Index: linux-2.4.24/include/linux/fs.h +=================================================================== +--- linux-2.4.24.orig/include/linux/fs.h Wed Mar 17 17:36:14 2004 ++++ linux-2.4.24/include/linux/fs.h Wed Mar 17 17:36:14 2004 @@ -73,6 +73,7 @@ extern int leases_enable, dir_notify_ena #define FMODE_READ 1 @@ -1615,7 +1647,7 @@ #define READ 0 #define WRITE 1 -@@ -338,6 +339,9 @@ extern void set_bh_page(struct buffer_he +@@ -340,6 +341,9 @@ extern void set_bh_page(struct buffer_he #define ATTR_MTIME_SET 256 #define ATTR_FORCE 512 /* Not a change, but a change it */ #define ATTR_ATTR_FLAG 1024 @@ -1625,7 +1657,7 @@ /* * This is the Inode Attributes structure, used for notify_change(). It -@@ -471,6 +475,7 @@ struct inode { +@@ -478,6 +482,7 @@ struct inode { struct pipe_inode_info *i_pipe; struct block_device *i_bdev; struct char_device *i_cdev; @@ -1633,7 +1665,7 @@ unsigned long i_dnotify_mask; /* Directory notify events */ struct dnotify_struct *i_dnotify; /* for directory notifications */ -@@ -542,6 +547,7 @@ struct file { +@@ -582,6 +587,7 @@ struct file { /* needed for tty driver, and maybe others */ void *private_data; @@ -1641,15 +1673,15 @@ /* preallocated helper kiobuf to speedup O_DIRECT */ struct kiobuf *f_iobuf; -@@ -661,6 +667,7 @@ struct nameidata { +@@ -702,6 +708,7 @@ struct nameidata { struct qstr last; unsigned int flags; int last_type; + struct lookup_intent *intent; }; - #define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */ -@@ -794,7 +801,8 @@ extern int vfs_symlink(struct inode *, s + /* +@@ -822,7 +829,8 @@ extern int vfs_symlink(struct inode *, s extern int vfs_link(struct dentry *, struct inode *, struct dentry *); extern int vfs_rmdir(struct inode *, struct dentry *); extern int vfs_unlink(struct inode *, struct dentry *); @@ -1659,7 +1691,7 @@ /* * File types -@@ -854,21 +862,32 @@ struct file_operations { +@@ -884,21 +892,32 @@ struct file_operations { struct inode_operations { int (*create) (struct inode *,struct dentry *,int); @@ -1692,7 +1724,7 @@ int (*getattr) (struct dentry *, struct iattr *); int (*setxattr) (struct dentry *, const char *, void *, size_t, int); ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); -@@ -1070,10 +1089,14 @@ static inline int get_lease(struct inode +@@ -1094,10 +1113,14 @@ static inline int get_lease(struct inode asmlinkage long sys_open(const char *, int, int); asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */ @@ -1708,7 +1740,7 @@ extern int filp_close(struct file *, fl_owner_t id); extern char * getname(const char *); -@@ -1335,6 +1358,7 @@ typedef int (*read_actor_t)(read_descrip +@@ -1386,6 +1409,7 @@ typedef int (*read_actor_t)(read_descrip extern loff_t default_llseek(struct file *file, loff_t offset, int origin); extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *)); @@ -1716,16 +1748,16 @@ extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *)); extern int FASTCALL(path_walk(const char *, struct nameidata *)); extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); -@@ -1346,6 +1370,8 @@ extern struct dentry * lookup_one_len(co +@@ -1397,6 +1421,8 @@ extern struct dentry * lookup_one_len(co extern struct dentry * lookup_hash(struct qstr *, struct dentry *); #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) +#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it) +#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it) + extern void inode_init_once(struct inode *); extern void iput(struct inode *); - extern void force_delete(struct inode *); -@@ -1455,6 +1481,8 @@ extern struct file_operations generic_ro +@@ -1500,6 +1526,8 @@ extern struct file_operations generic_ro extern int vfs_readlink(struct dentry *, char *, int, const char *); extern int vfs_follow_link(struct nameidata *, const char *); @@ -1734,8 +1766,10 @@ extern int page_readlink(struct dentry *, char *, int); extern int page_follow_link(struct dentry *, struct nameidata *); extern struct inode_operations page_symlink_inode_operations; ---- linux-2.4.20-vanilla/include/linux/fs_struct.h~vfs_intent-2.4.20-vanilla 2001-07-14 02:10:44.000000000 +0400 -+++ linux-2.4.20-vanilla-alexey/include/linux/fs_struct.h 2003-09-17 21:05:04.000000000 +0400 +Index: linux-2.4.24/include/linux/fs_struct.h +=================================================================== +--- linux-2.4.24.orig/include/linux/fs_struct.h Fri Jul 13 15:10:44 2001 ++++ linux-2.4.24/include/linux/fs_struct.h Wed Mar 17 17:36:14 2004 @@ -34,10 +34,12 @@ static inline void set_fs_root(struct fs write_lock(&fs->lock); old_root = fs->root; @@ -1762,19 +1796,23 @@ dput(old_pwd); mntput(old_pwdmnt); } ---- linux-2.4.20-vanilla/kernel/ksyms.c~vfs_intent-2.4.20-vanilla 2003-09-17 21:05:03.000000000 +0400 -+++ linux-2.4.20-vanilla-alexey/kernel/ksyms.c 2003-09-17 21:05:04.000000000 +0400 -@@ -269,6 +269,7 @@ EXPORT_SYMBOL(read_cache_page); - EXPORT_SYMBOL(set_page_dirty); +Index: linux-2.4.24/kernel/ksyms.c +=================================================================== +--- linux-2.4.24.orig/kernel/ksyms.c Wed Mar 17 17:36:14 2004 ++++ linux-2.4.24/kernel/ksyms.c Wed Mar 17 17:36:14 2004 +@@ -275,6 +275,7 @@ EXPORT_SYMBOL(set_page_dirty); + EXPORT_SYMBOL(mark_page_accessed); EXPORT_SYMBOL(vfs_readlink); EXPORT_SYMBOL(vfs_follow_link); +EXPORT_SYMBOL(vfs_follow_link_it); EXPORT_SYMBOL(page_readlink); EXPORT_SYMBOL(page_follow_link); EXPORT_SYMBOL(page_symlink_inode_operations); ---- linux-2.4.20-vanilla/kernel/fork.c~vfs_intent-2.4.20-vanilla 2003-05-16 05:29:15.000000000 +0400 -+++ linux-2.4.20-vanilla-alexey/kernel/fork.c 2003-09-17 21:05:04.000000000 +0400 -@@ -384,10 +384,13 @@ static inline struct fs_struct *__copy_f +Index: linux-2.4.24/kernel/fork.c +=================================================================== +--- linux-2.4.24.orig/kernel/fork.c Fri Nov 28 10:26:21 2003 ++++ linux-2.4.24/kernel/fork.c Wed Mar 17 17:36:14 2004 +@@ -386,10 +386,13 @@ static inline struct fs_struct *__copy_f fs->umask = old->umask; read_lock(&old->lock); fs->rootmnt = mntget(old->rootmnt); @@ -1788,8 +1826,10 @@ fs->altrootmnt = mntget(old->altrootmnt); fs->altroot = dget(old->altroot); } else { ---- linux-2.4.20-vanilla/kernel/exit.c~vfs_intent-2.4.20-vanilla 2003-05-16 05:29:15.000000000 +0400 -+++ linux-2.4.20-vanilla-alexey/kernel/exit.c 2003-09-17 21:05:04.000000000 +0400 +Index: linux-2.4.24/kernel/exit.c +=================================================================== +--- linux-2.4.24.orig/kernel/exit.c Thu Nov 28 15:53:15 2002 ++++ linux-2.4.24/kernel/exit.c Wed Mar 17 17:36:14 2004 @@ -238,11 +238,14 @@ static inline void __put_fs_struct(struc { /* No need to hold fs->lock if we are killing it */ @@ -1805,5 +1845,3 @@ dput(fs->altroot); mntput(fs->altrootmnt); } - -_ diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.21-chaos.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.21-chaos.patch index 7587ad2..09ef2f9 100644 --- a/lustre/kernel_patches/patches/vfs_intent-2.4.21-chaos.patch +++ b/lustre/kernel_patches/patches/vfs_intent-2.4.21-chaos.patch @@ -12,11 +12,11 @@ kernel/ksyms.c | 1 12 files changed, 558 insertions(+), 128 deletions(-) -Index: linux-2.4.21-chaos/fs/dcache.c +Index: linux-ia64/fs/dcache.c =================================================================== ---- linux-2.4.21-chaos.orig/fs/dcache.c 2003-09-19 03:49:54.000000000 +0400 -+++ linux-2.4.21-chaos/fs/dcache.c 2003-12-12 17:02:47.000000000 +0300 -@@ -186,6 +186,13 @@ +--- linux-ia64.orig/fs/dcache.c 2004-03-17 15:47:15.000000000 -0800 ++++ linux-ia64/fs/dcache.c 2004-03-17 16:05:28.000000000 -0800 +@@ -186,6 +186,13 @@ int d_invalidate(struct dentry * dentry) spin_unlock(&dcache_lock); return 0; } @@ -30,7 +30,7 @@ Index: linux-2.4.21-chaos/fs/dcache.c /* * Check whether to do a partial shrink_dcache * to get rid of unused child entries. -@@ -847,13 +854,19 @@ +@@ -850,13 +857,19 @@ void d_delete(struct dentry * dentry) * Adds a dentry to the hash according to its name. */ @@ -53,11 +53,11 @@ Index: linux-2.4.21-chaos/fs/dcache.c } #define do_switch(x,y) do { \ -Index: linux-2.4.21-chaos/fs/exec.c +Index: linux-ia64/fs/exec.c =================================================================== ---- linux-2.4.21-chaos.orig/fs/exec.c 2003-12-05 07:55:47.000000000 +0300 -+++ linux-2.4.21-chaos/fs/exec.c 2003-12-12 17:02:47.000000000 +0300 -@@ -119,8 +119,10 @@ +--- linux-ia64.orig/fs/exec.c 2004-03-17 15:47:15.000000000 -0800 ++++ linux-ia64/fs/exec.c 2004-03-17 16:05:28.000000000 -0800 +@@ -119,8 +119,10 @@ asmlinkage long sys_uselib(const char * struct file * file; struct nameidata nd; int error; @@ -69,7 +69,7 @@ Index: linux-2.4.21-chaos/fs/exec.c if (error) goto out; -@@ -132,7 +134,8 @@ +@@ -132,7 +134,8 @@ asmlinkage long sys_uselib(const char * if (error) goto exit; @@ -79,7 +79,7 @@ Index: linux-2.4.21-chaos/fs/exec.c error = PTR_ERR(file); if (IS_ERR(file)) goto out; -@@ -400,8 +403,10 @@ +@@ -400,8 +403,10 @@ struct file *open_exec(const char *name) struct inode *inode; struct file *file; int err = 0; @@ -91,7 +91,7 @@ Index: linux-2.4.21-chaos/fs/exec.c file = ERR_PTR(err); if (!err) { inode = nd.dentry->d_inode; -@@ -413,7 +418,8 @@ +@@ -413,7 +418,8 @@ struct file *open_exec(const char *name) err = -EACCES; file = ERR_PTR(err); if (!err) { @@ -101,7 +101,7 @@ Index: linux-2.4.21-chaos/fs/exec.c if (!IS_ERR(file)) { err = deny_write_access(file); if (err) { -@@ -425,6 +431,7 @@ +@@ -425,6 +431,7 @@ out: return file; } } @@ -109,7 +109,7 @@ Index: linux-2.4.21-chaos/fs/exec.c path_release(&nd); } goto out; -@@ -1348,7 +1355,7 @@ +@@ -1348,7 +1355,7 @@ int do_coredump(long signr, int exit_cod goto close_fail; if (!file->f_op->write) goto close_fail; @@ -118,10 +118,10 @@ Index: linux-2.4.21-chaos/fs/exec.c goto close_fail; retval = binfmt->core_dump(signr, regs, file); -Index: linux-2.4.21-chaos/fs/namei.c +Index: linux-ia64/fs/namei.c =================================================================== ---- linux-2.4.21-chaos.orig/fs/namei.c 2003-07-15 04:41:01.000000000 +0400 -+++ linux-2.4.21-chaos/fs/namei.c 2003-12-12 17:03:37.000000000 +0300 +--- linux-ia64.orig/fs/namei.c 2004-03-17 15:47:15.000000000 -0800 ++++ linux-ia64/fs/namei.c 2004-03-17 16:06:13.000000000 -0800 @@ -94,6 +94,13 @@ * XEmacs seems to be relying on it... */ @@ -136,7 +136,7 @@ Index: linux-2.4.21-chaos/fs/namei.c /* In order to reduce some races, while at the same time doing additional * checking and hopefully speeding things up, we copy filenames to the * kernel data space before using them.. -@@ -260,10 +267,19 @@ +@@ -260,10 +267,19 @@ void path_release(struct nameidata *nd) * Internal lookup() using the new generic dcache. * SMP-safe */ @@ -157,7 +157,7 @@ Index: linux-2.4.21-chaos/fs/namei.c if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) { dput(dentry); -@@ -281,11 +297,15 @@ +@@ -281,11 +297,15 @@ static struct dentry * cached_lookup(str * make sure that nobody added the entry to the dcache in the meantime.. * SMP-safe */ @@ -174,7 +174,7 @@ Index: linux-2.4.21-chaos/fs/namei.c down(&dir->i_sem); /* * First re-do the cached lookup just in case it was created -@@ -300,6 +320,9 @@ +@@ -300,6 +320,9 @@ static struct dentry * real_lookup(struc result = ERR_PTR(-ENOMEM); if (dentry) { lock_kernel(); @@ -184,7 +184,7 @@ Index: linux-2.4.21-chaos/fs/namei.c result = dir->i_op->lookup(dir, dentry); unlock_kernel(); if (result) -@@ -321,6 +344,15 @@ +@@ -321,6 +344,15 @@ static struct dentry * real_lookup(struc dput(result); result = ERR_PTR(-ENOENT); } @@ -200,7 +200,7 @@ Index: linux-2.4.21-chaos/fs/namei.c } return result; } -@@ -332,7 +364,8 @@ +@@ -332,7 +364,8 @@ static struct dentry * real_lookup(struc * Without that kind of total limit, nasty chains of consecutive * symlinks can cause almost arbitrarily long lookups. */ @@ -210,7 +210,7 @@ Index: linux-2.4.21-chaos/fs/namei.c { int err; if (current->link_count >= 8) -@@ -346,10 +379,12 @@ +@@ -346,10 +379,12 @@ static inline int do_follow_link(struct current->link_count++; current->total_link_count++; UPDATE_ATIME(dentry->d_inode); @@ -223,7 +223,7 @@ Index: linux-2.4.21-chaos/fs/namei.c path_release(nd); return -ELOOP; } -@@ -447,7 +482,8 @@ +@@ -447,7 +482,8 @@ static inline void follow_dotdot(struct * * We expect 'base' to be positive and a directory. */ @@ -233,7 +233,7 @@ Index: linux-2.4.21-chaos/fs/namei.c { struct dentry *dentry; struct inode *inode; -@@ -524,12 +560,12 @@ +@@ -524,12 +560,12 @@ int link_path_walk(const char * name, st break; } /* This does the actual lookups.. */ @@ -248,7 +248,7 @@ Index: linux-2.4.21-chaos/fs/namei.c err = PTR_ERR(dentry); if (IS_ERR(dentry)) break; -@@ -547,7 +583,7 @@ +@@ -547,7 +583,7 @@ int link_path_walk(const char * name, st goto out_dput; if (inode->i_op->follow_link) { @@ -257,7 +257,7 @@ Index: linux-2.4.21-chaos/fs/namei.c dput(dentry); if (err) goto return_err; -@@ -563,7 +599,7 @@ +@@ -563,7 +599,7 @@ int link_path_walk(const char * name, st nd->dentry = dentry; } err = -ENOTDIR; @@ -266,7 +266,7 @@ Index: linux-2.4.21-chaos/fs/namei.c break; continue; /* here ends the main loop */ -@@ -590,12 +626,12 @@ +@@ -590,12 +626,12 @@ last_component: if (err < 0) break; } @@ -281,7 +281,7 @@ Index: linux-2.4.21-chaos/fs/namei.c err = PTR_ERR(dentry); if (IS_ERR(dentry)) break; -@@ -605,7 +641,7 @@ +@@ -605,7 +641,7 @@ last_component: inode = dentry->d_inode; if ((lookup_flags & LOOKUP_FOLLOW) && inode && inode->i_op && inode->i_op->follow_link) { @@ -290,7 +290,7 @@ Index: linux-2.4.21-chaos/fs/namei.c dput(dentry); if (err) goto return_err; -@@ -619,7 +655,8 @@ +@@ -619,7 +655,8 @@ last_component: goto no_inode; if (lookup_flags & LOOKUP_DIRECTORY) { err = -ENOTDIR; @@ -300,7 +300,7 @@ Index: linux-2.4.21-chaos/fs/namei.c break; } goto return_base; -@@ -643,6 +680,25 @@ +@@ -643,6 +680,27 @@ return_reval: * Check the cached dentry for staleness. */ dentry = nd->dentry; @@ -316,17 +316,19 @@ Index: linux-2.4.21-chaos/fs/namei.c + &dentry->d_name, 0, NULL); + d_invalidate(dentry); + dput(dentry); -+ if (IS_ERR(new)) { ++ if (IS_ERR(new)) { + err = PTR_ERR(new); + break; + } + nd->dentry = new; + } ++ if (!nd->dentry->d_inode) ++ goto no_inode; + } else if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { err = -ESTALE; if (!dentry->d_op->d_revalidate(dentry, 0)) { -@@ -656,15 +712,28 @@ +@@ -656,15 +714,28 @@ out_dput: dput(dentry); break; } @@ -356,7 +358,7 @@ Index: linux-2.4.21-chaos/fs/namei.c } /* SMP-safe */ -@@ -749,6 +818,17 @@ +@@ -749,6 +820,17 @@ walk_init_root(const char *name, struct } /* SMP-safe */ @@ -374,7 +376,7 @@ Index: linux-2.4.21-chaos/fs/namei.c int path_lookup(const char *path, unsigned flags, struct nameidata *nd) { int error = 0; -@@ -763,6 +843,7 @@ +@@ -763,6 +845,7 @@ int path_init(const char *name, unsigned { nd->last_type = LAST_ROOT; /* if there are only slashes... */ nd->flags = flags; @@ -382,7 +384,7 @@ Index: linux-2.4.21-chaos/fs/namei.c if (*name=='/') return walk_init_root(name,nd); read_lock(¤t->fs->lock); -@@ -777,7 +858,8 @@ +@@ -777,7 +860,8 @@ int path_init(const char *name, unsigned * needs parent already locked. Doesn't follow mounts. * SMP-safe. */ @@ -392,7 +394,7 @@ Index: linux-2.4.21-chaos/fs/namei.c { struct dentry * dentry; struct inode *inode; -@@ -800,13 +882,16 @@ +@@ -800,13 +884,16 @@ struct dentry * lookup_hash(struct qstr goto out; } @@ -410,7 +412,7 @@ Index: linux-2.4.21-chaos/fs/namei.c dentry = inode->i_op->lookup(inode, new); unlock_kernel(); if (!dentry) -@@ -818,6 +903,12 @@ +@@ -818,6 +905,12 @@ out: return dentry; } @@ -423,7 +425,7 @@ Index: linux-2.4.21-chaos/fs/namei.c /* SMP-safe */ struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) { -@@ -839,7 +930,7 @@ +@@ -839,7 +932,7 @@ struct dentry * lookup_one_len(const cha } this.hash = end_name_hash(hash); @@ -432,7 +434,7 @@ Index: linux-2.4.21-chaos/fs/namei.c access: return ERR_PTR(-EACCES); } -@@ -870,6 +961,23 @@ +@@ -870,6 +963,23 @@ int __user_walk(const char *name, unsign return err; } @@ -456,7 +458,7 @@ Index: linux-2.4.21-chaos/fs/namei.c /* * It's inline, so penalty for filesystems that don't use sticky bit is * minimal. -@@ -967,7 +1075,8 @@ +@@ -967,7 +1077,8 @@ static inline int lookup_flags(unsigned return retval; } @@ -466,7 +468,7 @@ Index: linux-2.4.21-chaos/fs/namei.c { int error; -@@ -980,12 +1089,15 @@ +@@ -980,12 +1091,15 @@ int vfs_create(struct inode *dir, struct goto exit_lock; error = -EACCES; /* shouldn't it be ENOSYS? */ @@ -484,7 +486,7 @@ Index: linux-2.4.21-chaos/fs/namei.c unlock_kernel(); exit_lock: up(&dir->i_zombie); -@@ -994,6 +1106,11 @@ +@@ -994,6 +1108,11 @@ exit_lock: return error; } @@ -496,7 +498,7 @@ Index: linux-2.4.21-chaos/fs/namei.c /* * open_namei() * -@@ -1008,7 +1125,8 @@ +@@ -1008,7 +1127,8 @@ exit_lock: * for symlinks (where the permissions are checked later). * SMP-safe */ @@ -506,7 +508,7 @@ Index: linux-2.4.21-chaos/fs/namei.c { int acc_mode, error = 0; struct inode *inode; -@@ -1018,11 +1136,14 @@ +@@ -1018,11 +1138,14 @@ int open_namei(const char * pathname, in acc_mode = ACC_MODE(flag); @@ -522,7 +524,7 @@ Index: linux-2.4.21-chaos/fs/namei.c if (error) return error; dentry = nd->dentry; -@@ -1032,6 +1153,10 @@ +@@ -1032,6 +1155,10 @@ int open_namei(const char * pathname, in /* * Create - we need to know the parent. */ @@ -533,7 +535,7 @@ Index: linux-2.4.21-chaos/fs/namei.c error = path_lookup(pathname, LOOKUP_PARENT, nd); if (error) return error; -@@ -1047,7 +1172,7 @@ +@@ -1047,7 +1174,7 @@ int open_namei(const char * pathname, in dir = nd->dentry; down(&dir->d_inode->i_sem); @@ -542,7 +544,7 @@ Index: linux-2.4.21-chaos/fs/namei.c do_last: error = PTR_ERR(dentry); -@@ -1056,11 +1181,12 @@ +@@ -1056,11 +1183,12 @@ do_last: goto exit; } @@ -556,7 +558,7 @@ Index: linux-2.4.21-chaos/fs/namei.c up(&dir->d_inode->i_sem); dput(nd->dentry); nd->dentry = dentry; -@@ -1164,7 +1290,7 @@ +@@ -1164,7 +1292,7 @@ ok: if (!error) { DQUOT_INIT(inode); @@ -565,7 +567,7 @@ Index: linux-2.4.21-chaos/fs/namei.c } put_write_access(inode); if (error) -@@ -1176,8 +1302,10 @@ +@@ -1176,8 +1304,10 @@ ok: return 0; exit_dput: @@ -576,7 +578,7 @@ Index: linux-2.4.21-chaos/fs/namei.c path_release(nd); return error; -@@ -1196,7 +1324,10 @@ +@@ -1196,7 +1326,10 @@ do_link: * are done. Procfs-like symlinks just set LAST_BIND. */ UPDATE_ATIME(dentry->d_inode); @@ -587,7 +589,7 @@ Index: linux-2.4.21-chaos/fs/namei.c dput(dentry); if (error) return error; -@@ -1218,13 +1349,20 @@ +@@ -1218,13 +1351,20 @@ do_link: } dir = nd->dentry; down(&dir->d_inode->i_sem); @@ -610,7 +612,7 @@ Index: linux-2.4.21-chaos/fs/namei.c { struct dentry *dentry; -@@ -1232,7 +1370,7 @@ +@@ -1232,7 +1372,7 @@ static struct dentry *lookup_create(stru dentry = ERR_PTR(-EEXIST); if (nd->last_type != LAST_NORM) goto fail; @@ -619,12 +621,16 @@ Index: linux-2.4.21-chaos/fs/namei.c if (IS_ERR(dentry)) goto fail; if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) -@@ -1288,7 +1426,16 @@ +@@ -1288,7 +1428,20 @@ asmlinkage long sys_mknod(const char * f error = path_lookup(tmp, LOOKUP_PARENT, &nd); if (error) goto out; - dentry = lookup_create(&nd, 0); + ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out2; ++ } + if (nd.dentry->d_inode->i_op->mknod_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->mknod_raw(&nd, mode, dev); @@ -637,7 +643,7 @@ Index: linux-2.4.21-chaos/fs/namei.c error = PTR_ERR(dentry); if (!IS_POSIXACL(nd.dentry->d_inode)) -@@ -1310,6 +1457,7 @@ +@@ -1310,6 +1463,7 @@ asmlinkage long sys_mknod(const char * f dput(dentry); } up(&nd.dentry->d_inode->i_sem); @@ -645,11 +651,15 @@ Index: linux-2.4.21-chaos/fs/namei.c path_release(&nd); out: putname(tmp); -@@ -1357,7 +1505,14 @@ +@@ -1357,7 +1511,18 @@ asmlinkage long sys_mkdir(const char * p error = path_lookup(tmp, LOOKUP_PARENT, &nd); if (error) goto out; - dentry = lookup_create(&nd, 1); ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out2; ++ } + if (nd.dentry->d_inode->i_op->mkdir_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->mkdir_raw(&nd, mode); @@ -661,7 +671,7 @@ Index: linux-2.4.21-chaos/fs/namei.c error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { if (!IS_POSIXACL(nd.dentry->d_inode)) -@@ -1366,6 +1521,7 @@ +@@ -1366,6 +1531,7 @@ asmlinkage long sys_mkdir(const char * p dput(dentry); } up(&nd.dentry->d_inode->i_sem); @@ -669,7 +679,7 @@ Index: linux-2.4.21-chaos/fs/namei.c path_release(&nd); out: putname(tmp); -@@ -1466,8 +1622,16 @@ +@@ -1466,8 +1632,16 @@ asmlinkage long sys_rmdir(const char * p error = -EBUSY; goto exit1; } @@ -687,7 +697,7 @@ Index: linux-2.4.21-chaos/fs/namei.c error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { error = vfs_rmdir(nd.dentry->d_inode, dentry); -@@ -1525,8 +1689,15 @@ +@@ -1525,8 +1699,15 @@ asmlinkage long sys_unlink(const char * error = -EISDIR; if (nd.last_type != LAST_NORM) goto exit1; @@ -704,11 +714,15 @@ Index: linux-2.4.21-chaos/fs/namei.c error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { /* Why not before? Because we want correct error value */ -@@ -1593,15 +1764,23 @@ +@@ -1593,15 +1774,27 @@ asmlinkage long sys_symlink(const char * error = path_lookup(to, LOOKUP_PARENT, &nd); if (error) goto out; - dentry = lookup_create(&nd, 0); ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out2; ++ } + if (nd.dentry->d_inode->i_op->symlink_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->symlink_raw(&nd, from); @@ -730,11 +744,15 @@ Index: linux-2.4.21-chaos/fs/namei.c putname(to); } putname(from); -@@ -1677,7 +1856,14 @@ +@@ -1677,7 +1870,18 @@ asmlinkage long sys_link(const char * ol error = -EXDEV; if (old_nd.mnt != nd.mnt) goto out_release; - new_dentry = lookup_create(&nd, 0); ++ if (nd.last_type != LAST_NORM) { ++ error = -EEXIST; ++ goto out_release; ++ } + if (nd.dentry->d_inode->i_op->link_raw) { + struct inode_operations *op = nd.dentry->d_inode->i_op; + error = op->link_raw(&old_nd, &nd); @@ -746,7 +764,7 @@ Index: linux-2.4.21-chaos/fs/namei.c error = PTR_ERR(new_dentry); if (!IS_ERR(new_dentry)) { error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); -@@ -1721,7 +1907,7 @@ +@@ -1721,7 +1925,7 @@ exit: * locking]. */ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, @@ -755,7 +773,7 @@ Index: linux-2.4.21-chaos/fs/namei.c { int error; struct inode *target; -@@ -1800,7 +1986,7 @@ +@@ -1800,7 +2004,7 @@ out_unlock: } int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, @@ -764,7 +782,7 @@ Index: linux-2.4.21-chaos/fs/namei.c { int error; -@@ -1888,9 +2074,18 @@ +@@ -1888,9 +2092,18 @@ static inline int do_rename(const char * if (newnd.last_type != LAST_NORM) goto exit2; @@ -784,7 +802,7 @@ Index: linux-2.4.21-chaos/fs/namei.c error = PTR_ERR(old_dentry); if (IS_ERR(old_dentry)) goto exit3; -@@ -1906,16 +2101,16 @@ +@@ -1906,16 +2119,16 @@ static inline int do_rename(const char * if (newnd.last.name[newnd.last.len]) goto exit4; } @@ -803,7 +821,7 @@ Index: linux-2.4.21-chaos/fs/namei.c dput(new_dentry); exit4: dput(old_dentry); -@@ -1966,20 +2161,26 @@ +@@ -1966,20 +2179,26 @@ out: } static inline int @@ -832,7 +850,7 @@ Index: linux-2.4.21-chaos/fs/namei.c out: if (current->link_count || res || nd->last_type!=LAST_NORM) return res; -@@ -2003,7 +2204,13 @@ +@@ -2003,7 +2222,13 @@ fail: int vfs_follow_link(struct nameidata *nd, const char *link) { @@ -847,7 +865,7 @@ Index: linux-2.4.21-chaos/fs/namei.c } /* get the link contents into pagecache */ -@@ -2045,7 +2252,7 @@ +@@ -2045,7 +2270,7 @@ int page_follow_link(struct dentry *dent { struct page *page = NULL; char *s = page_getlink(dentry, &page); @@ -856,11 +874,11 @@ Index: linux-2.4.21-chaos/fs/namei.c if (page) { kunmap(page); page_cache_release(page); -Index: linux-2.4.21-chaos/fs/namespace.c +Index: linux-ia64/fs/namespace.c =================================================================== ---- linux-2.4.21-chaos.orig/fs/namespace.c 2003-07-15 04:41:01.000000000 +0400 -+++ linux-2.4.21-chaos/fs/namespace.c 2003-12-12 17:02:47.000000000 +0300 -@@ -98,6 +98,7 @@ +--- linux-ia64.orig/fs/namespace.c 2004-03-17 15:47:15.000000000 -0800 ++++ linux-ia64/fs/namespace.c 2004-03-17 16:05:28.000000000 -0800 +@@ -98,6 +98,7 @@ static void detach_mnt(struct vfsmount * { old_nd->dentry = mnt->mnt_mountpoint; old_nd->mnt = mnt->mnt_parent; @@ -868,7 +886,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c mnt->mnt_parent = mnt; mnt->mnt_mountpoint = mnt->mnt_root; list_del_init(&mnt->mnt_child); -@@ -109,6 +110,7 @@ +@@ -109,6 +110,7 @@ static void attach_mnt(struct vfsmount * { mnt->mnt_parent = mntget(nd->mnt); mnt->mnt_mountpoint = dget(nd->dentry); @@ -876,7 +894,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry)); list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts); nd->dentry->d_mounted++; -@@ -488,14 +490,17 @@ +@@ -488,14 +490,17 @@ static int do_loopback(struct nameidata { struct nameidata old_nd; struct vfsmount *mnt = NULL; @@ -896,7 +914,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c down_write(¤t->namespace->sem); err = -EINVAL; -@@ -518,6 +523,7 @@ +@@ -518,6 +523,7 @@ static int do_loopback(struct nameidata } up_write(¤t->namespace->sem); @@ -904,7 +922,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c path_release(&old_nd); return err; } -@@ -701,6 +707,7 @@ +@@ -701,6 +707,7 @@ long do_mount(char * dev_name, char * di unsigned long flags, void *data_page) { struct nameidata nd; @@ -912,7 +930,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c int retval = 0; int mnt_flags = 0; -@@ -725,10 +732,11 @@ +@@ -725,10 +732,11 @@ long do_mount(char * dev_name, char * di flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV); /* ... and get the mountpoint */ @@ -927,7 +945,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c if (flags & MS_REMOUNT) retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, data_page); -@@ -739,6 +747,8 @@ +@@ -739,6 +747,8 @@ long do_mount(char * dev_name, char * di else retval = do_add_mount(&nd, type_page, flags, mnt_flags, dev_name, data_page); @@ -936,7 +954,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c path_release(&nd); return retval; } -@@ -904,6 +914,8 @@ +@@ -904,6 +914,8 @@ asmlinkage long sys_pivot_root(const cha { struct vfsmount *tmp; struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd; @@ -945,7 +963,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c int error; if (!capable(CAP_SYS_ADMIN)) -@@ -911,14 +923,14 @@ +@@ -911,14 +923,14 @@ asmlinkage long sys_pivot_root(const cha lock_kernel(); @@ -962,7 +980,7 @@ Index: linux-2.4.21-chaos/fs/namespace.c if (error) goto out1; -@@ -973,8 +985,10 @@ +@@ -973,8 +985,10 @@ out2: up(&old_nd.dentry->d_inode->i_zombie); up_write(¤t->namespace->sem); path_release(&user_nd); @@ -973,10 +991,10 @@ Index: linux-2.4.21-chaos/fs/namespace.c path_release(&new_nd); out0: unlock_kernel(); -Index: linux-2.4.21-chaos/fs/open.c +Index: linux-ia64/fs/open.c =================================================================== ---- linux-2.4.21-chaos.orig/fs/open.c 2003-07-15 04:41:01.000000000 +0400 -+++ linux-2.4.21-chaos/fs/open.c 2003-12-12 17:02:47.000000000 +0300 +--- linux-ia64.orig/fs/open.c 2004-03-17 15:47:15.000000000 -0800 ++++ linux-ia64/fs/open.c 2004-03-17 16:05:28.000000000 -0800 @@ -19,6 +19,8 @@ #include @@ -986,7 +1004,7 @@ Index: linux-2.4.21-chaos/fs/open.c int vfs_statfs(struct super_block *sb, struct statfs *buf) { -@@ -95,9 +97,10 @@ +@@ -95,9 +97,10 @@ void fd_install(unsigned int fd, struct write_unlock(&files->file_lock); } @@ -998,7 +1016,7 @@ Index: linux-2.4.21-chaos/fs/open.c int error; struct iattr newattrs; -@@ -109,7 +112,13 @@ +@@ -109,7 +112,13 @@ int do_truncate(struct dentry *dentry, l down(&inode->i_sem); newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; @@ -1013,7 +1031,7 @@ Index: linux-2.4.21-chaos/fs/open.c up(&inode->i_sem); up_write(&inode->i_alloc_sem); return error; -@@ -120,12 +129,13 @@ +@@ -120,12 +129,13 @@ static inline long do_sys_truncate(const struct nameidata nd; struct inode * inode; int error; @@ -1028,7 +1046,7 @@ Index: linux-2.4.21-chaos/fs/open.c if (error) goto out; inode = nd.dentry->d_inode; -@@ -165,11 +175,13 @@ +@@ -165,11 +175,13 @@ static inline long do_sys_truncate(const error = locks_verify_truncate(inode, NULL, length); if (!error) { DQUOT_INIT(inode); @@ -1043,7 +1061,7 @@ Index: linux-2.4.21-chaos/fs/open.c path_release(&nd); out: return error; -@@ -217,7 +229,7 @@ +@@ -217,7 +229,7 @@ static inline long do_sys_ftruncate(unsi error = locks_verify_truncate(inode, file, length); if (!error) @@ -1052,7 +1070,7 @@ Index: linux-2.4.21-chaos/fs/open.c out_putf: fput(file); out: -@@ -262,11 +274,13 @@ +@@ -262,11 +274,13 @@ asmlinkage long sys_utime(char * filenam struct inode * inode; struct iattr newattrs; @@ -1067,7 +1085,7 @@ Index: linux-2.4.21-chaos/fs/open.c error = -EROFS; if (IS_RDONLY(inode)) goto dput_and_out; -@@ -281,11 +295,25 @@ +@@ -281,11 +295,25 @@ asmlinkage long sys_utime(char * filenam goto dput_and_out; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; @@ -1094,7 +1112,7 @@ Index: linux-2.4.21-chaos/fs/open.c error = notify_change(nd.dentry, &newattrs); dput_and_out: path_release(&nd); -@@ -306,12 +334,14 @@ +@@ -306,12 +334,14 @@ asmlinkage long sys_utimes(char * filena struct inode * inode; struct iattr newattrs; @@ -1110,7 +1128,7 @@ Index: linux-2.4.21-chaos/fs/open.c error = -EROFS; if (IS_RDONLY(inode)) goto dput_and_out; -@@ -326,7 +356,20 @@ +@@ -326,7 +356,20 @@ asmlinkage long sys_utimes(char * filena newattrs.ia_atime = times[0].tv_sec; newattrs.ia_mtime = times[1].tv_sec; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; @@ -1132,7 +1150,7 @@ Index: linux-2.4.21-chaos/fs/open.c if (current->fsuid != inode->i_uid && (error = permission(inode,MAY_WRITE)) != 0) goto dput_and_out; -@@ -349,6 +392,7 @@ +@@ -349,6 +392,7 @@ asmlinkage long sys_access(const char * int old_fsuid, old_fsgid; kernel_cap_t old_cap; int res; @@ -1140,7 +1158,7 @@ Index: linux-2.4.21-chaos/fs/open.c if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ return -EINVAL; -@@ -366,13 +410,14 @@ +@@ -366,13 +410,14 @@ asmlinkage long sys_access(const char * else current->cap_effective = current->cap_permitted; @@ -1156,7 +1174,7 @@ Index: linux-2.4.21-chaos/fs/open.c path_release(&nd); } -@@ -387,8 +432,9 @@ +@@ -387,8 +432,9 @@ asmlinkage long sys_chdir(const char * f { int error; struct nameidata nd; @@ -1167,7 +1185,7 @@ Index: linux-2.4.21-chaos/fs/open.c if (error) goto out; -@@ -399,6 +445,7 @@ +@@ -399,6 +445,7 @@ asmlinkage long sys_chdir(const char * f set_fs_pwd(current->fs, nd.mnt, nd.dentry); dput_and_out: @@ -1175,7 +1193,7 @@ Index: linux-2.4.21-chaos/fs/open.c path_release(&nd); out: return error; -@@ -438,9 +485,10 @@ +@@ -438,9 +485,10 @@ asmlinkage long sys_chroot(const char * { int error; struct nameidata nd; @@ -1188,7 +1206,7 @@ Index: linux-2.4.21-chaos/fs/open.c if (error) goto out; -@@ -456,39 +504,56 @@ +@@ -456,39 +504,56 @@ asmlinkage long sys_chroot(const char * set_fs_altroot(); error = 0; dput_and_out: @@ -1259,7 +1277,7 @@ Index: linux-2.4.21-chaos/fs/open.c fput(file); out: return err; -@@ -497,30 +562,14 @@ +@@ -497,30 +562,14 @@ out: asmlinkage long sys_chmod(const char * filename, mode_t mode) { struct nameidata nd; @@ -1291,7 +1309,7 @@ Index: linux-2.4.21-chaos/fs/open.c path_release(&nd); out: return error; -@@ -540,6 +589,20 @@ +@@ -540,6 +589,20 @@ static int chown_common(struct dentry * error = -EROFS; if (IS_RDONLY(inode)) goto out; @@ -1312,7 +1330,7 @@ Index: linux-2.4.21-chaos/fs/open.c error = -EPERM; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out; -@@ -644,6 +707,7 @@ +@@ -644,6 +707,7 @@ struct file *filp_open(const char * file { int namei_flags, error; struct nameidata nd; @@ -1320,7 +1338,7 @@ Index: linux-2.4.21-chaos/fs/open.c namei_flags = flags; if ((namei_flags+1) & O_ACCMODE) -@@ -651,14 +715,15 @@ +@@ -651,14 +715,15 @@ struct file *filp_open(const char * file if (namei_flags & O_TRUNC) namei_flags |= 2; @@ -1341,7 +1359,7 @@ Index: linux-2.4.21-chaos/fs/open.c { struct file * f; struct inode *inode; -@@ -695,7 +760,9 @@ +@@ -695,7 +760,9 @@ struct file *dentry_open(struct dentry * } if (f->f_op && f->f_op->open) { @@ -1351,7 +1369,7 @@ Index: linux-2.4.21-chaos/fs/open.c if (error) goto cleanup_all; } -@@ -708,6 +775,7 @@ +@@ -708,6 +775,7 @@ struct file *dentry_open(struct dentry * inode->i_mapping->a_ops->direct_sector_IO))) goto cleanup_all; @@ -1359,7 +1377,7 @@ Index: linux-2.4.21-chaos/fs/open.c return f; cleanup_all: -@@ -722,11 +790,17 @@ +@@ -722,11 +790,17 @@ cleanup_all: cleanup_file: put_filp(f); cleanup_dentry: @@ -1377,11 +1395,11 @@ Index: linux-2.4.21-chaos/fs/open.c /* * Find an empty file descriptor entry, and mark it busy. */ -Index: linux-2.4.21-chaos/fs/stat.c +Index: linux-ia64/fs/stat.c =================================================================== ---- linux-2.4.21-chaos.orig/fs/stat.c 2003-09-19 03:49:54.000000000 +0400 -+++ linux-2.4.21-chaos/fs/stat.c 2003-12-12 17:02:47.000000000 +0300 -@@ -17,10 +17,14 @@ +--- linux-ia64.orig/fs/stat.c 2004-03-17 15:47:15.000000000 -0800 ++++ linux-ia64/fs/stat.c 2004-03-17 16:06:13.000000000 -0800 +@@ -17,10 +17,12 @@ * Revalidate the inode. This is required for proper NFS attribute caching. */ static __inline__ int @@ -1390,15 +1408,13 @@ Index: linux-2.4.21-chaos/fs/stat.c { struct inode * inode = dentry->d_inode; - if (inode->i_op && inode->i_op->revalidate) -+ if (!inode) -+ return -ENOENT; + if (inode->i_op && inode->i_op->revalidate_it) + return inode->i_op->revalidate_it(dentry, it); + else if (inode->i_op && inode->i_op->revalidate) return inode->i_op->revalidate(dentry); return 0; } -@@ -143,13 +147,15 @@ +@@ -143,13 +145,15 @@ static int cp_new_stat(struct inode * in asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf) { struct nameidata nd; @@ -1416,7 +1432,7 @@ Index: linux-2.4.21-chaos/fs/stat.c path_release(&nd); } return error; -@@ -159,13 +165,15 @@ +@@ -159,13 +163,15 @@ asmlinkage long sys_stat(char * filename asmlinkage long sys_newstat(char * filename, struct stat * statbuf) { struct nameidata nd; @@ -1434,7 +1450,7 @@ Index: linux-2.4.21-chaos/fs/stat.c path_release(&nd); } return error; -@@ -180,13 +188,15 @@ +@@ -180,13 +186,15 @@ asmlinkage long sys_newstat(char * filen asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf) { struct nameidata nd; @@ -1452,7 +1468,7 @@ Index: linux-2.4.21-chaos/fs/stat.c path_release(&nd); } return error; -@@ -197,13 +207,15 @@ +@@ -197,13 +205,15 @@ asmlinkage long sys_lstat(char * filenam asmlinkage long sys_newlstat(char * filename, struct stat * statbuf) { struct nameidata nd; @@ -1470,7 +1486,7 @@ Index: linux-2.4.21-chaos/fs/stat.c path_release(&nd); } return error; -@@ -224,7 +236,7 @@ +@@ -224,7 +234,7 @@ asmlinkage long sys_fstat(unsigned int f if (f) { struct dentry * dentry = f->f_dentry; @@ -1479,7 +1495,7 @@ Index: linux-2.4.21-chaos/fs/stat.c if (!err) err = cp_old_stat(dentry->d_inode, statbuf); fput(f); -@@ -243,7 +255,7 @@ +@@ -243,7 +253,7 @@ asmlinkage long sys_newfstat(unsigned in if (f) { struct dentry * dentry = f->f_dentry; @@ -1488,7 +1504,7 @@ Index: linux-2.4.21-chaos/fs/stat.c if (!err) err = cp_new_stat(dentry->d_inode, statbuf); fput(f); -@@ -265,7 +277,7 @@ +@@ -265,7 +275,7 @@ asmlinkage long sys_readlink(const char error = -EINVAL; if (inode->i_op && inode->i_op->readlink && @@ -1497,7 +1513,7 @@ Index: linux-2.4.21-chaos/fs/stat.c UPDATE_ATIME(inode); error = inode->i_op->readlink(nd.dentry, buf, bufsiz); } -@@ -341,12 +353,14 @@ +@@ -341,12 +351,14 @@ asmlinkage long sys_stat64(char * filena { struct nameidata nd; int error; @@ -1514,7 +1530,7 @@ Index: linux-2.4.21-chaos/fs/stat.c path_release(&nd); } return error; -@@ -356,12 +370,14 @@ +@@ -356,12 +368,14 @@ asmlinkage long sys_lstat64(char * filen { struct nameidata nd; int error; @@ -1531,7 +1547,7 @@ Index: linux-2.4.21-chaos/fs/stat.c path_release(&nd); } return error; -@@ -376,7 +392,7 @@ +@@ -376,7 +390,7 @@ asmlinkage long sys_fstat64(unsigned lon if (f) { struct dentry * dentry = f->f_dentry; @@ -1540,10 +1556,10 @@ Index: linux-2.4.21-chaos/fs/stat.c if (!err) err = cp_new_stat64(dentry->d_inode, statbuf); fput(f); -Index: linux-2.4.21-chaos/include/linux/dcache.h +Index: linux-ia64/include/linux/dcache.h =================================================================== ---- linux-2.4.21-chaos.orig/include/linux/dcache.h 2003-12-05 16:54:33.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/dcache.h 2003-12-12 17:02:47.000000000 +0300 +--- linux-ia64.orig/include/linux/dcache.h 2004-03-17 15:47:15.000000000 -0800 ++++ linux-ia64/include/linux/dcache.h 2004-03-17 16:05:28.000000000 -0800 @@ -6,6 +6,51 @@ #include #include @@ -1596,7 +1612,7 @@ Index: linux-2.4.21-chaos/include/linux/dcache.h /* * linux/include/linux/dcache.h -@@ -96,8 +141,22 @@ +@@ -96,8 +141,22 @@ struct dentry_operations { int (*d_delete)(struct dentry *); void (*d_release)(struct dentry *); void (*d_iput)(struct dentry *, struct inode *); @@ -1619,7 +1635,7 @@ Index: linux-2.4.21-chaos/include/linux/dcache.h /* the dentry parameter passed to d_hash and d_compare is the parent * directory of the entries to be compared. It is used in case these * functions need any directory specific information for determining -@@ -129,6 +188,7 @@ +@@ -129,6 +188,7 @@ d_iput: no no yes * s_nfsd_free_path semaphore will be down */ #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ @@ -1627,11 +1643,11 @@ Index: linux-2.4.21-chaos/include/linux/dcache.h extern spinlock_t dcache_lock; -Index: linux-2.4.21-chaos/include/linux/fs.h +Index: linux-ia64/include/linux/fs.h =================================================================== ---- linux-2.4.21-chaos.orig/include/linux/fs.h 2003-12-12 17:02:46.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/fs.h 2003-12-12 17:02:47.000000000 +0300 -@@ -73,6 +73,7 @@ +--- linux-ia64.orig/include/linux/fs.h 2004-03-17 16:05:28.000000000 -0800 ++++ linux-ia64/include/linux/fs.h 2004-03-17 16:05:52.000000000 -0800 +@@ -73,6 +73,7 @@ extern int leases_enable, dir_notify_ena #define FMODE_READ 1 #define FMODE_WRITE 2 @@ -1639,7 +1655,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h #define READ 0 #define WRITE 1 -@@ -359,6 +360,9 @@ +@@ -359,6 +360,9 @@ extern void set_bh_page(struct buffer_he #define ATTR_MTIME_SET 256 #define ATTR_FORCE 512 /* Not a change, but a change it */ #define ATTR_ATTR_FLAG 1024 @@ -1649,7 +1665,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h /* * This is the Inode Attributes structure, used for notify_change(). It -@@ -496,6 +500,7 @@ +@@ -496,6 +500,7 @@ struct inode { struct pipe_inode_info *i_pipe; struct block_device *i_bdev; struct char_device *i_cdev; @@ -1657,7 +1673,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h unsigned long i_dnotify_mask; /* Directory notify events */ struct dnotify_struct *i_dnotify; /* for directory notifications */ -@@ -598,6 +603,7 @@ +@@ -598,6 +603,7 @@ struct file { /* needed for tty driver, and maybe others */ void *private_data; @@ -1665,7 +1681,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h /* preallocated helper kiobuf to speedup O_DIRECT */ struct kiobuf *f_iobuf; -@@ -726,6 +732,7 @@ +@@ -726,6 +732,7 @@ struct nameidata { struct qstr last; unsigned int flags; int last_type; @@ -1673,7 +1689,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h }; /* -@@ -846,7 +853,8 @@ +@@ -846,7 +853,8 @@ extern int vfs_symlink(struct inode *, s extern int vfs_link(struct dentry *, struct inode *, struct dentry *); extern int vfs_rmdir(struct inode *, struct dentry *); extern int vfs_unlink(struct inode *, struct dentry *); @@ -1683,7 +1699,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h /* * File types -@@ -920,21 +928,32 @@ +@@ -920,21 +928,32 @@ struct file_operations { struct inode_operations { int (*create) (struct inode *,struct dentry *,int); @@ -1716,7 +1732,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h int (*getattr) (struct dentry *, struct iattr *); int (*setxattr) (struct dentry *, const char *, const void *, size_t, int); ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); -@@ -1131,10 +1150,14 @@ +@@ -1131,10 +1150,14 @@ static inline int get_lease(struct inode asmlinkage long sys_open(const char *, int, int); asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */ @@ -1732,7 +1748,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h extern int filp_close(struct file *, fl_owner_t id); extern char * getname(const char *); -@@ -1425,6 +1448,7 @@ +@@ -1425,6 +1448,7 @@ typedef int (*read_actor_t)(read_descrip extern loff_t default_llseek(struct file *file, loff_t offset, int origin); extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *)); @@ -1740,7 +1756,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *)); extern int FASTCALL(path_walk(const char *, struct nameidata *)); extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); -@@ -1436,6 +1460,8 @@ +@@ -1436,6 +1460,8 @@ extern struct dentry * lookup_one_len(co extern struct dentry * lookup_hash(struct qstr *, struct dentry *); #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) @@ -1749,7 +1765,7 @@ Index: linux-2.4.21-chaos/include/linux/fs.h extern void inode_init_once(struct inode *); extern void iput(struct inode *); -@@ -1599,6 +1625,8 @@ +@@ -1599,6 +1625,8 @@ extern struct file_operations generic_ro extern int vfs_readlink(struct dentry *, char *, int, const char *); extern int vfs_follow_link(struct nameidata *, const char *); @@ -1758,11 +1774,11 @@ Index: linux-2.4.21-chaos/include/linux/fs.h extern int page_readlink(struct dentry *, char *, int); extern int page_follow_link(struct dentry *, struct nameidata *); extern struct inode_operations page_symlink_inode_operations; -Index: linux-2.4.21-chaos/include/linux/fs_struct.h +Index: linux-ia64/include/linux/fs_struct.h =================================================================== ---- linux-2.4.21-chaos.orig/include/linux/fs_struct.h 2003-12-05 16:54:33.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/fs_struct.h 2003-12-12 17:02:47.000000000 +0300 -@@ -37,10 +37,12 @@ +--- linux-ia64.orig/include/linux/fs_struct.h 2004-03-17 15:47:15.000000000 -0800 ++++ linux-ia64/include/linux/fs_struct.h 2004-03-17 16:05:28.000000000 -0800 +@@ -37,10 +37,12 @@ static inline void set_fs_root(struct fs write_lock(&fs->lock); old_root = fs->root; old_rootmnt = fs->rootmnt; @@ -1775,7 +1791,7 @@ Index: linux-2.4.21-chaos/include/linux/fs_struct.h dput(old_root); mntput(old_rootmnt); } -@@ -60,10 +62,12 @@ +@@ -60,10 +62,12 @@ static inline void set_fs_pwd(struct fs_ write_lock(&fs->lock); old_pwd = fs->pwd; old_pwdmnt = fs->pwdmnt; @@ -1788,11 +1804,11 @@ Index: linux-2.4.21-chaos/include/linux/fs_struct.h dput(old_pwd); mntput(old_pwdmnt); } -Index: linux-2.4.21-chaos/kernel/exit.c +Index: linux-ia64/kernel/exit.c =================================================================== ---- linux-2.4.21-chaos.orig/kernel/exit.c 2003-09-19 03:50:00.000000000 +0400 -+++ linux-2.4.21-chaos/kernel/exit.c 2003-12-12 17:02:47.000000000 +0300 -@@ -347,11 +347,14 @@ +--- linux-ia64.orig/kernel/exit.c 2004-03-17 15:47:15.000000000 -0800 ++++ linux-ia64/kernel/exit.c 2004-03-17 16:05:28.000000000 -0800 +@@ -347,11 +347,14 @@ static inline void __put_fs_struct(struc { /* No need to hold fs->lock if we are killing it */ if (atomic_dec_and_test(&fs->count)) { @@ -1807,11 +1823,11 @@ Index: linux-2.4.21-chaos/kernel/exit.c dput(fs->altroot); mntput(fs->altrootmnt); } -Index: linux-2.4.21-chaos/kernel/fork.c +Index: linux-ia64/kernel/fork.c =================================================================== ---- linux-2.4.21-chaos.orig/kernel/fork.c 2003-12-05 07:55:51.000000000 +0300 -+++ linux-2.4.21-chaos/kernel/fork.c 2003-12-12 17:02:47.000000000 +0300 -@@ -463,10 +463,13 @@ +--- linux-ia64.orig/kernel/fork.c 2004-03-17 15:47:15.000000000 -0800 ++++ linux-ia64/kernel/fork.c 2004-03-17 16:05:28.000000000 -0800 +@@ -463,10 +463,13 @@ static inline struct fs_struct *__copy_f fs->umask = old->umask; read_lock(&old->lock); fs->rootmnt = mntget(old->rootmnt); @@ -1825,11 +1841,11 @@ Index: linux-2.4.21-chaos/kernel/fork.c fs->altrootmnt = mntget(old->altrootmnt); fs->altroot = dget(old->altroot); } else { -Index: linux-2.4.21-chaos/kernel/ksyms.c +Index: linux-ia64/kernel/ksyms.c =================================================================== ---- linux-2.4.21-chaos.orig/kernel/ksyms.c 2003-12-12 17:02:46.000000000 +0300 -+++ linux-2.4.21-chaos/kernel/ksyms.c 2003-12-12 17:02:47.000000000 +0300 -@@ -318,6 +318,7 @@ +--- linux-ia64.orig/kernel/ksyms.c 2004-03-17 16:05:28.000000000 -0800 ++++ linux-ia64/kernel/ksyms.c 2004-03-17 16:05:51.000000000 -0800 +@@ -318,6 +318,7 @@ EXPORT_SYMBOL(read_cache_page); EXPORT_SYMBOL(set_page_dirty); EXPORT_SYMBOL(vfs_readlink); EXPORT_SYMBOL(vfs_follow_link); diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.21-suse2.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.21-suse2.patch index 492e32a..25d147d 100644 --- a/lustre/kernel_patches/patches/vfs_intent-2.4.21-suse2.patch +++ b/lustre/kernel_patches/patches/vfs_intent-2.4.21-suse2.patch @@ -316,7 +316,7 @@ Index: linux-2.4.21-suse2/fs/namei.c + &dentry->d_name, 0, NULL); + d_invalidate(dentry); + dput(dentry); -+ if (IS_ERR(new)) { ++ if (IS_ERR(new)) { + err = PTR_ERR(new); + break; + } diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.22-rh.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.22-rh.patch index ff5ef61..29ad74f 100644 --- a/lustre/kernel_patches/patches/vfs_intent-2.4.22-rh.patch +++ b/lustre/kernel_patches/patches/vfs_intent-2.4.22-rh.patch @@ -304,7 +304,7 @@ + &dentry->d_name, 0, NULL); + d_invalidate(dentry); + dput(dentry); -+ if (IS_ERR(new)) { ++ if (IS_ERR(new)) { + err = PTR_ERR(new); + break; + } diff --git a/lustre/kernel_patches/series/chaos-2.4.21 b/lustre/kernel_patches/series/chaos-2.4.21 index 8e20c51..bdcae1e 100644 --- a/lustre/kernel_patches/series/chaos-2.4.21 +++ b/lustre/kernel_patches/series/chaos-2.4.21 @@ -32,3 +32,4 @@ ext3-xattr-ptr-arith-fix.patch kernel_text_address-2.4.18-chaos.patch pagecache-lock-2.4.21-chaos.patch ext3-truncate-buffer-head.patch +inode-max-readahead-2.4.24.patch diff --git a/lustre/kernel_patches/series/hp-pnnl-2.4.20 b/lustre/kernel_patches/series/hp-pnnl-2.4.20 index 6cfe667..cb9c74c 100644 --- a/lustre/kernel_patches/series/hp-pnnl-2.4.20 +++ b/lustre/kernel_patches/series/hp-pnnl-2.4.20 @@ -2,7 +2,7 @@ configurable-x86-stack-2.4.20.patch dev_read_only_hp_2.4.20.patch exports_2.4.20-rh-hp.patch lustre_version.patch -vfs_intent-2.4.20-hp.patch +vfs_intent-2.4.20-hp.patch invalidate_show-2.4.20-hp.patch export-truncate.patch iod-stock-24-exports_hp.patch @@ -42,3 +42,5 @@ gfp_memalloc-2.4.22.patch ext3-xattr-ptr-arith-fix.patch procfs-ndynamic-2.4.patch ext3-truncate-buffer-head.patch +inode-max-readahead-2.4.24.patch +dcache_refcount_debug.patch diff --git a/lustre/kernel_patches/series/rh-2.4.20 b/lustre/kernel_patches/series/rh-2.4.20 index d9c6f39..06b2642 100644 --- a/lustre/kernel_patches/series/rh-2.4.20 +++ b/lustre/kernel_patches/series/rh-2.4.20 @@ -4,7 +4,7 @@ dsp.patch dev_read_only_2.4.20-rh.patch exports_2.4.20-rh-hp.patch lustre_version.patch -vfs_intent-2.4.20-rh.patch +vfs_intent-2.4.20-rh.patch invalidate_show-2.4.20-rh.patch iod-rmap-exports-2.4.20.patch export-truncate.patch @@ -28,7 +28,7 @@ ext3-o_direct-1.2.4.20-rh.patch ext3-no-write-super-chaos.patch dynamic-locks-2.4.20-rh.patch vfs-pdirops-2.4.20-rh.patch -ext3-pdirops-2.4.18-chaos.patch +ext3-pdirops-2.4.20-chaos.patch tcp_zero_copy_2.4.20_chaos.patch gpl_header-chaos-2.4.20.patch add_page_private.patch @@ -44,3 +44,4 @@ gfp_memalloc-2.4.20-rh.patch ext3-xattr-ptr-arith-fix.patch procfs-ndynamic-2.4.patch ext3-truncate-buffer-head.patch +inode-max-readahead-2.4.24.patch diff --git a/lustre/kernel_patches/series/vanilla-2.4.24 b/lustre/kernel_patches/series/vanilla-2.4.24 index 220d3bc..76ee9fa 100644 --- a/lustre/kernel_patches/series/vanilla-2.4.24 +++ b/lustre/kernel_patches/series/vanilla-2.4.24 @@ -5,7 +5,7 @@ configurable-x86-stack-2.4.20.patch dev_read_only_2.4.20-rh.patch exports_2.4.20-rh-hp.patch lustre_version.patch -vfs_intent-2.4.20-vanilla.patch +vfs_intent-2.4.20-vanilla.patch invalidate_show.patch export-truncate.patch iod-stock-exports-2.4.22.patch @@ -35,3 +35,4 @@ ext3-xattr-ptr-arith-fix.patch 3.5G-address-space-2.4.22-vanilla.patch procfs-ndynamic-2.4.patch ext3-truncate-buffer-head.patch +inode-max-readahead-2.4.24.patch diff --git a/lustre/liblustre/namei.c b/lustre/liblustre/namei.c index 1f23df9..3929e2c 100644 --- a/lustre/liblustre/namei.c +++ b/lustre/liblustre/namei.c @@ -312,7 +312,7 @@ static int lookup_it_finish(struct ptlrpc_request *request, int offset, int rc; /* NB 1 request reference will be taken away by ll_intent_lock() - * when I return + * when I return * Note: libsysio require the inode must be generated here */ if ((it->it_op & IT_CREAT) || !it_disposition(it, DISP_LOOKUP_NEG)) { @@ -352,7 +352,7 @@ static int lookup_it_finish(struct ptlrpc_request *request, int offset, rc = llu_glimpse_size(inode, &lvb); if (rc) { I_RELE(inode); - RETURN(-EIO); + RETURN(rc); } lli->lli_st_size = lvb.lvb_size; } diff --git a/lustre/llite/Makefile.am b/lustre/llite/Makefile.am index 493d95c..18c3a3a 100644 --- a/lustre/llite/Makefile.am +++ b/lustre/llite/Makefile.am @@ -10,7 +10,7 @@ modulefs_DATA = llite.o EXTRA_PROGRAMS = llite COMMON_SRC = dcache.c dir.c file.c llite_close.c llite_lib.c llite_nfs.c rw.c \ - lproc_llite.c namei.c symlink.c sysctl.c llite_internal.h + lproc_llite.c namei.c symlink.c llite_internal.h if LINUX25 llite_SOURCES = $(COMMON_SRC) rw26.c super25.c diff --git a/lustre/llite/Makefile.mk b/lustre/llite/Makefile.mk index 0cc6697d..40345b6 100644 --- a/lustre/llite/Makefile.mk +++ b/lustre/llite/Makefile.mk @@ -7,5 +7,5 @@ include $(src)/../portals/Kernelenv obj-y += llite.o llite-objs := llite_lib.o dcache.o super.o rw.o \ - super25.o file.o dir.o sysctl.o symlink.o namei.o lproc_llite.o \ + super25.o file.o dir.o symlink.o namei.o lproc_llite.o \ rw26.o llite_nfs.o llite_close.o diff --git a/lustre/llite/file.c b/lustre/llite/file.c index c786211..60c8304 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -368,8 +368,15 @@ void ll_pgcache_remove_extent(struct inode *inode, struct lov_stripe_md *lsm, * lockers handled correctly. fixes from bug 20 will make it * more efficient by associating locks with pages and with * batching writeback under the lock explicitly. */ - for (i = start, j = start % count ; i <= end; + for (i = start, j = start % count; i <= end; j++, i++, tmpex.l_extent.start += PAGE_CACHE_SIZE) { + if (j == count) { + CDEBUG(D_PAGE, "skip index %lu to %lu\n", i, i + skip); + i += skip; + j = 0; + if (i > end) + break; + } LASSERTF(tmpex.l_extent.start< lock->l_policy_data.l_extent.end, LPU64" >= "LPU64" start %lu i %lu end %lu\n", tmpex.l_extent.start, lock->l_policy_data.l_extent.end, @@ -389,8 +396,9 @@ void ll_pgcache_remove_extent(struct inode *inode, struct lov_stripe_md *lsm, page = find_get_page(inode->i_mapping, i); if (page == NULL) - goto next_index; - LL_CDEBUG_PAGE(D_PAGE, page, "locking page\n"); + continue; + LL_CDEBUG_PAGE(D_PAGE, page, "lock page idx %lu ext "LPU64"\n", + i, tmpex.l_extent.start); lock_page(page); /* page->mapping to check with racing against teardown */ @@ -425,13 +433,13 @@ void ll_pgcache_remove_extent(struct inode *inode, struct lov_stripe_md *lsm, } unlock_page(page); page_cache_release(page); - - next_index: - if (j == count) { - i += skip; - j = 0; - } } + LASSERTF(tmpex.l_extent.start <= + (lock->l_policy_data.l_extent.end == ~0ULL ? ~0ULL : + lock->l_policy_data.l_extent.end + 1), + "loop too long "LPU64" > "LPU64" start %lu i %lu end %lu\n", + tmpex.l_extent.start, lock->l_policy_data.l_extent.end, + start, i, end); EXIT; } @@ -615,9 +623,9 @@ int ll_glimpse_size(struct inode *inode, struct ost_lvb *lvb) LCK_PR, &flags, ll_extent_lock_callback, ldlm_completion_ast, ll_glimpse_callback, inode, sizeof(*lvb), lustre_swab_ost_lvb, &lockh); - if (rc > 0) { + if (rc != 0) { CERROR("obd_enqueue returned rc %d, returning -EIO\n", rc); - RETURN(-EIO); + RETURN(rc > 0 ? -EIO : rc); } lvb->lvb_size = lov_merge_size(lli->lli_smd, 0); @@ -810,10 +818,9 @@ static ssize_t ll_file_write(struct file *file, const char *buf, size_t count, retval = generic_file_write(file, buf, count, ppos); out: - /* XXX errors? */ - lprocfs_counter_add(ll_i2sbi(inode)->ll_stats, LPROC_LL_WRITE_BYTES, - retval); ll_extent_unlock(fd, inode, lsm, LCK_PW, &lockh); + lprocfs_counter_add(ll_i2sbi(inode)->ll_stats, LPROC_LL_WRITE_BYTES, + retval > 0 ? retval : 0); RETURN(retval); } @@ -878,7 +885,8 @@ static int ll_lov_recreate_obj(struct inode *inode, struct file *file, } static int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file, - int flags, struct lov_user_md *lum, int lum_size) + int flags, struct lov_user_md *lum, + int lum_size) { struct ll_inode_info *lli = ll_i2info(inode); struct file *f; @@ -1255,6 +1263,7 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it) struct inode *inode = dentry->d_inode; struct ll_inode_info *lli; struct lov_stripe_md *lsm; + int rc; ENTRY; if (!inode) { @@ -1273,7 +1282,7 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it) struct ll_sb_info *sbi = ll_i2sbi(dentry->d_inode); struct ll_fid fid; unsigned long valid = 0; - int rc, ealen = 0; + int ealen = 0; if (S_ISREG(inode->i_mode)) { ealen = obd_size_diskmd(sbi->ll_osc_exp, NULL); @@ -1301,12 +1310,11 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it) * the file */ { struct ost_lvb lvb; - ldlm_error_t err; - err = ll_glimpse_size(inode, &lvb); + rc = ll_glimpse_size(inode, &lvb); inode->i_size = lvb.lvb_size; } - RETURN(0); + RETURN(rc); } #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) diff --git a/lustre/llite/sysctl.c b/lustre/llite/sysctl.c deleted file mode 100644 index b626046..0000000 --- a/lustre/llite/sysctl.c +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * - * Copyright (C) 2001 Cluster File Systems, Inc. - * - * This code is issued under the GNU General Public License. - * See the file COPYING in this distribution - */ -#include -#include -#include -#include -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -struct ctl_table_header *ll_table_header = NULL; - -int ll_debug_level = 0; -int ll_print_entry = 1; - - -#define LL_SYSCTL 1 - -#define LL_DEBUG 1 /* control debugging */ -#define LL_ENTRY 2 /* control enter/leave pattern */ -#define LL_TIMEOUT 3 /* timeout on upcalls to become intrble */ -#define LL_HARD 4 /* mount type "hard" or "soft" */ -#define LL_VARS 5 -#define LL_INDEX 6 -#define LL_RESET 7 - -#define LL_VARS_SLOT 2 - -static ctl_table ll_table[] = { - {LL_DEBUG, "debug", &ll_debug_level, sizeof(int), 0644, NULL, &proc_dointvec}, - {LL_ENTRY, "trace", &ll_print_entry, sizeof(int), 0644, NULL, &proc_dointvec}, - { 0 } -}; - -static ctl_table top_table[] = { - {LL_SYSCTL, "lustre_light", NULL, 0, 0555, ll_table}, - {0} -}; - -void ll_sysctl_init (void) -{ - -#ifdef CONFIG_SYSCTL - if ( !ll_table_header ) - ll_table_header = register_sysctl_table(top_table, 0); -#endif -} - -void ll_sysctl_clean (void) -{ -#ifdef CONFIG_SYSCTL - if ( ll_table_header ) - unregister_sysctl_table(ll_table_header); - ll_table_header = NULL; -#endif -} diff --git a/lustre/lvfs/.cvsignore b/lustre/lvfs/.cvsignore index 49c6100..f686b81 100644 --- a/lustre/lvfs/.cvsignore +++ b/lustre/lvfs/.cvsignore @@ -7,3 +7,4 @@ Makefile.in .deps TAGS .*.cmd +fsfilt_extN.c diff --git a/lustre/lvfs/Makefile.am b/lustre/lvfs/Makefile.am index 1569d3b..9e91de3 100644 --- a/lustre/lvfs/Makefile.am +++ b/lustre/lvfs/Makefile.am @@ -34,6 +34,9 @@ fsfilt_ext3_SOURCES = fsfilt_ext3.c lvfs_internal.h endif endif +fsfilt_extN.c: fsfilt_ext3.c + sed -e "s/EXT3/EXTN/g" -e "s/ext3/extN/g" $< > $@ + include $(top_srcdir)/Rules if LINUX25 diff --git a/lustre/lvfs/fsfilt_ext3.c b/lustre/lvfs/fsfilt_ext3.c index 76a5088..25eb31c 100644 --- a/lustre/lvfs/fsfilt_ext3.c +++ b/lustre/lvfs/fsfilt_ext3.c @@ -71,10 +71,12 @@ struct fsfilt_cb_data { * the inode (which we will be changing anyways as part of this * transaction). */ -static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private) +static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private, + int logs) { /* For updates to the last recieved file */ - int nblocks = EXT3_DATA_TRANS_BLOCKS; + int nblocks = EXT3_SINGLEDATA_TRANS_BLOCKS; + journal_t *journal; void *handle; if (current->journal_info) { @@ -84,30 +86,26 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private) } switch(op) { - case FSFILT_OP_CREATE_LOG: - nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS+EXT3_DATA_TRANS_BLOCKS; - op = FSFILT_OP_CREATE; - break; - case FSFILT_OP_UNLINK_LOG: - nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS+EXT3_DATA_TRANS_BLOCKS; - op = FSFILT_OP_UNLINK; - break; - } - - switch(op) { case FSFILT_OP_RMDIR: case FSFILT_OP_UNLINK: + /* delete one file + create/update logs for each stripe */ nblocks += EXT3_DELETE_TRANS_BLOCKS; + nblocks += (EXT3_INDEX_EXTRA_TRANS_BLOCKS + + EXT3_SINGLEDATA_TRANS_BLOCKS) * logs; break; case FSFILT_OP_RENAME: /* modify additional directory */ - nblocks += EXT3_DATA_TRANS_BLOCKS; + nblocks += EXT3_SINGLEDATA_TRANS_BLOCKS; /* no break */ case FSFILT_OP_SYMLINK: /* additional block + block bitmap + GDT for long symlink */ nblocks += 3; /* no break */ case FSFILT_OP_CREATE: + /* create/update logs for each stripe */ + nblocks += (EXT3_INDEX_EXTRA_TRANS_BLOCKS + + EXT3_SINGLEDATA_TRANS_BLOCKS) * logs; + /* no break */ case FSFILT_OP_MKDIR: case FSFILT_OP_MKNOD: /* modify one inode + block bitmap + GDT */ @@ -115,21 +113,30 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private) /* no break */ case FSFILT_OP_LINK: /* modify parent directory */ - nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS+EXT3_DATA_TRANS_BLOCKS; + nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS + + EXT3_DATA_TRANS_BLOCKS; break; case FSFILT_OP_SETATTR: /* Setattr on inode */ nblocks += 1; break; - case FSFILT_OP_CANCEL_UNLINK_LOG: + case FSFILT_OP_CANCEL_UNLINK: + /* blocks for log header bitmap update OR + * blocks for catalog header bitmap update + unlink of logs */ nblocks = (LLOG_CHUNK_SIZE >> inode->i_blkbits) + - EXT3_DELETE_TRANS_BLOCKS; + EXT3_DELETE_TRANS_BLOCKS * logs; break; default: CERROR("unknown transaction start op %d\n", op); LBUG(); } LASSERT(current->journal_info == desc_private); + journal = EXT3_SB(inode->i_sb)->s_journal; + if (nblocks > journal->j_max_transaction_buffers) { + CERROR("too many credits %d for op %ux%u using %d instead\n", + nblocks, op, logs, journal->j_max_transaction_buffers); + nblocks = journal->j_max_transaction_buffers; + } journal_start: lock_kernel(); @@ -138,6 +145,9 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private) if (!IS_ERR(handle)) LASSERT(current->journal_info == handle); + else + CERROR("error starting handle for op %u (%u credits): rc %ld\n", + op, nblocks, PTR_ERR(handle)); return handle; } @@ -240,7 +250,7 @@ static int fsfilt_ext3_credits_needed(int objcount, struct fsfilt_objinfo *fso, */ static void *fsfilt_ext3_brw_start(int objcount, struct fsfilt_objinfo *fso, int niocount, struct niobuf_local *nb, - void *desc_private) + void *desc_private, int logs) { journal_t *journal; handle_t *handle; @@ -846,6 +856,37 @@ static int fsfilt_ext3_setup(struct super_block *sb) return 0; } +/* If fso is NULL, op is FSFILT operation, otherwise op is number of fso + objects. Logs is number of logfiles to update */ +static int fsfilt_ext3_get_op_len(int op, struct fsfilt_objinfo *fso, int logs) +{ + if ( !fso ) { + switch(op) { + case FSFILT_OP_CREATE: + /* directory leaf, index & indirect & EA*/ + return 4 + 3 * logs; + case FSFILT_OP_UNLINK: + return 3 * logs; + } + } else { + int i; + int needed = 0; + struct super_block *sb = fso->fso_dentry->d_inode->i_sb; + int blockpp = 1 << (PAGE_CACHE_SHIFT - sb->s_blocksize_bits); + int addrpp = EXT3_ADDR_PER_BLOCK(sb) * blockpp; + for (i = 0; i < op; i++, fso++) { + int nblocks = fso->fso_bufcnt * blockpp; + int ndindirect = min(nblocks, addrpp + 1); + int nindir = nblocks + ndindirect + 1; + + needed += nindir; + } + return needed + 3 * logs; + } + + return 0; +} + static struct fsfilt_operations fsfilt_ext3_ops = { fs_type: "ext3", fs_owner: THIS_MODULE, @@ -867,6 +908,7 @@ static struct fsfilt_operations fsfilt_ext3_ops = { fs_write_record: fsfilt_ext3_write_record, fs_read_record: fsfilt_ext3_read_record, fs_setup: fsfilt_ext3_setup, + fs_get_op_len: fsfilt_ext3_get_op_len, }; static int __init fsfilt_ext3_init(void) diff --git a/lustre/lvfs/fsfilt_extN.c b/lustre/lvfs/fsfilt_extN.c deleted file mode 100644 index 8756f9a..0000000 --- a/lustre/lvfs/fsfilt_extN.c +++ /dev/null @@ -1,865 +0,0 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * - * lustre/lib/fsfilt_extN.c - * Lustre filesystem abstraction routines - * - * Copyright (C) 2002, 2003 Cluster File Systems, Inc. - * Author: Andreas Dilger - * - * This file is part of Lustre, http://www.lustre.org. - * - * Lustre is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * Lustre is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Lustre; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#define DEBUG_SUBSYSTEM S_FILTER - -#include -#include -#include -#include -#include -#include -#include -#include -/* XXX ugh */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) - #include -#else - #include -#endif -#include -#include -#include -#include -#include - -static kmem_cache_t *fcb_cache; -static atomic_t fcb_cache_count = ATOMIC_INIT(0); - -struct fsfilt_cb_data { - struct journal_callback cb_jcb; /* jbd private data - MUST BE FIRST */ - fsfilt_cb_t cb_func; /* MDS/OBD completion function */ - struct obd_device *cb_obd; /* MDS/OBD completion device */ - __u64 cb_last_rcvd; /* MDS/OST last committed operation */ - void *cb_data; /* MDS/OST completion function data */ -}; - -#ifndef EXTN_XATTR_INDEX_TRUSTED /* temporary until we hit l28 kernel */ -#define EXTN_XATTR_INDEX_TRUSTED 4 -#endif -#define XATTR_LUSTRE_MDS_LOV_EA "lov" - -#define EXTN_XATTR_INDEX_LUSTRE 5 /* old */ -#define XATTR_LUSTRE_MDS_OBJID "system.lustre_mds_objid" /* old */ - -/* - * We don't currently need any additional blocks for rmdir and - * unlink transactions because we are storing the OST oa_id inside - * the inode (which we will be changing anyways as part of this - * transaction). - */ -static void *fsfilt_extN_start(struct inode *inode, int op, void *desc_private) -{ - /* For updates to the last recieved file */ - int nblocks = EXTN_DATA_TRANS_BLOCKS; - void *handle; - - if (current->journal_info) { - CDEBUG(D_INODE, "increasing refcount on %p\n", current->journal_info); - goto journal_start; - } - - switch(op) { - case FSFILT_OP_CREATE_LOG: - nblocks += EXTN_INDEX_EXTRA_TRANS_BLOCKS+EXTN_DATA_TRANS_BLOCKS; - op = FSFILT_OP_CREATE; - break; - case FSFILT_OP_UNLINK_LOG: - nblocks += EXTN_INDEX_EXTRA_TRANS_BLOCKS+EXTN_DATA_TRANS_BLOCKS; - op = FSFILT_OP_UNLINK; - break; - } - - switch(op) { - case FSFILT_OP_RMDIR: - case FSFILT_OP_UNLINK: - nblocks += EXTN_DELETE_TRANS_BLOCKS; - break; - case FSFILT_OP_RENAME: - /* modify additional directory */ - nblocks += EXTN_DATA_TRANS_BLOCKS; - /* no break */ - case FSFILT_OP_SYMLINK: - /* additional block + block bitmap + GDT for long symlink */ - nblocks += 3; - /* no break */ - case FSFILT_OP_CREATE: - case FSFILT_OP_MKDIR: - case FSFILT_OP_MKNOD: - /* modify one inode + block bitmap + GDT */ - nblocks += 3; - /* no break */ - case FSFILT_OP_LINK: - /* modify parent directory */ - nblocks += EXTN_INDEX_EXTRA_TRANS_BLOCKS+EXTN_DATA_TRANS_BLOCKS; - break; - case FSFILT_OP_SETATTR: - /* Setattr on inode */ - nblocks += 1; - break; - default: CERROR("unknown transaction start op %d\n", op); - LBUG(); - } - - LASSERT(current->journal_info == desc_private); - - journal_start: - lock_kernel(); - handle = journal_start(EXTN_JOURNAL(inode), nblocks); - unlock_kernel(); - - if (!IS_ERR(handle)) - LASSERT(current->journal_info == handle); - return handle; -} - -/* - * Calculate the number of buffer credits needed to write multiple pages in - * a single extN transaction. No, this shouldn't be here, but as yet extN - * doesn't have a nice API for calculating this sort of thing in advance. - * - * See comment above extN_writepage_trans_blocks for details. We assume - * no data journaling is being done, but it does allow for all of the pages - * being non-contiguous. If we are guaranteed contiguous pages we could - * reduce the number of (d)indirect blocks a lot. - * - * With N blocks per page and P pages, for each inode we have at most: - * N*P indirect - * min(N*P, blocksize/4 + 1) dindirect blocks - * niocount tindirect - * - * For the entire filesystem, we have at most: - * min(sum(nindir + P), ngroups) bitmap blocks (from the above) - * min(sum(nindir + P), gdblocks) group descriptor blocks (from the above) - * objcount inode blocks - * 1 superblock - * 2 * EXTN_SINGLEDATA_TRANS_BLOCKS for the quota files - * - * 1 EXTN_DATA_TRANS_BLOCKS for the last_rcvd update. - */ -static int fsfilt_extN_credits_needed(int objcount, struct fsfilt_objinfo *fso) -{ - struct super_block *sb = fso->fso_dentry->d_inode->i_sb; - int blockpp = 1 << (PAGE_CACHE_SHIFT - sb->s_blocksize_bits); - int addrpp = EXTN_ADDR_PER_BLOCK(sb) * blockpp; - int nbitmaps = 0; - int ngdblocks = 0; - int needed = objcount + 1; - int i; - - for (i = 0; i < objcount; i++, fso++) { - int nblocks = fso->fso_bufcnt * blockpp; - int ndindirect = min(nblocks, addrpp + 1); - int nindir = nblocks + ndindirect + 1; - - nbitmaps += nindir + nblocks; - ngdblocks += nindir + nblocks; - - needed += nindir; - } - - /* Assumes extN and extN have same sb_info layout at the start. */ - if (nbitmaps > EXTN_SB(sb)->s_groups_count) - nbitmaps = EXTN_SB(sb)->s_groups_count; - if (ngdblocks > EXTN_SB(sb)->s_gdb_count) - ngdblocks = EXTN_SB(sb)->s_gdb_count; - - needed += nbitmaps + ngdblocks; - - /* last_rcvd update */ - needed += EXTN_DATA_TRANS_BLOCKS; - -#ifdef CONFIG_QUOTA - /* We assume that there will be 1 bit set in s_dquot.flags for each - * quota file that is active. This is at least true for now. - */ - needed += hweight32(sb_any_quota_enabled(sb)) * - EXTN_SINGLEDATA_TRANS_BLOCKS; -#endif - - return needed; -} - -/* We have to start a huge journal transaction here to hold all of the - * metadata for the pages being written here. This is necessitated by - * the fact that we do lots of prepare_write operations before we do - * any of the matching commit_write operations, so even if we split - * up to use "smaller" transactions none of them could complete until - * all of them were opened. By having a single journal transaction, - * we eliminate duplicate reservations for common blocks like the - * superblock and group descriptors or bitmaps. - * - * We will start the transaction here, but each prepare_write will - * add a refcount to the transaction, and each commit_write will - * remove a refcount. The transaction will be closed when all of - * the pages have been written. - */ -static void *fsfilt_extN_brw_start(int objcount, struct fsfilt_objinfo *fso, - int niocount, void *desc_private) -{ - journal_t *journal; - handle_t *handle; - int needed; - ENTRY; - - LASSERT(current->journal_info == desc_private); - journal = EXTN_SB(fso->fso_dentry->d_inode->i_sb)->s_journal; - needed = fsfilt_extN_credits_needed(objcount, fso); - - /* The number of blocks we could _possibly_ dirty can very large. - * We reduce our request if it is absurd (and we couldn't get that - * many credits for a single handle anyways). - * - * At some point we have to limit the size of I/Os sent at one time, - * increase the size of the journal, or we have to calculate the - * actual journal requirements more carefully by checking all of - * the blocks instead of being maximally pessimistic. It remains to - * be seen if this is a real problem or not. - */ - if (needed > journal->j_max_transaction_buffers) { - CERROR("want too many journal credits (%d) using %d instead\n", - needed, journal->j_max_transaction_buffers); - needed = journal->j_max_transaction_buffers; - } - - lock_kernel(); - handle = journal_start(journal, needed); - unlock_kernel(); - if (IS_ERR(handle)) { - CERROR("can't get handle for %d credits: rc = %ld\n", needed, - PTR_ERR(handle)); - } else { - LASSERT(handle->h_buffer_credits >= needed); - LASSERT(current->journal_info == handle); - } - - RETURN(handle); -} - -static int fsfilt_extN_commit(struct inode *inode, void *h, int force_sync) -{ - int rc; - handle_t *handle = h; - - LASSERT(current->journal_info == handle); - if (force_sync) - handle->h_sync = 1; /* recovery likes this */ - - lock_kernel(); - rc = journal_stop(handle); - unlock_kernel(); - - // LASSERT(current->journal_info == NULL); - return rc; -} - -static int fsfilt_extN_commit_async(struct inode *inode, void *h, - void **wait_handle) -{ - transaction_t *transaction; - unsigned long tid, rtid; - handle_t *handle = h; - journal_t *journal; - int rc; - - LASSERT(current->journal_info == handle); - - lock_kernel(); - transaction = handle->h_transaction; - journal = transaction->t_journal; - tid = transaction->t_tid; - /* we don't want to be blocked */ - handle->h_sync = 0; - rc = journal_stop(handle); - if (rc) { - CERROR("error while stopping transaction: %d\n", rc); - unlock_kernel(); - return rc; - } - - rtid = log_start_commit(journal, transaction); - if (rtid != tid) - CERROR("strange race: %lu != %lu\n", - (unsigned long) tid, (unsigned long) rtid); - unlock_kernel(); - - *wait_handle = (void *) tid; - CDEBUG(D_INODE, "commit async: %lu\n", (unsigned long) tid); - return 0; -} - -static int fsfilt_extN_commit_wait(struct inode *inode, void *h) -{ - tid_t tid = (tid_t)(long)h; - - CDEBUG(D_INODE, "commit wait: %lu\n", (unsigned long) tid); - if (is_journal_aborted(EXTN_JOURNAL(inode))) - return -EIO; - - log_wait_commit(EXTN_JOURNAL(inode), tid); - - return 0; -} - -static int fsfilt_extN_setattr(struct dentry *dentry, void *handle, - struct iattr *iattr, int do_trunc) -{ - struct inode *inode = dentry->d_inode; - int rc; - - lock_kernel(); - - /* A _really_ horrible hack to avoid removing the data stored - * in the block pointers; this is really the "small" stripe MD data. - * We can avoid further hackery by virtue of the MDS file size being - * zero all the time (which doesn't invoke block truncate at unlink - * time), so we assert we never change the MDS file size from zero. */ - if (iattr->ia_valid & ATTR_SIZE && !do_trunc) { - /* ATTR_SIZE would invoke truncate: clear it */ - iattr->ia_valid &= ~ATTR_SIZE; - EXTN_I(inode)->i_disksize = inode->i_size = iattr->ia_size; - - /* make sure _something_ gets set - so new inode - * goes to disk (probably won't work over XFS */ - if (!(iattr->ia_valid & (ATTR_MODE | ATTR_MTIME | ATTR_CTIME))){ - iattr->ia_valid |= ATTR_MODE; - iattr->ia_mode = inode->i_mode; - } - } - - /* Don't allow setattr to change file type */ - iattr->ia_mode = (inode->i_mode & S_IFMT)|(iattr->ia_mode & ~S_IFMT); - - /* We set these flags on the client, but have already checked perms - * so don't confuse inode_change_ok. */ - iattr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET); - - if (inode->i_op->setattr) { - rc = inode->i_op->setattr(dentry, iattr); - } else { - rc = inode_change_ok(inode, iattr); - if (!rc) - rc = inode_setattr(inode, iattr); - } - - unlock_kernel(); - - return rc; -} - -static int fsfilt_extN_iocontrol(struct inode * inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int rc = 0; - ENTRY; - - if (inode->i_fop->ioctl) - rc = inode->i_fop->ioctl(inode, file, cmd, arg); - else - RETURN(-ENOTTY); - - RETURN(rc); -} - -#undef INLINE_EA -#undef OLD_EA -static int fsfilt_extN_set_md(struct inode *inode, void *handle, - void *lmm, int lmm_size) -{ - int rc, old_ea = 0; - -#ifdef INLINE_EA /* can go away before 1.0 - just for testing bug 2097 now */ - /* Nasty hack city - store stripe MD data in the block pointers if - * it will fit, because putting it in an EA currently kills the MDS - * performance. We'll fix this with "fast EAs" in the future. - */ - if (inode->i_blocks == 0 && lmm_size <= sizeof(EXTN_I(inode)->i_data) - - sizeof(EXTN_I(inode)->i_data[0])) { - unsigned old_size = EXTN_I(inode)->i_data[0]; - if (old_size != 0) { - LASSERT(old_size < sizeof(EXTN_I(inode)->i_data)); - CERROR("setting EA on %lu/%u again... interesting\n", - inode->i_ino, inode->i_generation); - } - - EXTN_I(inode)->i_data[0] = cpu_to_le32(lmm_size); - memcpy(&EXTN_I(inode)->i_data[1], lmm, lmm_size); - mark_inode_dirty(inode); - return 0; - } -#endif -#ifdef OLD_EA - /* keep this when we get rid of OLD_EA (too noisy during conversion) */ - if (EXTN_I(inode)->i_file_acl /* || large inode EA flag */) { - CWARN("setting EA on %lu/%u again... interesting\n", - inode->i_ino, inode->i_generation); - old_ea = 1; - } - - lock_kernel(); - /* this can go away before 1.0. For bug 2097 testing only. */ - rc = extN_xattr_set_handle(handle, inode, EXTN_XATTR_INDEX_LUSTRE, - XATTR_LUSTRE_MDS_OBJID, lmm, lmm_size, 0); -#else - lock_kernel(); - rc = extN_xattr_set_handle(handle, inode, EXTN_XATTR_INDEX_TRUSTED, - XATTR_LUSTRE_MDS_LOV_EA, lmm, lmm_size, 0); - - /* This tries to delete the old-format LOV EA, but only as long as we - * have successfully saved the new-format LOV EA (we can always try - * the conversion again the next time the file is accessed). It is - * possible (although unlikely) that the new-format LOV EA couldn't be - * saved because it ran out of space but we would need a file striped - * over least 123 OSTs before the two EAs filled a 4kB block. - * - * This can be removed when all filesystems have converted to the - * new EA format, but otherwise adds little if any overhead. If we - * wanted backward compatibility for existing files, we could keep - * the old EA around for a while but we'd have to clean it up later. */ - if (rc >= 0 && old_ea) { - int err = extN_xattr_set_handle(handle, inode, - EXTN_XATTR_INDEX_LUSTRE, - XATTR_LUSTRE_MDS_OBJID, - NULL, 0, 0); - if (err) - CERROR("error deleting old LOV EA on %lu/%u: rc %d\n", - inode->i_ino, inode->i_generation, err); - } -#endif - unlock_kernel(); - - if (rc) - CERROR("error adding MD data to inode %lu: rc = %d\n", - inode->i_ino, rc); - return rc; -} - -/* Must be called with i_sem held */ -static int fsfilt_extN_get_md(struct inode *inode, void *lmm, int lmm_size) -{ - int rc; - - LASSERT(down_trylock(&inode->i_sem) != 0); - lock_kernel(); - /* Keep support for reading "inline EAs" until we convert - * users over to new format entirely. See bug 841/2097. */ - if (inode->i_blocks == 0 && EXTN_I(inode)->i_data[0]) { - unsigned size = le32_to_cpu(EXTN_I(inode)->i_data[0]); - void *handle; - - LASSERT(size < sizeof(EXTN_I(inode)->i_data)); - if (lmm) { - if (size > lmm_size) { - CERROR("inline EA on %lu/%u bad size %u > %u\n", - inode->i_ino, inode->i_generation, - size, lmm_size); - return -ERANGE; - } - memcpy(lmm, &EXTN_I(inode)->i_data[1], size); - } - -#ifndef INLINE_EA - /* migrate LOV EA data to external block - keep same format */ - CWARN("DEBUG: migrate inline EA for inode %lu/%u to block\n", - inode->i_ino, inode->i_generation); - - handle = journal_start(EXTN_JOURNAL(inode), - EXTN_XATTR_TRANS_BLOCKS); - if (!IS_ERR(handle)) { - int err; - rc = fsfilt_extN_set_md(inode, handle, - &EXTN_I(inode)->i_data[1],size); - if (rc == 0) { - memset(EXTN_I(inode)->i_data, 0, - sizeof(EXTN_I(inode)->i_data)); - mark_inode_dirty(inode); - } - err = journal_stop(handle); - if (err && rc == 0) - rc = err; - } else { - rc = PTR_ERR(handle); - } -#endif - unlock_kernel(); - return size; - } - - rc = extN_xattr_get(inode, EXTN_XATTR_INDEX_TRUSTED, - XATTR_LUSTRE_MDS_LOV_EA, lmm, lmm_size); - /* try old EA type if new one failed - MDS will convert it for us */ - if (rc == -ENODATA) { - CDEBUG(D_INFO,"failed new LOV EA %d/%s from inode %lu: rc %d\n", - EXTN_XATTR_INDEX_TRUSTED, XATTR_LUSTRE_MDS_LOV_EA, - inode->i_ino, rc); - - rc = extN_xattr_get(inode, EXTN_XATTR_INDEX_LUSTRE, - XATTR_LUSTRE_MDS_OBJID, lmm, lmm_size); - } - unlock_kernel(); - - /* This gives us the MD size */ - if (lmm == NULL) - return (rc == -ENODATA) ? 0 : rc; - - if (rc < 0) { - CDEBUG(D_INFO, "error getting EA %d/%s from inode %lu: rc %d\n", - EXTN_XATTR_INDEX_LUSTRE, XATTR_LUSTRE_MDS_OBJID, - inode->i_ino, rc); - memset(lmm, 0, lmm_size); - return (rc == -ENODATA) ? 0 : rc; - } - - return rc; -} - -static ssize_t fsfilt_extN_readpage(struct file *file, char *buf, size_t count, - loff_t *off) -{ - struct inode *inode = file->f_dentry->d_inode; - int rc = 0; - - if (S_ISREG(inode->i_mode)) - rc = file->f_op->read(file, buf, count, off); - else { - const int blkbits = inode->i_sb->s_blocksize_bits; - const int blksize = inode->i_sb->s_blocksize; - - CDEBUG(D_EXT2, "reading "LPSZ" at dir %lu+%llu\n", - count, inode->i_ino, *off); - while (count > 0) { - struct buffer_head *bh; - - bh = NULL; - if (*off < inode->i_size) { - int err = 0; - - bh = extN_bread(NULL, inode, *off >> blkbits, - 0, &err); - - CDEBUG(D_EXT2, "read %u@%llu\n", blksize, *off); - - if (bh) { - memcpy(buf, bh->b_data, blksize); - brelse(bh); - } else if (err) { - /* XXX in theory we should just fake - * this buffer and continue like extN, - * especially if this is a partial read - */ - CERROR("error read dir %lu+%llu: %d\n", - inode->i_ino, *off, err); - RETURN(err); - } - } - if (!bh) { - struct extN_dir_entry_2 *fake = (void *)buf; - - CDEBUG(D_EXT2, "fake %u@%llu\n", blksize, *off); - memset(fake, 0, sizeof(*fake)); - fake->rec_len = cpu_to_le32(blksize); - } - count -= blksize; - buf += blksize; - *off += blksize; - rc += blksize; - } - } - - return rc; -} - -static void fsfilt_extN_cb_func(struct journal_callback *jcb, int error) -{ - struct fsfilt_cb_data *fcb = (struct fsfilt_cb_data *)jcb; - - fcb->cb_func(fcb->cb_obd, fcb->cb_last_rcvd, fcb->cb_data, error); - - OBD_SLAB_FREE(fcb, fcb_cache, sizeof *fcb); - atomic_dec(&fcb_cache_count); -} - -static int fsfilt_extN_add_journal_cb(struct obd_device *obd, __u64 last_rcvd, - void *handle, fsfilt_cb_t cb_func, - void *cb_data) -{ - struct fsfilt_cb_data *fcb; - - OBD_SLAB_ALLOC(fcb, fcb_cache, GFP_NOFS, sizeof *fcb); - if (fcb == NULL) - RETURN(-ENOMEM); - - atomic_inc(&fcb_cache_count); - fcb->cb_func = cb_func; - fcb->cb_obd = obd; - fcb->cb_last_rcvd = last_rcvd; - fcb->cb_data = cb_data; - - CDEBUG(D_EXT2, "set callback for last_rcvd: "LPD64"\n", last_rcvd); - lock_kernel(); - journal_callback_set(handle, fsfilt_extN_cb_func, - (struct journal_callback *)fcb); - unlock_kernel(); - - return 0; -} - -/* - * We need to hack the return value for the free inode counts because - * the current EA code requires one filesystem block per inode with EAs, - * so it is possible to run out of blocks before we run out of inodes. - * - * This can be removed when the extN EA code is fixed. - */ -static int fsfilt_extN_statfs(struct super_block *sb, struct obd_statfs *osfs) -{ - struct kstatfs sfs; - int rc; - - memset(&sfs, 0, sizeof(sfs)); - - rc = sb->s_op->statfs(sb, &sfs); - - if (!rc && sfs.f_bfree < sfs.f_ffree) { - sfs.f_files = (sfs.f_files - sfs.f_ffree) + sfs.f_bfree; - sfs.f_ffree = sfs.f_bfree; - } - - statfs_pack(osfs, &sfs); - return rc; -} - -static int fsfilt_extN_sync(struct super_block *sb) -{ - return extN_force_commit(sb); -} - -extern int extN_map_inode_page(struct inode *inode, struct page *page, - unsigned long *blocks, int *created, int create); -int fsfilt_extN_map_inode_page(struct inode *inode, struct page *page, - unsigned long *blocks, int *created, int create) -{ - return extN_map_inode_page(inode, page, blocks, created, create); -} - -extern int extN_prep_san_write(struct inode *inode, long *blocks, - int nblocks, loff_t newsize); -static int fsfilt_extN_prep_san_write(struct inode *inode, long *blocks, - int nblocks, loff_t newsize) -{ - return extN_prep_san_write(inode, blocks, nblocks, newsize); -} - -static int fsfilt_extN_read_record(struct file * file, void *buf, - int size, loff_t *offs) -{ - struct buffer_head *bh; - unsigned long block, boffs; - struct inode *inode = file->f_dentry->d_inode; - int err; - - if (inode->i_size < *offs + size) { - size = inode->i_size - *offs; - if (size < 0) { - CERROR("size %llu is too short for read %u@%llu\n", - inode->i_size, size, *offs); - return -EIO; - } else if (size == 0) - return 0; - } - - block = *offs >> inode->i_blkbits; - bh = extN_bread(NULL, inode, block, 0, &err); - if (!bh) { - CERROR("can't read block: %d\n", err); - return err; - } - - boffs = (unsigned)*offs % bh->b_size; - if (boffs + size > bh->b_size) { - CERROR("request crosses block's border. offset %llu, size %u\n", - *offs, size); - brelse(bh); - return -EIO; - } - - memcpy(buf, bh->b_data + boffs, size); - brelse(bh); - *offs += size; - return 0; -} - -static int fsfilt_extN_write_record(struct file *file, void *buf, int size, - loff_t *offs, int force_sync) -{ - struct buffer_head *bh; - unsigned long block, boffs; - struct inode *inode = file->f_dentry->d_inode; - loff_t old_size = inode->i_size; - journal_t *journal; - handle_t *handle; - int err; - - journal = EXTN_SB(inode->i_sb)->s_journal; - handle = journal_start(journal, EXTN_DATA_TRANS_BLOCKS + 2); - if (IS_ERR(handle)) { - CERROR("can't start transaction\n"); - return PTR_ERR(handle); - } - - block = *offs >> inode->i_blkbits; - if (*offs + size > inode->i_size) { - down(&inode->i_sem); - if (*offs + size > inode->i_size) - inode->i_size = *offs + size; - if (inode->i_size > EXTN_I(inode)->i_disksize) - EXTN_I(inode)->i_disksize = inode->i_size; - up(&inode->i_sem); - } - - bh = extN_bread(handle, inode, block, 1, &err); - if (!bh) { - CERROR("can't read/create block: %d\n", err); - goto out; - } - - /* This is a hack only needed because extN_get_block_handle() updates - * i_disksize after marking the inode dirty in extN_splice_branch(). - * We will fix that when we get a chance, as extN_mark_inode_dirty() - * is not without cost, nor is it even exported. - */ - if (inode->i_size > old_size) - mark_inode_dirty(inode); - - boffs = (unsigned)*offs % bh->b_size; - if (boffs + size > bh->b_size) { - CERROR("request crosses block's border. offset %llu, size %u\n", - *offs, size); - err = -EIO; - goto out; - } - - err = extN_journal_get_write_access(handle, bh); - if (err) { - CERROR("journal_get_write_access() returned error %d\n", err); - goto out; - } - memcpy(bh->b_data + boffs, buf, size); - err = extN_journal_dirty_metadata(handle, bh); - if (err) { - CERROR("journal_dirty_metadata() returned error %d\n", err); - goto out; - } - - if (force_sync) - handle->h_sync = 1; /* recovery likes this */ -out: - if (bh) - brelse(bh); - journal_stop(handle); - if (err == 0) - *offs += size; - return err; -} - -static int fsfilt_extN_setup(struct super_block *sb) -{ -#if 0 - EXTN_SB(sb)->dx_lock = fsfilt_extN_dx_lock; - EXTN_SB(sb)->dx_unlock = fsfilt_extN_dx_unlock; -#endif -#ifdef S_PDIROPS - CWARN("Enabling PDIROPS\n"); - set_opt(EXTN_SB(sb)->s_mount_opt, PDIROPS); - sb->s_flags |= S_PDIROPS; -#endif - return 0; -} - -static struct fsfilt_operations fsfilt_extN_ops = { - fs_type: "extN", - fs_owner: THIS_MODULE, - fs_start: fsfilt_extN_start, - fs_brw_start: fsfilt_extN_brw_start, - fs_commit: fsfilt_extN_commit, - fs_commit_async: fsfilt_extN_commit_async, - fs_commit_wait: fsfilt_extN_commit_wait, - fs_setattr: fsfilt_extN_setattr, - fs_iocontrol: fsfilt_extN_iocontrol, - fs_set_md: fsfilt_extN_set_md, - fs_get_md: fsfilt_extN_get_md, - fs_readpage: fsfilt_extN_readpage, - fs_add_journal_cb: fsfilt_extN_add_journal_cb, - fs_statfs: fsfilt_extN_statfs, - fs_sync: fsfilt_extN_sync, - fs_map_inode_page: fsfilt_extN_map_inode_page, - fs_prep_san_write: fsfilt_extN_prep_san_write, - fs_write_record: fsfilt_extN_write_record, - fs_read_record: fsfilt_extN_read_record, - fs_setup: fsfilt_extN_setup, -}; - -static int __init fsfilt_extN_init(void) -{ - int rc; - - //rc = extN_xattr_register(); - fcb_cache = kmem_cache_create("fsfilt_extN_fcb", - sizeof(struct fsfilt_cb_data), 0, - 0, NULL, NULL); - if (!fcb_cache) { - CERROR("error allocating fsfilt journal callback cache\n"); - GOTO(out, rc = -ENOMEM); - } - - rc = fsfilt_register_ops(&fsfilt_extN_ops); - - if (rc) - kmem_cache_destroy(fcb_cache); -out: - return rc; -} - -static void __exit fsfilt_extN_exit(void) -{ - int rc; - - fsfilt_unregister_ops(&fsfilt_extN_ops); - rc = kmem_cache_destroy(fcb_cache); - - if (rc || atomic_read(&fcb_cache_count)) { - CERROR("can't free fsfilt callback cache: count %d, rc = %d\n", - atomic_read(&fcb_cache_count), rc); - } - - //rc = extN_xattr_unregister(); -} - -module_init(fsfilt_extN_init); -module_exit(fsfilt_extN_exit); - -MODULE_AUTHOR("Cluster File Systems, Inc. "); -MODULE_DESCRIPTION("Lustre extN Filesystem Helper v0.1"); -MODULE_LICENSE("GPL"); diff --git a/lustre/lvfs/fsfilt_reiserfs.c b/lustre/lvfs/fsfilt_reiserfs.c index 9864eda..b38ba4a 100644 --- a/lustre/lvfs/fsfilt_reiserfs.c +++ b/lustre/lvfs/fsfilt_reiserfs.c @@ -33,7 +33,6 @@ #define DEBUG_SUBSYSTEM S_FILTER #include -#include #include #include #include @@ -49,15 +48,22 @@ #include #include +/* XXX We cannot include linux/reiserfs_fs.h here, because of symbols clash, + but we need MAX_HEIGHT definition for proper reserve calculations +#include +*/ +#define MAX_HEIGHT 5 /* maximal height of a tree. don't change this without + changing JOURNAL_PER_BALANCE_CNT */ + static void *fsfilt_reiserfs_start(struct inode *inode, int op, - void *desc_private) + void *desc_private, int logs) { return (void *)0xf00f00be; } static void *fsfilt_reiserfs_brw_start(int objcount, struct fsfilt_objinfo *fso, int niocount, struct niobuf_local *nb, - void *desc_private) + void *desc_private, int logs) { return (void *)0xf00f00be; } @@ -177,6 +183,35 @@ static int fsfilt_reiserfs_sync(struct super_block *sb) return fsync_dev(sb->s_dev); } +/* If fso is NULL, op is FSFILT operation, otherwise op is number of fso + objects. Logs is number of logfiles to update */ +static int fsfilt_reiserfs_get_op_len(int op, struct fsfilt_objinfo *fso, + int logs) +{ + if ( !fso ) { + switch(op) { + case FSFILT_OP_CREATE: + /* directory leaf, index & indirect & EA*/ + return MAX_HEIGHT + logs; + case FSFILT_OP_UNLINK: + return MAX_HEIGHT + logs; + } + + } else { + int i; + int needed = MAX_HEIGHT; + struct super_block *sb = fso->fso_dentry->d_inode->i_sb; + int blockpp = 1 << (PAGE_CACHE_SHIFT - sb->s_blocksize_bits); + for (i = 0; i < op; i++, fso++) { + int nblocks = fso->fso_bufcnt * blockpp; + + needed += nblocks; + } + return needed + logs; + } + + return 0; +} static struct fsfilt_operations fsfilt_reiserfs_ops = { fs_type: "reiserfs", fs_owner: THIS_MODULE, @@ -190,6 +225,7 @@ static struct fsfilt_operations fsfilt_reiserfs_ops = { fs_add_journal_cb: fsfilt_reiserfs_add_journal_cb, fs_statfs: fsfilt_reiserfs_statfs, fs_sync: fsfilt_reiserfs_sync, + fs_get_op_len: fsfilt_reiserfs_get_op_len, }; static int __init fsfilt_reiserfs_init(void) diff --git a/lustre/mds/mds_fs.c b/lustre/mds/mds_fs.c index df159ac..ee9ed2d 100644 --- a/lustre/mds/mds_fs.c +++ b/lustre/mds/mds_fs.c @@ -138,6 +138,7 @@ int mds_client_free(struct obd_export *exp, int clear_client) med->med_idx, med->med_off, med->med_mcd->mcd_uuid); LASSERT(bitmap); + /* Clear the bit _after_ zeroing out the client so we don't race with mds_client_add and zero out new clients.*/ if (!test_bit(med->med_idx, bitmap)) { @@ -402,11 +403,16 @@ int mds_fs_setup(struct obd_device *obd, struct vfsmount *mnt) dentry = lookup_one_len("__iopen__", current->fs->pwd, strlen("__iopen__")); - if (IS_ERR(dentry) || !dentry->d_inode) { - rc = (IS_ERR(dentry)) ? PTR_ERR(dentry): -ENOENT; - CERROR("cannot open iopen FH directory: rc = %d\n", rc); + if (IS_ERR(dentry)) { + rc = PTR_ERR(dentry); + CERROR("cannot lookup __iopen__ directory: rc = %d\n", rc); GOTO(err_pop, rc); } + if (!dentry->d_inode) { + rc = -ENOENT; + CERROR("__iopen__ directory has no inode? rc = %d\n", rc); + GOTO(err_fid, rc); + } mds->mds_fid_de = dentry; dentry = simple_mkdir(current->fs->pwd, "PENDING", 0777, 1); @@ -589,9 +595,9 @@ int mds_obd_create(struct obd_export *exp, struct obdo *oa, handle = fsfilt_start(exp->exp_obd, mds->mds_objects_dir->d_inode, FSFILT_OP_RENAME, NULL); - if (IS_ERR(handle)) + if (IS_ERR(handle)) GOTO(out_dput, rc = PTR_ERR(handle)); - + lock_kernel(); rc = vfs_rename(mds->mds_objects_dir->d_inode, filp->f_dentry, mds->mds_objects_dir->d_inode, new_child); @@ -646,8 +652,10 @@ int mds_obd_destroy(struct obd_export *exp, struct obdo *oa, GOTO(out_dput, rc = IS_ERR(de) ? PTR_ERR(de) : -ENOENT); } - handle = fsfilt_start(obd, mds->mds_objects_dir->d_inode, - FSFILT_OP_UNLINK_LOG, oti); + /* Stripe count is 1 here since this is some MDS specific stuff + that is unlinked, not spanned across multiple OSTs */ + handle = fsfilt_start_log(obd, mds->mds_objects_dir->d_inode, + FSFILT_OP_UNLINK, oti, 1); if (IS_ERR(handle)) { GOTO(out_dput, rc = PTR_ERR(handle)); } diff --git a/lustre/mds/mds_open.c b/lustre/mds/mds_open.c index e959402..8b8bae0 100644 --- a/lustre/mds/mds_open.c +++ b/lustre/mds/mds_open.c @@ -791,14 +791,14 @@ int mds_open(struct mds_update_record *rec, int offset, * opened this file and is only replaying the RPC, so we open the * inode by fid (at some large expense in security). */ if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) { - DEBUG_REQ(D_HA, req, "open replay, disp: "LPX64"\n", + DEBUG_REQ(D_HA, req, "open replay, disp: "LPX64"\n", rep->lock_policy_res1); LASSERT(rec->ur_fid2->id); - + rc = mds_open_by_fid(req, rec->ur_fid2, body, rec->ur_flags, rec, rep); - if (rc != -ENOENT) + if (rc != -ENOENT) RETURN(rc); /* We didn't find the correct inode on disk either, so we * need to re-create it via a regular replay. */ @@ -1021,6 +1021,7 @@ int mds_mfd_close(struct ptlrpc_request *req, struct obd_device *obd, void *handle = NULL; struct mds_body *request_body = NULL, *reply_body = NULL; struct dentry_params dp; + struct lov_mds_md *lmm; ENTRY; if (req != NULL) { @@ -1061,8 +1062,10 @@ int mds_mfd_close(struct ptlrpc_request *req, struct obd_device *obd, LASSERT(pending_child->d_inode != NULL); cleanup_phase = 2; /* dput(pending_child) when finished */ - handle = fsfilt_start(obd, pending_dir, FSFILT_OP_UNLINK_LOG, - NULL); + lmm = lustre_msg_buf(req->rq_repmsg, 1, 0); + handle = fsfilt_start_log(obd, pending_dir, + FSFILT_OP_UNLINK, NULL, + le32_to_cpu(lmm->lmm_stripe_count)); if (IS_ERR(handle)) { rc = PTR_ERR(handle); handle = NULL; @@ -1072,10 +1075,10 @@ int mds_mfd_close(struct ptlrpc_request *req, struct obd_device *obd, if (req != NULL && (reply_body->valid & OBD_MD_FLEASIZE) && mds_log_op_unlink(obd, pending_child->d_inode, - lustre_msg_buf(req->rq_repmsg, 1, 0), - req->rq_repmsg->buflens[1], - lustre_msg_buf(req->rq_repmsg, 2, 0), - req->rq_repmsg->buflens[2]) > 0) { + lustre_msg_buf(req->rq_repmsg, 1, 0), + req->rq_repmsg->buflens[1], + lustre_msg_buf(req->rq_repmsg, 2, 0), + req->rq_repmsg->buflens[2]) > 0) { reply_body->valid |= OBD_MD_FLCOOKIE; } diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c index 9e5f972..96ea3a7 100644 --- a/lustre/mds/mds_reint.c +++ b/lustre/mds/mds_reint.c @@ -1198,8 +1198,11 @@ static int mds_reint_unlink(struct mds_update_record *rec, int offset, rc = vfs_rmdir(dparent->d_inode, dchild); break; case S_IFREG: { - handle = fsfilt_start(obd, dparent->d_inode, - FSFILT_OP_UNLINK_LOG, NULL); + struct lov_mds_md *lmm = lustre_msg_buf(req->rq_repmsg, + offset + 1, 0); + handle = fsfilt_start_log(obd, dparent->d_inode, + FSFILT_OP_UNLINK, NULL, + le32_to_cpu(lmm->lmm_stripe_count)); if (IS_ERR(handle)) GOTO(cleanup, rc = PTR_ERR(handle)); diff --git a/lustre/mds/mds_unlink_open.c b/lustre/mds/mds_unlink_open.c index 330be73..87e9a27 100644 --- a/lustre/mds/mds_unlink_open.c +++ b/lustre/mds/mds_unlink_open.c @@ -180,7 +180,8 @@ static int mds_unlink_orphan(struct obd_device *obd, struct dentry *dchild, rc = 0; } - handle = fsfilt_start(obd, pending_dir, FSFILT_OP_UNLINK_LOG, NULL); + handle = fsfilt_start_log(obd, pending_dir, FSFILT_OP_UNLINK, NULL, + le32_to_cpu(lmm->lmm_stripe_count)); if (IS_ERR(handle)) { rc = PTR_ERR(handle); CERROR("error fsfilt_start: %d\n", rc); diff --git a/lustre/obdclass/class_obd.c b/lustre/obdclass/class_obd.c index e3351a6..83a6563 100644 --- a/lustre/obdclass/class_obd.c +++ b/lustre/obdclass/class_obd.c @@ -650,7 +650,7 @@ static void cleanup_obdclass(void) #ifdef __KERNEL__ #include #define LUSTRE_MIN_VERSION 28 -#define LUSTRE_MAX_VERSION 33 +#define LUSTRE_MAX_VERSION 34 #if (LUSTRE_KERNEL_VERSION < LUSTRE_MIN_VERSION) # error Cannot continue: Your Lustre kernel patch is older than the sources #elif (LUSTRE_KERNEL_VERSION > LUSTRE_MAX_VERSION) diff --git a/lustre/obdclass/llog_lvfs.c b/lustre/obdclass/llog_lvfs.c index 168a004..28503f2 100644 --- a/lustre/obdclass/llog_lvfs.c +++ b/lustre/obdclass/llog_lvfs.c @@ -163,25 +163,30 @@ static int llog_lvfs_read_header(struct llog_handle *handle) rc = llog_lvfs_read_blob(obd, handle->lgh_file, handle->lgh_hdr, LLOG_CHUNK_SIZE, 0); if (rc) { - CERROR("error reading log header\n"); + CERROR("error reading log header from %*s\n", + handle->lgh_file->f_dentry->d_name.len, + handle->lgh_file->f_dentry->d_name.name); } else { struct llog_rec_hdr *llh_hdr = &handle->lgh_hdr->llh_hdr; /* * These need to be fixed for bug 1987 */ if (llh_hdr->lrh_type != LLOG_HDR_MAGIC) { - CERROR("bad log header magic: %#x (expecting %#x)\n", + CERROR("bad log %*s header magic: %#x (expected %#x)\n", + handle->lgh_file->f_dentry->d_name.len, + handle->lgh_file->f_dentry->d_name.name, llh_hdr->lrh_type, LLOG_HDR_MAGIC); rc = -EIO; } else if (llh_hdr->lrh_len != LLOG_CHUNK_SIZE) { - CERROR("incorrectly sized log header: %#x " - "(expecting %#x)\n", + CERROR("incorrectly sized log %*s header: %#x " + "(expected %#x)\n", + handle->lgh_file->f_dentry->d_name.len, + handle->lgh_file->f_dentry->d_name.name, llh_hdr->lrh_len, LLOG_CHUNK_SIZE); CERROR("you may need to re-run lconf --write_conf.\n"); rc = -EIO; } } - handle->lgh_last_idx = handle->lgh_hdr->llh_tail.lrt_index; handle->lgh_file->f_pos = handle->lgh_file->f_dentry->d_inode->i_size; @@ -555,17 +560,25 @@ static int llog_lvfs_destroy(struct llog_handle *handle) int rc; ENTRY; - fdentry = handle->lgh_file->f_dentry; + fdentry = handle->lgh_file->f_dentry; if (!strcmp(fdentry->d_parent->d_name.name, "LOGS")) { + struct obd_device *obd = handle->lgh_ctxt->loc_exp->exp_obd; struct inode *inode = fdentry->d_parent->d_inode; + struct obd_run_ctxt saved; + + push_ctxt(&saved, &obd->obd_ctxt, NULL); + dget(fdentry); rc = llog_lvfs_close(handle); - if (rc) - RETURN(rc); - down(&inode->i_sem); - rc = vfs_unlink(inode, fdentry); - up(&inode->i_sem); - RETURN(rc); + if (rc == 0) { + down(&inode->i_sem); + rc = vfs_unlink(inode, fdentry); + up(&inode->i_sem); + } + + dput(fdentry); + pop_ctxt(&saved, &obd->obd_ctxt, NULL); + RETURN(rc); } oa = obdo_alloc(); diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c index d2f6369..e36921a 100644 --- a/lustre/obdfilter/filter.c +++ b/lustre/obdfilter/filter.c @@ -1881,13 +1881,13 @@ static int filter_precreate(struct obd_device *obd, struct obdo *oa, } else { CERROR("Serious error: objid %*s already " "exists; is this filesystem corrupt?\n", - dchild->d_name.len, dchild->d_name.name); + dchild->d_name.len, dchild->d_name.name); } GOTO(cleanup, rc = -EEXIST); } - handle = fsfilt_start(obd, dparent->d_inode, - FSFILT_OP_CREATE_LOG, NULL); + handle = fsfilt_start_log(obd, dparent->d_inode, + FSFILT_OP_CREATE, NULL, 1); if (IS_ERR(handle)) GOTO(cleanup, rc = PTR_ERR(handle)); cleanup_phase = 3; @@ -2053,7 +2053,7 @@ static int filter_destroy(struct obd_export *exp, struct obdo *oa, goto acquire_locks; } - handle = fsfilt_start(obd, dparent->d_inode, FSFILT_OP_UNLINK_LOG, oti); + handle = fsfilt_start_log(obd, dparent->d_inode,FSFILT_OP_UNLINK,oti,1); if (IS_ERR(handle)) GOTO(cleanup, rc = PTR_ERR(handle)); cleanup_phase = 3; diff --git a/lustre/obdfilter/filter_io.c b/lustre/obdfilter/filter_io.c index 7e305f5..773baf4 100644 --- a/lustre/obdfilter/filter_io.c +++ b/lustre/obdfilter/filter_io.c @@ -151,7 +151,7 @@ static void filter_grant_incoming(struct obd_export *exp, struct obdo *oa) EXIT; } -#define GRANT_FOR_LLOG 16 +#define GRANT_FOR_LLOG(obd) 16 /* Figure out how much space is available between what we've granted * and what remains in the filesystem. Compensate for ext3 indirect @@ -177,8 +177,8 @@ restat: avail = obd->obd_osfs.os_bavail; left = avail - (avail >> (blockbits - 3)); /* (d)indirect */ - if (left > GRANT_FOR_LLOG) { - left = (left - GRANT_FOR_LLOG) << blockbits; + if (left > GRANT_FOR_LLOG(obd)) { + left = (left - GRANT_FOR_LLOG(obd)) << blockbits; } else { left = 0 /* << blockbits */; } @@ -235,10 +235,13 @@ long filter_grant(struct obd_export *exp, obd_size current_grant, * avoid overgranting in face of multiple RPCs in flight). This * essentially will be able to control the OSC_MAX_RIF for a client. * - * If we do have a large disparity and multiple RPCs in flight we - * might grant "too much" but that's OK because it means we are - * dirtying a lot on the client and will likely use it up quickly. */ + * If we do have a large disparity between what the client thinks it + * has and what we think it has, don't grant very much and let the + * client consume its grant first. Either it just has lots of RPCs + * in flight, or it was evicted and its grants will soon be used up. */ if (current_grant < want) { + if (current_grant > fed->fed_grant + FILTER_GRANT_CHUNK) + want = 65536; grant = min((want >> blockbits) / 2, (fs_space_left >> blockbits) / 8); grant <<= blockbits; diff --git a/lustre/obdfilter/filter_lvb.c b/lustre/obdfilter/filter_lvb.c index acfba4c..f664e70 100644 --- a/lustre/obdfilter/filter_lvb.c +++ b/lustre/obdfilter/filter_lvb.c @@ -174,14 +174,14 @@ static int filter_lvbo_update(struct ldlm_resource *res, struct lustre_msg *m, if (dentry->d_inode->i_size > lvb->lvb_size || !increase) { CDEBUG(D_DLMTRACE, "res: "LPU64" updating lvb size from disk: " - LPU64" -> "LPU64"\n", res->lr_name.name[0], + LPU64" -> %llu\n", res->lr_name.name[0], lvb->lvb_size, dentry->d_inode->i_size); lvb->lvb_size = dentry->d_inode->i_size; } if (dentry->d_inode->i_mtime > lvb->lvb_mtime || !increase) { CDEBUG(D_DLMTRACE, "res: "LPU64" updating lvb mtime from disk: " - LPU64" -> "LPU64"\n", res->lr_name.name[0], - lvb->lvb_mtime,(__u64)LTIME_S(dentry->d_inode->i_mtime)); + LPU64" -> %lu\n", res->lr_name.name[0], + lvb->lvb_mtime, LTIME_S(dentry->d_inode->i_mtime)); lvb->lvb_mtime = LTIME_S(dentry->d_inode->i_mtime); } f_dput(dentry); diff --git a/lustre/ptlrpc/llog_server.c b/lustre/ptlrpc/llog_server.c index 4236519..fa53b3c 100644 --- a/lustre/ptlrpc/llog_server.c +++ b/lustre/ptlrpc/llog_server.c @@ -272,8 +272,8 @@ int llog_origin_handle_cancel(struct ptlrpc_request *req) LASSERT(cathandle != NULL); inode = cathandle->lgh_file->f_dentry->d_inode; - handle = fsfilt_start(disk_obd, inode, - FSFILT_OP_CANCEL_UNLINK_LOG, NULL); + handle = fsfilt_start_log(disk_obd, inode, + FSFILT_OP_CANCEL_UNLINK, NULL, 1); if (IS_ERR(handle)) { CERROR("fsfilt_start failed: %ld\n", PTR_ERR(handle)); GOTO(pop_ctxt, rc = PTR_ERR(handle)); diff --git a/lustre/ptlrpc/recover.c b/lustre/ptlrpc/recover.c index 613cb48..18bc6f4 100644 --- a/lustre/ptlrpc/recover.c +++ b/lustre/ptlrpc/recover.c @@ -347,28 +347,26 @@ static int ptlrpc_recover_import_no_retry(struct obd_import *imp, spin_lock_irqsave(&imp->imp_lock, flags); if (imp->imp_state != LUSTRE_IMP_DISCON) { in_recovery = 1; - } + } spin_unlock_irqrestore(&imp->imp_lock, flags); if (in_recovery == 1) RETURN(-EALREADY); - rc = ptlrpc_connect_import(imp, new_uuid); if (rc) RETURN(rc); - CDEBUG(D_ERROR, "%s: recovery started, waiting\n", + CDEBUG(D_ERROR, "%s: recovery started, waiting\n", imp->imp_target_uuid.uuid); lwi = LWI_TIMEOUT(MAX(obd_timeout * HZ, 1), NULL, NULL); - rc = l_wait_event(imp->imp_recovery_waitq, + rc = l_wait_event(imp->imp_recovery_waitq, !ptlrpc_import_in_recovery(imp), &lwi); - CDEBUG(D_ERROR, "%s: recovery finished\n", + CDEBUG(D_ERROR, "%s: recovery finished\n", imp->imp_target_uuid.uuid); RETURN(rc); - } void ptlrpc_fail_export(struct obd_export *exp) diff --git a/lustre/tests/replay-ost-single.sh b/lustre/tests/replay-ost-single.sh index d0e534f..4cb5131 100755 --- a/lustre/tests/replay-ost-single.sh +++ b/lustre/tests/replay-ost-single.sh @@ -137,24 +137,28 @@ kbytesfree() { test_6() { f=$DIR/$tfile - sync + rm $f 2>/dev/null && sync && sleep 2 && sync # wait for delete thread + grep [0-9] /proc/fs/lustre/osc/OSC*MNT*/kbytes* before=`kbytesfree` dd if=/dev/urandom bs=1024 count=5120 of=$f #define OBD_FAIL_MDS_REINT_NET_REP 0x119 do_facet mds "sysctl -w lustre.fail_loc=0x80000119" sync + sleep 1 # ensure we have a fresh statfs + grep [0-9] /proc/fs/lustre/osc/OSC*MNT*/kbytes* after_dd=`kbytesfree` echo "before: $before after_dd: $after_dd" - (( before > after_dd )) || return 1 + (( $before > $after_dd )) || return 1 rm -f $f fail ost $CHECKSTAT -t file $f && return 2 || true sync # let the delete happen sleep 2 + grep [0-9] /proc/fs/lustre/osc/OSC*MNT*/kbytes* after=`kbytesfree` echo "before: $before after: $after" - (( before == after )) || return 3 + (( $before <= $after + 40 )) || return 3 # take OST logs into account } run_test 6 "Fail OST before obd_destroy" diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 538d819..7495312 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -7,8 +7,8 @@ set -e ONLY=${ONLY:-"$*"} -# bug number for skipped test: -ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-""} +# bug number for skipped test: 2399 (temporarily until new kernels arrive) +ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-"48"} # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT! [ "$ALWAYS_EXCEPT$EXCEPT" ] && echo "Skipping tests: $ALWAYS_EXCEPT $EXCEPT" @@ -1474,14 +1474,36 @@ test_47() { } run_test 47 "Device nodes check ================================" -test_48() { - mkdir $DIR/d48 - cd $DIR/d48 - mv $DIR/d48 $DIR/d48.new || error "move directory failed" - mkdir $DIR/d48 || error "recreate diectory failed" - ls || error "can't list after recreate directory" -} -run_test 48 "Access renamed current working directory ==========" +test_48a() { + mkdir $DIR/d48a + cd $DIR/d48a + mv $DIR/d48a $DIR/d48.new || error "move directory failed" + mkdir $DIR/d48a || error "recreate directory failed" + touch foo || error "'touch foo' failed after recreating cwd" + mkdir bar || error "'mkdir foo' failed after recreating cwd" + ls . || error "'ls .' failed after recreating cwd" + ls .. || error "'ls ..' failed after removing cwd" + cd . || error "'cd .' failed after recreating cwd" + mkdir . && error "'mkdir .' worked after recreating cwd" + rmdir . && error "'rmdir .' worked after recreating cwd" + ln -s . baz || error "'ln -s .' failed after recreating cwd" +} +run_test 48a "Access renamed working dir (should return errors)=" + +test_48b() { + mkdir $DIR/d48b + cd $DIR/d48b + rmdir $DIR/d48b || error "remove cwd $DIR/d48b failed" + touch foo && error "'touch foo' worked after removing cwd" + mkdir foo && error "'mkdir foo' worked after removing cwd" + ls . && error "'ls .' worked after removing cwd" + ls .. || error "'ls ..' failed after removing cwd" + cd . && error "'cd .' worked after recreate cwd" + mkdir . && error "'mkdir .' worked after removing cwd" + rmdir . && error "'rmdir .' worked after removing cwd" + ln -s . foo && error "'ln -s .' worked after removing cwd" || true +} +run_test 48b "Access removed working dir (should return errors)=" test_50() { # bug 1485 -- 1.8.3.1