Whamcloud - gitweb
LU-271 Skip permission check for NFS open after create
[fs/lustre-release.git] / lustre / llite / file.c
index 05daf03..d316e18 100644 (file)
@@ -502,12 +502,8 @@ int ll_file_open(struct inode *inode, struct file *file)
         CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), flags %o\n", inode->i_ino,
                inode->i_generation, inode, file->f_flags);
 
-#ifdef HAVE_VFS_INTENT_PATCHES
-        it = file->f_it;
-#else
         it = file->private_data; /* XXX: compat macro */
         file->private_data = NULL; /* prevent ll_local_open assertion */
-#endif
 
         fd = ll_file_data_get();
         if (fd == NULL)
@@ -543,7 +539,7 @@ int ll_file_open(struct inode *inode, struct file *file)
                  * dentry_open after call to open_namei that checks permissions.
                  * Only nfsd_open call dentry_open directly without checking
                  * permissions and because of that this code below is safe. */
-                if (oit.it_flags & FMODE_WRITE)
+                if (oit.it_flags & (FMODE_WRITE | FMODE_READ))
                         oit.it_flags |= MDS_OPEN_OWNEROVERRIDE;
 
                 /* We do not want O_EXCL here, presumably we opened the file
@@ -830,8 +826,9 @@ static ssize_t ll_file_io_generic(const struct lu_env *env,
                 struct vvp_io_args *args, struct file *file,
                 enum cl_io_type iot, loff_t *ppos, size_t count)
 {
-        struct cl_io       *io;
-        ssize_t             result;
+        struct ll_inode_info *lli = ll_i2info(file->f_dentry->d_inode);
+        struct cl_io         *io;
+        ssize_t               result;
         ENTRY;
 
         io = &ccc_env_info(env)->cti_io;
@@ -840,7 +837,6 @@ static ssize_t ll_file_io_generic(const struct lu_env *env,
         if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) {
                 struct vvp_io *vio = vvp_env_io(env);
                 struct ccc_io *cio = ccc_env_io(env);
-                struct ll_inode_info *lli = ll_i2info(file->f_dentry->d_inode);
                 int write_sem_locked = 0;
 
                 cio->cui_fd  = LUSTRE_FPRIVATE(file);
@@ -859,6 +855,8 @@ static ssize_t ll_file_io_generic(const struct lu_env *env,
                                 if(cfs_down_interruptible(&lli->lli_write_sem))
                                         GOTO(out, result = -ERESTARTSYS);
                                 write_sem_locked = 1;
+                        } else if (iot == CIT_READ) {
+                                cfs_down_read(&lli->lli_trunc_sem);
                         }
                         break;
                 case IO_SENDFILE:
@@ -876,6 +874,8 @@ static ssize_t ll_file_io_generic(const struct lu_env *env,
                 result = cl_io_loop(env, io);
                 if (write_sem_locked)
                         cfs_up(&lli->lli_write_sem);
+                else if (args->via_io_subtype == IO_NORMAL && iot == CIT_READ)
+                        cfs_up_read(&lli->lli_trunc_sem);
         } else {
                 /* cl_io_rw_init() handled IO */
                 result = io->ci_result;
@@ -888,6 +888,8 @@ static ssize_t ll_file_io_generic(const struct lu_env *env,
         GOTO(out, result);
 out:
         cl_io_fini(env, io);
+        if (iot == CIT_WRITE)
+                lli->lli_write_rc = result < 0 ? : 0;
         return result;
 }
 
@@ -1223,7 +1225,7 @@ static int ll_lov_recreate(struct inode *inode, obd_id id, obd_seq seq,
         lsm_size = sizeof(*lsm) + (sizeof(struct lov_oinfo) *
                    (lsm->lsm_stripe_count));
 
-        OBD_ALLOC(lsm2, lsm_size);
+        OBD_ALLOC_LARGE(lsm2, lsm_size);
         if (lsm2 == NULL)
                 GOTO(out, rc = -ENOMEM);
 
@@ -1237,7 +1239,7 @@ static int ll_lov_recreate(struct inode *inode, obd_id id, obd_seq seq,
         memcpy(lsm2, lsm, lsm_size);
         rc = obd_create(exp, oa, &lsm2, &oti);
 
-        OBD_FREE(lsm2, lsm_size);
+        OBD_FREE_LARGE(lsm2, lsm_size);
         GOTO(out, rc);
 out:
         ll_inode_size_unlock(inode, 0);
@@ -1408,18 +1410,18 @@ static int ll_lov_setea(struct inode *inode, struct file *file,
         if (!cfs_capable(CFS_CAP_SYS_ADMIN))
                 RETURN(-EPERM);
 
-        OBD_ALLOC(lump, lum_size);
+        OBD_ALLOC_LARGE(lump, lum_size);
         if (lump == NULL) {
                 RETURN(-ENOMEM);
         }
         if (cfs_copy_from_user(lump, (struct lov_user_md  *)arg, lum_size)) {
-                OBD_FREE(lump, lum_size);
+                OBD_FREE_LARGE(lump, lum_size);
                 RETURN(-EFAULT);
         }
 
         rc = ll_lov_setstripe_ea_info(inode, file, flags, lump, lum_size);
 
-        OBD_FREE(lump, lum_size);
+        OBD_FREE_LARGE(lump, lum_size);
         RETURN(rc);
 }
 
@@ -1692,7 +1694,7 @@ static int ll_ioctl_fiemap(struct inode *inode, unsigned long arg)
         num_bytes = sizeof(*fiemap_s) + (extent_count *
                                          sizeof(struct ll_fiemap_extent));
 
-        OBD_VMALLOC(fiemap_s, num_bytes);
+        OBD_ALLOC_LARGE(fiemap_s, num_bytes);
         if (fiemap_s == NULL)
                 RETURN(-ENOMEM);
 
@@ -1725,13 +1727,19 @@ static int ll_ioctl_fiemap(struct inode *inode, unsigned long arg)
                 rc = -EFAULT;
 
 error:
-        OBD_VFREE(fiemap_s, num_bytes);
+        OBD_FREE_LARGE(fiemap_s, num_bytes);
         RETURN(rc);
 }
 
+#ifdef HAVE_UNLOCKED_IOCTL
+long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+        struct inode *inode = file->f_dentry->d_inode;
+#else
 int ll_file_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                   unsigned long arg)
 {
+#endif
         struct ll_file_data *fd = LUSTRE_FPRIVATE(file);
         int flags;
         ENTRY;
@@ -1888,6 +1896,10 @@ int ll_flush(struct file *file)
         struct lov_stripe_md *lsm = lli->lli_smd;
         int rc, err;
 
+        /* the application should know write failure already. */
+        if (lli->lli_write_rc)
+                return 0;
+
         /* catch async errors that were recorded back when async writeback
          * failed for pages in this mapping. */
         rc = lli->lli_async_rc;
@@ -1940,27 +1952,33 @@ int ll_fsync(struct file *file, struct dentry *dentry, int data)
                 ptlrpc_req_finished(req);
 
         if (data && lsm) {
-                struct obdo *oa;
+                struct obd_info *oinfo;
 
-                OBDO_ALLOC(oa);
-                if (!oa)
+                OBD_ALLOC_PTR(oinfo);
+                if (!oinfo)
                         RETURN(rc ? rc : -ENOMEM);
-
-                oa->o_id = lsm->lsm_object_id;
-                oa->o_seq = lsm->lsm_object_seq;
-                oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;
-                obdo_from_inode(oa, inode, &ll_i2info(inode)->lli_fid,
+                OBDO_ALLOC(oinfo->oi_oa);
+                if (!oinfo->oi_oa) {
+                        OBD_FREE_PTR(oinfo);
+                        RETURN(rc ? rc : -ENOMEM);
+                }
+                oinfo->oi_oa->o_id = lsm->lsm_object_id;
+                oinfo->oi_oa->o_seq = lsm->lsm_object_seq;
+                oinfo->oi_oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;
+                obdo_from_inode(oinfo->oi_oa, inode, &ll_i2info(inode)->lli_fid,
                                 OBD_MD_FLTYPE | OBD_MD_FLATIME |
                                 OBD_MD_FLMTIME | OBD_MD_FLCTIME |
                                 OBD_MD_FLGROUP);
-
-                oc = ll_osscapa_get(inode, CAPA_OPC_OSS_WRITE);
-                err = obd_sync(ll_i2sbi(inode)->ll_dt_exp, oa, lsm,
-                               0, OBD_OBJECT_EOF, oc);
-                capa_put(oc);
+                oinfo->oi_md = lsm;
+                oinfo->oi_capa = ll_osscapa_get(inode, CAPA_OPC_OSS_WRITE);
+                err = obd_sync_rqset(ll_i2sbi(inode)->ll_dt_exp, oinfo, 0,
+                                     OBD_OBJECT_EOF);
+                capa_put(oinfo->oi_capa);
                 if (!rc)
                         rc = err;
-                OBDO_FREE(oa);
+                OBDO_FREE(oinfo->oi_oa);
+                OBD_FREE_PTR(oinfo);
+                lli->lli_write_rc = err < 0 ? : 0;
         }
 
         RETURN(rc);
@@ -1975,7 +1993,7 @@ int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
                                            .ei_cbdata = file_lock };
         struct md_op_data *op_data;
         struct lustre_handle lockh = {0};
-        ldlm_policy_data_t flock;
+        ldlm_policy_data_t flock = {{0}};
         int flags = 0;
         int rc;
         ENTRY;
@@ -1987,13 +2005,18 @@ int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock)
 
         if (file_lock->fl_flags & FL_FLOCK) {
                 LASSERT((cmd == F_SETLKW) || (cmd == F_SETLK));
-                /* set missing params for flock() calls */
-                file_lock->fl_end = OFFSET_MAX;
-                file_lock->fl_pid = current->tgid;
+                /* flocks are whole-file locks */
+                flock.l_flock.end = OFFSET_MAX;
+                /* For flocks owner is determined by the local file desctiptor*/
+                flock.l_flock.owner = (unsigned long)file_lock->fl_file;
+        } else if (file_lock->fl_flags & FL_POSIX) {
+                flock.l_flock.owner = (unsigned long)file_lock->fl_owner;
+                flock.l_flock.start = file_lock->fl_start;
+                flock.l_flock.end = file_lock->fl_end;
+        } else {
+                RETURN(-EINVAL);
         }
         flock.l_flock.pid = file_lock->fl_pid;
-        flock.l_flock.start = file_lock->fl_start;
-        flock.l_flock.end = file_lock->fl_end;
 
         switch (file_lock->fl_type) {
         case F_RDLCK:
@@ -2164,10 +2187,16 @@ int __ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
 
         exp = ll_i2mdexp(inode);
 
+        /* XXX: Enable OBD_CONNECT_ATTRFID to reduce unnecessary getattr RPC.
+         *      But under CMD case, it caused some lock issues, should be fixed
+         *      with new CMD ibits lock. See bug 12718 */
         if (exp->exp_connect_flags & OBD_CONNECT_ATTRFID) {
                 struct lookup_intent oit = { .it_op = IT_GETATTR };
                 struct md_op_data *op_data;
 
+                if (ibits == MDS_INODELOCK_LOOKUP)
+                        oit.it_op = IT_LOOKUP;
+
                 /* Call getattr by fid, so do not provide name at all. */
                 op_data = ll_prep_md_op_data(NULL, dentry->d_parent->d_inode,
                                              dentry->d_inode, NULL, 0, 0,
@@ -2244,14 +2273,14 @@ out:
         return rc;
 }
 
-int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it)
+int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
+                           __u64 ibits)
 {
         struct inode *inode = dentry->d_inode;
         int rc;
         ENTRY;
 
-        rc = __ll_inode_revalidate_it(dentry, it, MDS_INODELOCK_UPDATE |
-                                                  MDS_INODELOCK_LOOKUP);
+        rc = __ll_inode_revalidate_it(dentry, it, ibits);
 
         /* if object not yet allocated, don't validate size */
         if (rc == 0 && ll_i2info(dentry->d_inode)->lli_smd == NULL) {
@@ -2277,7 +2306,8 @@ int ll_getattr_it(struct vfsmount *mnt, struct dentry *de,
         struct ll_inode_info *lli = ll_i2info(inode);
         int res = 0;
 
-        res = ll_inode_revalidate_it(de, it);
+        res = ll_inode_revalidate_it(de, it, MDS_INODELOCK_UPDATE |
+                                             MDS_INODELOCK_LOOKUP);
         ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETATTR, 1);
 
         if (res)
@@ -2326,7 +2356,7 @@ int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
 
         num_bytes = sizeof(*fiemap) + (extent_count *
                                        sizeof(struct ll_fiemap_extent));
-        OBD_VMALLOC(fiemap, num_bytes);
+        OBD_ALLOC_LARGE(fiemap, num_bytes);
 
         if (fiemap == NULL)
                 RETURN(-ENOMEM);
@@ -2345,7 +2375,7 @@ int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
         memcpy(fieinfo->fi_extents_start, &fiemap->fm_extents[0],
                fiemap->fm_mapped_extents * sizeof(struct ll_fiemap_extent));
 
-        OBD_VFREE(fiemap, num_bytes);
+        OBD_FREE_LARGE(fiemap, num_bytes);
         return rc;
 }
 #endif
@@ -2479,7 +2509,11 @@ struct file_operations ll_file_operations = {
         .READ_METHOD    = READ_FUNCTION,
         .write          = ll_file_write,
         .WRITE_METHOD   = WRITE_FUNCTION,
+#ifdef HAVE_UNLOCKED_IOCTL
+        .unlocked_ioctl = ll_file_ioctl,
+#else
         .ioctl          = ll_file_ioctl,
+#endif
         .open           = ll_file_open,
         .release        = ll_file_release,
         .mmap           = ll_file_mmap,
@@ -2499,7 +2533,11 @@ struct file_operations ll_file_operations_flock = {
         .READ_METHOD    = READ_FUNCTION,
         .write          = ll_file_write,
         .WRITE_METHOD   = WRITE_FUNCTION,
+#ifdef HAVE_UNLOCKED_IOCTL
+        .unlocked_ioctl = ll_file_ioctl,
+#else
         .ioctl          = ll_file_ioctl,
+#endif
         .open           = ll_file_open,
         .release        = ll_file_release,
         .mmap           = ll_file_mmap,
@@ -2524,7 +2562,11 @@ struct file_operations ll_file_operations_noflock = {
         .READ_METHOD    = READ_FUNCTION,
         .write          = ll_file_write,
         .WRITE_METHOD   = WRITE_FUNCTION,
+#ifdef HAVE_UNLOCKED_IOCTL
+        .unlocked_ioctl = ll_file_ioctl,
+#else
         .ioctl          = ll_file_ioctl,
+#endif
         .open           = ll_file_open,
         .release        = ll_file_release,
         .mmap           = ll_file_mmap,
@@ -2544,9 +2586,6 @@ struct file_operations ll_file_operations_noflock = {
 };
 
 struct inode_operations ll_file_inode_operations = {
-#ifdef HAVE_VFS_INTENT_PATCHES
-        .setattr_raw    = ll_setattr_raw,
-#endif
         .setattr        = ll_setattr,
         .truncate       = ll_truncate,
         .getattr        = ll_getattr,