Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 21 Feb 2011 23:01:38 +0000 (15:01 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 21 Feb 2011 23:01:38 +0000 (15:01 -0800)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client:
  ceph: keep reference to parent inode on ceph_dentry
  ceph: queue cap_snaps once per realm
  libceph: fix socket write error handling
  libceph: fix socket read error handling

1  2 
fs/ceph/dir.c
fs/ceph/super.h

diff --combined fs/ceph/dir.c
@@@ -42,11 -42,11 +42,11 @@@ int ceph_init_dentry(struct dentry *den
  
        if (dentry->d_parent == NULL ||   /* nfs fh_to_dentry */
            ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
 -              dentry->d_op = &ceph_dentry_ops;
 +              d_set_d_op(dentry, &ceph_dentry_ops);
        else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR)
 -              dentry->d_op = &ceph_snapdir_dentry_ops;
 +              d_set_d_op(dentry, &ceph_snapdir_dentry_ops);
        else
 -              dentry->d_op = &ceph_snap_dentry_ops;
 +              d_set_d_op(dentry, &ceph_snap_dentry_ops);
  
        di = kmem_cache_alloc(ceph_dentry_cachep, GFP_NOFS | __GFP_ZERO);
        if (!di)
@@@ -60,6 -60,7 +60,7 @@@
        }
        di->dentry = dentry;
        di->lease_session = NULL;
+       di->parent_inode = igrab(dentry->d_parent->d_inode);
        dentry->d_fsdata = di;
        dentry->d_time = jiffies;
        ceph_dentry_lru_add(dentry);
@@@ -112,7 -113,7 +113,7 @@@ static int __dcache_readdir(struct fil
        dout("__dcache_readdir %p at %llu (last %p)\n", dir, filp->f_pos,
             last);
  
 -      spin_lock(&dcache_lock);
 +      spin_lock(&parent->d_lock);
  
        /* start at beginning? */
        if (filp->f_pos == 2 || last == NULL ||
@@@ -136,7 -137,6 +137,7 @@@ more
                        fi->at_end = 1;
                        goto out_unlock;
                }
 +              spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
                if (!d_unhashed(dentry) && dentry->d_inode &&
                    ceph_snap(dentry->d_inode) != CEPH_SNAPDIR &&
                    ceph_ino(dentry->d_inode) != CEPH_INO_CEPH &&
                     dentry->d_name.len, dentry->d_name.name, di->offset,
                     filp->f_pos, d_unhashed(dentry) ? " unhashed" : "",
                     !dentry->d_inode ? " null" : "");
 +              spin_unlock(&dentry->d_lock);
                p = p->prev;
                dentry = list_entry(p, struct dentry, d_u.d_child);
                di = ceph_dentry(dentry);
        }
  
 -      atomic_inc(&dentry->d_count);
 -      spin_unlock(&dcache_lock);
 +      dget_dlock(dentry);
 +      spin_unlock(&dentry->d_lock);
 +      spin_unlock(&parent->d_lock);
  
        dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, filp->f_pos,
             dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
  
        filp->f_pos++;
  
 -      /* make sure a dentry wasn't dropped while we didn't have dcache_lock */
 +      /* make sure a dentry wasn't dropped while we didn't have parent lock */
        if (!ceph_i_test(dir, CEPH_I_COMPLETE)) {
                dout(" lost I_COMPLETE on %p; falling back to mds\n", dir);
                err = -EAGAIN;
                goto out;
        }
  
 -      spin_lock(&dcache_lock);
 +      spin_lock(&parent->d_lock);
        p = p->prev;    /* advance to next dentry */
        goto more;
  
  out_unlock:
 -      spin_unlock(&dcache_lock);
 +      spin_unlock(&parent->d_lock);
  out:
        if (last)
                dput(last);
@@@ -990,12 -988,7 +991,12 @@@ static int dir_lease_is_valid(struct in
   */
  static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd)
  {
 -      struct inode *dir = dentry->d_parent->d_inode;
 +      struct inode *dir;
 +
 +      if (nd->flags & LOOKUP_RCU)
 +              return -ECHILD;
 +
 +      dir = dentry->d_parent->d_inode;
  
        dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry,
             dentry->d_name.len, dentry->d_name.name, dentry->d_inode,
@@@ -1033,7 -1026,7 +1034,7 @@@ static void ceph_dentry_release(struct 
        u64 snapid = CEPH_NOSNAP;
  
        if (!IS_ROOT(dentry)) {
-               parent_inode = dentry->d_parent->d_inode;
+               parent_inode = di->parent_inode;
                if (parent_inode)
                        snapid = ceph_snap(parent_inode);
        }
                kmem_cache_free(ceph_dentry_cachep, di);
                dentry->d_fsdata = NULL;
        }
+       if (parent_inode)
+               iput(parent_inode);
  }
  
  static int ceph_snapdir_d_revalidate(struct dentry *dentry,
diff --combined fs/ceph/super.h
@@@ -207,6 -207,7 +207,7 @@@ struct ceph_dentry_info 
        struct dentry *dentry;
        u64 time;
        u64 offset;
+       struct inode *parent_inode;
  };
  
  struct ceph_inode_xattrs_info {
@@@ -666,7 -667,7 +667,7 @@@ extern void ceph_queue_invalidate(struc
  extern void ceph_queue_writeback(struct inode *inode);
  
  extern int ceph_do_getattr(struct inode *inode, int mask);
 -extern int ceph_permission(struct inode *inode, int mask);
 +extern int ceph_permission(struct inode *inode, int mask, unsigned int flags);
  extern int ceph_setattr(struct dentry *dentry, struct iattr *attr);
  extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry,
                        struct kstat *stat);