Kaynağa Gözat

vfs: default to generic_readlink()

If i_op->readlink is NULL, but i_op->get_link is set then vfs_readlink()
defaults to calling generic_readlink().

The IOP_DEFAULT_READLINK flag indicates that the above conditions are met
and the default action can be taken.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Miklos Szeredi 8 yıl önce
ebeveyn
işleme
76fca90e9f

+ 4 - 0
Documentation/filesystems/porting

@@ -596,3 +596,7 @@ in your dentry operations instead.
 [mandatory]
 [mandatory]
 	->rename() has an added flags argument.  Any flags not handled by the
 	->rename() has an added flags argument.  Any flags not handled by the
         filesystem should result in EINVAL being returned.
         filesystem should result in EINVAL being returned.
+--
+[recommended]
+	->readlink is optional for symlinks.  Don't set, unless filesystem needs
+	to fake something for readlink(2).

+ 6 - 3
Documentation/filesystems/vfs.txt

@@ -451,9 +451,6 @@ otherwise noted.
 	exist; this is checked by the VFS.  Unlike plain rename,
 	exist; this is checked by the VFS.  Unlike plain rename,
 	source and target may be of different type.
 	source and target may be of different type.
 
 
-  readlink: called by the readlink(2) system call. Only required if
-	you want to support reading symbolic links
-
   get_link: called by the VFS to follow a symbolic link to the
   get_link: called by the VFS to follow a symbolic link to the
 	inode it points to.  Only required if you want to support
 	inode it points to.  Only required if you want to support
 	symbolic links.  This method returns the symlink body
 	symbolic links.  This method returns the symlink body
@@ -468,6 +465,12 @@ otherwise noted.
 	argument.  If request can't be handled without leaving RCU mode,
 	argument.  If request can't be handled without leaving RCU mode,
 	have it return ERR_PTR(-ECHILD).
 	have it return ERR_PTR(-ECHILD).
 
 
+  readlink: this is now just an override for use by readlink(2) for the
+	cases when ->get_link uses nd_jump_link() or object is not in
+	fact a symlink.  Normally filesystems should only implement
+	->get_link for symlinks and readlink(2) will automatically use
+	that.
+
   permission: called by the VFS to check for access rights on a POSIX-like
   permission: called by the VFS to check for access rights on a POSIX-like
   	filesystem.
   	filesystem.
 
 

+ 12 - 3
fs/namei.c

@@ -4682,10 +4682,19 @@ int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
 {
 {
 	struct inode *inode = d_inode(dentry);
 	struct inode *inode = d_inode(dentry);
 
 
-	if (!inode->i_op->readlink)
-		return -EINVAL;
+	if (unlikely(!(inode->i_opflags & IOP_DEFAULT_READLINK))) {
+		if (unlikely(inode->i_op->readlink))
+			return inode->i_op->readlink(dentry, buffer, buflen);
+
+		if (!d_is_symlink(dentry))
+			return -EINVAL;
+
+		spin_lock(&inode->i_lock);
+		inode->i_opflags |= IOP_DEFAULT_READLINK;
+		spin_unlock(&inode->i_lock);
+	}
 
 
-	return inode->i_op->readlink(dentry, buffer, buflen);
+	return generic_readlink(dentry, buffer, buflen);
 }
 }
 EXPORT_SYMBOL(vfs_readlink);
 EXPORT_SYMBOL(vfs_readlink);
 
 

+ 1 - 0
include/linux/fs.h

@@ -595,6 +595,7 @@ is_uncached_acl(struct posix_acl *acl)
 #define IOP_LOOKUP	0x0002
 #define IOP_LOOKUP	0x0002
 #define IOP_NOFOLLOW	0x0004
 #define IOP_NOFOLLOW	0x0004
 #define IOP_XATTR	0x0008
 #define IOP_XATTR	0x0008
+#define IOP_DEFAULT_READLINK	0x0010
 
 
 /*
 /*
  * Keep mostly read-only and often accessed (especially for
  * Keep mostly read-only and often accessed (especially for