--- /dev/null
+--- lustre/extN/inode.orig.c 2002-12-29 18:48:56.000000000 +0800
++++ lustre/extN/inode.c 2002-12-29 19:17:24.000000000 +0800
+@@ -2728,3 +2728,85 @@
+ * here, in extN_aops_journal_start() to ensure that the forthcoming "see if we
+ * need to extend" test in extN_prepare_write() succeeds.
+ */
++
++/* for each block: 1 ind + 1 dind + 1 tind
++ * for each block: 3 bitmap blocks
++ * for each block: 3 group descriptor blocks
++ * i inode block
++ * 1 superblock
++ * 2 * EXTN_SINGLEDATA_TRANS_BLOCKS for the quote files
++ * ((1+1+1) * 3 * nblocks) + 1 + 1 + 2 * EXTN_SINGLEDATA_TRANS_BLOCKS
++ *
++ * XXX assuming:
++ * (1) fs logic block size == page size
++ * (2) extN in writeback mode
++ */
++static inline int extN_san_write_trans_blocks(int nblocks)
++{
++ int ret;
++
++ ret = (1 + 1 + 1) * 3 * nblocks + 1 + 1;
++
++#ifdef CONFIG_QUOTA
++ ret += 2 * EXTN_SINGLEDATA_TRANS_BLOCKS;
++#endif
++
++ return ret;
++}
++
++/* Alloc blocks for an inode, while don't create any buffer/page
++ * for data I/O; set the inode size if file is extended.
++ *
++ * @inode: target inode
++ * @blocks: array of logic block number
++ * @nblocks: how many blocks need be alloced
++ * @newsize: new filesize we should set
++ *
++ * return: 0 success, otherwise failed
++ * (*blocks) contains physical block number alloced
++ *
++ * XXX this assume the fs block size == page size
++ */
++int extN_prep_san_write(struct inode *inode, long *blocks,
++ int nblocks, loff_t newsize)
++{
++ handle_t *handle;
++ struct buffer_head bh_tmp;
++ int needed_blocks;
++ int i, ret, ret2;
++
++ needed_blocks = extN_san_write_trans_blocks(nblocks);
++
++ lock_kernel();
++ handle = extN_journal_start(inode, needed_blocks);
++ if (IS_ERR(handle)) {
++ unlock_kernel();
++ return PTR_ERR(handle);
++ }
++ unlock_kernel();
++
++ /* alloc blocks one by one */
++ for (i = 0; i < nblocks; i++) {
++ ret = extN_get_block_handle(handle, inode, blocks[i],
++ &bh_tmp, 1);
++ if (ret)
++ break;
++
++ blocks[i] = bh_tmp.b_blocknr;
++ }
++
++ /* set inode size if needed */
++ if (!ret && (newsize > inode->i_size)) {
++ inode->i_size = newsize;
++ extN_mark_inode_dirty(handle, inode);
++ }
++
++ lock_kernel();
++ ret2 = extN_journal_stop(handle, inode);
++ unlock_kernel();
++
++ if (!ret)
++ ret = ret2;
++ return ret;
++}
++EXPORT_SYMBOL(extN_prep_san_write);
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2001 Cluster File Systems, Inc. <info@clusterfs.com>
+ *
+ * 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.
+ *
+ * User-space Lustre headers.
+ *
+ */
+#ifndef LIBLUSTRE_H__
+#define LIBLUSTRE_H__
+
+#include <sys/mman.h>
+#include <asm/page.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+
+#include <portals/list.h>
+#include <portals/p30.h>
+
+/* definitions for liblustre */
+
+/* always adopt 2.5 definitions */
+#define LINUX_VERSION_CODE 1
+#define KERNEL_VERSION(a,b,c) 0
+
+static inline void inter_module_put(void *a)
+{
+ return;
+}
+
+extern ptl_handle_ni_t tcpnal_ni;
+
+static inline void *inter_module_get(char *arg)
+{
+
+ if (strcmp(arg, "tcpnal_ni") == 0 )
+ return &tcpnal_ni;
+ else
+ return NULL;
+
+}
+
+
+/* cheats for now */
+
+struct work_struct {
+ void (*ws_task)(void *arg);
+ void *ws_arg;
+};
+
+static inline void prepare_work(struct work_struct *q, void (*t)(void *),
+ void *arg)
+{
+ q->ws_task = t;
+ q->ws_arg = arg;
+ return;
+}
+
+static inline void schedule_work(struct work_struct *q)
+{
+ q->ws_task(q->ws_arg);
+}
+
+
+#define strnlen(a,b) strlen(a)
+static inline void *kmalloc(int size, int prot)
+{
+ return malloc(size);
+}
+#define vmalloc malloc
+#define vfree free
+#define kfree(a) free(a)
+#define GFP_KERNEL 1
+#define GFP_HIGHUSER 1
+#define IS_ERR(a) (abs((int)(a)) < 500 ? 1 : 0)
+#define PTR_ERR(a) ((int)(a))
+
+#define capable(foo) 1
+#define CAP_SYS_ADMIN 1
+
+typedef struct {
+ void *cwd;
+
+}mm_segment_t;
+
+typedef void *read_proc_t;
+typedef void *write_proc_t;
+
+
+/* modules */
+
+struct module {
+ int count;
+};
+
+static inline void MODULE_AUTHOR(char *name)
+{
+ printf("%s\n", name);
+}
+#define MODULE_DESCRIPTION(name) MODULE_AUTHOR(name)
+#define MODULE_LICENSE(name) MODULE_AUTHOR(name)
+
+#define THIS_MODULE NULL
+#define __init
+#define __exit
+
+/* devices */
+
+static inline int misc_register(void *foo)
+{
+ return 0;
+}
+#define misc_deregister misc_register
+
+#define __MOD_INC_USE_COUNT(m) (m->count++)
+#define __MOD_DEC_USE_COUNT(m) (m->count--)
+#define MOD_INC_USE_COUNT do {int a = 1; a++; } while (0)
+#define MOD_DEC_USE_COUNT do {int a = 1; a++; } while (0)
+
+/* module initialization */
+extern int init_obdclass(void);
+extern int ptlrpc_init(void);
+extern int ldlm_init(void);
+extern int osc_init(void);
+extern int echo_client_init(void);
+
+
+/* general stuff */
+#define jiffies 0
+
+#define EXPORT_SYMBOL(S)
+
+typedef int spinlock_t;
+typedef __u64 kdev_t;
+
+#define SPIN_LOCK_UNLOCKED 0
+#define spin_lock(l) do {int a = 1; a++; } while (0)
+#define spin_unlock(l) do {int a= 1; a++; } while (0)
+#define spin_lock_init(l) do {int a= 1; a++; } while (0)
+static inline void spin_lock_bh(spinlock_t *l)
+{
+ return;
+}
+static inline void spin_unlock_bh(spinlock_t *l)
+{
+ return;
+}
+static inline void spin_lock_irqrestore(a,b)
+{
+ return;
+}
+static inline void spin_unlock_irqrestore(a,b)
+{
+ return;
+}
+static inline void spin_lock_irqsave(a,b)
+{
+ return;
+}
+
+#define barrier() do {int a= 1; a++; } while (0)
+
+/* registering symbols */
+
+#define ERESTARTSYS ERESTART
+#define HZ 1
+
+/* random */
+
+static inline void get_random_bytes(void *ptr, int size)
+{
+ static int r;
+ int *p = (int *)ptr;
+ int *end = p + (size / sizeof(int));
+ r = rand();
+ while ( p + sizeof(int) < end ) {
+ *p = r;
+ p++;
+ }
+}
+
+/* memory */
+
+static inline int copy_from_user(void *a,void *b, int c)
+{
+ memcpy(a,b,c);
+ return 0;
+}
+
+static inline int copy_to_user(void *a,void *b, int c)
+{
+ memcpy(a,b,c);
+ return 0;
+}
+
+
+/* slabs */
+typedef struct {
+ int size;
+} kmem_cache_t;
+#define SLAB_HWCACHE_ALIGN 0
+static inline kmem_cache_t *kmem_cache_create(name,objsize,c,d,e,f)
+{
+ return malloc(objsize);
+};
+
+static inline int kmem_cache_destroy(kmem_cache_t *a)
+{
+ free(a);
+ return 0;
+}
+#define kmem_cache_validate(a,b) 1
+#define kmem_cache_alloc(cache, prio) malloc(cache->size)
+#define kmem_cache_free(cache, obj) OBD_FREE(obj, cache->size)
+#define PORTAL_SLAB_ALLOC(lock,cache,size) do { lock = kmem_cache_alloc(cache,prio); } while (0)
+#define PORTAL_SLAB_FREE(lock,cache,size) do { lock = kmem_cache_alloc(cache,prio); } while (0)
+
+struct page {
+ void *addr;
+ int index;
+};
+
+#define kmap(page) (page)->addr
+#define kunmap(a) do { int foo = 1; foo++; } while (0)
+
+static inline struct page *alloc_pages(mask,foo)
+{
+ struct page *pg = malloc(sizeof(*pg));
+
+ if (!pg)
+ return NULL;
+#ifdef MAP_ANONYMOUS
+ pg->addr = mmap(0, PAGE_SIZE, PROT_WRITE, MAP_ANONYMOUS, 0, 0);
+#else
+ pg->addr = malloc(PAGE_SIZE);
+#endif
+
+ if (!pg->addr) {
+ free(pg);
+ return NULL;
+ }
+ return pg;
+}
+
+static inline void __free_pages(struct page *pg, int what)
+{
+#ifdef MAP_ANONYMOUS
+ munmap(pg->addr, PAGE_SIZE);
+#else
+ free(pg->addr);
+#endif
+ free(pg);
+}
+
+/* arithmetic */
+#define do_div(a,b) (a)/(b)
+
+/* dentries / intents */
+struct lookup_intent {
+ void *it_iattr;
+};
+
+struct iattr {
+ int mode;
+};
+
+struct dentry {
+ int d_count;
+};
+struct file {
+ struct dentry *f_dentry;
+ void *private_data;
+} ;
+
+struct vfsmount {
+ void *pwd;
+};
+#define cpu_to_le32(x) ((__u32)(x))
+
+/* semaphores */
+struct semaphore {
+ int count;
+};
+
+#define down(a) do {(a)->count++;} while (0)
+#define up(a) do {(a)->count--;} while (0)
+#define sema_init(a,b) do { (a)->count = b; } while (0)
+
+typedef struct {
+ struct list_head sleepers;
+} wait_queue_head_t;
+
+typedef struct {
+ struct list_head sleeping;
+ void *process;
+} wait_queue_t;
+
+struct signal {
+ int signal;
+};
+
+struct task_struct {
+ int state;
+ struct signal pending;
+ char comm[32];
+ int pid;
+};
+
+extern struct task_struct *current;
+
+
+
+#define set_current_state(foo) do { current->state = foo; } while (0)
+
+#define init_waitqueue_entry(q,p) do { (q)->process = p; } while (0)
+#define add_wait_queue(q,p) do { list_add(&(q)->sleepers, &(p)->sleeping); } while (0)
+#define del_wait_queue(p) do { list_del(&(p)->sleeping); } while (0)
+#define remove_wait_queue(q,p) do { list_del(&(p)->sleeping); } while (0)
+
+#define init_waitqueue_head(l) INIT_LIST_HEAD(&(l)->sleepers)
+#define wake_up(l) do { int a; a++; } while (0)
+#define wait_event(l,m) do { int a; a++; } while (0)
+#define TASK_INTERRUPTIBLE 0
+#define TASK_UNINTERRUPTIBLE 1
+#define TASK_RUNNING 2
+
+
+#define schedule() do { int a; a++; } while (0)
+static inline int schedule_timeout(t)
+{
+ return 0;
+}
+
+#define lock_kernel() do { int a; a++; } while (0)
+#define daemonize(l) do { int a; a++; } while (0)
+#define sigfillset(l) do { int a; a++; } while (0)
+#define recalc_sigpending(l) do { int a; a++; } while (0)
+#define kernel_thread(l,m,n)
+
+static inline int call_usermodehelper(char *prog, char **argv, char **evnp)
+{
+ return 0;
+}
+
+
+
+#define KERN_INFO
+
+
+
+struct timer_list {
+ struct list_head tl_list;
+ void (*function)(unsigned long unused);
+ void *data;
+ int expires;
+};
+
+static inline int timer_pending(struct timer_list *l)
+{
+ if (l->expires > jiffies)
+ return 1;
+ else
+ return 0;
+}
+
+static inline int init_timer(struct timer_list *l)
+{
+ INIT_LIST_HEAD(&l->tl_list);
+ return 0;
+}
+
+static inline void mod_timer(struct timer_list *l, int thetime)
+{
+ l->expires = thetime;
+}
+
+static inline void del_timer(struct timer_list *l)
+{
+ free(l);
+}
+
+typedef struct { volatile int counter; } atomic_t;
+
+#define atomic_read(a) ((a)->counter)
+#define atomic_set(a,b) do {(a)->counter = b; } while (0)
+#define atomic_dec_and_test(a) ((--((a)->counter)) == 0)
+#define atomic_inc(a) (((a)->counter)++)
+#define atomic_dec(a) do { (a)->counter--; } while (0)
+#define atomic_add(b,a) do {(a)->counter += b;} while (0)
+#define atomic_sub(b,a) do {(a)->counter -= b;} while (0)
+
+#define LBUG() do { sleep(1000000); } while (0)
+
+#include <linux/obd_support.h>
+#include <linux/lustre_idl.h>
+#include <linux/lustre_lib.h>
+#include <linux/lustre_import.h>
+#include <linux/lustre_export.h>
+#include <linux/lustre_net.h>
+
+
+#endif
+
fs/nfsd/vfs.c
fs/open.c
fs/stat.c
+fs/exec.c
include/linux/dcache.h
include/linux/fs.h
kernel/ksyms.c
--- /dev/null
+#!/bin/sh
+set -e
+
+#
+# Runs create.pl and rename.pl on two mountpoints with increasing load, varying
+# debug levels. Assumes that the node is already setup with llmount2.sh
+#
+
+SRCDIR="`dirname $0`"
+CREATE=$SRCDIR/create.pl
+
+debug_client_on()
+{
+ echo -1 > /proc/sys/portals/debug
+}
+
+debug_client_off()
+{
+ echo 0 > /proc/sys/portals/debug
+}
+
+MNT=${MNT:-/mnt/lustre}
+
+debug_client_on
+echo "create.pl, 2 mounts, 1 thread, 10 ops, debug on"
+perl $CREATE -- $MNT 2 10
+echo "create.pl, 2 mounts, 1 thread, 100 ops, debug on"
+perl $CREATE --silent -- $MNT 2 100
+echo "create.pl --mcreate=0, 2 mounts, 1 thread, 10 ops, debug on"
+perl $CREATE --mcreate=0 -- $MNT 2 10
+echo "create.pl --mcreate=0, 2 mounts, 1 thread, 100 ops, debug on"
+perl $CREATE --mcreate=0 --silent -- $MNT 2 100
+echo "rename.pl, 2 mounts, 1 thread, 10 ops, debug on"
+perl rename.pl --count=2 $MNT 10
+echo "rename.pl, 2 mounts, 1 thread, 100 ops, debug on"
+perl rename.pl --count=2 --silent $MNT 100
+
+debug_client_off
+echo "create.pl, 2 mounts, 1 thread, 1000 ops, debug off"
+perl $CREATE --silent -- $MNT 2 1000
+echo "create.pl --mcreate=0, 2 mounts, 1 thread, 1000 ops, debug off"
+perl $CREATE --silent --mcreate=0 -- $MNT 2 1000
+echo "rename.pl, 2 mounts, 1 thread, 1000 ops, debug off"
+perl rename.pl --count=2 --silent $MNT 1000
+
+debug_client_on
+echo "create.pl, 2 mounts, 2 threads, 100 ops, debug on"
+perl $CREATE --silent -- $MNT 2 100 &
+perl $CREATE --silent -- $MNT 2 100 &
+wait
+echo "create.pl --mcreate=0, 2 mounts, 2 threads, 100 ops, debug on"
+perl $CREATE --silent --mcreate=0 -- $MNT 2 100 &
+perl $CREATE --silent --mcreate=0 -- $MNT 2 100 &
+wait
+echo "rename.pl, 2 mounts, 2 thread, 1000 ops, debug on"
+perl rename.pl --count=2 --silent $MNT 1000 &
+perl rename.pl --count=2 --silent $MNT 1000 &
+wait
+
+debug_client_off
+echo "create.pl, 2 mounts, 2 threads, 2000 ops, debug off"
+perl $CREATE --silent -- $MNT 2 2000 &
+perl $CREATE --silent -- $MNT 2 2000 &
+wait
+echo "create.pl --mcreate=0, 2 mounts, 2 threads, 2000 ops, debug off"
+perl $CREATE --silent --mcreate=0 -- $MNT 2 2000 &
+perl $CREATE --silent --mcreate=0 -- $MNT 2 2000 &
+wait
+echo "rename.pl, 2 mounts, 2 threads, 2000 ops, debug off"
+perl rename.pl --count=2 --silent $MNT 2000 &
+perl rename.pl --count=2 --silent $MNT 2000 &
+wait
+
+debug_client_on
+echo "create.pl, 2 mounts, 4 threads, 100 ops, debug on"
+for i in `seq 1 4`; do
+ perl $CREATE --silent -- $MNT 2 100 &
+done
+wait
+echo "create.pl --mcreate=0, 2 mounts, 4 threads, 100 ops, debug on"
+for i in `seq 1 4`; do
+ perl $CREATE --silent --mcreate=0 -- $MNT 2 100 &
+done
+wait
+echo "rename.pl, 2 mounts, 4 threads, 2000 ops, debug on"
+for i in `seq 1 4`; do
+ perl rename.pl --count=2 --silent $MNT 2000 &
+done
+wait
+
+debug_client_off
+echo "create.pl, 2 mounts, 4 threads, 2000 ops, debug off"
+for i in `seq 1 4`; do
+ perl $CREATE --silent -- $MNT 2 2000 &
+done
+wait
+echo "create.pl --mcreate=0, 2 mounts, 4 threads, 2000 ops, debug off"
+for i in `seq 1 4`; do
+ perl $CREATE --silent --mcreate=0 -- $MNT 2 2000 &
+done
+wait
+echo "rename.pl, 2 mounts, 4 threads, 2000 ops, debug off"
+for i in `seq 1 4`; do
+ perl rename.pl --count=2 --silent $MNT 2000 &
+done
+wait
+
+debug_client_on
+echo "create.pl, 2 mounts, 8 threads, 500 ops, debug on"
+for i in `seq 1 8`; do
+ perl $CREATE --silent -- $MNT 2 500 &
+done
+wait
+echo "create.pl --mcreate=0, 2 mounts, 8 threads, 500 ops, debug on"
+for i in `seq 1 8`; do
+ perl $CREATE --silent --mcreate=0 -- $MNT 2 500 &
+done
+wait
+echo "rename.pl, 2 mounts, 8 threads, 2000 ops, debug on"
+for i in `seq 1 8`; do
+ perl rename.pl --count=2 --silent $MNT 2000 &
+done
+wait
+
+debug_client_off
+echo "create.pl, 2 mounts, 8 threads, 2000 ops, debug off"
+for i in `seq 1 8`; do
+ perl $CREATE --silent -- $MNT 2 2000 &
+done
+wait
+echo "create.pl --mcreate=0, 2 mounts, 8 threads, 2000 ops, debug off"
+for i in `seq 1 8`; do
+ perl $CREATE --silent --mcreate=0 -- $MNT 2 2000 &
+done
+wait
+echo "rename.pl, 2 mounts, 8 threads, 2000 ops, debug off"
+for i in `seq 1 8`; do
+ perl rename.pl --count=2 --silent $MNT 2000 &
+done
+wait
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <liblustre.h>
+#include <linux/lustre_lib.h>
+#include <linux/obd.h>
+
+int main(int argc, char **argv)
+{
+ struct obd_ioctl_data data;
+ char rawbuf[8192], parent[4096], *buf = rawbuf, *base, *t;
+ int max = sizeof(rawbuf), fd, offset, rc;
+
+ if (argc != 2) {
+ printf("usage: %s filename\n", argv[0]);
+ return 1;
+ }
+
+ base = argv[1];
+ t = strrchr(base, '/');
+ if (!t) {
+ strcpy(parent, ".");
+ offset = -1;
+ } else {
+ strncpy(parent, base, t - base);
+ offset = t - base - 1;
+ }
+
+ fd = open(parent, O_RDONLY);
+ if (fd < 0) {
+ printf("open(%s) error: %s\n", parent, strerror(errno));
+ exit(errno);
+ }
+
+ memset(&data, 0, sizeof(data));
+ data.ioc_version = OBD_IOCTL_VERSION;
+ data.ioc_len = sizeof(data);
+ if (offset >= 0)
+ data.ioc_inlbuf1 = base + offset + 2;
+ else
+ data.ioc_inlbuf1 = base;
+ data.ioc_inllen1 = strlen(data.ioc_inlbuf1) + 1;
+
+ if (obd_ioctl_pack(&data, &buf, max)) {
+ printf("ioctl_pack failed.\n");
+ exit(1);
+ }
+
+ rc = ioctl(fd, IOC_MDC_LOOKUP, buf);
+ if (rc < 0) {
+ printf("ioctl(%s/%s) error: %s\n", parent,
+ data.ioc_inlbuf1, strerror(errno));
+ exit(errno);
+ }
+
+ return 0;
+}