aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-29 15:30:13 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-29 15:30:13 -0400
commitb78b6b3a9af239549ea863e085223d1d4f65a608 (patch)
treefb55713cba98edd270df2c54a7590a2be7e1be10 /fs/fuse
parent7f4708abf16ae48e58a9190898253bc7c94a30c1 (diff)
parent5ae90d8e467e625e447000cb4335c4db973b1095 (diff)
Merge 3.11-rc3 into driver-core-next
We want these fixes in this branch. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dir.c51
1 files changed, 36 insertions, 15 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 0eda52738ec4..72a5d5b04494 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1223,30 +1223,46 @@ static int fuse_direntplus_link(struct file *file,
1223 if (name.name[1] == '.' && name.len == 2) 1223 if (name.name[1] == '.' && name.len == 2)
1224 return 0; 1224 return 0;
1225 } 1225 }
1226
1227 if (invalid_nodeid(o->nodeid))
1228 return -EIO;
1229 if (!fuse_valid_type(o->attr.mode))
1230 return -EIO;
1231
1226 fc = get_fuse_conn(dir); 1232 fc = get_fuse_conn(dir);
1227 1233
1228 name.hash = full_name_hash(name.name, name.len); 1234 name.hash = full_name_hash(name.name, name.len);
1229 dentry = d_lookup(parent, &name); 1235 dentry = d_lookup(parent, &name);
1230 if (dentry && dentry->d_inode) { 1236 if (dentry) {
1231 inode = dentry->d_inode; 1237 inode = dentry->d_inode;
1232 if (get_node_id(inode) == o->nodeid) { 1238 if (!inode) {
1239 d_drop(dentry);
1240 } else if (get_node_id(inode) != o->nodeid ||
1241 ((o->attr.mode ^ inode->i_mode) & S_IFMT)) {
1242 err = d_invalidate(dentry);
1243 if (err)
1244 goto out;
1245 } else if (is_bad_inode(inode)) {
1246 err = -EIO;
1247 goto out;
1248 } else {
1233 struct fuse_inode *fi; 1249 struct fuse_inode *fi;
1234 fi = get_fuse_inode(inode); 1250 fi = get_fuse_inode(inode);
1235 spin_lock(&fc->lock); 1251 spin_lock(&fc->lock);
1236 fi->nlookup++; 1252 fi->nlookup++;
1237 spin_unlock(&fc->lock); 1253 spin_unlock(&fc->lock);
1238 1254
1255 fuse_change_attributes(inode, &o->attr,
1256 entry_attr_timeout(o),
1257 attr_version);
1258
1239 /* 1259 /*
1240 * The other branch to 'found' comes via fuse_iget() 1260 * The other branch to 'found' comes via fuse_iget()
1241 * which bumps nlookup inside 1261 * which bumps nlookup inside
1242 */ 1262 */
1243 goto found; 1263 goto found;
1244 } 1264 }
1245 err = d_invalidate(dentry);
1246 if (err)
1247 goto out;
1248 dput(dentry); 1265 dput(dentry);
1249 dentry = NULL;
1250 } 1266 }
1251 1267
1252 dentry = d_alloc(parent, &name); 1268 dentry = d_alloc(parent, &name);
@@ -1259,25 +1275,30 @@ static int fuse_direntplus_link(struct file *file,
1259 if (!inode) 1275 if (!inode)
1260 goto out; 1276 goto out;
1261 1277
1262 alias = d_materialise_unique(dentry, inode); 1278 if (S_ISDIR(inode->i_mode)) {
1263 err = PTR_ERR(alias); 1279 mutex_lock(&fc->inst_mutex);
1264 if (IS_ERR(alias)) 1280 alias = fuse_d_add_directory(dentry, inode);
1265 goto out; 1281 mutex_unlock(&fc->inst_mutex);
1282 err = PTR_ERR(alias);
1283 if (IS_ERR(alias)) {
1284 iput(inode);
1285 goto out;
1286 }
1287 } else {
1288 alias = d_splice_alias(inode, dentry);
1289 }
1290
1266 if (alias) { 1291 if (alias) {
1267 dput(dentry); 1292 dput(dentry);
1268 dentry = alias; 1293 dentry = alias;
1269 } 1294 }
1270 1295
1271found: 1296found:
1272 fuse_change_attributes(inode, &o->attr, entry_attr_timeout(o),
1273 attr_version);
1274
1275 fuse_change_entry_timeout(dentry, o); 1297 fuse_change_entry_timeout(dentry, o);
1276 1298
1277 err = 0; 1299 err = 0;
1278out: 1300out:
1279 if (dentry) 1301 dput(dentry);
1280 dput(dentry);
1281 return err; 1302 return err;
1282} 1303}
1283 1304