Whamcloud - gitweb
- a few more header cleanups
authorpschwan <pschwan>
Mon, 11 Mar 2002 14:58:49 +0000 (14:58 +0000)
committerpschwan <pschwan>
Mon, 11 Mar 2002 14:58:49 +0000 (14:58 +0000)
- removed some unused code
- inserted many extra BUG()s to catch problems early
- fixed a use of the incorrect inode, and fixed the directory bug
- enabled mds_open/mds_close
- fixed a small leak in an error case
- removed an extra set_page_dirty() in the write path
- added an open/write/close/open/unlink/read/truncate/write/read/close test

lustre/include/linux/lustre_light.h
lustre/lib/page.c
lustre/llite/dir.c
lustre/llite/file.c
lustre/llite/namei.c
lustre/llite/rw.c
lustre/mds/handler.c
lustre/mds/mds_reint.c
lustre/tests/Makefile.am
lustre/tests/llmount.sh
lustre/tests/openunlink.c [new file with mode: 0644]

index 4ebe4dc..b4a2c23 100644 (file)
@@ -66,31 +66,7 @@ static inline struct obd_conn *ll_i2obdconn(struct inode *inode)
        return &(ll_i2sbi(inode))->ll_conn;
 }
 
-
-
-
-
-/* super.c */ 
-struct ll_pgrq {
-        struct list_head         rq_plist;      /* linked list of req's */
-        unsigned long            rq_jiffies;
-        struct page             *rq_page;       /* page to be written */
-};
-
-extern struct list_head ll_super_list;       /* list of all LL superblocks */
-
-
-
 /* dir.c */
-#define EXT2_DIR_PAD                    4
-#define EXT2_DIR_ROUND                  (EXT2_DIR_PAD - 1)
-#define EXT2_DIR_REC_LEN(name_len)      (((name_len) + 8 + EXT2_DIR_ROUND) & \
-                                         ~EXT2_DIR_ROUND)
-#define EXT2_NAME_LEN 255
-
-int ll_check_dir_entry (const char * function, struct inode * dir,
-                        struct ext2_dir_entry_2 * de, struct page * page,
-                        unsigned long offset);
 extern struct file_operations ll_dir_operations;
 extern struct inode_operations ll_dir_inode_operations;
 
@@ -98,71 +74,11 @@ extern struct inode_operations ll_dir_inode_operations;
 extern struct file_operations ll_file_operations;
 extern struct inode_operations ll_file_inode_operations;
 
-/* flush.c */
-void ll_dequeue_pages(struct inode *inode);
-int ll_flushd_init(void);
-int ll_flushd_cleanup(void);
-int ll_flush_reqs(struct list_head *inode_list, unsigned long check_time);
-int ll_flush_dirty_pages(unsigned long check_time);
-
-/* namei.c */
-/*
- * Structure of the super block
- */
-
-
-#define EXT2_SB(sb)     (&((sb)->u.ext2_sb))
-/*
- * Maximal count of links to a file
- */
-#define EXT2_LINK_MAX           32000
-/*
- * Ext2 directory file types.  Only the low 3 bits are used.  The
- * other bits are reserved for now.
- */
-#define EXT2_FT_UNKNOWN         0
-#define EXT2_FT_REG_FILE        1
-#define EXT2_FT_DIR             2
-#define EXT2_FT_CHRDEV          3
-#define EXT2_FT_BLKDEV          4
-#define EXT2_FT_FIFO            5
-#define EXT2_FT_SOCK            6
-#define EXT2_FT_SYMLINK         7
-
-#define EXT2_FT_MAX             8
-
-#define EXT2_BTREE_FL                   0x00001000 /* btree format dir */
-#define EXT2_RESERVED_FL                0x80000000 /* reserved for ext2 lib */
-#define EXT2_FEATURE_INCOMPAT_FILETYPE          0x0002
-#define EXT2_HAS_COMPAT_FEATURE(sb,mask)                        \
-        ( EXT2_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) )
-#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask)                      \
-        ( EXT2_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) )
-
 /* rw.c */
-int ll_do_writepage(struct page *, int sync);
-int ll_init_pgrqcache(void);
-void ll_cleanup_pgrqcache(void);
-inline void ll_pgrq_del(struct ll_pgrq *pgrq);
-int ll_readpage(struct file *file, struct page *page);
-int ll_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to);
-int ll_commit_write(struct file *file, struct page *page, unsigned from, unsigned to);
-int ll_writepage(struct page *page);
 struct page *ll_getpage(struct inode *inode, unsigned long offset,
                            int create, int locked);
-int ll_write_one_page(struct file *file, struct page *page,
-                         unsigned long offset, unsigned long bytes,
-                         const char * buf);
-int ll_do_vec_wr(struct inode **inodes, obd_count num_io, obd_count num_oa,
-                    struct obdo **obdos, obd_count *oa_bufs,
-                    struct page **pages, char **bufs, obd_size *counts,
-                    obd_off *offsets, obd_flag *flags);
 void ll_truncate(struct inode *inode);
 
-/* super.c */
-extern long ll_cache_count;
-extern long ll_mutex_start;
-
 /* symlink.c */
 extern struct inode_operations ll_fast_symlink_inode_operations;
 extern struct inode_operations ll_symlink_inode_operations;
index 50b559b..ecd00d3 100644 (file)
 
 #define DEBUG_SUBSYSTEM S_OST
 
-#include <linux/obd_support.h>
 #include <linux/obd_class.h>
 #include <linux/lustre_lib.h>
-#include <linux/lustre_idl.h>
-#include <linux/lustre_mds.h>
-#include <linux/lustre_light.h>
 
 /*
  * Remove page from dirty list
index 2a02a04..887cf11 100644 (file)
@@ -73,6 +73,7 @@ static int ll_dir_readpage(struct file *file, struct page *page)
        }
 
        if (Page_Uptodate(page)) {
+                CERROR("Explain this please?\n");
                EXIT;
                goto readpage_out;
        }
@@ -83,11 +84,12 @@ static int ll_dir_readpage(struct file *file, struct page *page)
                          buf, &request);
        kunmap(page); 
         ptlrpc_free_req(request);
+        EXIT;
+
+ readpage_out:
         if ( !rc )
                 SetPageUptodate(page);
 
-        EXIT;
- readpage_out:
        UnlockPage(page);
         return rc;
 } /* ll_dir_readpage */
index 0d5bb4f..f9bdb92 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/lustre_light.h>
 
 extern int ll_setattr(struct dentry *de, struct iattr *attr);
+extern inline struct obdo * ll_oa_from_inode(struct inode *inode, int valid);
 
 static int ll_file_open(struct inode *inode, struct file *file)
 {
@@ -47,7 +48,7 @@ static int ll_file_open(struct inode *inode, struct file *file)
        int flags = 0; 
        struct ptlrpc_request *req;
        struct ll_file_data *fd;
-       struct obdo oa; 
+       struct obdo *oa;
         struct ll_sb_info *sbi = ll_i2sbi(inode);
        ENTRY;
 
@@ -57,11 +58,11 @@ static int ll_file_open(struct inode *inode, struct file *file)
                goto out;
        }
 
-       memset(&oa, 0, sizeof(oa)); 
-       oa.o_valid = OBD_MD_FLMODE | OBD_MD_FLID; 
-       oa.o_mode = inode->i_mode;
-       oa.o_id = HTON__u64((__u64)inode->i_ino);
-       rc = obd_open(ll_i2obdconn(inode),  &oa); 
+        oa = ll_oa_from_inode(inode, (OBD_MD_FLMODE | OBD_MD_FLID));
+        if (oa == NULL)
+                BUG();
+       rc = obd_open(ll_i2obdconn(inode), oa); 
+        obdo_free(oa);
        if (rc) { 
                if (rc > 0) 
                        rc = -rc;
@@ -94,7 +95,7 @@ static int ll_file_release(struct inode *inode, struct file *file)
        int rc;
        struct ptlrpc_request *req;
        struct ll_file_data *fd;
-       struct obdo oa; 
+       struct obdo *oa;
         struct ll_sb_info *sbi = ll_i2sbi(inode);
        ENTRY;
 
@@ -105,11 +106,11 @@ static int ll_file_release(struct inode *inode, struct file *file)
                goto out;
        }
 
-       memset(&oa, 0, sizeof(oa)); 
-       oa.o_valid = OBD_MD_FLMODE | OBD_MD_FLID; 
-       oa.o_mode = inode->i_mode;
-       oa.o_id = HTON__u64((__u64)inode->i_ino);
-       rc = obd_close(ll_i2obdconn(inode),  &oa); 
+        oa = ll_oa_from_inode(inode, (OBD_MD_FLMODE | OBD_MD_FLID));
+        if (oa == NULL)
+                BUG();
+       rc = obd_close(ll_i2obdconn(inode), oa); 
+        obdo_free(oa);
        if (rc) { 
                if (rc > 0) 
                        rc = -rc;
index aa33c80..0b9ba68 100644 (file)
@@ -101,6 +101,7 @@ static struct dentry *ll_lookup(struct inode * dir, struct dentry *dentry)
                          OBD_MD_FLNOTOBD|OBD_MD_FLBLOCKS, &request);
         if ( err ) {
                 CERROR("obdo_fromid failed\n");
+                ptlrpc_free_req(request);
                 EXIT;
                 return ERR_PTR(-abs(err)); 
         }
@@ -149,7 +150,6 @@ static struct inode *ll_create_node(struct inode *dir, const char *name,
        err = mdc_create(&sbi->ll_mds_client, dir, name, namelen, tgt, tgtlen,
                         mode, id,  current->uid, current->gid, time, &request);
        if (err) { 
-                ptlrpc_free_req(request);
                 inode = ERR_PTR(err);
                 EXIT;
                 goto out;
@@ -168,6 +168,7 @@ static struct inode *ll_create_node(struct inode *dir, const char *name,
         if (IS_ERR(inode)) {
                 CERROR("new_inode -fatal:  %ld\n", PTR_ERR(inode));
                 inode = ERR_PTR(-EIO);
+                BUG();
                 EXIT;
                 goto out;
         }
@@ -177,6 +178,7 @@ static struct inode *ll_create_node(struct inode *dir, const char *name,
                       rep->ino, atomic_read(&inode->i_count), 
                       inode->i_nlink);
                 iput(inode);
+                BUG();
                 inode = ERR_PTR(-EIO);
                 EXIT;
                 goto out;
index 4a2eed2..71e78e3 100644 (file)
@@ -188,40 +188,43 @@ extern void set_page_clean(struct page *);
 
 
 /* returns the page unlocked, but with a reference */
-int ll_readpage(struct file *file, struct page *page)
+static int ll_readpage(struct file *file, struct page *page)
 {
        struct inode *inode = page->mapping->host;
-        int rc;
+        int rc = 0;
 
         ENTRY;
 
-       if ( ((inode->i_size + PAGE_CACHE_SIZE -1)>>PAGE_SHIFT) 
-            <= page->index) {
+        if (!PageLocked(page))
+                BUG();
+
+       if ( ((inode->i_size + PAGE_CACHE_SIZE -1)>>PAGE_SHIFT)
+             <= page->index) {
                memset(kmap(page), 0, PAGE_CACHE_SIZE);
                kunmap(page);
+                EXIT;
                goto readpage_out;
        }
 
        if (Page_Uptodate(page)) {
+                CERROR("Explain this please?\n");
                EXIT;
                goto readpage_out;
        }
 
         rc = ll_brw(OBD_BRW_READ, inode, page, 0);
-        if ( rc ) {
-               EXIT; 
-               return rc;
-        } 
+        EXIT;
 
  readpage_out:
-       SetPageUptodate(page);
+        if (!rc)
+                SetPageUptodate(page);
        UnlockPage(page);
-        EXIT;
         return 0;
 } /* ll_readpage */
 
 
-int ll_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+static int ll_prepare_write(struct file *file, struct page *page, unsigned from,
+                     unsigned to)
 {
         struct inode *inode = page->mapping->host;
         obd_off offset = ((obd_off)page->index) << PAGE_SHIFT;
@@ -230,6 +233,9 @@ int ll_prepare_write(struct file *file, struct page *page, unsigned from, unsign
         ENTRY; 
         
        addr = kmap(page);
+        if (!PageLocked(page))
+                BUG();
+
         if (Page_Uptodate(page)) { 
                 EXIT;
                goto prepare_done;
@@ -238,40 +244,45 @@ int ll_prepare_write(struct file *file, struct page *page, unsigned from, unsign
         if ( offset + from >= inode->i_size ) {
                memset(addr, 0, PAGE_SIZE); 
                 EXIT;
-                return 0;
+                goto prepare_done;
         }
         
         rc = ll_brw(OBD_BRW_READ, inode, page, 0);
-        if ( !rc ) {
-                SetPageUptodate(page);
-        } 
 
  prepare_done:
-       set_page_dirty(page);
+        if ( !rc )
+                SetPageUptodate(page);
+
         EXIT;
         return rc;
 }
 
 /* returns the page unlocked, but with a reference */
-int ll_writepage(struct page *page)
+static int ll_writepage(struct page *page)
 {
         struct inode *inode = page->mapping->host;
         int err;
         ENTRY;
 
+        BUG();
+
+        if (!PageLocked(page))
+                BUG();
+
        err = ll_brw(OBD_BRW_WRITE, inode, page, 1);
         if ( !err ) {
-                SetPageUptodate(page);
+                //SetPageUptodate(page);
                set_page_clean(page);
        } else {
                CERROR("ll_brw failure %d\n", err);
        }
+        UnlockPage(page); 
         EXIT;
        return err;
 }
 
 /* SYNCHRONOUS I/O to object storage for an inode -- object attr will be updated too */
-int ll_commit_write(struct file *file, struct page *page, 
+static int ll_commit_write(struct file *file, struct page *page, 
                    unsigned from, unsigned to)
 {
        int create = 1;
@@ -291,15 +302,16 @@ int ll_commit_write(struct file *file, struct page *page,
                return -ENOMEM;
        }
 
+        if (!PageLocked(page))
+                BUG();
+        if (!Page_Uptodate(page))
+                BUG(); 
+
        CDEBUG(D_INODE, "commit_page writing (at %d) to %d, count %Ld\n", 
               from, to, count);
 
         err = obd_brw(OBD_BRW_WRITE, ll_i2obdconn(inode), num_obdo, &oa,
                       &bufs_per_obdo, &page, &count, &offset, &flags);
-        if ( !err ) {
-                SetPageUptodate(page);
-               set_page_clean(page);
-       }
         kunmap(page);
 
        if (offset + to > inode->i_size) {
index 5e5a46a..5aab742 100644 (file)
@@ -123,6 +123,7 @@ struct dentry *mds_fid2dentry(struct mds_obd *mds, struct ll_fid *fid,
                        inode->i_nlink, atomic_read(&inode->i_count),
                        inode->i_generation,
                        generation);
+                BUG();
                iput(inode);
                return ERR_PTR(-ESTALE);
        }
@@ -239,8 +240,6 @@ int mds_open(struct ptlrpc_request *req)
        }               
        
        rep->objid = (__u64) (unsigned long)file; 
-       //mds_get_objid(inode, &rep->objid);
-       dput(de); 
        return 0;
 }
 
@@ -272,6 +271,7 @@ int mds_close(struct ptlrpc_request *req)
        }
 
         file = (struct file *)(unsigned long) req->rq_req.mds->objid;
+
         req->rq_rephdr->status = filp_close(file, 0); 
        dput(de); 
        return 0;
@@ -389,6 +389,16 @@ int mds_handle(struct obd_device *dev, struct ptlrpc_service *svc,
                rc = mds_reint(req);
                break;
 
+        case MDS_OPEN:
+                CDEBUG(D_INODE, "open\n");
+                rc = mds_open(req);
+                break;
+
+        case MDS_CLOSE:
+                CDEBUG(D_INODE, "close\n");
+                rc = mds_close(req);
+                break;
+
        default:
                return ptlrpc_error(dev, svc, req);
        }
index 76523e6..7bf85ea 100644 (file)
@@ -102,6 +102,7 @@ static int mds_reint_create(struct mds_update_record *rec,
        de = mds_fid2dentry(&req->rq_obd->u.mds, rec->ur_fid1, NULL);
        if (IS_ERR(de)) { 
                req->rq_rephdr->status = -ESTALE;
+                BUG();
                EXIT;
                return 0;
        }
@@ -113,6 +114,7 @@ static int mds_reint_create(struct mds_update_record *rec,
                CERROR("child lookup error %d\n", rc);
                dput(de); 
                req->rq_rephdr->status = -ESTALE;
+                BUG();
                EXIT;
                return 0;
        }
@@ -122,6 +124,7 @@ static int mds_reint_create(struct mds_update_record *rec,
                       de->d_inode->i_ino, rec->ur_name);
                dput(de); 
                req->rq_rephdr->status = -EEXIST;
+                BUG();
                EXIT;
                return 0;
        }
@@ -129,7 +132,6 @@ static int mds_reint_create(struct mds_update_record *rec,
        switch (type) {
        case S_IFREG: { 
                rc = vfs_create(de->d_inode, dchild, rec->ur_mode);
-               
                EXIT;
                break;
        }
@@ -182,6 +184,7 @@ static int mds_reint_unlink(struct mds_update_record *rec,
 
        de = mds_fid2dentry(&req->rq_obd->u.mds, rec->ur_fid1, NULL);
        if (IS_ERR(de)) { 
+                BUG();
                req->rq_rephdr->status = -ESTALE;
                EXIT;
                return 0;
@@ -192,6 +195,7 @@ static int mds_reint_unlink(struct mds_update_record *rec,
        rc = PTR_ERR(dchild);
        if (IS_ERR(dchild)) { 
                CERROR("child lookup error %d\n", rc);
+                BUG();
                dput(de); 
                req->rq_rephdr->status = -ESTALE;
                EXIT;
@@ -201,6 +205,7 @@ static int mds_reint_unlink(struct mds_update_record *rec,
        if (!dchild->d_inode) {
                CERROR("child doesn't exist (dir %ld, name %s\n", 
                       de->d_inode->i_ino, rec->ur_name);
+                BUG();
                dput(de); 
                req->rq_rephdr->status = -ESTALE;
                EXIT;
@@ -244,7 +249,6 @@ static int mds_reint_link(struct mds_update_record *rec,
 
        de_tgt_dir = mds_fid2dentry(&req->rq_obd->u.mds, rec->ur_fid2, NULL);
        if (IS_ERR(de_tgt_dir)) { 
-               rc = -ESTALE;
                EXIT;
                goto out_link;
        }
@@ -252,7 +256,7 @@ static int mds_reint_link(struct mds_update_record *rec,
        dchild = lookup_one_len(rec->ur_name, de_tgt_dir, rec->ur_namelen - 1);
        if (IS_ERR(dchild)) { 
                CERROR("child lookup error %d\n", rc);
-               req->rq_rephdr->status = -ESTALE;
+                EXIT;
                goto out_link;
        }
 
@@ -264,13 +268,13 @@ static int mds_reint_link(struct mds_update_record *rec,
        }
 
        rc = vfs_link(de_src, de_tgt_dir->d_inode, dchild); 
+        EXIT;
 
  out_link:
        req->rq_rephdr->status = rc;
        l_dput(de_src);
        l_dput(de_tgt_dir); 
        l_dput(dchild); 
-       EXIT;
        return 0;
 }
 
@@ -294,7 +298,6 @@ static int mds_reint_rename(struct mds_update_record *rec,
 
        de_tgtdir = mds_fid2dentry(&req->rq_obd->u.mds, rec->ur_fid2, NULL);
        if (IS_ERR(de_tgtdir)) { 
-               rc = -ESTALE;
                EXIT;
                goto out_rename;
        }
@@ -302,16 +305,19 @@ static int mds_reint_rename(struct mds_update_record *rec,
        de_old = lookup_one_len(rec->ur_name, de_srcdir, rec->ur_namelen - 1);
        if (IS_ERR(de_old)) { 
                CERROR("child lookup error %d\n", rc);
+                EXIT;
                goto out_rename;
        }
 
        de_new = lookup_one_len(rec->ur_tgt, de_tgtdir, rec->ur_tgtlen - 1);
        if (IS_ERR(de_new)) { 
                CERROR("child lookup error %d\n", rc);
+                EXIT;
                goto out_rename;
        }
 
        rc = vfs_rename(de_srcdir->d_inode, de_old, de_tgtdir->d_inode, de_new);
+        EXIT;
 
  out_rename:
        req->rq_rephdr->status = rc;
@@ -319,7 +325,6 @@ static int mds_reint_rename(struct mds_update_record *rec,
        l_dput(de_old); 
        l_dput(de_tgtdir); 
        l_dput(de_srcdir); 
-       EXIT;
        return 0;
 }
 
@@ -355,8 +360,6 @@ int mds_reint_rec(struct mds_update_record *rec, struct ptlrpc_request *req)
        req->rq_rephdr->xid = req->rq_reqhdr->xid;
 
        rc = reinters[rec->ur_opcode](rec, req); 
-       req->rq_status = rc;
-
        return rc;
 } 
 
index fb9f04f..6995651 100644 (file)
@@ -2,8 +2,9 @@ CFLAGS:=-g -I. -I/usr/include/glib-1.2 -I/usr/lib/glib/include -I../include -Wal
 KFLAGS:=
 CPPFLAGS :=
 # LDADD := -lreadline -ltermcap # -lefence
-bin_PROGRAMS = testreq truncate
+bin_PROGRAMS = openunlink testreq truncate
 
 testreq_SOURCES = testreq.c
 truncate_SOURCES = truncate.c
+openunlink_SOURCES = openunlink.c
 
index 0fcaa83..30a9286 100755 (executable)
@@ -20,7 +20,7 @@ mke2fs -b 4096 -F /tmp/ost
 losetup ${LOOP}0 /tmp/ost || exit -1
 
 dd if=/dev/zero of=/tmp/mds bs=1024 count=10000
-mke2fs -b 4096 -F /tmp/mds
+mke2fs -b 4096 -N 150000 -F /tmp/mds
 losetup ${LOOP}1 /tmp/mds || exit -1
 
 mknod /dev/obd c 10 241
diff --git a/lustre/tests/openunlink.c b/lustre/tests/openunlink.c
new file mode 100644 (file)
index 0000000..dddf6a8
--- /dev/null
@@ -0,0 +1,122 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h> 
+#include <stdlib.h>
+#include <unistd.h>
+
+#define T1 "write before unlink\n"
+#define T2 "write after unlink\n"
+char buf[128];
+
+int main(int argc, char **argv)
+{
+        int fd, rc;
+
+        if (argc != 2) {
+                fprintf(stderr, "usage: %s filename\n", argv[1]); 
+                exit(1);
+        } else { 
+                fprintf(stderr, "congratulations - program starting\n"); 
+        }
+
+        fprintf(stderr, "opening\n");
+        fd = open(argv[1], O_RDWR | O_TRUNC | O_CREAT, 0644);
+        if (fd == -1) { 
+                fprintf(stderr, "open (before) %s\n", strerror(errno)); 
+                exit(1); 
+        }
+
+        fprintf(stderr, "writing\n");
+        rc = write(fd, T1, strlen(T1) + 1); 
+        if (rc != strlen(T1) + 1) { 
+                fprintf(stderr, "write (before) %s\n", strerror(errno)); 
+                exit(1); 
+        }
+
+        fprintf(stderr, "closing\n");
+        rc = close(fd); 
+        if (rc )  { 
+                fprintf(stderr, "close (before) %s\n", strerror(errno)); 
+                exit(1); 
+        }
+
+        fprintf(stderr, "opening again\n");
+        fd = open(argv[1], O_RDWR );
+        if (fd == -1) { 
+                fprintf(stderr, "open (before) %s\n", strerror(errno)); 
+                exit(1); 
+        }
+
+        fprintf(stderr, "unlinking\n");
+        rc = unlink(argv[1]); 
+        if (rc )  { 
+                fprintf(stderr, "open %s\n", strerror(errno)); 
+                exit(1); 
+        }
+
+        fprintf(stderr, "reading\n");
+        rc = read(fd, buf, strlen(T1) + 1); 
+        if (rc != strlen(T1) + 1) { 
+                fprintf(stderr, "read -after %s rc %d\n", strerror(errno), rc); 
+                exit(1); 
+        }
+
+        fprintf(stderr, "comparing data\n");
+        if (memcmp(buf, T1, strlen(T1) + 1) ) { 
+                fprintf(stderr, "FAILURE: read wrong data after unlink\n");
+                exit(1); 
+        }       
+
+        fprintf(stderr, "truncating\n");
+        rc = ftruncate(fd, 0); 
+        if (rc )  { 
+                fprintf(stderr, "truncate -after unl %s\n", strerror(errno)); 
+                exit(1); 
+        }
+        
+        fprintf(stderr, "seeking\n");
+        rc = lseek(fd, 0, SEEK_SET);
+        if (rc != 0 )  { 
+                fprintf(stderr, "seek (before write) %s\n", strerror(errno)); 
+                exit(1); 
+        }
+
+        fprintf(stderr, "writing again\n");
+        rc = write(fd, T2, strlen(T2) + 1); 
+        if (rc != strlen(T2) + 1) { 
+                fprintf(stderr, "write (before) %s (rc %d)\n", strerror(errno), rc); 
+                exit(1); 
+        }
+
+        fprintf(stderr, "seeking\n");
+        rc = lseek(fd, 0, SEEK_SET);
+        if (rc != 0 )  { 
+                fprintf(stderr, "seek (before read) %s\n", strerror(errno)); 
+                exit(1); 
+        }
+
+        fprintf(stderr, "reading again\n");
+        rc = read(fd, buf, strlen(T2) + 1); 
+        if (rc != strlen(T2) + 1) { 
+                fprintf(stderr, "read (after trunc) %s\n", strerror(errno)); 
+                exit(1); 
+        }
+
+        fprintf(stderr, "comparing data again\n");
+        if (memcmp(buf, T2, strlen(T2) + 1) ) { 
+                fprintf(stderr, "FAILURE: read wrong data after trunc\n");
+                exit(1); 
+        }       
+
+        fprintf(stderr, "closing again\n");
+        rc = close(fd); 
+        if (rc )  { 
+                fprintf(stderr, "close (before) %s\n", strerror(errno)); 
+                exit(1); 
+        }
+
+        fprintf(stderr, "SUCCESS - goto beer\n"); 
+        return 0; 
+}