Re: BUG REPORT: kernel nfs between 2.4.19-pre2 (server) and 2.2.21-pre3 (client)

From: Stephan von Krawczynski (skraw@ithnet.com)
Date: Fri Mar 22 2002 - 08:19:42 EST


On Fri, 22 Mar 2002 12:07:55 +0100
Trond Myklebust <trond.myklebust@fys.uio.no> wrote:

> >>>>> " " == Stephan von Krawczynski <skraw@ithnet.com> writes:
> > The files are obviously not deleted from the server. Can you
> > give me a short hint in where to look after this specific case
> > (source location). I will try to do some debugging around the
> > place to see what is going on.
>
> Those decisions are supposed to be made in the fh_to_dentry()
> 'struct super_operations' method. For ReiserFS, that would be in
> fs/reiserfs/inode.c:reiserfs_fh_to_dentry().
>
> It would indeed be a good idea to try sticking some debugging
> 'printk's in there in order to see what is failing...

Well, I seem to be really stupid, watch this:

struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, __u32 *data,
                                     int len, int fhtype, int parent) {
    struct cpu_key key ;
    struct inode *inode = NULL ;
    struct list_head *lp;
    struct dentry *result;

    /* fhtype happens to reflect the number of u32s encoded.
     * due to a bug in earlier code, fhtype might indicate there
     * are more u32s then actually fitted.
     * so if fhtype seems to be more than len, reduce fhtype.
     * Valid types are:
     * 2 - objectid + dir_id - legacy support
     * 3 - objectid + dir_id + generation
     * 4 - objectid + dir_id + objectid and dirid of parent - legacy
     * 5 - objectid + dir_id + generation + objectid and dirid of parent
     * 6 - as above plus generation of directory
     * 6 does not fit in NFSv2 handles
     */
    if (fhtype > len) {
            if (fhtype != 6 || len != 5)
                    printk(KERN_WARNING "nfsd/reiserfs, fhtype=%d, len=%d - odd\n",
                           fhtype, len);
            fhtype = 5;
    }
    if (fhtype < 2 || (parent && fhtype < 4)) {
        printk(KERN_WARNING "fh: 1\n");
        goto out ;
        }

    if (! parent) {
            /* this works for handles from old kernels because the default
            ** reiserfs generation number is the packing locality.
            */
            key.on_disk_key.k_objectid = data[0] ;
            key.on_disk_key.k_dir_id = data[1] ;
            inode = reiserfs_iget(sb, &key) ;
            if (!inode)
                    printk(KERN_WARNING "fh: 2a\n");
                    
            if (inode && !IS_ERR(inode) && (fhtype == 3 || fhtype >= 5) &&
                data[2] != inode->i_generation) {
                    iput(inode) ;
                    printk(KERN_WARNING "fh: 2\n");
                    inode = NULL ;
            }
    } else {
            key.on_disk_key.k_objectid = data[fhtype>=5?3:2] ;
            key.on_disk_key.k_dir_id = data[fhtype>=5?4:3] ;
            inode = reiserfs_iget(sb, &key) ;
            if (!inode)
                    printk(KERN_WARNING "fh: 3a\n");
            
            if (inode && !IS_ERR(inode) && fhtype == 6 &&
                data[5] != inode->i_generation) {
                    iput(inode) ;
                    printk(KERN_WARNING "fh: 3\n");
                    inode = NULL ;
            }
    }
out:
    if (IS_ERR(inode))
        return ERR_PTR(PTR_ERR(inode));
    if (!inode)
        return ERR_PTR(-ESTALE) ;

    /* now to find a dentry.
     * If possible, get a well-connected one
     */
    spin_lock(&dcache_lock);
    for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
            result = list_entry(lp,struct dentry, d_alias);
            
            if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
                    dget_locked(result);
                    result->d_vfs_flags |= DCACHE_REFERENCED;
                    spin_unlock(&dcache_lock);
                    iput(inode);
                    return result;
            }
    }
    spin_unlock(&dcache_lock);
    result = d_alloc_root(inode);
    if (result == NULL) {
            iput(inode);
            printk(KERN_WARNING "fh: 4\n");
            
            return ERR_PTR(-ENOMEM);
    }
    result->d_flags |= DCACHE_NFSD_DISCONNECTED;
    return result;

}

As you can see I put printks just around everywhere, where a false exit seems possible. Only I get _no_ output from it in my testcase.

Is this really the correct spot to look at?

What else can I do?

Regards,
Stephan

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Mar 23 2002 - 22:00:27 EST