diff options
Diffstat (limited to 'fs/nfsd/nfsctl.c')
-rw-r--r-- | fs/nfsd/nfsctl.c | 19 |
1 files changed, 9 insertions, 10 deletions
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 13c548733860..3cf4f6aa48d6 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
@@ -1171,13 +1171,17 @@ static struct inode *nfsd_get_inode(struct super_block *sb, umode_t mode) | |||
1171 | return inode; | 1171 | return inode; |
1172 | } | 1172 | } |
1173 | 1173 | ||
1174 | static int __nfsd_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | 1174 | static int __nfsd_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode, struct nfsdfs_client *ncl) |
1175 | { | 1175 | { |
1176 | struct inode *inode; | 1176 | struct inode *inode; |
1177 | 1177 | ||
1178 | inode = nfsd_get_inode(dir->i_sb, mode); | 1178 | inode = nfsd_get_inode(dir->i_sb, mode); |
1179 | if (!inode) | 1179 | if (!inode) |
1180 | return -ENOMEM; | 1180 | return -ENOMEM; |
1181 | if (ncl) { | ||
1182 | inode->i_private = ncl; | ||
1183 | kref_get(&ncl->cl_ref); | ||
1184 | } | ||
1181 | d_add(dentry, inode); | 1185 | d_add(dentry, inode); |
1182 | inc_nlink(dir); | 1186 | inc_nlink(dir); |
1183 | fsnotify_mkdir(dir, dentry); | 1187 | fsnotify_mkdir(dir, dentry); |
@@ -1194,17 +1198,14 @@ static struct dentry *nfsd_mkdir(struct dentry *parent, struct nfsdfs_client *nc | |||
1194 | dentry = d_alloc_name(parent, name); | 1198 | dentry = d_alloc_name(parent, name); |
1195 | if (!dentry) | 1199 | if (!dentry) |
1196 | goto out_err; | 1200 | goto out_err; |
1197 | ret = __nfsd_mkdir(d_inode(parent), dentry, S_IFDIR | 0600); | 1201 | ret = __nfsd_mkdir(d_inode(parent), dentry, S_IFDIR | 0600, ncl); |
1198 | if (ret) | 1202 | if (ret) |
1199 | goto out_err; | 1203 | goto out_err; |
1200 | if (ncl) { | ||
1201 | d_inode(dentry)->i_private = ncl; | ||
1202 | kref_get(&ncl->cl_ref); | ||
1203 | } | ||
1204 | out: | 1204 | out: |
1205 | inode_unlock(dir); | 1205 | inode_unlock(dir); |
1206 | return dentry; | 1206 | return dentry; |
1207 | out_err: | 1207 | out_err: |
1208 | dput(dentry); | ||
1208 | dentry = ERR_PTR(ret); | 1209 | dentry = ERR_PTR(ret); |
1209 | goto out; | 1210 | goto out; |
1210 | } | 1211 | } |
@@ -1214,11 +1215,9 @@ static void clear_ncl(struct inode *inode) | |||
1214 | struct nfsdfs_client *ncl = inode->i_private; | 1215 | struct nfsdfs_client *ncl = inode->i_private; |
1215 | 1216 | ||
1216 | inode->i_private = NULL; | 1217 | inode->i_private = NULL; |
1217 | synchronize_rcu(); | ||
1218 | kref_put(&ncl->cl_ref, ncl->cl_release); | 1218 | kref_put(&ncl->cl_ref, ncl->cl_release); |
1219 | } | 1219 | } |
1220 | 1220 | ||
1221 | |||
1222 | static struct nfsdfs_client *__get_nfsdfs_client(struct inode *inode) | 1221 | static struct nfsdfs_client *__get_nfsdfs_client(struct inode *inode) |
1223 | { | 1222 | { |
1224 | struct nfsdfs_client *nc = inode->i_private; | 1223 | struct nfsdfs_client *nc = inode->i_private; |
@@ -1232,9 +1231,9 @@ struct nfsdfs_client *get_nfsdfs_client(struct inode *inode) | |||
1232 | { | 1231 | { |
1233 | struct nfsdfs_client *nc; | 1232 | struct nfsdfs_client *nc; |
1234 | 1233 | ||
1235 | rcu_read_lock(); | 1234 | inode_lock_shared(inode); |
1236 | nc = __get_nfsdfs_client(inode); | 1235 | nc = __get_nfsdfs_client(inode); |
1237 | rcu_read_unlock(); | 1236 | inode_unlock_shared(inode); |
1238 | return nc; | 1237 | return nc; |
1239 | } | 1238 | } |
1240 | /* from __rpc_unlink */ | 1239 | /* from __rpc_unlink */ |