Switch gfs2 to nd_set_link()
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 14 Jan 2010 05:59:16 +0000 (00:59 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 3 Mar 2010 18:00:22 +0000 (13:00 -0500)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/gfs2/ops_inode.c

index 84350e1..4e64352 100644 (file)
@@ -976,122 +976,62 @@ out:
 }
 
 /**
- * gfs2_readlinki - return the contents of a symlink
- * @ip: the symlink's inode
- * @buf: a pointer to the buffer to be filled
- * @len: a pointer to the length of @buf
+ * gfs2_follow_link - Follow a symbolic link
+ * @dentry: The dentry of the link
+ * @nd: Data that we pass to vfs_follow_link()
  *
- * If @buf is too small, a piece of memory is kmalloc()ed and needs
- * to be freed by the caller.
+ * This can handle symlinks of any size.
  *
- * Returns: errno
+ * Returns: 0 on success or error code
  */
 
-static int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len)
+static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
+       struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
        struct gfs2_holder i_gh;
        struct buffer_head *dibh;
        unsigned int x;
+       char *buf;
        int error;
 
        gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
        error = gfs2_glock_nq(&i_gh);
        if (error) {
                gfs2_holder_uninit(&i_gh);
-               return error;
+               nd_set_link(nd, ERR_PTR(error));
+               return NULL;
        }
 
        if (!ip->i_disksize) {
                gfs2_consist_inode(ip);
-               error = -EIO;
+               buf = ERR_PTR(-EIO);
                goto out;
        }
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
-       if (error)
+       if (error) {
+               buf = ERR_PTR(error);
                goto out;
-
-       x = ip->i_disksize + 1;
-       if (x > *len) {
-               *buf = kmalloc(x, GFP_NOFS);
-               if (!*buf) {
-                       error = -ENOMEM;
-                       goto out_brelse;
-               }
        }
 
-       memcpy(*buf, dibh->b_data + sizeof(struct gfs2_dinode), x);
-       *len = x;
-
-out_brelse:
+       x = ip->i_disksize + 1;
+       buf = kmalloc(x, GFP_NOFS);
+       if (!buf)
+               buf = ERR_PTR(-ENOMEM);
+       else
+               memcpy(buf, dibh->b_data + sizeof(struct gfs2_dinode), x);
        brelse(dibh);
 out:
        gfs2_glock_dq_uninit(&i_gh);
-       return error;
-}
-
-/**
- * gfs2_readlink - Read the value of a symlink
- * @dentry: the symlink
- * @buf: the buffer to read the symlink data into
- * @size: the size of the buffer
- *
- * Returns: errno
- */
-
-static int gfs2_readlink(struct dentry *dentry, char __user *user_buf,
-                        int user_size)
-{
-       struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
-       char array[GFS2_FAST_NAME_SIZE], *buf = array;
-       unsigned int len = GFS2_FAST_NAME_SIZE;
-       int error;
-
-       error = gfs2_readlinki(ip, &buf, &len);
-       if (error)
-               return error;
-
-       if (user_size > len - 1)
-               user_size = len - 1;
-
-       if (copy_to_user(user_buf, buf, user_size))
-               error = -EFAULT;
-       else
-               error = user_size;
-
-       if (buf != array)
-               kfree(buf);
-
-       return error;
+       nd_set_link(nd, buf);
+       return NULL;
 }
 
-/**
- * gfs2_follow_link - Follow a symbolic link
- * @dentry: The dentry of the link
- * @nd: Data that we pass to vfs_follow_link()
- *
- * This can handle symlinks of any size. It is optimised for symlinks
- * under GFS2_FAST_NAME_SIZE.
- *
- * Returns: 0 on success or error code
- */
-
-static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
+static void gfs2_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
 {
-       struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
-       char array[GFS2_FAST_NAME_SIZE], *buf = array;
-       unsigned int len = GFS2_FAST_NAME_SIZE;
-       int error;
-
-       error = gfs2_readlinki(ip, &buf, &len);
-       if (!error) {
-               error = vfs_follow_link(nd, buf);
-               if (buf != array)
-                       kfree(buf);
-       } else
-               path_put(&nd->path);
-
-       return ERR_PTR(error);
+       char *s = nd_get_link(nd);
+       if (!IS_ERR(s))
+               kfree(s);
 }
 
 /**
@@ -1426,8 +1366,9 @@ const struct inode_operations gfs2_dir_iops = {
 };
 
 const struct inode_operations gfs2_symlink_iops = {
-       .readlink = gfs2_readlink,
+       .readlink = generic_readlink,
        .follow_link = gfs2_follow_link,
+       .put_link = gfs2_put_link,
        .permission = gfs2_permission,
        .setattr = gfs2_setattr,
        .getattr = gfs2_getattr,