aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exportfs/expfs.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 13:34:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 13:34:35 -0400
commit1193755ac6328ad240ba987e6ec41d5e8baf0680 (patch)
tree40bf847d7e3ebaa57b107151d14e6cd1d280cc6d /fs/exportfs/expfs.c
parent4edebed86690eb8db9af3ab85baf4a34e73266cc (diff)
parent0ef97dcfce4179a2eba046b855ee2f91d6f1b414 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs changes from Al Viro. "A lot of misc stuff. The obvious groups: * Miklos' atomic_open series; kills the damn abuse of ->d_revalidate() by NFS, which was the major stumbling block for all work in that area. * ripping security_file_mmap() and dealing with deadlocks in the area; sanitizing the neighborhood of vm_mmap()/vm_munmap() in general. * ->encode_fh() switched to saner API; insane fake dentry in mm/cleancache.c gone. * assorted annotations in fs (endianness, __user) * parts of Artem's ->s_dirty work (jff2 and reiserfs parts) * ->update_time() work from Josef. * other bits and pieces all over the place. Normally it would've been in two or three pull requests, but signal.git stuff had eaten a lot of time during this cycle ;-/" Fix up trivial conflicts in Documentation/filesystems/vfs.txt (the 'truncate_range' inode method was removed by the VM changes, the VFS update adds an 'update_time()' method), and in fs/btrfs/ulist.[ch] (due to sparse fix added twice, with other changes nearby). * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (95 commits) nfs: don't open in ->d_revalidate vfs: retry last component if opening stale dentry vfs: nameidata_to_filp(): don't throw away file on error vfs: nameidata_to_filp(): inline __dentry_open() vfs: do_dentry_open(): don't put filp vfs: split __dentry_open() vfs: do_last() common post lookup vfs: do_last(): add audit_inode before open vfs: do_last(): only return EISDIR for O_CREAT vfs: do_last(): check LOOKUP_DIRECTORY vfs: do_last(): make ENOENT exit RCU safe vfs: make follow_link check RCU safe vfs: do_last(): use inode variable vfs: do_last(): inline walk_component() vfs: do_last(): make exit RCU safe vfs: split do_lookup() Btrfs: move over to use ->update_time fs: introduce inode operation ->update_time reiserfs: get rid of resierfs_sync_super reiserfs: mark the superblock as dirty a bit later ...
Diffstat (limited to 'fs/exportfs/expfs.c')
-rw-r--r--fs/exportfs/expfs.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index b05acb796135..b0201ca6e9c6 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -304,24 +304,23 @@ out:
304 304
305/** 305/**
306 * export_encode_fh - default export_operations->encode_fh function 306 * export_encode_fh - default export_operations->encode_fh function
307 * @dentry: the dentry to encode 307 * @inode: the object to encode
308 * @fh: where to store the file handle fragment 308 * @fh: where to store the file handle fragment
309 * @max_len: maximum length to store there 309 * @max_len: maximum length to store there
310 * @connectable: whether to store parent information 310 * @parent: parent directory inode, if wanted
311 * 311 *
312 * This default encode_fh function assumes that the 32 inode number 312 * This default encode_fh function assumes that the 32 inode number
313 * is suitable for locating an inode, and that the generation number 313 * is suitable for locating an inode, and that the generation number
314 * can be used to check that it is still valid. It places them in the 314 * can be used to check that it is still valid. It places them in the
315 * filehandle fragment where export_decode_fh expects to find them. 315 * filehandle fragment where export_decode_fh expects to find them.
316 */ 316 */
317static int export_encode_fh(struct dentry *dentry, struct fid *fid, 317static int export_encode_fh(struct inode *inode, struct fid *fid,
318 int *max_len, int connectable) 318 int *max_len, struct inode *parent)
319{ 319{
320 struct inode * inode = dentry->d_inode;
321 int len = *max_len; 320 int len = *max_len;
322 int type = FILEID_INO32_GEN; 321 int type = FILEID_INO32_GEN;
323 322
324 if (connectable && (len < 4)) { 323 if (parent && (len < 4)) {
325 *max_len = 4; 324 *max_len = 4;
326 return 255; 325 return 255;
327 } else if (len < 2) { 326 } else if (len < 2) {
@@ -332,14 +331,9 @@ static int export_encode_fh(struct dentry *dentry, struct fid *fid,
332 len = 2; 331 len = 2;
333 fid->i32.ino = inode->i_ino; 332 fid->i32.ino = inode->i_ino;
334 fid->i32.gen = inode->i_generation; 333 fid->i32.gen = inode->i_generation;
335 if (connectable && !S_ISDIR(inode->i_mode)) { 334 if (parent) {
336 struct inode *parent;
337
338 spin_lock(&dentry->d_lock);
339 parent = dentry->d_parent->d_inode;
340 fid->i32.parent_ino = parent->i_ino; 335 fid->i32.parent_ino = parent->i_ino;
341 fid->i32.parent_gen = parent->i_generation; 336 fid->i32.parent_gen = parent->i_generation;
342 spin_unlock(&dentry->d_lock);
343 len = 4; 337 len = 4;
344 type = FILEID_INO32_GEN_PARENT; 338 type = FILEID_INO32_GEN_PARENT;
345 } 339 }
@@ -352,11 +346,22 @@ int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len,
352{ 346{
353 const struct export_operations *nop = dentry->d_sb->s_export_op; 347 const struct export_operations *nop = dentry->d_sb->s_export_op;
354 int error; 348 int error;
349 struct dentry *p = NULL;
350 struct inode *inode = dentry->d_inode, *parent = NULL;
355 351
352 if (connectable && !S_ISDIR(inode->i_mode)) {
353 p = dget_parent(dentry);
354 /*
355 * note that while p might've ceased to be our parent already,
356 * it's still pinned by and still positive.
357 */
358 parent = p->d_inode;
359 }
356 if (nop->encode_fh) 360 if (nop->encode_fh)
357 error = nop->encode_fh(dentry, fid->raw, max_len, connectable); 361 error = nop->encode_fh(inode, fid->raw, max_len, parent);
358 else 362 else
359 error = export_encode_fh(dentry, fid, max_len, connectable); 363 error = export_encode_fh(inode, fid, max_len, parent);
364 dput(p);
360 365
361 return error; 366 return error;
362} 367}