0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/fs.h>
0009 #include <linux/namei.h>
0010 #include <linux/dns_resolver.h>
0011 #include "internal.h"
0012
0013 static atomic_t afs_autocell_ino;
0014
0015
0016
0017
0018
0019
0020 static int afs_iget5_pseudo_test(struct inode *inode, void *opaque)
0021 {
0022 return 0;
0023 }
0024
0025
0026
0027
0028 static int afs_iget5_pseudo_set(struct inode *inode, void *opaque)
0029 {
0030 struct afs_super_info *as = AFS_FS_S(inode->i_sb);
0031 struct afs_vnode *vnode = AFS_FS_I(inode);
0032 struct afs_fid *fid = opaque;
0033
0034 vnode->volume = as->volume;
0035 vnode->fid = *fid;
0036 inode->i_ino = fid->vnode;
0037 inode->i_generation = fid->unique;
0038 return 0;
0039 }
0040
0041
0042
0043
0044
0045 struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root)
0046 {
0047 struct afs_super_info *as = AFS_FS_S(sb);
0048 struct afs_vnode *vnode;
0049 struct inode *inode;
0050 struct afs_fid fid = {};
0051
0052 _enter("");
0053
0054 if (as->volume)
0055 fid.vid = as->volume->vid;
0056 if (root) {
0057 fid.vnode = 1;
0058 fid.unique = 1;
0059 } else {
0060 fid.vnode = atomic_inc_return(&afs_autocell_ino);
0061 fid.unique = 0;
0062 }
0063
0064 inode = iget5_locked(sb, fid.vnode,
0065 afs_iget5_pseudo_test, afs_iget5_pseudo_set, &fid);
0066 if (!inode) {
0067 _leave(" = -ENOMEM");
0068 return ERR_PTR(-ENOMEM);
0069 }
0070
0071 _debug("GOT INODE %p { ino=%lu, vl=%llx, vn=%llx, u=%x }",
0072 inode, inode->i_ino, fid.vid, fid.vnode, fid.unique);
0073
0074 vnode = AFS_FS_I(inode);
0075
0076
0077 BUG_ON(!(inode->i_state & I_NEW));
0078
0079 netfs_inode_init(&vnode->netfs, NULL);
0080 inode->i_size = 0;
0081 inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
0082 if (root) {
0083 inode->i_op = &afs_dynroot_inode_operations;
0084 inode->i_fop = &simple_dir_operations;
0085 } else {
0086 inode->i_op = &afs_autocell_inode_operations;
0087 }
0088 set_nlink(inode, 2);
0089 inode->i_uid = GLOBAL_ROOT_UID;
0090 inode->i_gid = GLOBAL_ROOT_GID;
0091 inode->i_ctime = inode->i_atime = inode->i_mtime = current_time(inode);
0092 inode->i_blocks = 0;
0093 inode->i_generation = 0;
0094
0095 set_bit(AFS_VNODE_PSEUDODIR, &vnode->flags);
0096 if (!root) {
0097 set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags);
0098 inode->i_flags |= S_AUTOMOUNT;
0099 }
0100
0101 inode->i_flags |= S_NOATIME;
0102 unlock_new_inode(inode);
0103 _leave(" = %p", inode);
0104 return inode;
0105 }
0106
0107
0108
0109
0110
0111 static int afs_probe_cell_name(struct dentry *dentry)
0112 {
0113 struct afs_cell *cell;
0114 struct afs_net *net = afs_d2net(dentry);
0115 const char *name = dentry->d_name.name;
0116 size_t len = dentry->d_name.len;
0117 int ret;
0118
0119
0120 if (name[0] == '.') {
0121 if (len == 1)
0122 return -EINVAL;
0123 name++;
0124 len--;
0125 }
0126
0127 cell = afs_find_cell(net, name, len, afs_cell_trace_use_probe);
0128 if (!IS_ERR(cell)) {
0129 afs_unuse_cell(net, cell, afs_cell_trace_unuse_probe);
0130 return 0;
0131 }
0132
0133 ret = dns_query(net->net, "afsdb", name, len, "srv=1",
0134 NULL, NULL, false);
0135 if (ret == -ENODATA)
0136 ret = -EDESTADDRREQ;
0137 return ret;
0138 }
0139
0140
0141
0142
0143
0144 struct inode *afs_try_auto_mntpt(struct dentry *dentry, struct inode *dir)
0145 {
0146 struct afs_vnode *vnode = AFS_FS_I(dir);
0147 struct inode *inode;
0148 int ret = -ENOENT;
0149
0150 _enter("%p{%pd}, {%llx:%llu}",
0151 dentry, dentry, vnode->fid.vid, vnode->fid.vnode);
0152
0153 if (!test_bit(AFS_VNODE_AUTOCELL, &vnode->flags))
0154 goto out;
0155
0156 ret = afs_probe_cell_name(dentry);
0157 if (ret < 0)
0158 goto out;
0159
0160 inode = afs_iget_pseudo_dir(dir->i_sb, false);
0161 if (IS_ERR(inode)) {
0162 ret = PTR_ERR(inode);
0163 goto out;
0164 }
0165
0166 _leave("= %p", inode);
0167 return inode;
0168
0169 out:
0170 _leave("= %d", ret);
0171 return ret == -ENOENT ? NULL : ERR_PTR(ret);
0172 }
0173
0174
0175
0176
0177
0178 static struct dentry *afs_lookup_atcell(struct dentry *dentry)
0179 {
0180 struct afs_cell *cell;
0181 struct afs_net *net = afs_d2net(dentry);
0182 struct dentry *ret;
0183 char *name;
0184 int len;
0185
0186 if (!net->ws_cell)
0187 return ERR_PTR(-ENOENT);
0188
0189 ret = ERR_PTR(-ENOMEM);
0190 name = kmalloc(AFS_MAXCELLNAME + 1, GFP_KERNEL);
0191 if (!name)
0192 goto out_p;
0193
0194 down_read(&net->cells_lock);
0195 cell = net->ws_cell;
0196 if (cell) {
0197 len = cell->name_len;
0198 memcpy(name, cell->name, len + 1);
0199 }
0200 up_read(&net->cells_lock);
0201
0202 ret = ERR_PTR(-ENOENT);
0203 if (!cell)
0204 goto out_n;
0205
0206 ret = lookup_one_len(name, dentry->d_parent, len);
0207
0208
0209
0210
0211
0212 out_n:
0213 kfree(name);
0214 out_p:
0215 return ret;
0216 }
0217
0218
0219
0220
0221 static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentry,
0222 unsigned int flags)
0223 {
0224 _enter("%pd", dentry);
0225
0226 ASSERTCMP(d_inode(dentry), ==, NULL);
0227
0228 if (flags & LOOKUP_CREATE)
0229 return ERR_PTR(-EOPNOTSUPP);
0230
0231 if (dentry->d_name.len >= AFSNAMEMAX) {
0232 _leave(" = -ENAMETOOLONG");
0233 return ERR_PTR(-ENAMETOOLONG);
0234 }
0235
0236 if (dentry->d_name.len == 5 &&
0237 memcmp(dentry->d_name.name, "@cell", 5) == 0)
0238 return afs_lookup_atcell(dentry);
0239
0240 return d_splice_alias(afs_try_auto_mntpt(dentry, dir), dentry);
0241 }
0242
0243 const struct inode_operations afs_dynroot_inode_operations = {
0244 .lookup = afs_dynroot_lookup,
0245 };
0246
0247
0248
0249
0250 static int afs_dynroot_d_revalidate(struct dentry *dentry, unsigned int flags)
0251 {
0252 return 1;
0253 }
0254
0255
0256
0257
0258
0259
0260
0261 static int afs_dynroot_d_delete(const struct dentry *dentry)
0262 {
0263 return d_really_is_positive(dentry);
0264 }
0265
0266 const struct dentry_operations afs_dynroot_dentry_operations = {
0267 .d_revalidate = afs_dynroot_d_revalidate,
0268 .d_delete = afs_dynroot_d_delete,
0269 .d_release = afs_d_release,
0270 .d_automount = afs_d_automount,
0271 };
0272
0273
0274
0275
0276
0277 int afs_dynroot_mkdir(struct afs_net *net, struct afs_cell *cell)
0278 {
0279 struct super_block *sb = net->dynroot_sb;
0280 struct dentry *root, *subdir;
0281 int ret;
0282
0283 if (!sb || atomic_read(&sb->s_active) == 0)
0284 return 0;
0285
0286
0287 root = sb->s_root;
0288 inode_lock(root->d_inode);
0289 subdir = lookup_one_len(cell->name, root, cell->name_len);
0290 if (IS_ERR(subdir)) {
0291 ret = PTR_ERR(subdir);
0292 goto unlock;
0293 }
0294
0295
0296 subdir->d_fsdata = (void *)1UL;
0297 ret = 0;
0298 unlock:
0299 inode_unlock(root->d_inode);
0300 return ret;
0301 }
0302
0303
0304
0305
0306
0307 void afs_dynroot_rmdir(struct afs_net *net, struct afs_cell *cell)
0308 {
0309 struct super_block *sb = net->dynroot_sb;
0310 struct dentry *root, *subdir;
0311
0312 if (!sb || atomic_read(&sb->s_active) == 0)
0313 return;
0314
0315 root = sb->s_root;
0316 inode_lock(root->d_inode);
0317
0318
0319 subdir = try_lookup_one_len(cell->name, root, cell->name_len);
0320 if (IS_ERR_OR_NULL(subdir)) {
0321 _debug("lookup %ld", PTR_ERR(subdir));
0322 goto no_dentry;
0323 }
0324
0325 _debug("rmdir %pd %u", subdir, d_count(subdir));
0326
0327 if (subdir->d_fsdata) {
0328 _debug("unpin %u", d_count(subdir));
0329 subdir->d_fsdata = NULL;
0330 dput(subdir);
0331 }
0332 dput(subdir);
0333 no_dentry:
0334 inode_unlock(root->d_inode);
0335 _leave("");
0336 }
0337
0338
0339
0340
0341 int afs_dynroot_populate(struct super_block *sb)
0342 {
0343 struct afs_cell *cell;
0344 struct afs_net *net = afs_sb2net(sb);
0345 int ret;
0346
0347 mutex_lock(&net->proc_cells_lock);
0348
0349 net->dynroot_sb = sb;
0350 hlist_for_each_entry(cell, &net->proc_cells, proc_link) {
0351 ret = afs_dynroot_mkdir(net, cell);
0352 if (ret < 0)
0353 goto error;
0354 }
0355
0356 ret = 0;
0357 out:
0358 mutex_unlock(&net->proc_cells_lock);
0359 return ret;
0360
0361 error:
0362 net->dynroot_sb = NULL;
0363 goto out;
0364 }
0365
0366
0367
0368
0369
0370 void afs_dynroot_depopulate(struct super_block *sb)
0371 {
0372 struct afs_net *net = afs_sb2net(sb);
0373 struct dentry *root = sb->s_root, *subdir, *tmp;
0374
0375
0376 mutex_lock(&net->proc_cells_lock);
0377 if (net->dynroot_sb == sb)
0378 net->dynroot_sb = NULL;
0379 mutex_unlock(&net->proc_cells_lock);
0380
0381 if (root) {
0382 inode_lock(root->d_inode);
0383
0384
0385 list_for_each_entry_safe(subdir, tmp, &root->d_subdirs, d_child) {
0386 if (subdir->d_fsdata) {
0387 subdir->d_fsdata = NULL;
0388 dput(subdir);
0389 }
0390 }
0391
0392 inode_unlock(root->d_inode);
0393 }
0394 }