Skip to content

Commit

Permalink
Merge branch 'for-linus-1' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/viro/vfs

Pull vfs updates from Al Viro:
 "In this pile: pathname resolution rewrite.

   - recursion in link_path_walk() is gone.

   - nesting limits on symlinks are gone (the only limit remaining is
     that the total amount of symlinks is no more than 40, no matter how
     nested).

   - "fast" (inline) symlinks are handled without leaving rcuwalk mode.

   - stack footprint (independent of the nesting) is below kilobyte now,
     about on par with what it used to be with one level of nested
     symlinks and ~2.8 times lower than it used to be in the worst case.

   - struct nameidata is entirely private to fs/namei.c now (not even
     opaque pointers are being passed around).

   - ->follow_link() and ->put_link() calling conventions had been
     changed; all in-tree filesystems converted, out-of-tree should be
     able to follow reasonably easily.

     For out-of-tree conversions, see Documentation/filesystems/porting
     for details (and in-tree filesystems for examples of conversion).

  That has sat in -next since mid-May, seems to survive all testing
  without regressions and merges clean with v4.1"

* 'for-linus-1' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (131 commits)
  turn user_{path_at,path,lpath,path_dir}() into static inlines
  namei: move saved_nd pointer into struct nameidata
  inline user_path_create()
  inline user_path_parent()
  namei: trim do_last() arguments
  namei: stash dfd and name into nameidata
  namei: fold path_cleanup() into terminate_walk()
  namei: saner calling conventions for filename_parentat()
  namei: saner calling conventions for filename_create()
  namei: shift nameidata down into filename_parentat()
  namei: make filename_lookup() reject ERR_PTR() passed as name
  namei: shift nameidata inside filename_lookup()
  namei: move putname() call into filename_lookup()
  namei: pass the struct path to store the result down into path_lookupat()
  namei: uninline set_root{,_rcu}()
  namei: be careful with mountpoint crossings in follow_dotdot_rcu()
  Documentation: remove outdated information from automount-support.txt
  get rid of assorted nameidata-related debris
  lustre: kill unused helper
  lustre: kill unused macro (LOOKUP_CONTINUE)
  ...
  • Loading branch information
torvalds committed Jun 22, 2015
2 parents b953c0d + b853a16 commit 052b398
Show file tree
Hide file tree
Showing 86 changed files with 1,222 additions and 1,522 deletions.
4 changes: 2 additions & 2 deletions Documentation/filesystems/Locking
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ prototypes:
int (*rename2) (struct inode *, struct dentry *,
struct inode *, struct dentry *, unsigned int);
int (*readlink) (struct dentry *, char __user *,int);
void * (*follow_link) (struct dentry *, struct nameidata *);
void (*put_link) (struct dentry *, struct nameidata *, void *);
const char *(*follow_link) (struct dentry *, void **);
void (*put_link) (struct inode *, void *);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int, unsigned int);
int (*get_acl)(struct inode *, int);
Expand Down
51 changes: 13 additions & 38 deletions Documentation/filesystems/automount-support.txt
Original file line number Diff line number Diff line change
@@ -1,41 +1,15 @@
Support is available for filesystems that wish to do automounting support (such
as kAFS which can be found in fs/afs/). This facility includes allowing
in-kernel mounts to be performed and mountpoint degradation to be
requested. The latter can also be requested by userspace.
Support is available for filesystems that wish to do automounting
support (such as kAFS which can be found in fs/afs/ and NFS in
fs/nfs/). This facility includes allowing in-kernel mounts to be
performed and mountpoint degradation to be requested. The latter can
also be requested by userspace.


======================
IN-KERNEL AUTOMOUNTING
======================

A filesystem can now mount another filesystem on one of its directories by the
following procedure:

(1) Give the directory a follow_link() operation.

When the directory is accessed, the follow_link op will be called, and
it will be provided with the location of the mountpoint in the nameidata
structure (vfsmount and dentry).

(2) Have the follow_link() op do the following steps:

(a) Call vfs_kern_mount() to call the appropriate filesystem to set up a
superblock and gain a vfsmount structure representing it.

(b) Copy the nameidata provided as an argument and substitute the dentry
argument into it the copy.

(c) Call do_add_mount() to install the new vfsmount into the namespace's
mountpoint tree, thus making it accessible to userspace. Use the
nameidata set up in (b) as the destination.

If the mountpoint will be automatically expired, then do_add_mount()
should also be given the location of an expiration list (see further
down).

(d) Release the path in the nameidata argument and substitute in the new
vfsmount and its root dentry. The ref counts on these will need
incrementing.
See section "Mount Traps" of Documentation/filesystems/autofs4.txt

Then from userspace, you can just do something like:

Expand All @@ -61,17 +35,18 @@ AUTOMATIC MOUNTPOINT EXPIRY
===========================

Automatic expiration of mountpoints is easy, provided you've mounted the
mountpoint to be expired in the automounting procedure outlined above.
mountpoint to be expired in the automounting procedure outlined separately.

To do expiration, you need to follow these steps:

(3) Create at least one list off which the vfsmounts to be expired can be
hung. Access to this list will be governed by the vfsmount_lock.
(1) Create at least one list off which the vfsmounts to be expired can be
hung.

(4) In step (2c) above, the call to do_add_mount() should be provided with a
pointer to this list. It will hang the vfsmount off of it if it succeeds.
(2) When a new mountpoint is created in the ->d_automount method, add
the mnt to the list using mnt_set_expiry()
mnt_set_expiry(newmnt, &afs_vfsmounts);

(5) When you want mountpoints to be expired, call mark_mounts_for_expiry()
(3) When you want mountpoints to be expired, call mark_mounts_for_expiry()
with a pointer to this list. This will process the list, marking every
vfsmount thereon for potential expiry on the next call.

Expand Down
17 changes: 17 additions & 0 deletions Documentation/filesystems/porting
Original file line number Diff line number Diff line change
Expand Up @@ -483,3 +483,20 @@ in your dentry operations instead.
--
[mandatory]
->aio_read/->aio_write are gone. Use ->read_iter/->write_iter.
---
[recommended]
for embedded ("fast") symlinks just set inode->i_link to wherever the
symlink body is and use simple_follow_link() as ->follow_link().
--
[mandatory]
calling conventions for ->follow_link() have changed. Instead of returning
cookie and using nd_set_link() to store the body to traverse, we return
the body to traverse and store the cookie using explicit void ** argument.
nameidata isn't passed at all - nd_jump_link() doesn't need it and
nd_[gs]et_link() is gone.
--
[mandatory]
calling conventions for ->put_link() have changed. It gets inode instead of
dentry, it does not get nameidata at all and it gets called only when cookie
is non-NULL. Note that link body isn't available anymore, so if you need it,
store it as cookie.
22 changes: 12 additions & 10 deletions Documentation/filesystems/vfs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,8 @@ struct inode_operations {
int (*rename2) (struct inode *, struct dentry *,
struct inode *, struct dentry *, unsigned int);
int (*readlink) (struct dentry *, char __user *,int);
void * (*follow_link) (struct dentry *, struct nameidata *);
void (*put_link) (struct dentry *, struct nameidata *, void *);
const char *(*follow_link) (struct dentry *, void **);
void (*put_link) (struct inode *, void *);
int (*permission) (struct inode *, int);
int (*get_acl)(struct inode *, int);
int (*setattr) (struct dentry *, struct iattr *);
Expand Down Expand Up @@ -436,16 +436,18 @@ otherwise noted.

follow_link: called by the VFS to follow a symbolic link to the
inode it points to. Only required if you want to support
symbolic links. This method returns a void pointer cookie
that is passed to put_link().
symbolic links. This method returns the symlink body
to traverse (and possibly resets the current position with
nd_jump_link()). If the body won't go away until the inode
is gone, nothing else is needed; if it needs to be otherwise
pinned, the data needed to release whatever we'd grabbed
is to be stored in void * variable passed by address to
follow_link() instance.

put_link: called by the VFS to release resources allocated by
follow_link(). The cookie returned by follow_link() is passed
to this method as the last parameter. It is used by
filesystems such as NFS where page cache is not stable
(i.e. page that was installed when the symbolic link walk
started might not be in the page cache at the end of the
walk).
follow_link(). The cookie stored by follow_link() is passed
to this method as the last parameter; only called when
cookie isn't NULL.

permission: called by the VFS to check for access rights on a POSIX-like
filesystem.
Expand Down
15 changes: 0 additions & 15 deletions drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,22 +189,7 @@ static inline int ll_quota_off(struct super_block *sb, int off, int remount)
#endif



/*
* After 3.1, kernel's nameidata.intent.open.flags is different
* with lustre's lookup_intent.it_flags, as lustre's it_flags'
* lower bits equal to FMODE_xxx while kernel doesn't transliterate
* lower bits of nameidata.intent.open.flags to FMODE_xxx.
* */
#include <linux/version.h>
static inline int ll_namei_to_lookup_intent_flag(int flag)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
flag = (flag & ~O_ACCMODE) | OPEN_FMODE(flag);
#endif
return flag;
}

#include <linux/fs.h>

# define ll_umode_t umode_t
Expand Down
6 changes: 0 additions & 6 deletions drivers/staging/lustre/lustre/llite/llite_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,6 @@
#define VM_FAULT_RETRY 0
#endif

/* Kernel 3.1 kills LOOKUP_CONTINUE, LOOKUP_PARENT is equivalent to it.
* seem kernel commit 49084c3bb2055c401f3493c13edae14d49128ca0 */
#ifndef LOOKUP_CONTINUE
#define LOOKUP_CONTINUE LOOKUP_PARENT
#endif

/** Only used on client-side for indicating the tail of dir hash/offset. */
#define LL_DIR_END_OFF 0x7fffffffffffffffULL
#define LL_DIR_END_OFF_32BIT 0x7fffffffUL
Expand Down
26 changes: 8 additions & 18 deletions drivers/staging/lustre/lustre/llite/symlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,40 +118,30 @@ static int ll_readlink_internal(struct inode *inode,
return rc;
}

static void *ll_follow_link(struct dentry *dentry, struct nameidata *nd)
static const char *ll_follow_link(struct dentry *dentry, void **cookie)
{
struct inode *inode = d_inode(dentry);
struct ptlrpc_request *request = NULL;
int rc;
char *symname = NULL;

CDEBUG(D_VFSTRACE, "VFS Op\n");
/* Limit the recursive symlink depth to 5 instead of default
* 8 links when kernel has 4k stack to prevent stack overflow.
* For 8k stacks we need to limit it to 7 for local servers. */
if (THREAD_SIZE < 8192 && current->link_count >= 6) {
rc = -ELOOP;
} else if (THREAD_SIZE == 8192 && current->link_count >= 8) {
rc = -ELOOP;
} else {
ll_inode_size_lock(inode);
rc = ll_readlink_internal(inode, &request, &symname);
ll_inode_size_unlock(inode);
}
ll_inode_size_lock(inode);
rc = ll_readlink_internal(inode, &request, &symname);
ll_inode_size_unlock(inode);
if (rc) {
ptlrpc_req_finished(request);
request = NULL;
symname = ERR_PTR(rc);
return ERR_PTR(rc);
}

nd_set_link(nd, symname);
/* symname may contain a pointer to the request message buffer,
* we delay request releasing until ll_put_link then.
*/
return request;
*cookie = request;
return symname;
}

static void ll_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
static void ll_put_link(struct inode *unused, void *cookie)
{
ptlrpc_req_finished(cookie);
}
Expand Down
2 changes: 0 additions & 2 deletions fs/9p/v9fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,6 @@ extern int v9fs_vfs_unlink(struct inode *i, struct dentry *d);
extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d);
extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
extern void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd,
void *p);
extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses,
struct p9_fid *fid,
struct super_block *sb, int new);
Expand Down
Loading

0 comments on commit 052b398

Please sign in to comment.