]> err.no Git - linux-2.6/blobdiff - fs/cifs/inode.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6] / fs / cifs / inode.c
index b1a4a65eaa08e0b24f1c1daf83700113f38a742b..24eb4d392155b8d4482e7ff94f369c0a8c3a035d 100644 (file)
 #include "cifs_debug.h"
 #include "cifs_fs_sb.h"
 
+
+static void cifs_set_ops(struct inode *inode)
+{
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+
+       switch (inode->i_mode & S_IFMT) {
+       case S_IFREG:
+               inode->i_op = &cifs_file_inode_ops;
+               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
+                       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+                               inode->i_fop = &cifs_file_direct_nobrl_ops;
+                       else
+                               inode->i_fop = &cifs_file_direct_ops;
+               } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+                       inode->i_fop = &cifs_file_nobrl_ops;
+               else { /* not direct, send byte range locks */
+                       inode->i_fop = &cifs_file_ops;
+               }
+
+
+               /* check if server can support readpages */
+               if (cifs_sb->tcon->ses->server->maxBuf <
+                               PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
+                       inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
+               else
+                       inode->i_data.a_ops = &cifs_addr_ops;
+               break;
+       case S_IFDIR:
+               inode->i_op = &cifs_dir_inode_ops;
+               inode->i_fop = &cifs_dir_ops;
+               break;
+       case S_IFLNK:
+               inode->i_op = &cifs_symlink_inode_ops;
+               break;
+       default:
+               init_special_inode(inode, inode->i_mode, inode->i_rdev);
+               break;
+       }
+}
+
+static void cifs_unix_info_to_inode(struct inode *inode,
+               FILE_UNIX_BASIC_INFO *info, int force_uid_gid)
+{
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+       struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
+       __u64 num_of_bytes = le64_to_cpu(info->NumOfBytes);
+       __u64 end_of_file = le64_to_cpu(info->EndOfFile);
+
+       inode->i_atime = cifs_NTtimeToUnix(le64_to_cpu(info->LastAccessTime));
+       inode->i_mtime =
+               cifs_NTtimeToUnix(le64_to_cpu(info->LastModificationTime));
+       inode->i_ctime = cifs_NTtimeToUnix(le64_to_cpu(info->LastStatusChange));
+       inode->i_mode = le64_to_cpu(info->Permissions);
+
+       /*
+        * Since we set the inode type below we need to mask off
+        * to avoid strange results if bits set above.
+        */
+       inode->i_mode &= ~S_IFMT;
+       switch (le32_to_cpu(info->Type)) {
+       case UNIX_FILE:
+               inode->i_mode |= S_IFREG;
+               break;
+       case UNIX_SYMLINK:
+               inode->i_mode |= S_IFLNK;
+               break;
+       case UNIX_DIR:
+               inode->i_mode |= S_IFDIR;
+               break;
+       case UNIX_CHARDEV:
+               inode->i_mode |= S_IFCHR;
+               inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor),
+                                     le64_to_cpu(info->DevMinor) & MINORMASK);
+               break;
+       case UNIX_BLOCKDEV:
+               inode->i_mode |= S_IFBLK;
+               inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor),
+                                     le64_to_cpu(info->DevMinor) & MINORMASK);
+               break;
+       case UNIX_FIFO:
+               inode->i_mode |= S_IFIFO;
+               break;
+       case UNIX_SOCKET:
+               inode->i_mode |= S_IFSOCK;
+               break;
+       default:
+               /* safest to call it a file if we do not know */
+               inode->i_mode |= S_IFREG;
+               cFYI(1, ("unknown type %d", le32_to_cpu(info->Type)));
+               break;
+       }
+
+       if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) &&
+           !force_uid_gid)
+               inode->i_uid = cifs_sb->mnt_uid;
+       else
+               inode->i_uid = le64_to_cpu(info->Uid);
+
+       if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) &&
+           !force_uid_gid)
+               inode->i_gid = cifs_sb->mnt_gid;
+       else
+               inode->i_gid = le64_to_cpu(info->Gid);
+
+       inode->i_nlink = le64_to_cpu(info->Nlinks);
+
+       spin_lock(&inode->i_lock);
+       if (is_size_safe_to_change(cifsInfo, end_of_file)) {
+               /*
+                * We can not safely change the file size here if the client
+                * is writing to it due to potential races.
+                */
+               i_size_write(inode, end_of_file);
+
+               /*
+                * i_blocks is not related to (i_size / i_blksize),
+                * but instead 512 byte (2**9) size is required for
+                * calculating num blocks.
+                */
+               inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
+       }
+       spin_unlock(&inode->i_lock);
+}
+
 int cifs_get_inode_info_unix(struct inode **pinode,
        const unsigned char *search_path, struct super_block *sb, int xid)
 {
@@ -74,7 +198,6 @@ int cifs_get_inode_info_unix(struct inode **pinode,
                }
        } else {
                struct cifsInodeInfo *cifsInfo;
-               __u32 type = le32_to_cpu(findData.Type);
                __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
                __u64 end_of_file = le64_to_cpu(findData.EndOfFile);
 
@@ -105,112 +228,16 @@ int cifs_get_inode_info_unix(struct inode **pinode,
                /* this is ok to set on every inode revalidate */
                atomic_set(&cifsInfo->inUse, 1);
 
-               inode->i_atime =
-                   cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
-               inode->i_mtime =
-                   cifs_NTtimeToUnix(le64_to_cpu
-                               (findData.LastModificationTime));
-               inode->i_ctime =
-                   cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
-               inode->i_mode = le64_to_cpu(findData.Permissions);
-               /* since we set the inode type below we need to mask off
-                  to avoid strange results if bits set above */
-               inode->i_mode &= ~S_IFMT;
-               if (type == UNIX_FILE) {
-                       inode->i_mode |= S_IFREG;
-               } else if (type == UNIX_SYMLINK) {
-                       inode->i_mode |= S_IFLNK;
-               } else if (type == UNIX_DIR) {
-                       inode->i_mode |= S_IFDIR;
-               } else if (type == UNIX_CHARDEV) {
-                       inode->i_mode |= S_IFCHR;
-                       inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
-                               le64_to_cpu(findData.DevMinor) & MINORMASK);
-               } else if (type == UNIX_BLOCKDEV) {
-                       inode->i_mode |= S_IFBLK;
-                       inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
-                               le64_to_cpu(findData.DevMinor) & MINORMASK);
-               } else if (type == UNIX_FIFO) {
-                       inode->i_mode |= S_IFIFO;
-               } else if (type == UNIX_SOCKET) {
-                       inode->i_mode |= S_IFSOCK;
-               } else {
-                       /* safest to call it a file if we do not know */
-                       inode->i_mode |= S_IFREG;
-                       cFYI(1, ("unknown type %d", type));
-               }
+               cifs_unix_info_to_inode(inode, &findData, 0);
 
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
-                       inode->i_uid = cifs_sb->mnt_uid;
-               else
-                       inode->i_uid = le64_to_cpu(findData.Uid);
-
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
-                       inode->i_gid = cifs_sb->mnt_gid;
-               else
-                       inode->i_gid = le64_to_cpu(findData.Gid);
-
-               inode->i_nlink = le64_to_cpu(findData.Nlinks);
-
-               spin_lock(&inode->i_lock);
-               if (is_size_safe_to_change(cifsInfo, end_of_file)) {
-               /* can not safely change the file size here if the
-                  client is writing to it due to potential races */
-                       i_size_write(inode, end_of_file);
-
-               /* blksize needs to be multiple of two. So safer to default to
-               blksize and blkbits set in superblock so 2**blkbits and blksize
-               will match rather than setting to:
-               (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
-
-               /* This seems incredibly stupid but it turns out that i_blocks
-                  is not related to (i_size / i_blksize), instead 512 byte size
-                  is required for calculating num blocks */
-
-               /* 512 bytes (2**9) is the fake blocksize that must be used */
-               /* for this calculation */
-                       inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
-               }
-               spin_unlock(&inode->i_lock);
 
                if (num_of_bytes < end_of_file)
                        cFYI(1, ("allocation size less than end of file"));
                cFYI(1, ("Size %ld and blocks %llu",
                        (unsigned long) inode->i_size,
                        (unsigned long long)inode->i_blocks));
-               if (S_ISREG(inode->i_mode)) {
-                       cFYI(1, ("File inode"));
-                       inode->i_op = &cifs_file_inode_ops;
-                       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
-                               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
-                                       inode->i_fop =
-                                               &cifs_file_direct_nobrl_ops;
-                               else
-                                       inode->i_fop = &cifs_file_direct_ops;
-                       } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
-                               inode->i_fop = &cifs_file_nobrl_ops;
-                       else /* not direct, send byte range locks */
-                               inode->i_fop = &cifs_file_ops;
-
-                       /* check if server can support readpages */
-                       if (pTcon->ses->server->maxBuf <
-                           PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
-                               inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
-                       else
-                               inode->i_data.a_ops = &cifs_addr_ops;
-               } else if (S_ISDIR(inode->i_mode)) {
-                       cFYI(1, ("Directory inode"));
-                       inode->i_op = &cifs_dir_inode_ops;
-                       inode->i_fop = &cifs_dir_ops;
-               } else if (S_ISLNK(inode->i_mode)) {
-                       cFYI(1, ("Symbolic Link inode"));
-                       inode->i_op = &cifs_symlink_inode_ops;
-               /* tmp_inode->i_fop = */ /* do not need to set to anything */
-               } else {
-                       cFYI(1, ("Init special inode"));
-                       init_special_inode(inode, inode->i_mode,
-                                          inode->i_rdev);
-               }
+
+               cifs_set_ops(inode);
        }
        return rc;
 }
@@ -490,9 +517,9 @@ int cifs_get_inode_info(struct inode **pinode,
                        if (decode_sfu_inode(inode,
                                         le64_to_cpu(pfindData->EndOfFile),
                                         search_path,
-                                        cifs_sb, xid)) {
+                                        cifs_sb, xid))
                                cFYI(1, ("Unrecognized sfu inode type"));
-                       }
+
                        cFYI(1, ("sfu mode 0%o", inode->i_mode));
                } else {
                        inode->i_mode |= S_IFREG;
@@ -546,36 +573,7 @@ int cifs_get_inode_info(struct inode **pinode,
                        atomic_set(&cifsInfo->inUse, 1);
                }
 
-               if (S_ISREG(inode->i_mode)) {
-                       cFYI(1, ("File inode"));
-                       inode->i_op = &cifs_file_inode_ops;
-                       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
-                               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
-                                       inode->i_fop =
-                                               &cifs_file_direct_nobrl_ops;
-                               else
-                                       inode->i_fop = &cifs_file_direct_ops;
-                       } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
-                               inode->i_fop = &cifs_file_nobrl_ops;
-                       else /* not direct, send byte range locks */
-                               inode->i_fop = &cifs_file_ops;
-
-                       if (pTcon->ses->server->maxBuf <
-                            PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
-                               inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
-                       else
-                               inode->i_data.a_ops = &cifs_addr_ops;
-               } else if (S_ISDIR(inode->i_mode)) {
-                       cFYI(1, ("Directory inode"));
-                       inode->i_op = &cifs_dir_inode_ops;
-                       inode->i_fop = &cifs_dir_ops;
-               } else if (S_ISLNK(inode->i_mode)) {
-                       cFYI(1, ("Symbolic Link inode"));
-                       inode->i_op = &cifs_symlink_inode_ops;
-               } else {
-                       init_special_inode(inode, inode->i_mode,
-                                          inode->i_rdev);
-               }
+               cifs_set_ops(inode);
        }
        kfree(buf);
        return rc;
@@ -792,17 +790,12 @@ psx_del_no_retry:
 }
 
 static void posix_fill_in_inode(struct inode *tmp_inode,
-       FILE_UNIX_BASIC_INFO *pData, int *pobject_type, int isNewInode)
+       FILE_UNIX_BASIC_INFO *pData, int isNewInode)
 {
+       struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
        loff_t local_size;
        struct timespec local_mtime;
 
-       struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
-       struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
-
-       __u32 type = le32_to_cpu(pData->Type);
-       __u64 num_of_bytes = le64_to_cpu(pData->NumOfBytes);
-       __u64 end_of_file = le64_to_cpu(pData->EndOfFile);
        cifsInfo->time = jiffies;
        atomic_inc(&cifsInfo->inUse);
 
@@ -810,115 +803,27 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
        local_mtime = tmp_inode->i_mtime;
        local_size  = tmp_inode->i_size;
 
-       tmp_inode->i_atime =
-           cifs_NTtimeToUnix(le64_to_cpu(pData->LastAccessTime));
-       tmp_inode->i_mtime =
-           cifs_NTtimeToUnix(le64_to_cpu(pData->LastModificationTime));
-       tmp_inode->i_ctime =
-           cifs_NTtimeToUnix(le64_to_cpu(pData->LastStatusChange));
-
-       tmp_inode->i_mode = le64_to_cpu(pData->Permissions);
-       /* since we set the inode type below we need to mask off type
-          to avoid strange results if bits above were corrupt */
-       tmp_inode->i_mode &= ~S_IFMT;
-       if (type == UNIX_FILE) {
-               *pobject_type = DT_REG;
-               tmp_inode->i_mode |= S_IFREG;
-       } else if (type == UNIX_SYMLINK) {
-               *pobject_type = DT_LNK;
-               tmp_inode->i_mode |= S_IFLNK;
-       } else if (type == UNIX_DIR) {
-               *pobject_type = DT_DIR;
-               tmp_inode->i_mode |= S_IFDIR;
-       } else if (type == UNIX_CHARDEV) {
-               *pobject_type = DT_CHR;
-               tmp_inode->i_mode |= S_IFCHR;
-               tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),
-                               le64_to_cpu(pData->DevMinor) & MINORMASK);
-       } else if (type == UNIX_BLOCKDEV) {
-               *pobject_type = DT_BLK;
-               tmp_inode->i_mode |= S_IFBLK;
-               tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),
-                               le64_to_cpu(pData->DevMinor) & MINORMASK);
-       } else if (type == UNIX_FIFO) {
-               *pobject_type = DT_FIFO;
-               tmp_inode->i_mode |= S_IFIFO;
-       } else if (type == UNIX_SOCKET) {
-               *pobject_type = DT_SOCK;
-               tmp_inode->i_mode |= S_IFSOCK;
-       } else {
-               /* safest to just call it a file */
-               *pobject_type = DT_REG;
-               tmp_inode->i_mode |= S_IFREG;
-               cFYI(1, ("unknown inode type %d", type));
-       }
-
-#ifdef CONFIG_CIFS_DEBUG2
-       cFYI(1, ("object type: %d", type));
-#endif
-       tmp_inode->i_uid = le64_to_cpu(pData->Uid);
-       tmp_inode->i_gid = le64_to_cpu(pData->Gid);
-       tmp_inode->i_nlink = le64_to_cpu(pData->Nlinks);
-
-       spin_lock(&tmp_inode->i_lock);
-       if (is_size_safe_to_change(cifsInfo, end_of_file)) {
-               /* can not safely change the file size here if the
-               client is writing to it due to potential races */
-               i_size_write(tmp_inode, end_of_file);
+       cifs_unix_info_to_inode(tmp_inode, pData, 1);
+       cifs_set_ops(tmp_inode);
 
-       /* 512 bytes (2**9) is the fake blocksize that must be used */
-       /* for this calculation, not the real blocksize */
-               tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
-       }
-       spin_unlock(&tmp_inode->i_lock);
-
-       if (S_ISREG(tmp_inode->i_mode)) {
-               cFYI(1, ("File inode"));
-               tmp_inode->i_op = &cifs_file_inode_ops;
-
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
-                       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
-                               tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
-                       else
-                               tmp_inode->i_fop = &cifs_file_direct_ops;
+       if (!S_ISREG(tmp_inode->i_mode))
+               return;
 
-               } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
-                       tmp_inode->i_fop = &cifs_file_nobrl_ops;
-               else
-                       tmp_inode->i_fop = &cifs_file_ops;
-
-               if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
-                  (cifs_sb->tcon->ses->server->maxBuf <
-                       PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
-                       tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
-               else
-                       tmp_inode->i_data.a_ops = &cifs_addr_ops;
-
-               if (isNewInode)
-                       return; /* No sense invalidating pages for new inode
-                                  since we we have not started caching
-                                  readahead file data yet */
+       /*
+        * No sense invalidating pages for new inode
+        * since we we have not started caching
+        * readahead file data yet.
+        */
+       if (isNewInode)
+               return;
 
-               if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
-                       (local_size == tmp_inode->i_size)) {
-                       cFYI(1, ("inode exists but unchanged"));
-               } else {
-                       /* file may have changed on server */
-                       cFYI(1, ("invalidate inode, readdir detected change"));
-                       invalidate_remote_inode(tmp_inode);
-               }
-       } else if (S_ISDIR(tmp_inode->i_mode)) {
-               cFYI(1, ("Directory inode"));
-               tmp_inode->i_op = &cifs_dir_inode_ops;
-               tmp_inode->i_fop = &cifs_dir_ops;
-       } else if (S_ISLNK(tmp_inode->i_mode)) {
-               cFYI(1, ("Symbolic Link inode"));
-               tmp_inode->i_op = &cifs_symlink_inode_ops;
-/* tmp_inode->i_fop = *//* do not need to set to anything */
+       if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
+               (local_size == tmp_inode->i_size)) {
+               cFYI(1, ("inode exists but unchanged"));
        } else {
-               cFYI(1, ("Special inode"));
-               init_special_inode(tmp_inode, tmp_inode->i_mode,
-                                  tmp_inode->i_rdev);
+               /* file may have changed on server */
+               cFYI(1, ("invalidate inode, readdir detected change"));
+               invalidate_remote_inode(tmp_inode);
        }
 }
 
@@ -968,7 +873,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
                        cFYI(1, ("posix mkdir returned 0x%x", rc));
                        d_drop(direntry);
                } else {
-                       int obj_type;
                        if (pInfo->Type == cpu_to_le32(-1)) {
                                /* no return info, go query for it */
                                kfree(pInfo);
@@ -1004,7 +908,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
                        /* we already checked in POSIXCreate whether
                           frame was long enough */
                        posix_fill_in_inode(direntry->d_inode,
-                                       pInfo, &obj_type, 1 /* NewInode */);
+                                       pInfo, 1 /* NewInode */);
 #ifdef CONFIG_CIFS_DEBUG2
                        cFYI(1, ("instantiated dentry %p %s to inode %p",
                                direntry, direntry->d_name.name, newinode));
@@ -1214,9 +1118,8 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
                } /* if we can not get memory just leave rc as EEXIST */
        }
 
-       if (rc) {
+       if (rc)
                cFYI(1, ("rename rc %d", rc));
-       }
 
        if ((rc == -EIO) || (rc == -EEXIST)) {
                int oplock = FALSE;