@@ -66,5 +66,15 @@ struct cifs_sb_info {
struct backing_dev_info bdi;
struct delayed_work prune_tlinks;
struct rcu_head rcu;
+ struct list_head rtdislist; /* list of disconnected root dentries */
+ spinlock_t rtdislock; /* lock for disconnected root dentry list */
+};
+
+struct cifs_rdelem {
+ int rdcount;
+ struct list_head rdlist;
+ char * rdname;
+ struct dentry * rdentry;
+ struct inode * rdinode;
};
#endif /* _CIFS_FS_SB_H */
@@ -570,6 +570,38 @@ static const struct super_operations cifs_super_ops = {
#endif
};
+void
+cifs_free_rdelem(struct cifs_rdelem *rdelem)
+{
+ kfree(rdelem->rdname);
+ kfree(rdelem);
+}
+
+struct cifs_rdelem *
+cifs_alloc_rdelem(char *full_path, struct dentry *rdentry,
+ struct inode *rdinode)
+{
+ struct cifs_rdelem *rdelem;
+
+ rdelem = kmalloc(sizeof(struct cifs_rdelem), GFP_KERNEL);
+ if (!rdelem) {
+ cifs_dbg(FYI, "%s Can't allocate root dentry\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ rdelem->rdname = kstrdup(full_path, GFP_KERNEL);
+ if (!rdelem->rdname) {
+ cifs_dbg(FYI, "%s Can't allocate root dentry name\n", __func__);
+ kfree(rdelem);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ rdelem->rdinode = rdinode;
+ rdelem->rdentry = rdentry;
+
+ return rdelem;
+}
+
/*
* Get root dentry from superblock according to prefix path mount option.
* Return dentry with refcount + 1 on success and NULL otherwise.
@@ -3171,6 +3171,9 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
spin_lock_init(&cifs_sb->tlink_tree_lock);
cifs_sb->tlink_tree = RB_ROOT;
+ spin_lock_init(&cifs_sb->rtdislock);
+ INIT_LIST_HEAD(&cifs_sb->rtdislist);
+
/*
* Temporarily set r/wsize for matching superblock. If we end up using
* new sb then client will later negotiate it downward if needed.